Index: netui/test/webapps/drt/coreWeb/WEB-INF/src/mockportal/MockPortletTag.java
===================================================================
--- netui/test/webapps/drt/coreWeb/WEB-INF/src/mockportal/MockPortletTag.java	(revision 109213)
+++ netui/test/webapps/drt/coreWeb/WEB-INF/src/mockportal/MockPortletTag.java	(working copy)
@@ -70,7 +70,7 @@
             //
             String requestURI = currentURL != null ? outerRequest.getContextPath() + currentURL : null;
             ScopedRequest scopedRequest = 
-                    ScopedServletUtils.getScopedRequest( outerRequest, requestURI, outerServletContext, _portletID, true );
+                    ScopedServletUtils.getScopedRequest( outerRequest, requestURI, outerServletContext, _portletID, false );
             ScopedResponse scopedResponse =
                     ScopedServletUtils.getScopedResponse( outerResponse, scopedRequest );
             
@@ -108,8 +108,6 @@
             
             boolean submittedThisPortlet = ( scopedRequest.getParameter( "_submit" ) != null );
 
-            String uri = ( currentURL != null ? currentURL : _pageFlowURI );
-            
             if ( currentURL == null )   // First time -- execute the begin action
             {
                 if ( actionResolver != null )
@@ -255,7 +253,8 @@
     {
         HttpServletRequest outerRequest = ( HttpServletRequest ) pageContext.getRequest();        
         ScopedRequest scopedRequest = 
-                ScopedServletUtils.getScopedRequest( outerRequest, null, pageContext.getServletContext(), _portletID, true );
+                ScopedServletUtils.getScopedRequest( outerRequest, null, pageContext.getServletContext(),
+                                                     _portletID, false );
         scopedRequest.persistAttributes();
         
         pageContext.removeAttribute( "mockCurrentUrl" );
Index: netui/test/webapps/drt/coreWeb/WEB-INF/src/mockportal/MockPortalUrlRewriter.java
===================================================================
--- netui/test/webapps/drt/coreWeb/WEB-INF/src/mockportal/MockPortalUrlRewriter.java	(revision 109213)
+++ netui/test/webapps/drt/coreWeb/WEB-INF/src/mockportal/MockPortalUrlRewriter.java	(working copy)
@@ -22,7 +22,6 @@
 import org.apache.beehive.netui.pageflow.util.URLRewriterService;
 import org.apache.beehive.netui.pageflow.PageFlowConstants;
 
-import javax.servlet.jsp.PageContext;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
Index: netui/src/tags-html/org/apache/beehive/netui/tags/AbstractClassicTag.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/AbstractClassicTag.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/AbstractClassicTag.java	(working copy)
@@ -17,12 +17,9 @@
  */
 package org.apache.beehive.netui.tags;
 
-import org.apache.beehive.netui.pageflow.util.URLRewriterService;
+import org.apache.beehive.netui.core.urls.URLRewriterService;
 import org.apache.beehive.netui.script.ExpressionEvaluationException;
 import org.apache.beehive.netui.script.ExpressionEvaluator;
-import org.apache.beehive.netui.script.ExpressionEvaluatorFactory;
-import org.apache.beehive.netui.script.ExpressionUpdateException;
-import org.apache.beehive.netui.script.common.ImplicitObjectBean;
 import org.apache.beehive.netui.script.common.ImplicitObjectUtil;
 import org.apache.beehive.netui.tags.naming.FormDataNameInterceptor;
 import org.apache.beehive.netui.tags.naming.IndexedNameInterceptor;
@@ -36,8 +33,6 @@
 import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.PageContext;
 import javax.servlet.jsp.tagext.BodyTagSupport;
-import javax.servlet.jsp.tagext.Tag;
-import javax.servlet.jsp.tagext.JspTag;
 import javax.servlet.jsp.tagext.SimpleTagSupport;
 import java.util.*;
 
Index: netui/src/tags-html/org/apache/beehive/netui/tags/tree/Tree.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/tree/Tree.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/tree/Tree.java	(working copy)
@@ -17,10 +17,10 @@
  */
 package org.apache.beehive.netui.tags.tree;
 
+import org.apache.beehive.netui.core.urls.MutableURI;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
 import org.apache.beehive.netui.script.ExpressionUpdateException;
 import org.apache.beehive.netui.script.IllegalExpressionException;
 import org.apache.beehive.netui.tags.*;
@@ -28,7 +28,6 @@
 import org.apache.beehive.netui.tags.html.JavaScriptUtils;
 import org.apache.beehive.netui.tags.rendering.*;
 import org.apache.beehive.netui.util.Bundle;
-import org.apache.beehive.netui.util.FileUtils;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -36,7 +35,9 @@
 import javax.servlet.jsp.PageContext;
 import javax.servlet.ServletContext;
 import java.io.IOException;
+import java.net.URISyntaxException;
 import java.net.URLEncoder;
+import java.util.HashMap;
 
 
 /**
@@ -734,7 +735,7 @@
         // In devMode we will verify the structure of the tree.  This will not run in
         // production mode.
         ServletContext servletContext = InternalUtils.getServletContext(request);
-        boolean devMode = !ContextCache.get(servletContext).getServerAdapter().isInProductionMode();
+        boolean devMode = !ServerAdapterManager.getServerAdapter(servletContext).isInProductionMode();
         if (devMode) {
             boolean error = false;
             StringBuilder errorText = new StringBuilder(64);
@@ -793,7 +794,7 @@
         // boolean flag that will indicate if there is an open anchor created
         boolean closeAnchor = false;
         if (!_runAtClient)
-            closeAnchor = renderExpansionAnchor(sb, anchorRenderer, request, response, node, encodedNodeName);
+            closeAnchor = renderExpansionAnchor(sb, anchorRenderer, request, response, node, nodeName);
         else {
             // Render client expansion and initialize the tree JavaScript support
             closeAnchor = renderClientExpansionAnchor(sb, anchorRenderer, node, encodedNodeName);
@@ -860,20 +861,32 @@
             // process the action into a URL
             PageContext pageContext = getPageContext();
             if (action != null && selectionLink == null) {
-                String qualifiedAction = PageflowTagUtils.qualifiedAction(pageContext.getServletContext(),action);
-                selectionLink = PageflowTagUtils.createActionURL(request, qualifiedAction);
-                selectionLink = PageflowTagUtils.addParam(selectionLink, TreeElement.SELECTED_NODE, encodedNodeName);
-                if (_tagId != null)
-                    selectionLink = PageflowTagUtils.addParam(selectionLink, TreeElement.TREE_ID, _tagId);
+                HashMap params = new HashMap();
+                params.put(TreeElement.SELECTED_NODE, nodeName);
+                if (_tagId != null) {
+                    params.put(TreeElement.TREE_ID, _tagId);
+                }
 
                 // Add the jpf ScopeID param if necessary.
                 String scope = node.getScope();
                 if (scope != null) {
-                    selectionLink = PageflowTagUtils.addParam(selectionLink, ScopedServletUtils.SCOPE_ID_PARAM, scope);
+                    params.put(ScopedServletUtils.SCOPE_ID_PARAM, scope);
                 }
 
-                if ((selectionLink != null) && (!FileUtils.isAbsoluteURI(selectionLink)))
-                    selectionLink = PageflowTagUtils.prepareActionUrl(pageContext, selectionLink);
+                MutableURI uri = null;
+                try {
+                    uri = PageFlowTagUtils.rewrittenActionURL(pageContext, action, params, null);
+                }
+                catch (URISyntaxException e) {
+                    // report the error...
+                    String s = Bundle.getString("Tags_Tree_Node_URLException",
+                                                new Object[]{action, e.getMessage()});
+                    registerTagError(s, e);
+                }
+
+                if (uri != null) {
+                    selectionLink = response.encodeURL(uri.toString());
+                }
             }
         }
 
@@ -988,7 +1001,7 @@
 
     private boolean renderExpansionAnchor(StringBuilder sb, TagRenderingBase anchorRenderer,
                                           HttpServletRequest request, HttpServletResponse response,
-                                          TreeElement node, String encodedNodeName)
+                                          TreeElement node, String nodeName)
             throws JspException
     {
         // Render the tree state image for this node
@@ -997,31 +1010,32 @@
         if (action == null) {
             action = _iState.getSelectionAction();
         }
-        boolean isAction = PageflowTagUtils.isAction(request, response, pageContext.getServletContext(), action);
+        boolean isAction = PageFlowTagUtils.isAction(request, response, pageContext.getServletContext(), action);
         if (!isAction) {
             registerTagError(Bundle.getString("Tags_BadAction", action), null);
             return false;
         }
-        String qualifiedAction = PageflowTagUtils.qualifiedAction(pageContext.getServletContext(),action);
-        action = PageflowTagUtils.createActionURL(request, qualifiedAction);
-        action = PageflowTagUtils.prepareActionUrl(pageContext, action);
 
         // encode the tree parameters into the action.
-        String amp = TagRenderingBase.getAmp(request);
-        if (action.indexOf("?") > -1) {
-            action = action + amp + TreeElement.EXPAND_NODE + "=" + encodedNodeName;
+        HashMap params = new HashMap();
+        params.put(TreeElement.EXPAND_NODE, nodeName);
+        assert (_tagId != null);
+        params.put(TreeElement.TREE_ID, _tagId);
+        MutableURI uri = null;
+        try {
+            uri = PageFlowTagUtils.rewrittenActionURL(pageContext, action, params, null);
         }
-        else {
-            action = action + "?" + TreeElement.EXPAND_NODE + "=" + encodedNodeName;
+        catch (URISyntaxException e) {
+            // report the error...
+            String s = Bundle.getString("Tags_Tree_Node_URLException",
+                                        new Object[]{action, e.getMessage()});
+            registerTagError(s, e);
         }
-        assert (_tagId != null);
-        action = action + amp + TreeElement.TREE_ID + "=" + _tagId;
 
-
         boolean ret = false;
-        if ((action != null) && !node.isLeaf()) {
+        if ((uri != null) && !node.isLeaf()) {
             _anchorState.clear();
-            _anchorState.href = action;
+            _anchorState.href = response.encodeURL(uri.toString());
             _anchorState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, TARGET, _iState.getExpandTarget());
             sb.append("      ");
             StringBuilderRenderAppender writer = new StringBuilderRenderAppender(sb);
Index: netui/src/tags-html/org/apache/beehive/netui/tags/tree/TreeItem.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/tree/TreeItem.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/tree/TreeItem.java	(working copy)
@@ -17,8 +17,8 @@
  */
 package org.apache.beehive.netui.tags.tree;
 
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
 import org.apache.beehive.netui.tags.AbstractSimpleTag;
+import org.apache.beehive.netui.tags.PageFlowTagUtils;
 import org.apache.beehive.netui.util.Bundle;
 
 import javax.servlet.http.HttpServletRequest;
@@ -302,7 +302,7 @@
         if (_action != null) {
             HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
             HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
-            boolean isAction = PageflowTagUtils.isAction(request, response, pageContext.getServletContext(), _action);
+            boolean isAction = PageFlowTagUtils.isAction(request, response, pageContext.getServletContext(), _action);
             if (!isAction) {
                 registerTagError(Bundle.getString("Tags_BadAction", _action), null);
             }
Index: netui/src/tags-html/org/apache/beehive/netui/tags/PageFlowTagUtils.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/PageFlowTagUtils.java	(revision 57093)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/PageFlowTagUtils.java	(working copy)
@@ -15,428 +15,174 @@
  *
  * $Header:$
  */
-package org.apache.beehive.netui.pageflow.util;
+package org.apache.beehive.netui.tags;
 
-//java imports
-import java.net.URLEncoder;
-import java.net.MalformedURLException;
-import java.util.Map;
-import java.util.Iterator;
-
-//internal imports
+import org.apache.beehive.netui.core.urls.MutableURI;
+import org.apache.beehive.netui.core.urls.URLRewriter;
+import org.apache.beehive.netui.core.urls.URLRewriterService;
 import org.apache.beehive.netui.pageflow.FlowController;
 import org.apache.beehive.netui.pageflow.FlowControllerFactory;
+import org.apache.beehive.netui.pageflow.PageFlowConstants;
+import org.apache.beehive.netui.pageflow.PageFlowUtils;
+import org.apache.beehive.netui.pageflow.SecurityProtocol;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
 
-import org.apache.beehive.netui.util.logging.Logger;
-import org.apache.beehive.netui.util.FileUtils;
-
-//external imports
+import java.util.Map;
 import javax.servlet.jsp.PageContext;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletRequest;
 
-import org.apache.struts.config.ModuleConfig;
-import org.apache.struts.config.ForwardConfig;
-import org.apache.struts.Globals;
-import org.apache.struts.util.MessageResources;
-import org.apache.struts.util.RequestUtils;
 
-import static org.apache.beehive.netui.pageflow.PageFlowConstants.ACTION_EXTENSION;
-
-
 /**
  * @exclude
- */ 
-public class PageflowTagUtils
+ */
+public class PageFlowTagUtils
 {
-    private static final Logger logger = Logger.getInstance( PageflowTagUtils.class );
-
-    /**
-     * The message resources for this package.
-     */
-    private static MessageResources messages =
-        MessageResources.getMessageResources("org.apache.struts.util.LocalStrings");
-
-    public static String getRewrittenFormAction(HttpServletRequest request, String action, PageContext pageContext)
+    public static MutableURI rewrittenActionURL( PageContext pageContext, String action, Map params, String location )
+            throws java.net.URISyntaxException
     {
-        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
-        String qualifiedAction = PageflowTagUtils.qualifiedAction(pageContext.getServletContext(),action);
-        String actionUrl = createActionURL(request, qualifiedAction);
-
-        actionUrl = prepareActionUrl(pageContext, actionUrl);
-
-        return response.encodeURL(actionUrl);
-    }
-
-    public static String prepareActionUrl(PageContext pageContext, String url)
-    {
         ServletContext servletContext = pageContext.getServletContext();
         ServletRequest request = pageContext.getRequest();
-        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
+        HttpServletResponse response = ( HttpServletResponse ) pageContext.getResponse();
+        String qualifiedAction = InternalUtils.qualifiedAction( servletContext, action );
+        String actionUrl = InternalUtils.createActionURL( ( HttpServletRequest ) request, qualifiedAction );
+        MutableURI uri = new MutableURI( actionUrl );
 
-        String templateType = URLRewriter.ACTION_UNSECURE;
+        if ( params != null )
+        {
+            String encoding = response.getCharacterEncoding();
+            uri.addParameters( params, false, encoding );
+        }
 
-        if (URLRewriterService.needsSecure(request, servletContext, url, true))
-            templateType = URLRewriter.ACTION_SECURE;
+        if ( location != null ) { uri.setFragment( location ); }
 
-        url = URLRewriterService.rewriteURL(servletContext, request, response, url, templateType);
+        boolean needsToBeSecure = needsSecure( servletContext, request, actionUrl, true );
+        URLRewriterService.rewriteURL( servletContext, request, response, uri,
+                                       URLRewriter.Type.ACTION, needsToBeSecure );
 
-        return response.encodeURL(url);
+        return uri;
     }
 
-    public static String prepareResourceUrl(PageContext pageContext, String url)
+    public static MutableURI rewrittenResourceURL( PageContext pageContext, String url, Map params, String location )
+            throws java.net.URISyntaxException
     {
-        if ( FileUtils.isAbsoluteURI(url) )
+        HttpServletResponse response = ( HttpServletResponse ) pageContext.getResponse();
+        MutableURI uri = new MutableURI( url );
+        if ( params != null )
         {
-            return url;
+            String encoding = response.getCharacterEncoding();
+            uri.addParameters( params, false, encoding );
         }
-        
-        ServletContext servletContext = pageContext.getServletContext();
-        HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
-        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
 
+        if ( location != null ) { uri.setFragment( location ); }
 
-        if (!url.startsWith("/"))
+        if ( uri.isAbsolute() ) { return uri; }
+
+        HttpServletRequest request = ( HttpServletRequest ) pageContext.getRequest();
+        if ( !url.startsWith( "/" ) && !url.equals( "" ) )
         {
             String reqUri = request.getRequestURI();
-            String path = reqUri.substring(0, reqUri.lastIndexOf("/") + 1);
-            url = path + url;
+            String path = reqUri.substring( 0, reqUri.lastIndexOf( '/' ) + 1 );
+            uri.setPath( path + uri.getPath() );
         }
 
-        String templateType = URLRewriter.RESOURCE_UNSECURE;
+        ServletContext servletContext = pageContext.getServletContext();
+        boolean needsToBeSecure = needsSecure( servletContext, request, url, true );
+        URLRewriterService.rewriteURL( servletContext, request, response, uri,
+                                       URLRewriter.Type.RESOURCE, needsToBeSecure );
 
-        if (URLRewriterService.needsSecure(request, servletContext, url, true))
-            templateType = URLRewriter.RESOURCE_SECURE;
-
-        url = URLRewriterService.rewriteURL(servletContext, request, response, url, templateType);
-
-        return response.encodeURL(url);
+        return uri;
     }
 
-    public static String createActionURL(HttpServletRequest servletRequest, String qualifiedAction)
+    public static boolean isAction( HttpServletRequest request, HttpServletResponse response,
+                                    ServletContext servletContext, String action )
     {
-        String pageURI = InternalUtils.getDecodedURI( servletRequest );
-        int lastSlash = pageURI.lastIndexOf( '/' );
-        if ( lastSlash != -1 )
+        boolean isAnAction = true;
+        FlowController flowController = InternalUtils.getCurrentPageFlow( request, false );
+        if ( flowController != null )
         {
-            StringBuilder value = new StringBuilder(qualifiedAction.length() + 16);
-            value.append( pageURI.substring( 0, lastSlash ) );
-            value.append(qualifiedAction);
-            return value.toString();
-        }
-        return qualifiedAction;
-    }
-
-    public static String createActionPath(HttpServletRequest request, String qualifiedAction)
-    {
-
-        ModuleConfig appConfig = (ModuleConfig) request.getAttribute(Globals.MODULE_KEY);
-        if (appConfig != null)
-        {
-            StringBuilder value = new StringBuilder(qualifiedAction.length() + 16);
-            value.append(appConfig.getPrefix());
-            value.append(qualifiedAction);
-            return value.toString();
-        }
-        return qualifiedAction;
-    }
-
-    public static String qualifiedAction(ServletContext servletContext, String action)
-    {
-        StringBuilder sb = new StringBuilder(32);
-
-        // Use our servlet mapping, if one is specified
-        String servletMapping = (String) servletContext.getAttribute(Globals.SERVLET_KEY);
-        if (servletMapping != null)
-        {
-            String queryString = null;
-            int question = action.indexOf("?");
-            if (question >= 0)
+            String checkAction = action;
+            if ( checkAction.startsWith( "/" ) )
             {
-                queryString = action.substring(question);
+                checkAction = checkAction.substring( 1 );
             }
-            String actionMapping = URLRewriterService.getActionMappingName(action);
-            if (servletMapping.startsWith("*."))
+            if ( checkAction.endsWith( PageFlowConstants.ACTION_EXTENSION ) )
             {
-                sb.append(actionMapping);
-                sb.append(servletMapping.substring(1));
+                checkAction = checkAction.substring( 0, checkAction.length() - PageFlowConstants.ACTION_EXTENSION.length() );
             }
-            else if (servletMapping.endsWith("/*"))
-            {
-                sb.append(servletMapping.substring(0, servletMapping.length() - 2));
-                sb.append(actionMapping);
-            }
-            else if (servletMapping.equals("/"))
-            {
-                sb.append(actionMapping);
-            }
-            if (queryString != null) {
-                sb.append(queryString);
-            }
-        }
+            isAnAction = flowController.isAction( checkAction );
 
-        // Otherwise, assume extension mapping is in use and extension is
-        // already included in the action property
-        else
-        {
-            if (!action.startsWith("/"))
+            if ( !isAnAction )
             {
-                sb.append("/");
-            }
-            sb.append(action);
-        }
-        return sb.toString();
-    }
-
-    public static boolean isAction(HttpServletRequest request, HttpServletResponse response, ServletContext servletContext, String action)
-    {
-        boolean isAnAction = true;
-        FlowController flowController = InternalUtils.getCurrentPageFlow(request, false);
-        if (flowController != null)
-        {
-            String checkAction = action;
-            if (checkAction.startsWith("/"))
-                checkAction = checkAction.substring(1);
-            if (checkAction.endsWith(ACTION_EXTENSION))
-                checkAction = checkAction.substring(0, checkAction.length() - ACTION_EXTENSION.length());
-            isAnAction = flowController.isAction(checkAction);
-
-            if (!isAnAction)
-            {
                 FlowController globalController =
                         FlowControllerFactory.getSharedFlowForRequest( request, response, servletContext );
-                if (globalController != null)
-                    isAnAction = globalController.isAction(checkAction);
+                if ( globalController != null )
+                {
+                    isAnAction = globalController.isAction( checkAction );
+                }
             }
         }
 
         return isAnAction;
     }
 
-
-    // @struts : from org.apache.struts.util.RequestUtils RC 1.1
-    public static String computeURL
-    (
-        PageContext pageContext,
-        String forward,
-        String href,
-        String page,
-        Map params,
-        String anchor,
-        boolean redirect)
-        throws MalformedURLException {
-
-        return computeURL(pageContext, forward, href, page, null, params,
-			  anchor, redirect);
-    }
-
-    // @struts : from org.apache.struts.util.RequestUtils RC 1.1
-    public static String computeURL(
-        PageContext pageContext,
-        String forward,
-        String href,
-        String page,
-        String action,
-        Map params,
-        String anchor,
-        boolean redirect)
-        throws MalformedURLException
+    /**
+     * Tell whether a given URI should be written to be secure.
+     *
+     * @param request          the current HttpServletRequest.
+     * @param context          the current ServletContext.
+     * @param uri              the URI to check.
+     * @param stripContextPath if <code>true</code>, strip the webapp context path from the URI before
+     *                         processing it.
+     * @return <code>true</code> when:
+     *         <ul>
+     *         <li>the given URI is configured in the deployment descriptor to be secure (according to
+     *         {@link org.apache.beehive.netui.core.SecurityProtocol}), or
+     *         <li>the given URI is not configured in the deployment descriptor, and the current request
+     *         is secure ({@link javax.servlet.http.HttpServletRequest#isSecure} returns
+     *         <code>true</code>).
+     *         </ul>
+     *         <code>false</code> when:
+     *         <ul>
+     *         <li>the given URI is configured explicitly in the deployment descriptor to be unsecure
+     *         (according to {@link org.apache.beehive.netui.core.SecurityProtocol}), or
+     *         <li>the given URI is not configured in the deployment descriptor, and the current request
+     *         is unsecure ({@link javax.servlet.http.HttpServletRequest#isSecure} returns
+     *         <code>false</code>).
+     *         </ul>
+     */
+    public static boolean needsSecure( ServletContext context, ServletRequest request,
+                                       String uri, boolean stripContextPath )
     {
-
-        String encoding = pageContext.getResponse().getCharacterEncoding();
-
-        // Validate that exactly one specifier was included
-        int n = 0;
-        if (forward != null) {
-            n++;
-        }
-        if (href != null) {
-            n++;
-        }
-        if (page != null) {
-            n++;
-        }
-        if (action != null) {
-            n++;
-        }
-        if (n != 1) {
-            throw new MalformedURLException(messages.getMessage("computeURL.specifier"));
-        }
-
-        HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
-
-        // Look up the module configuration for this request
-        ModuleConfig config =
-            (ModuleConfig) request.getAttribute(Globals.MODULE_KEY);
-        if (config == null) { // Backwards compatibility hack
-            config =
-                (ModuleConfig) pageContext.getServletContext().getAttribute(Globals.MODULE_KEY);
-            InternalUtils.setCurrentModule( config, request );
-        }
-
-        // Calculate the appropriate URL
-        StringBuilder url = new StringBuilder(32);
-        if (forward != null) {
-            ForwardConfig fc = config.findForwardConfig(forward);
-            if (fc == null) {
-                throw new MalformedURLException(messages.getMessage("computeURL.forward", forward));
+        // Get the web-app relative path for security check
+        String secureCheck = uri;
+        if ( stripContextPath )
+        {
+            String contextPath = ( ( HttpServletRequest ) request ).getContextPath();
+            if ( secureCheck.startsWith( contextPath ) )
+            {
+                secureCheck = secureCheck.substring( contextPath.length() );
             }
-            if (fc.getRedirect()) {
-                redirect = true;
-            }
-            if (fc.getPath().startsWith("/")) {
-                url.append(request.getContextPath());
-                url.append(RequestUtils.forwardURL(request, fc));
-            } else {
-                url.append(fc.getPath());
-            }
-        } else if (href != null) {
-            url.append(href);
-        } else if (action != null) {
-            url.append(RequestUtils.getActionMappingURL(action, pageContext));
-
-        } else /* if (page != null) */ {
-            url.append(request.getContextPath());
-            url.append(RequestUtils.pageURL(request, page));
         }
 
-        // Add anchor if requested (replacing any existing anchor)
-        if (anchor != null) {
-            String temp = url.toString();
-            int hash = temp.indexOf('#');
-            if (hash >= 0) {
-                url.setLength(hash);
-            }
-            url.append('#');
-            url.append(encodeURL(anchor,encoding));
+        boolean secure = false;
+        if ( secureCheck.indexOf( '?' ) > -1 )
+        {
+            secureCheck = secureCheck.substring( 0, secureCheck.indexOf( '?' ) );
         }
 
-        // Add dynamic parameters if requested
-        if ((params != null) && (params.size() > 0)) {
-            addParameters(url,encoding,redirect,params);
+        SecurityProtocol sp = PageFlowUtils.getSecurityProtocol( secureCheck, context, ( HttpServletRequest ) request );
+        if ( sp.equals( SecurityProtocol.UNSPECIFIED ) )
+        {
+            secure = request.isSecure();
         }
-
-        return (url.toString());
-    }
-
-    //
-    public static void addParameters(StringBuilder url,String encoding,
-                                     boolean redirect,Map params)
-    {
-        String anchor;
-        // Add dynamic parameters if requested
-        if ((params != null) && (params.size() > 0)) {
-
-            // Save any existing anchor
-            String temp = url.toString();
-            int hash = temp.indexOf('#');
-            if (hash >= 0) {
-                anchor = temp.substring(hash + 1);
-                url.setLength(hash);
-                temp = url.toString();
-            } else {
-                anchor = null;
-            }
-
-            // Define the parameter separator
-            String separator = "&amp;";
-            if (redirect) {
-                separator = "&";
-            }
-
-            // Add the required request parameters
-            boolean question = temp.indexOf('?') >= 0;
-            Iterator keys = params.keySet().iterator();
-            while (keys.hasNext()) {
-                String key = (String) keys.next();
-                Object value = params.get(key);
-                if (value == null) {
-                    if (!question) {
-                        url.append('?');
-                        question = true;
-                    } else {
-                        url.append(separator);
-                    }
-                    url.append(encodeURL(key,encoding));
-                    url.append('='); // Interpret null as "no value"
-                } else if (value instanceof String) {
-                    if (!question) {
-                        url.append('?');
-                        question = true;
-                    } else {
-                        url.append(separator);
-                    }
-                    url.append(encodeURL(key,encoding));
-                    url.append('=');
-                    url.append(encodeURL((String) value,encoding));
-                } else if (value instanceof String[]) {
-                    String values[] = (String[]) value;
-                    for (int i = 0; i < values.length; i++) {
-                        if (!question) {
-                            url.append('?');
-                            question = true;
-                        } else {
-                            url.append(separator);
-                        }
-                        url.append(encodeURL(key,encoding));
-                        url.append('=');
-                        url.append(encodeURL(values[i],encoding));
-                    }
-                } else /* Convert other objects to a string */ {
-                    if (!question) {
-                        url.append('?');
-                        question = true;
-                    } else {
-                        url.append(separator);
-                    }
-                    url.append(encodeURL(key,encoding));
-                    url.append('=');
-                    url.append(encodeURL(value.toString(),encoding));
-                }
-            }
-
-            // Re-add the saved anchor (if any)
-            if (anchor != null) {
-                url.append('#');
-                url.append(encodeURL(anchor,encoding));
-            }
+        else
+        {
+            secure = sp.equals( SecurityProtocol.SECURE );
         }
-    }
 
-
-    // @struts : from org.apache.struts.util.RequestUtils RC 1.1
-    // This has been modified from the strut to assume 1.4 because we ship 
-    // with that.
-    public static String encodeURL(String url, String encoding)
-    {
-        String encodedURL = null;
-        try {
-            encodedURL = URLEncoder.encode(url,encoding);
-        }
-        catch (java.io.UnsupportedEncodingException e) {
-            logger.error( "Unsupported encoding:" + encoding, e );
-            // try this in utf-8 and log the exception
-            try {
-                encodedURL = URLEncoder.encode(url,"UTF-8");
-            }
-            catch (java.io.UnsupportedEncodingException ignore) {}
-        }
-        return encodedURL;
+        return secure;
     }
-    
-    /**
-     * Add a parameter to the given URL.
-     * 
-     * @param url the URL to which to append. 
-     * @param paramName the name of the parameter to add.
-     * @param paramVal the value of the parameter to add.
-     * @return the URL, with the given parameter added.
-     */ 
-    public static String addParam(String url, String paramName, String paramVal)
-    {
-        return url + (url.indexOf('?') != -1 ? '&' : '?') + paramName + '=' + paramVal;
-    }
 }
Index: netui/src/tags-html/org/apache/beehive/netui/tags/html/Exceptions.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/html/Exceptions.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/html/Exceptions.java	(working copy)
@@ -17,7 +17,7 @@
  */
 package org.apache.beehive.netui.tags.html;
 
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 import org.apache.beehive.netui.tags.AbstractSimpleTag;
 import org.apache.beehive.netui.util.HtmlExceptionFormatter;
 import org.apache.struts.Globals;
@@ -114,7 +114,7 @@
         }
 
         if (!_showStackTrace && _showDevModeStackTrace) {
-            boolean devMode = !ContextCache.get(pageContext.getServletContext()).getServerAdapter().isInProductionMode();
+            boolean devMode = !ServerAdapterManager.getServerAdapter(pageContext.getServletContext()).isInProductionMode();
             if (devMode)
                 _showStackTrace = true;
         }
Index: netui/src/tags-html/org/apache/beehive/netui/tags/html/Image.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/html/Image.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/html/Image.java	(working copy)
@@ -17,8 +17,8 @@
  */
 package org.apache.beehive.netui.tags.html;
 
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
-import org.apache.beehive.netui.tags.HtmlUtils;
+import org.apache.beehive.netui.core.urls.MutableURI;
+import org.apache.beehive.netui.tags.PageFlowTagUtils;
 import org.apache.beehive.netui.tags.rendering.AbstractHtmlState;
 import org.apache.beehive.netui.tags.rendering.ImageTag;
 import org.apache.beehive.netui.tags.rendering.TagRenderingBase;
@@ -27,9 +27,9 @@
 import org.apache.beehive.netui.util.ParamHelper;
 
 import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.jsp.JspException;
+import java.net.URISyntaxException;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -302,16 +302,23 @@
 
         // Generate the name definition or image element
 
-        // the src attribute
-        String srcurl = url(_state.src);
-        if (srcurl != null) {
-            srcurl = PageflowTagUtils.prepareResourceUrl(pageContext, srcurl);
-            if (_location != null) {
-                srcurl = srcurl + "#" + _location;
+        MutableURI uri = null;
+        if (_state.src != null) {
+            try {
+                uri = PageFlowTagUtils.rewrittenResourceURL(pageContext, _state.src, _params, _location);
             }
-            _state.src = srcurl;
+            catch (URISyntaxException e) {
+                // report the error...
+                String s = Bundle.getString("Tags_Image_URLException",
+                                            new Object[]{_state.src, e.getMessage()});
+                registerTagError(s, e);
+            }
         }
 
+        if (uri != null) {
+            _state.src = ((HttpServletResponse) pageContext.getResponse()).encodeURL(uri.toString());
+        }
+
         // we assume that tagId will over have override id if both
         // are defined.
         // @todo: should we move the tagId stuff to the base class?
@@ -352,31 +359,4 @@
         _id = null;
         _params = null;
     }
-
-    /**
-     * Return the specified src URL, modified as necessary with optional
-     * request parameters.
-     * @param url The URL to be modified (or null if this url will not be used)
-     * @throws JspException if an error occurs preparing the URL
-     */
-    protected String url(String url)
-            throws JspException
-    {
-
-        if (url == null || _params == null)
-            return url;
-
-        HttpServletRequest req = (HttpServletRequest) pageContext.getRequest();
-        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
-        String encoding = response.getCharacterEncoding();
-
-        StringBuilder src = new StringBuilder(128);
-        if (url.startsWith("/")) {
-            src.append(req.getContextPath());
-        }
-
-        url = HtmlUtils.addParams(url, _params, encoding);
-        src.append(url);
-        return src.toString();
-    }
 }
Index: netui/src/tags-html/org/apache/beehive/netui/tags/html/Form.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/html/Form.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/html/Form.java	(working copy)
@@ -17,15 +17,17 @@
  */
 package org.apache.beehive.netui.tags.html;
 
+import org.apache.beehive.netui.core.urls.URLRewriterService;
+import org.apache.beehive.netui.core.urls.MutableURI;
 import org.apache.beehive.netui.pageflow.*;
 import org.apache.beehive.netui.pageflow.internal.ContextCache;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
-import org.apache.beehive.netui.pageflow.util.URLRewriterService;
 import org.apache.beehive.netui.script.common.ImplicitObjectUtil;
 import org.apache.beehive.netui.tags.IHtmlIdWriter;
+import org.apache.beehive.netui.tags.PageFlowTagUtils;
 import org.apache.beehive.netui.tags.rendering.*;
 import org.apache.beehive.netui.util.Bundle;
+import org.apache.beehive.netui.util.logging.Logger;
 import org.apache.beehive.netui.util.ParamHelper;
 import org.apache.struts.Globals;
 import org.apache.struts.action.ActionForm;
@@ -196,6 +198,8 @@
      */
     public final String ID_REQUEST_ATTRIBUTE = "netuiIdGenerator";
 
+    private static final Logger logger = Logger.getInstance(Form.class);
+
     // unique name of the form
     private static String FORM_ID = "Netui_Form_";
 
@@ -290,7 +294,6 @@
             throws JspException
     {
         _state.action = setRequiredValueAttribute(action, "action");
-        ;
     }
 
     /**
@@ -712,32 +715,32 @@
             _state.method = FORM_POST;
 
         // encode the action
-        String actionUrl = PageflowTagUtils.getRewrittenFormAction(request, _state.action, pageContext);
+        MutableURI actionUrl = null;
+        try {
+            actionUrl = PageFlowTagUtils.rewrittenActionURL(pageContext, _state.action, null, _location);
+        }
+        catch ( java.net.URISyntaxException e ) {
+            // report the error...
+            logger.error(Bundle.getString("Tags_URISyntaxException"));
+            String s = Bundle.getString("Tags_Form_URLException",
+                                        new Object[]{_state.action, e.getMessage()});
+            registerTagError(s, e);
+        }
 
         // If the rewritten form action contains request parameters, turn them into hidden fields --
         // it's not legal to include them in the action URI on a GET.
-        int query = actionUrl.indexOf('?');
         Map extraHiddenParams = null;
-        if (query != -1 && _state.method != null && _state.method.equalsIgnoreCase(FORM_GET)
+        if (actionUrl != null && _state.method != null && _state.method.equalsIgnoreCase(FORM_GET)
                 && !URLRewriterService.allowParamsOnFormAction(pageContext.getServletContext(), request)) {
-            extraHiddenParams = new LinkedHashMap();
-            StringTokenizer tok = new StringTokenizer(actionUrl.substring(query + 1), "&");
-            while (tok.hasMoreTokens()) {
-                String keyVal = tok.nextToken();
-                int eq = keyVal.indexOf('=');
-                if (eq != -1) {
-                    extraHiddenParams.put(keyVal.substring(0, eq), keyVal.substring(eq + 1));
-                }
-                else {
-                    extraHiddenParams.put(keyVal, "");
-                }
-            }
+            extraHiddenParams = actionUrl.getParameters();
+            actionUrl.setQuery(null);
+        }
 
-            actionUrl = actionUrl.substring(0, query);
+        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
+        if (actionUrl != null) {
+            _state.action = response.encodeURL( actionUrl.toString() );
         }
 
-        _state.action = actionUrl;
-
         WriteRenderAppender writer = new WriteRenderAppender(pageContext);
         TagRenderingBase br = TagRenderingBase.Factory.getRendering(TagRenderingBase.FORM_TAG, request);
         br.doStartTag(writer, _state);
@@ -774,9 +777,14 @@
 
         // add the extra hidden parameters
         if (extraHiddenParams != null) {
-            for (Iterator i = extraHiddenParams.entrySet().iterator(); i.hasNext();) {
-                Map.Entry entry = (Map.Entry) i.next();
-                writeHiddenParam((String) entry.getKey(), (String) entry.getValue(), writer, request,true);
+            Iterator names = extraHiddenParams.keySet().iterator();
+            while (names.hasNext()) {
+                String name = (String) names.next();
+                List valueList = (List) extraHiddenParams.get(name);
+                Iterator values = valueList.iterator();
+                while (values.hasNext()) {
+                    writeHiddenParam(name, (String) values.next(), writer, request, true);
+                }
             }
         }
 
@@ -901,7 +909,7 @@
         _flowController = PageFlowUtils.getCurrentPageFlow(request);
 
         // check to see if this is a bad action
-        boolean isAction = PageflowTagUtils.isAction(request, response, servletContext, _state.action);
+        boolean isAction = PageFlowTagUtils.isAction(request, response, servletContext, _state.action);
         if (!isAction) {
             registerTagError(Bundle.getString("Tags_BadAction", _state.action), null);
             return;
Index: netui/src/tags-html/org/apache/beehive/netui/tags/html/RewriteURL.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/html/RewriteURL.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/html/RewriteURL.java	(working copy)
@@ -17,11 +17,14 @@
  */
 package org.apache.beehive.netui.tags.html;
 
-import org.apache.beehive.netui.pageflow.util.URLRewriter;
-import org.apache.beehive.netui.pageflow.util.URLRewriterService;
+import org.apache.beehive.netui.core.urls.MutableURI;
+import org.apache.beehive.netui.core.urls.URLRewriter;
+import org.apache.beehive.netui.core.urls.URLRewriterService;
 import org.apache.beehive.netui.tags.AbstractClassicTag;
-import org.apache.beehive.netui.util.FileUtils;
+import org.apache.beehive.netui.tags.PageFlowTagUtils;
+import org.apache.beehive.netui.util.Bundle;
 
+import java.net.URISyntaxException;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -85,20 +88,25 @@
         HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
         ServletContext context = pageContext.getServletContext();
 
-        String type = URLRewriter.ACTION_UNSECURE;
-        boolean absoluteUrl = false;
+        MutableURI uri = null;
+        try {
+            boolean needsToBeSecure = false;
+            uri = new MutableURI(url);
+            if (!uri.isAbsolute() && PageFlowTagUtils.needsSecure(context, request, url, true)) {
+                needsToBeSecure = true;
+            }
 
-        if (FileUtils.isAbsoluteURI(url))
-            absoluteUrl = true;
+            URLRewriterService.rewriteURL(context, request, response, uri, URLRewriter.Type.ACTION, needsToBeSecure);
+            //TODO... why no call to response.encodeURL(uri.toString()) for session ID?
+            write(uri.toString());
+        }
+        catch (URISyntaxException e) {
+            // report the error...
+            String s = Bundle.getString("Tags_RewriteURL_URLException",
+                                        new Object[]{url, e.getMessage()});
+            registerTagError(s, e);
+        }
 
-        if ((!absoluteUrl) && (URLRewriterService.needsSecure(request,
-                context, url, true)))
-            type = URLRewriter.ACTION_SECURE;
-
-        String internalHref = URLRewriterService.rewriteURL(context, request, response,
-                url, type);
-
-        write(internalHref);
         localRelease();
         return SKIP_BODY;
     }
Index: netui/src/tags-html/org/apache/beehive/netui/tags/html/AnchorBase.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/html/AnchorBase.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/html/AnchorBase.java	(working copy)
@@ -1,16 +1,14 @@
 package org.apache.beehive.netui.tags.html;
 
+import org.apache.beehive.netui.core.urls.MutableURI;
 import org.apache.beehive.netui.tags.rendering.*;
 import org.apache.beehive.netui.tags.ByRef;
 import org.apache.beehive.netui.tags.IScriptReporter;
 import org.apache.beehive.netui.tags.HtmlUtils;
+import org.apache.beehive.netui.tags.PageFlowTagUtils;
 import org.apache.beehive.netui.util.Bundle;
 import org.apache.beehive.netui.util.ParamHelper;
-import org.apache.beehive.netui.util.FileUtils;
 import org.apache.beehive.netui.util.logging.Logger;
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
-import org.apache.beehive.netui.pageflow.util.URLRewriter;
-import org.apache.beehive.netui.pageflow.util.URLRewriterService;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 
 import javax.servlet.jsp.JspException;
@@ -18,9 +16,9 @@
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
+import java.net.URISyntaxException;
 import java.util.HashMap;
 import java.util.Map;
-import java.net.MalformedURLException;
 
 /**
  * This is the base class that provides most of the features necessary to create an anchor and an area. The Anchor
@@ -330,7 +328,7 @@
         }
 
         // report that action is not an action
-        if ((_action != null) && (!PageflowTagUtils.isAction(request, response, ctxt, _action))) {
+        if ((_action != null) && (!PageFlowTagUtils.isAction(request, response, ctxt, _action))) {
             String s = null;
             if (_action.equals("")) {
                 s = Bundle.getString("Tags_NullBadAction", null);
@@ -341,9 +339,6 @@
             registerTagError(s, null);
         }
 
-        String internalHref = _state.href;
-        boolean absoluteUrl = false;
-
         // we assume that tagId will over have override id if both
         // are defined.
         if (tagId != null) {
@@ -358,36 +353,6 @@
             _state.href = "";
         }
         else {
-            // Generate the opening anchor element
-            String type = URLRewriter.ACTION_UNSECURE;
-
-            if (_action != null) {
-                // simply set this to the result of mangling the action
-                String qualifiedAction = PageflowTagUtils.qualifiedAction(ctxt, _action);
-                String actionUrl = PageflowTagUtils.createActionPath(request, qualifiedAction);
-                if (URLRewriterService.needsSecure(request, ctxt, actionUrl, false))
-                    type = URLRewriter.ACTION_SECURE;
-                internalHref = PageflowTagUtils.createActionURL(request, qualifiedAction);
-            }
-            else if (_href != null) {
-                internalHref = _href;
-                if (FileUtils.isAbsoluteURI(internalHref)) {
-                    absoluteUrl = true;
-                }
-                else if (!internalHref.startsWith("/")) {
-                    // for internal hrefs, we need to see if we need to secure the request
-                    if (!_href.equals("")) {
-                        String reqUri = request.getRequestURI();
-                        String path = reqUri.substring(0, reqUri.lastIndexOf("/") + 1);
-                        internalHref = path + internalHref;
-
-                        // is this a secure operation?
-                        if ((!absoluteUrl) && (URLRewriterService.needsSecure(request, ctxt, internalHref, true)))
-                            type = URLRewriter.ACTION_SECURE;
-                    }
-                }
-            }
-
             // Add the jpfScopeID parameter, if the scope attribute is present.
             if (_scope != null) {
                 if (_params == null) {
@@ -396,29 +361,39 @@
                 _params.put(ScopedServletUtils.SCOPE_ID_PARAM, _scope);
             }
 
-            if (!absoluteUrl) {
-                internalHref = calculateURL(internalHref, _location);
-            }
-            else {
-                if ((_params != null) && (_params.size() > 0)) {
-                    StringBuilder sb = new StringBuilder(internalHref);
-                    String encoding = response.getCharacterEncoding();
-                    PageflowTagUtils.addParameters(sb, encoding, false, _params);
-                    internalHref = sb.toString();
+            // Generate the opening anchor element
+            MutableURI uri = null;
+            try {
+                if (_action != null) {
+                    uri = PageFlowTagUtils.rewrittenActionURL(pageContext, _action, _params, _location);
                 }
+                else if (_href != null) {
+                    //TODO... OK to use rewrittenResourceURL implying type=RESOURCE for rewriting?
+                    uri = PageFlowTagUtils.rewrittenResourceURL(pageContext, _href, _params, _location);
+                }
             }
+            catch (URISyntaxException e) {
+                // report the error...
+                logger.error(Bundle.getString("Tags_URISyntaxException"));
+                String s = Bundle.getString("Tags_Anchor_URLException",
+                                            new Object[]{e.getMessage()});
+                registerTagError(s, e);
+            }
 
-            if (internalHref == null) {
+            if (uri == null) {
                 if (hasErrors()) {
                     return false;
                 }
             }
-
-            if (!absoluteUrl) {
-                internalHref = URLRewriterService.rewriteURL(ctxt, request, response, internalHref, type);
-                internalHref = qualifyUrlToContext(internalHref);
+            else {
+                //TODO... shouldn't this also be a call to response.encodeURL(uri.toString()) for session ID?
+                if (uri.isAbsolute()) {
+                    _state.href = uri.toXMLString();
+                }
+                else {
+                    _state.href = qualifyUrlToContext(uri.toString());
+                }
             }
-            _state.href = internalHref;
         }
 
         // We need to combine the onclick features
@@ -447,7 +422,7 @@
         // if the user override the onclick we will ignor this
         if (_state.onClick == null && _formSubmit && formAction != null) {
             String realFormName = getRealFormName();
-            _state.onClick = jsu.writeAnchorFormSubmitAction(realFormName, internalHref);
+            _state.onClick = jsu.writeAnchorFormSubmitAction(realFormName, _state.href);
             if (_form != null)
                 _form.generateRealName();
         }
@@ -502,30 +477,6 @@
     }
 
     /**
-     * Return the complete URL to which this hyperlink will direct the user.
-     * @param href
-     * @param location
-     * @return
-     * @throws JspException
-     */
-    private String calculateURL(String href, String location) throws JspException
-    {
-        String url = null;
-        try {
-            url = PageflowTagUtils.computeURL(pageContext, null, href, null, null, _params, location, true);
-        }
-        catch (MalformedURLException e) {
-            // report the error...
-            logger.error(Bundle.getString("Tags_MalformedURLException"));
-            String s = null;
-            s = Bundle.getString("Tags_Anchor_URLException",
-                    new Object[]{e.getMessage()});
-            registerTagError(s, e);
-        }
-        return url;
-    }
-
-    /**
      * Return the action attribute for the nearest form.
      * @return The action attribute of the enclosing form
      */
Index: netui/src/tags-html/org/apache/beehive/netui/tags/html/BindingUpdateErrors.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/html/BindingUpdateErrors.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/html/BindingUpdateErrors.java	(working copy)
@@ -19,8 +19,8 @@
 
 import org.apache.beehive.netui.pageflow.ServerAdapter;
 import org.apache.beehive.netui.pageflow.internal.BindingUpdateError;
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 import org.apache.beehive.netui.tags.AbstractSimpleTag;
 import org.apache.beehive.netui.util.Bundle;
 
@@ -116,7 +116,7 @@
         }
 
         PageContext pageContext = getPageContext();
-        ServerAdapter sa = ContextCache.get(pageContext.getServletContext()).getServerAdapter();
+        ServerAdapter sa = ServerAdapterManager.getServerAdapter(pageContext.getServletContext());
         ServletRequest request = pageContext.getRequest();
         assert(sa != null);
 
Index: netui/src/tags-html/org/apache/beehive/netui/tags/html/Button.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/html/Button.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/html/Button.java	(working copy)
@@ -17,10 +17,10 @@
  */
 package org.apache.beehive.netui.tags.html;
 
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
-import org.apache.beehive.netui.pageflow.util.URLRewriterService;
+import org.apache.beehive.netui.core.urls.URLRewriterService;
 import org.apache.beehive.netui.tags.HtmlUtils;
 import org.apache.beehive.netui.tags.IHtmlAccessable;
+import org.apache.beehive.netui.tags.PageFlowTagUtils;
 import org.apache.beehive.netui.tags.rendering.AbstractHtmlState;
 import org.apache.beehive.netui.tags.rendering.InputSubmitTag;
 import org.apache.beehive.netui.tags.rendering.TagRenderingBase;
@@ -229,7 +229,7 @@
         _state.disabled = isDisabled();
 
         if (_action != null) {
-            boolean isAction = PageflowTagUtils.isAction(request, response, pageContext.getServletContext(), _action);
+            boolean isAction = PageFlowTagUtils.isAction(request, response, pageContext.getServletContext(), _action);
             if (isAction) {
                 String overrideAction = ACTION_OVERRIDE + _action;
                 overrideAction = HtmlUtils.addParams(overrideAction, _params, response.getCharacterEncoding());
Index: netui/src/tags-html/org/apache/beehive/netui/tags/html/ImageAnchor.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/html/ImageAnchor.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/html/ImageAnchor.java	(working copy)
@@ -17,12 +17,14 @@
  */
 package org.apache.beehive.netui.tags.html;
 
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
+import org.apache.beehive.netui.core.urls.MutableURI;
 import org.apache.beehive.netui.tags.IHtmlAccessable;
 import org.apache.beehive.netui.tags.ByRef;
+import org.apache.beehive.netui.tags.PageFlowTagUtils;
 import org.apache.beehive.netui.tags.rendering.*;
 import org.apache.beehive.netui.util.Bundle;
 
+import java.net.URISyntaxException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.jsp.JspException;
@@ -424,16 +426,33 @@
 
         // set the source and lowsrc attributes
         // the lowsrc is deprecated and should be removed.
+        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
         if (_imgState.src != null) {
-            _imgState.src = PageflowTagUtils.prepareResourceUrl(pageContext, _imgState.src);
+            try {
+                MutableURI uri = PageFlowTagUtils.rewrittenResourceURL(pageContext, _imgState.src, null, null);
+                _imgState.src = response.encodeURL(uri.toString());
+            }
+            catch (URISyntaxException e) {
+                // report the error...
+                String s = Bundle.getString("Tags_Image_URLException",
+                                            new Object[]{_imgState.src, e.getMessage()});
+                registerTagError(s, e);
+            }
         }
 
         // set the rollover image
         if (_rolloverImage != null) {
-            _rolloverImage = PageflowTagUtils.prepareResourceUrl(pageContext, _rolloverImage);
-            _rolloverImage = qualifyUrlToContext(_rolloverImage);
+            try {
+                MutableURI uri = PageFlowTagUtils.rewrittenResourceURL(pageContext, _rolloverImage, null, null);
+                _rolloverImage = response.encodeURL(qualifyUrlToContext(uri.toString()));
+            }
+            catch (URISyntaxException e) {
+                // report the error...
+                String s = Bundle.getString("Tags_Rollover_Image_URLException",
+                                            new Object[]{_rolloverImage, e.getMessage()});
+                registerTagError(s, e);
+            }
 
-            HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
             if (getJavaScriptAttribute(ONMOUSEOUT) == null) {
                 _imgState.onmouseout = "swapImage(this,'" + response.encodeURL(_imgState.src) + "')";
             }
Index: netui/src/tags-html/org/apache/beehive/netui/tags/html/ImageButton.java
===================================================================
--- netui/src/tags-html/org/apache/beehive/netui/tags/html/ImageButton.java	(revision 109213)
+++ netui/src/tags-html/org/apache/beehive/netui/tags/html/ImageButton.java	(working copy)
@@ -17,8 +17,9 @@
  */
 package org.apache.beehive.netui.tags.html;
 
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
+import org.apache.beehive.netui.core.urls.MutableURI;
 import org.apache.beehive.netui.tags.IHtmlAccessable;
+import org.apache.beehive.netui.tags.PageFlowTagUtils;
 import org.apache.beehive.netui.tags.rendering.AbstractHtmlState;
 import org.apache.beehive.netui.tags.rendering.InputImageTag;
 import org.apache.beehive.netui.tags.rendering.TagRenderingBase;
@@ -27,8 +28,10 @@
 import org.apache.struts.Globals;
 import org.apache.struts.config.ModuleConfig;
 
+import java.net.URISyntaxException;
 import javax.servlet.ServletRequest;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import javax.servlet.jsp.JspException;
 
 /**
@@ -300,10 +303,19 @@
             _state.id = _id;
         }
 
+        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
         tmp = src();
         if (tmp != null) {
-            tmp = PageflowTagUtils.prepareResourceUrl(pageContext, tmp);
-            _state.src = tmp;
+            try {
+                MutableURI uri = PageFlowTagUtils.rewrittenResourceURL(pageContext, tmp, null, null);
+                _state.src = response.encodeURL(uri.toString());
+            }
+            catch (URISyntaxException e) {
+                // report the error...
+                String s = Bundle.getString("Tags_Image_URLException",
+                                            new Object[]{_state.src, e.getMessage()});
+                registerTagError(s, e);
+            }
         }
 
         _state.disabled = isDisabled();
@@ -316,12 +328,20 @@
                 return EVAL_PAGE;
             }
 
-            _rolloverImage = PageflowTagUtils.prepareResourceUrl(pageContext, _rolloverImage);
-            _rolloverImage = qualifyUrlToContext(_rolloverImage);
+            try {
+                MutableURI uri = PageFlowTagUtils.rewrittenResourceURL(pageContext, _rolloverImage, null, null);
+                _rolloverImage = response.encodeURL(qualifyUrlToContext(uri.toString()));
+            }
+            catch (URISyntaxException e) {
+                // report the error...
+                String s = Bundle.getString("Tags_Rollover_Image_URLException",
+                                            new Object[]{_rolloverImage, e.getMessage()});
+                registerTagError(s, e);
+            }
         }
 
         if ((getJavaScriptAttribute(ONMOUSEOUT) == null) && (_rolloverImage != null)) {
-            setOnMouseOut("swapImage(this,'" + tmp + "')");
+            setOnMouseOut("swapImage(this,'" + _state.src + "')");
         }
         if ((getJavaScriptAttribute(ONMOUSEOVER) == null) && (_rolloverImage != null)) {
             setOnMouseOver("swapImage(this,'" + _rolloverImage + "')");
Index: netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/model/PagerModel.java
===================================================================
--- netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/model/PagerModel.java	(revision 109213)
+++ netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/model/PagerModel.java	(working copy)
@@ -19,7 +19,7 @@
 
 import org.apache.beehive.netui.databinding.datagrid.services.PagerService;
 import org.apache.beehive.netui.databinding.datagrid.util.JspUtil;
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
+import org.apache.beehive.netui.pageflow.internal.InternalUtils;
 import org.apache.beehive.netui.util.logging.Logger;
 
 import javax.servlet.jsp.PageContext;
@@ -106,8 +106,8 @@
         String pageUri = null;
         if (_pageAction != null) {
             PageContext pageContext = JspUtil.getPageContext(_model.getJspContext());
-            String qualifiedAction = PageflowTagUtils.qualifiedAction(pageContext.getServletContext(), _pageAction);
-            pageUri = PageflowTagUtils.createActionURL((HttpServletRequest) pageContext.getRequest(), qualifiedAction);
+            String qualifiedAction = InternalUtils.qualifiedAction(pageContext.getServletContext(), _pageAction);
+            pageUri = InternalUtils.createActionURL((HttpServletRequest) pageContext.getRequest(), qualifiedAction);
         } else if (_pageHref != null) {
             pageUri = _pageHref;
         }
Index: netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/rendering/impl/PreviousNextPagerRenderer.java
===================================================================
--- netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/rendering/impl/PreviousNextPagerRenderer.java	(revision 109213)
+++ netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/rendering/impl/PreviousNextPagerRenderer.java	(working copy)
@@ -20,12 +20,8 @@
 import org.apache.beehive.netui.databinding.datagrid.model.PagerModel;
 import org.apache.beehive.netui.databinding.datagrid.model.DataGridModel;
 import org.apache.beehive.netui.databinding.datagrid.services.PagerService;
-import org.apache.beehive.netui.databinding.datagrid.util.JspUtil;
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
 import org.apache.beehive.netui.util.logging.Logger;
 
-import javax.servlet.jsp.PageContext;
-
 public class PreviousNextPagerRenderer
     extends AbstractPagerRenderer
 {
Index: netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/rendering/impl/AbstractPagerRenderer.java
===================================================================
--- netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/rendering/impl/AbstractPagerRenderer.java	(revision 109213)
+++ netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/rendering/impl/AbstractPagerRenderer.java	(working copy)
@@ -22,11 +22,7 @@
 import org.apache.beehive.netui.databinding.datagrid.model.PagerModel;
 import org.apache.beehive.netui.databinding.datagrid.model.DataGridModel;
 import org.apache.beehive.netui.databinding.datagrid.rendering.IPagerRenderer;
-import org.apache.beehive.netui.databinding.datagrid.util.JspUtil;
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
 
-import javax.servlet.jsp.PageContext;
-
 /**
  * todo: lots of i18n here
  */
Index: netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/rendering/impl/FirstPreviousNextLastPagerRenderer.java
===================================================================
--- netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/rendering/impl/FirstPreviousNextLastPagerRenderer.java	(revision 109213)
+++ netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/rendering/impl/FirstPreviousNextLastPagerRenderer.java	(working copy)
@@ -18,14 +18,10 @@
 package org.apache.beehive.netui.databinding.datagrid.rendering.impl;
 
 import org.apache.beehive.netui.util.logging.Logger;
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
 import org.apache.beehive.netui.databinding.datagrid.model.PagerModel;
 import org.apache.beehive.netui.databinding.datagrid.model.DataGridModel;
 import org.apache.beehive.netui.databinding.datagrid.services.PagerService;
-import org.apache.beehive.netui.databinding.datagrid.util.JspUtil;
 
-import javax.servlet.jsp.PageContext;
-
 public class FirstPreviousNextLastPagerRenderer
     extends AbstractPagerRenderer
 {
Index: netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/util/JspUtil.java
===================================================================
--- netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/util/JspUtil.java	(revision 109213)
+++ netui/src/tags-databinding/org/apache/beehive/netui/databinding/datagrid/util/JspUtil.java	(working copy)
@@ -17,21 +17,17 @@
  */
 package org.apache.beehive.netui.databinding.datagrid.util;
 
+import java.net.URISyntaxException;
 import java.util.HashMap;
 import java.util.Map;
-import java.net.MalformedURLException;
 import javax.servlet.jsp.JspContext;
 import javax.servlet.jsp.PageContext;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.ServletContext;
 
+import org.apache.beehive.netui.core.urls.MutableURI;
 import org.apache.beehive.netui.util.logging.Logger;
-import org.apache.beehive.netui.util.FileUtils;
-import org.apache.beehive.netui.pageflow.util.URLRewriter;
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
-import org.apache.beehive.netui.pageflow.util.URLRewriterService;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
+import org.apache.beehive.netui.tags.PageFlowTagUtils;
 
 public class JspUtil
 {
@@ -54,50 +50,10 @@
     }
 
     public static final String createURL(String href, String action, String location, String scope, Map params, JspContext jspContext)
-        throws MalformedURLException
+        throws URISyntaxException
     {
         PageContext pageContext = getPageContext(jspContext);
-        HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
-        HttpServletResponse response = (HttpServletResponse)pageContext.getResponse();
-        ServletContext ctxt = pageContext.getServletContext();
-        boolean absoluteUrl = false;
 
-        // Generate the opening anchor element
-        String type = URLRewriter.ACTION_UNSECURE;
-
-        String internalHref = null;
-        if(action != null)
-        {
-            // simply set this to the result of mangling the action
-            String qualifiedAction = PageflowTagUtils.qualifiedAction(ctxt,action);
-            String actionUrl = PageflowTagUtils.createActionPath(request, qualifiedAction);
-            if(URLRewriterService.needsSecure(request, ctxt, actionUrl, false))
-                type = URLRewriter.ACTION_SECURE;
-            internalHref = PageflowTagUtils.createActionURL(request, qualifiedAction);
-        }
-        else if(href != null)
-        {
-            internalHref = href;
-            if(FileUtils.isAbsoluteURI(internalHref))
-            {
-                absoluteUrl = true;
-            }
-            else if(!internalHref.startsWith("/"))
-            {
-                // for internal hrefs, we need to see if we need to secure the request
-                if(!href.equals(""))
-                {
-                    String reqUri = request.getRequestURI();
-                    String path = reqUri.substring(0, reqUri.lastIndexOf("/") + 1);
-                    internalHref = path + internalHref;
-
-                    // is this a secure operation?
-                    if((!absoluteUrl) && (URLRewriterService.needsSecure(request, ctxt, internalHref, true)))
-                        type = URLRewriter.ACTION_SECURE;
-                }
-            }
-        }
-
         // Add the jpfScopeID parameter, if the scope attribute is present.
         if(scope != null)
         {
@@ -108,35 +64,24 @@
             params.put(ScopedServletUtils.SCOPE_ID_PARAM, scope);
         }
 
-        if(!absoluteUrl)
+        // Generate the opening anchor element
+        MutableURI uri = null;
+        if(action != null)
         {
-            internalHref = calculateURL(pageContext, internalHref, location, params);
+            uri = PageFlowTagUtils.rewrittenActionURL(pageContext, action, params, location);
         }
-        else
+        else if(href != null)
         {
-            if((params != null) && (params.size() > 0))
-            {
-                StringBuilder sb = new StringBuilder(internalHref);
-                String encoding = response.getCharacterEncoding();
-                PageflowTagUtils.addParameters(sb, encoding, false, params);
-                internalHref = sb.toString();
-            }
+            //TODO... OK to use rewrittenResourceURL implying type=RESOURCE for rewriting?
+            uri = PageFlowTagUtils.rewrittenResourceURL(pageContext, href, params, location);
         }
 
-        assert internalHref != null;
+        assert uri != null;
 
-        if(!absoluteUrl)
-        {
-            internalHref = URLRewriterService.rewriteURL(ctxt, request, response, internalHref, type);
-            //internalHref = qualifyUrlToContext(internalHref);
+        //TODO... shouldn't this also be a call to response.encodeURL(uri.toString()) for session ID?
+        if (uri.isAbsolute()) {
+            return uri.toXMLString();
         }
-        return internalHref;
+        return uri.toString();
     }
-
-    private static final String calculateURL(PageContext pageContext, String href, String location, Map params)
-        throws MalformedURLException
-    {
-        String url = PageflowTagUtils.computeURL(pageContext, null, href, null, null, params, location, true);
-        return url;
-    }
 }
Index: netui/src/tags-databinding/org/apache/beehive/netui/tags/databinding/datagrid/AnchorColumn.java
===================================================================
--- netui/src/tags-databinding/org/apache/beehive/netui/tags/databinding/datagrid/AnchorColumn.java	(revision 109213)
+++ netui/src/tags-databinding/org/apache/beehive/netui/tags/databinding/datagrid/AnchorColumn.java	(working copy)
@@ -32,7 +32,7 @@
 import org.apache.beehive.netui.util.logging.Logger;
 import org.apache.beehive.netui.util.ParamHelper;
 
-import java.net.MalformedURLException;
+import java.net.URISyntaxException;
 import java.util.HashMap;
 
 /**
@@ -126,7 +126,7 @@
         String url = null;
         try {
             url = JspUtil.createURL(_href, _action, null, _scopeId, _params, dgm.getJspContext());
-        } catch (MalformedURLException mue) {
+        } catch (URISyntaxException mue) {
             /* todo: real, tag based error reporting */
             if (_logger.isErrorEnabled())
                 _logger.error("Exception creating URL with href " + _href + " action " + _action, mue);
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/Forward.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/Forward.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/Forward.java	(working copy)
@@ -37,6 +37,7 @@
 import org.apache.beehive.netui.pageflow.config.PageFlowActionForward;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
 import org.apache.beehive.netui.pageflow.internal.ContextCache;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 import org.apache.beehive.netui.pageflow.handler.ReloadableClassHandler;
 
 
@@ -577,7 +578,7 @@
     {
         PageFlowActionForward.ActionOutput[] actionOutputs = fc.getActionOutputs();
         boolean isInProductionMode =
-                ContextCache.get( _servletContext ).getServerAdapter().isInProductionMode();
+                ServerAdapterManager.getServerAdapter( _servletContext ).isInProductionMode();
             
         for ( int i = 0; i < actionOutputs.length; ++i )
         {
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java	(working copy)
@@ -21,8 +21,8 @@
 import org.apache.beehive.netui.pageflow.internal.ActionResultImpl;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
 import org.apache.beehive.netui.pageflow.internal.RequestValues;
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 import org.apache.beehive.netui.pageflow.scoping.ScopedRequest;
 import org.apache.beehive.netui.pageflow.scoping.ScopedResponse;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
@@ -680,7 +680,7 @@
     public static SecurityProtocol getSecurityProtocol( String uri, ServletContext servletContext,
                                                         HttpServletRequest request )
     {
-        return ContextCache.get( servletContext ).getServerAdapter().getSecurityProtocol( uri, request );
+        return ServerAdapterManager.getServerAdapter( servletContext ).getSecurityProtocol( uri, request );
     }
     
     /**
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/JavaControlUtils.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/JavaControlUtils.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/JavaControlUtils.java	(working copy)
@@ -37,7 +37,6 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.beehive.netui.util.logging.Logger;
-import org.apache.beehive.netui.pageflow.PageFlowUtils;
 
 
 /**
@@ -131,7 +130,7 @@
         if ( createIfMissing )
         {
             beanContext =
-                ContextCache.get( servletContext ).getServerAdapter().createControlBeanContext( request, response );
+                ServerAdapterManager.getServerAdapter( servletContext ).createControlBeanContext( request, response );
             request.getSession().setAttribute( CONTROL_CONTEXT_CLASSNAME, beanContext );
             request.setAttribute( CONTROL_CONTEXT_CLASSNAME, beanContext );
         }
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/ContextCache.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/ContextCache.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/ContextCache.java	(working copy)
@@ -22,11 +22,8 @@
 import org.apache.beehive.netui.util.config.bean.NetuiConfigDocument;
 import org.apache.beehive.netui.util.config.bean.PageflowHandlers;
 import org.apache.beehive.netui.util.config.bean.PageflowConfig;
-import org.apache.beehive.netui.util.DiscoveryUtils;
 import org.apache.beehive.netui.pageflow.PageFlowActionServlet;
 import org.apache.beehive.netui.pageflow.PageFlowContextListener;
-import org.apache.beehive.netui.pageflow.ServerAdapter;
-import org.apache.beehive.netui.pageflow.DefaultServerAdapter;
 import org.apache.beehive.netui.pageflow.handler.LoginHandler;
 import org.apache.beehive.netui.pageflow.handler.ForwardRedirectHandler;
 import org.apache.beehive.netui.pageflow.handler.ReloadableClassHandler;
@@ -48,7 +45,6 @@
     private static final String DEFAULT_FWD_REDIRECT_HANDLER_CLASS = DefaultForwardRedirectHandler.class.getName();
     private static final String DEFAULT_RELOADABLE_CLASS_HANDLER_CLASS = DefaultReloadableClassHandler.class.getName();
     private static final String DEFAULT_EXCEPTIONS_HANDLER_CLASS = DefaultExceptionsHandler.class.getName();
-    private static final String SERVER_ADAPTER_PROP = "pageflow.serveradapter";
     private static final int DEFAULT_MAX_FORWARDS_PER_REQUEST = 25;
     private static final int DEFAULT_MAX_NESTING_STACK_DEPTH = 10;
     
@@ -62,9 +58,8 @@
     private LoginHandler _loginHandler = null;
     private ReloadableClassHandler _reloadableClassHandler = null;
     private ExceptionsHandler _exceptionsHandler = null;
-    private ServerAdapter _serverAdapter = null;
+
     
-    
     public ForwardRedirectHandler getForwardRedirectHandler()
     {
         return _forwardRedirectHandler;
@@ -175,8 +170,6 @@
     }
     private ContextCache( ServletContext servletContext )
     {
-        _serverAdapter = createServerAdapter( servletContext );
-        
         //
         // Try loading some settings (max-forwards-per-requst, max-nesting-stack-depth, ensure-secure-forwards) from
         // the deprecated locations first, then fall back to netui-config.xml.
@@ -303,83 +296,4 @@
         
         return null;
     }
-    
-    private static ServerAdapter tryServerAdapter( Class serverAdapterClass, ServletContext servletContext )
-    {
-        try
-        {
-            ServerAdapter sa = ( ServerAdapter ) serverAdapterClass.newInstance();
-            
-            try
-            {
-                if ( sa.accept( servletContext ) )
-                {
-                    _log.info( "ServerAdapter " + serverAdapterClass.getName() + " accepted." );
-                    sa.setServletContext( servletContext );
-                    return sa;
-                }
-                else
-                {
-                    _log.info( "ServerAdapter " + serverAdapterClass.getName() + " is present but did not accept." );
-                }
-            }
-            catch ( Exception e )
-            {
-                _log.error( serverAdapterClass.getName() + ".accept() threw an exception.", e );
-            }
-            catch ( LinkageError e )
-            {
-                _log.error( serverAdapterClass.getName() + ".accept() caused a linkage error and may be out of date.", e );
-            }
-        }
-        catch ( InstantiationException e )
-        {
-            _log.error( "Could not create instance of ServerAdapter class " + serverAdapterClass.getName(), e );
-        }
-        catch ( IllegalAccessException e )
-        {
-            _log.error( "Could not create instance of ServerAdapter class " + serverAdapterClass.getName(), e );
-        }
-        catch ( Exception e )
-        {
-            _log.error( "Error creating instance of ServerAdapter class " + serverAdapterClass.getName(), e );
-        }
-        
-        return null;
-    }
-    
-    private static ServerAdapter createServerAdapter( ServletContext servletContext )
-    {
-        String serverAdapterClassName = System.getProperty( SERVER_ADAPTER_PROP );
-        
-        if ( serverAdapterClassName != null )
-        {
-            Class serverAdapterClass = DiscoveryUtils.loadServiceClass( serverAdapterClassName, ServerAdapter.class );
-            
-            if ( serverAdapterClass != null )
-            {
-                ServerAdapter sa = tryServerAdapter( serverAdapterClass, servletContext );
-                if ( sa != null ) return sa;
-            }
-        }
-        
-        Class[] classes = DiscoveryUtils.getServiceClasses( ServerAdapter.class );
-        
-        for ( int i = 0; i < classes.length; i++ )
-        {
-            ServerAdapter sa = tryServerAdapter( classes[i], servletContext );
-            if ( sa != null ) return sa;
-        }
-        
-        _log.info( "No ServerAdapter specified or discovered; using " + DefaultServerAdapter.class );
-        ServerAdapter sa =
-               new DefaultServerAdapter(){ public boolean accept( ServletContext servletContext ) { return true; } };
-        sa.setServletContext( servletContext );
-        return sa;
-    }
-
-    public ServerAdapter getServerAdapter()
-    {
-        return _serverAdapter;
-    }
 }
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultLoginHandler.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultLoginHandler.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultLoginHandler.java	(working copy)
@@ -41,12 +41,12 @@
     public void login( String username, String password, HttpServletRequest request, HttpServletResponse response )
         throws LoginException
     {
-        ContextCache.get( getServletContext() ).getServerAdapter().login( username, password, request, response );
+        ServerAdapterManager.getServerAdapter( getServletContext() ).login( username, password, request, response );
     }
 
     public void logout( boolean invalidateSessions, HttpServletRequest request, HttpServletResponse response )
     {
-        ContextCache.get( getServletContext() ).getServerAdapter().logout( invalidateSessions, request, response );
+        ServerAdapterManager.getServerAdapter( getServletContext() ).logout( invalidateSessions, request, response );
     }
 
     public boolean isUserInRole( String roleName, HttpServletRequest request )
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultReloadableClassHandler.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultReloadableClassHandler.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultReloadableClassHandler.java	(working copy)
@@ -52,7 +52,7 @@
         if ( false )
         {
             ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
-            ServerAdapter serverAdapter = ContextCache.get( servletContext ).getServerAdapter();
+            ServerAdapter serverAdapter = ServerAdapterManager.getServerAdapter( servletContext );
             File[] classDirs = null;
             
             // TODO: make this configurable in netui-config.xml.  You should be able to specify absolute files
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java	(working copy)
@@ -17,10 +17,10 @@
  */
 package org.apache.beehive.netui.pageflow.internal;
 
+import org.apache.beehive.netui.core.urls.URLRewriterService;
 import org.apache.beehive.netui.pageflow.*;
 import org.apache.beehive.netui.pageflow.handler.ReloadableClassHandler;
 import org.apache.beehive.netui.pageflow.config.PageFlowControllerConfig;
-import org.apache.beehive.netui.pageflow.config.PageFlowActionMapping;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 import org.apache.beehive.netui.util.logging.Logger;
 import org.apache.beehive.netui.util.Bundle;
@@ -37,7 +37,6 @@
 import java.io.IOException;
 import java.io.PrintStream;
 import java.lang.reflect.Method;
-import java.lang.reflect.Field;
 import java.util.Map;
 import java.util.Iterator;
 import java.util.HashMap;
@@ -52,7 +51,6 @@
 import org.apache.struts.action.ActionServlet;
 import org.apache.struts.action.DynaActionFormClass;
 import org.apache.struts.action.DynaActionForm;
-import org.apache.struts.action.Action;
 import org.apache.struts.config.ModuleConfig;
 import org.apache.struts.config.ControllerConfig;
 import org.apache.struts.config.FormBeanConfig;
@@ -95,7 +93,7 @@
                                          HttpServletResponse response, ServletContext servletContext )
             throws IOException
     {
-        boolean prodMode = ContextCache.get( servletContext ).getServerAdapter().isInProductionMode();
+        boolean prodMode = ServerAdapterManager.getServerAdapter( servletContext ).isInProductionMode();
         
         if ( prodMode && ! RequestValues.avoidDirectResponseOutput( request ) )
         {
@@ -981,6 +979,98 @@
         assert request.getSession( false ) != null : "getServletContext() called before session created";
         return request.getSession( true ).getServletContext();
     }
-    
 
+    public static String createActionURL( HttpServletRequest servletRequest, String qualifiedAction )
+    {
+        String pageURI = getDecodedURI( servletRequest );
+        int lastSlash = pageURI.lastIndexOf( '/' );
+        if ( lastSlash != -1 )
+        {
+            StringBuilder value = new StringBuilder( qualifiedAction.length() + 16 );
+            value.append( pageURI.substring( 0, lastSlash ) );
+            value.append( qualifiedAction );
+            return value.toString();
+        }
+
+        return qualifiedAction;
+    }
+
+    public static String createActionPath( HttpServletRequest request, String qualifiedAction )
+    {
+        ModuleConfig appConfig = ( ModuleConfig ) request.getAttribute( Globals.MODULE_KEY );
+        if ( appConfig != null )
+        {
+            StringBuilder value = new StringBuilder( qualifiedAction.length() + 16 );
+            value.append( appConfig.getPrefix() );
+            value.append( qualifiedAction );
+            return value.toString();
+        }
+
+        return qualifiedAction;
+    }
+
+    public static String qualifiedAction( ServletContext servletContext, String action )
+    {
+        assert action != null;
+        StringBuilder sb = new StringBuilder( 32 );
+
+        // Use our servlet mapping, if one is specified
+        String servletMapping = ( String ) servletContext.getAttribute( Globals.SERVLET_KEY );
+        if ( servletMapping != null )
+        {
+            String queryString = null;
+            int question = action.indexOf( '?' );
+            if ( question >= 0 )
+            {
+                queryString = action.substring( question );
+            }
+            String actionMapping = URLRewriterService.getActionMappingName( action );
+            if ( servletMapping.startsWith( "*." ) )
+            {
+                sb.append( actionMapping );
+                sb.append( servletMapping.substring( 1 ) );
+            }
+            else if ( servletMapping.endsWith( "/*" ) )
+            {
+                sb.append( servletMapping.substring( 0, servletMapping.length() - 2 ) );
+                sb.append( actionMapping );
+            }
+            else if ( servletMapping.equals( "/" ) )
+            {
+                sb.append( actionMapping );
+            }
+            if ( queryString != null )
+            {
+                sb.append( queryString );
+            }
+        }
+
+        // Otherwise, assume extension mapping is in use and extension is
+        // already included in the action property
+        else
+        {
+            if ( !action.startsWith( "/" ) )
+            {
+                sb.append( '/' );
+            }
+            sb.append( action );
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Add a parameter to the given URL. Assumes there is no trailing
+     * anchor/fragment indicated with a '#'.
+     *
+     * @param url       the URL to which to append.
+     * @param paramName the name of the parameter to add.
+     * @param paramVal  the value of the parameter to add.
+     * @return the URL, with the given parameter added.
+     */
+    public static String addParam( String url, String paramName, String paramVal )
+    {
+        return url + ( url.indexOf( '?' ) != -1 ? '&' : '?' ) + paramName + '=' + paramVal;
+    }
+
 }
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java	(working copy)
@@ -55,20 +55,20 @@
 import org.apache.beehive.netui.util.logging.Logger;
 import org.apache.beehive.netui.util.ServletUtils;
 import org.apache.beehive.netui.util.FileUtils;
-import org.apache.beehive.netui.pageflow.internal.JavaControlUtils;
-import org.apache.beehive.netui.pageflow.util.PageflowTagUtils;
-
-import org.apache.beehive.netui.pageflow.util.URLRewriterService;
+import org.apache.beehive.netui.core.urls.URLRewriterService;
 import org.apache.beehive.netui.pageflow.config.PageFlowActionForward;
 import org.apache.beehive.netui.pageflow.config.PageFlowActionMapping;
 import org.apache.beehive.netui.pageflow.config.PageFlowActionFormBean;
 import org.apache.beehive.netui.pageflow.interceptor.ActionInterceptorChain;
 import org.apache.beehive.netui.pageflow.interceptor.InterceptorForward;
 import org.apache.beehive.netui.pageflow.internal.ContextCache;
+import org.apache.beehive.netui.pageflow.internal.DefaultURLRewriter;
 import org.apache.beehive.netui.pageflow.internal.RequestValues;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
+import org.apache.beehive.netui.pageflow.internal.JavaControlUtils;
 import org.apache.beehive.netui.pageflow.internal.FlowControllerAction;
 import org.apache.beehive.netui.pageflow.internal.DeferredPageFlowException;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 import org.apache.beehive.netui.pageflow.scoping.ScopedRequest;
 import org.apache.beehive.netui.pageflow.handler.ForwardRedirectHandler;
@@ -474,7 +474,7 @@
     {
         String uri = InternalUtils.getDecodedServletPath( request );
         ServletContext servletContext = getServletContext();
-        ServerAdapter serverAdapter = ContextCache.get( servletContext ).getServerAdapter();
+        ServerAdapter serverAdapter = ServerAdapterManager.getServerAdapter( servletContext );
 
         //
         // Allow weblogic to do a security check on forwarded requests, if that feature is enabled.
@@ -567,8 +567,8 @@
                 {
                     String actionPath = paramName.substring( ACTION_OVERRIDE_PARAM_PREFIX_LEN );
 
-                    String qualifiedAction = PageflowTagUtils.qualifiedAction(servletContext,actionPath);
-                    actionPath = PageflowTagUtils.createActionPath(request, qualifiedAction );
+                    String qualifiedAction = InternalUtils.qualifiedAction(servletContext,actionPath);
+                    actionPath = InternalUtils.createActionPath(request, qualifiedAction );
 
                     if ( _log.isDebugEnabled() )
                     {
@@ -698,13 +698,19 @@
         //
         // Callback to the server adapter.
         //
-        contextCache.getServerAdapter().beginRequest( request, response );
+        ServerAdapter serverAdapter = ServerAdapterManager.getServerAdapter( servletContext );
+        serverAdapter.beginRequest( request, response );
         
         //
         // Initialize the ControlBeanContext in the session.
         //
         JavaControlUtils.initializeControlContext( request, response, servletContext );
-        
+
+        //
+        // Register the default URLRewriter
+        //
+        URLRewriterService.registerURLRewriter( request, new DefaultURLRewriter() );
+
         try
         {
             processInternal( request, response );
@@ -719,7 +725,7 @@
             //
             // Callback to the server adapter.
             //
-            contextCache.getServerAdapter().endRequest( request, response );
+            serverAdapter.endRequest( request, response );
         }
 
         if ( _log.isTraceEnabled() )
@@ -1243,7 +1249,7 @@
         String scopeID = request.getParameter( ScopedServletUtils.SCOPE_ID_PARAM );
         if ( scopeID != null )
         {
-            return PageflowTagUtils.addParam( url, ScopedServletUtils.SCOPE_ID_PARAM, scopeID );
+            return InternalUtils.addParam( url, ScopedServletUtils.SCOPE_ID_PARAM, scopeID );
         }
         else
         {
@@ -1421,8 +1427,8 @@
             {
                 try
                 {
-                    ServerAdapter sa = contextCache.getServerAdapter();
-                    
+                    ServerAdapter sa = ServerAdapterManager.getServerAdapter( servletContext );
+
                     if ( request.isSecure() )
                     {
                         if ( sp.equals( SecurityProtocol.UNSECURE ) )
@@ -1461,7 +1467,7 @@
     protected void processNoCache( HttpServletRequest request, HttpServletResponse response )
     {
         if ( moduleConfig.getControllerConfig().getNocache()
-                || ! ContextCache.get( getServletContext() ).getServerAdapter().isInProductionMode() )
+                || ! ServerAdapterManager.getServerAdapter( getServletContext() ).isInProductionMode() )
         {
             //
             // The call to PageFlowJspFilter.preventCache() will cause caching to be prevented
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/util/PageflowTagUtils.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/util/PageflowTagUtils.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/util/PageflowTagUtils.java	(working copy)
@@ -1,442 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation.
- *
- * Licensed 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.
- *
- * $Header:$
- */
-package org.apache.beehive.netui.pageflow.util;
-
-//java imports
-import java.net.URLEncoder;
-import java.net.MalformedURLException;
-import java.util.Map;
-import java.util.Iterator;
-
-//internal imports
-import org.apache.beehive.netui.pageflow.FlowController;
-import org.apache.beehive.netui.pageflow.FlowControllerFactory;
-import org.apache.beehive.netui.pageflow.internal.InternalUtils;
-
-import org.apache.beehive.netui.util.logging.Logger;
-import org.apache.beehive.netui.util.FileUtils;
-
-//external imports
-import javax.servlet.jsp.PageContext;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.struts.config.ModuleConfig;
-import org.apache.struts.config.ForwardConfig;
-import org.apache.struts.Globals;
-import org.apache.struts.util.MessageResources;
-import org.apache.struts.util.RequestUtils;
-
-import static org.apache.beehive.netui.pageflow.PageFlowConstants.ACTION_EXTENSION;
-
-
-/**
- * @exclude
- */ 
-public class PageflowTagUtils
-{
-    private static final Logger logger = Logger.getInstance( PageflowTagUtils.class );
-
-    /**
-     * The message resources for this package.
-     */
-    private static MessageResources messages =
-        MessageResources.getMessageResources("org.apache.struts.util.LocalStrings");
-
-    public static String getRewrittenFormAction(HttpServletRequest request, String action, PageContext pageContext)
-    {
-        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
-        String qualifiedAction = PageflowTagUtils.qualifiedAction(pageContext.getServletContext(),action);
-        String actionUrl = createActionURL(request, qualifiedAction);
-
-        actionUrl = prepareActionUrl(pageContext, actionUrl);
-
-        return response.encodeURL(actionUrl);
-    }
-
-    public static String prepareActionUrl(PageContext pageContext, String url)
-    {
-        ServletContext servletContext = pageContext.getServletContext();
-        ServletRequest request = pageContext.getRequest();
-        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
-
-        String templateType = URLRewriter.ACTION_UNSECURE;
-
-        if (URLRewriterService.needsSecure(request, servletContext, url, true))
-            templateType = URLRewriter.ACTION_SECURE;
-
-        url = URLRewriterService.rewriteURL(servletContext, request, response, url, templateType);
-
-        return response.encodeURL(url);
-    }
-
-    public static String prepareResourceUrl(PageContext pageContext, String url)
-    {
-        if ( FileUtils.isAbsoluteURI(url) )
-        {
-            return url;
-        }
-        
-        ServletContext servletContext = pageContext.getServletContext();
-        HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
-        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
-
-
-        if (!url.startsWith("/"))
-        {
-            String reqUri = request.getRequestURI();
-            String path = reqUri.substring(0, reqUri.lastIndexOf("/") + 1);
-            url = path + url;
-        }
-
-        String templateType = URLRewriter.RESOURCE_UNSECURE;
-
-        if (URLRewriterService.needsSecure(request, servletContext, url, true))
-            templateType = URLRewriter.RESOURCE_SECURE;
-
-        url = URLRewriterService.rewriteURL(servletContext, request, response, url, templateType);
-
-        return response.encodeURL(url);
-    }
-
-    public static String createActionURL(HttpServletRequest servletRequest, String qualifiedAction)
-    {
-        String pageURI = InternalUtils.getDecodedURI( servletRequest );
-        int lastSlash = pageURI.lastIndexOf( '/' );
-        if ( lastSlash != -1 )
-        {
-            StringBuilder value = new StringBuilder(qualifiedAction.length() + 16);
-            value.append( pageURI.substring( 0, lastSlash ) );
-            value.append(qualifiedAction);
-            return value.toString();
-        }
-        return qualifiedAction;
-    }
-
-    public static String createActionPath(HttpServletRequest request, String qualifiedAction)
-    {
-
-        ModuleConfig appConfig = (ModuleConfig) request.getAttribute(Globals.MODULE_KEY);
-        if (appConfig != null)
-        {
-            StringBuilder value = new StringBuilder(qualifiedAction.length() + 16);
-            value.append(appConfig.getPrefix());
-            value.append(qualifiedAction);
-            return value.toString();
-        }
-        return qualifiedAction;
-    }
-
-    public static String qualifiedAction(ServletContext servletContext, String action)
-    {
-        StringBuilder sb = new StringBuilder(32);
-
-        // Use our servlet mapping, if one is specified
-        String servletMapping = (String) servletContext.getAttribute(Globals.SERVLET_KEY);
-        if (servletMapping != null)
-        {
-            String queryString = null;
-            int question = action.indexOf("?");
-            if (question >= 0)
-            {
-                queryString = action.substring(question);
-            }
-            String actionMapping = URLRewriterService.getActionMappingName(action);
-            if (servletMapping.startsWith("*."))
-            {
-                sb.append(actionMapping);
-                sb.append(servletMapping.substring(1));
-            }
-            else if (servletMapping.endsWith("/*"))
-            {
-                sb.append(servletMapping.substring(0, servletMapping.length() - 2));
-                sb.append(actionMapping);
-            }
-            else if (servletMapping.equals("/"))
-            {
-                sb.append(actionMapping);
-            }
-            if (queryString != null) {
-                sb.append(queryString);
-            }
-        }
-
-        // Otherwise, assume extension mapping is in use and extension is
-        // already included in the action property
-        else
-        {
-            if (!action.startsWith("/"))
-            {
-                sb.append("/");
-            }
-            sb.append(action);
-        }
-        return sb.toString();
-    }
-
-    public static boolean isAction(HttpServletRequest request, HttpServletResponse response, ServletContext servletContext, String action)
-    {
-        boolean isAnAction = true;
-        FlowController flowController = InternalUtils.getCurrentPageFlow(request, false);
-        if (flowController != null)
-        {
-            String checkAction = action;
-            if (checkAction.startsWith("/"))
-                checkAction = checkAction.substring(1);
-            if (checkAction.endsWith(ACTION_EXTENSION))
-                checkAction = checkAction.substring(0, checkAction.length() - ACTION_EXTENSION.length());
-            isAnAction = flowController.isAction(checkAction);
-
-            if (!isAnAction)
-            {
-                FlowController globalController =
-                        FlowControllerFactory.getSharedFlowForRequest( request, response, servletContext );
-                if (globalController != null)
-                    isAnAction = globalController.isAction(checkAction);
-            }
-        }
-
-        return isAnAction;
-    }
-
-
-    // @struts : from org.apache.struts.util.RequestUtils RC 1.1
-    public static String computeURL
-    (
-        PageContext pageContext,
-        String forward,
-        String href,
-        String page,
-        Map params,
-        String anchor,
-        boolean redirect)
-        throws MalformedURLException {
-
-        return computeURL(pageContext, forward, href, page, null, params,
-			  anchor, redirect);
-    }
-
-    // @struts : from org.apache.struts.util.RequestUtils RC 1.1
-    public static String computeURL(
-        PageContext pageContext,
-        String forward,
-        String href,
-        String page,
-        String action,
-        Map params,
-        String anchor,
-        boolean redirect)
-        throws MalformedURLException
-    {
-
-        String encoding = pageContext.getResponse().getCharacterEncoding();
-
-        // Validate that exactly one specifier was included
-        int n = 0;
-        if (forward != null) {
-            n++;
-        }
-        if (href != null) {
-            n++;
-        }
-        if (page != null) {
-            n++;
-        }
-        if (action != null) {
-            n++;
-        }
-        if (n != 1) {
-            throw new MalformedURLException(messages.getMessage("computeURL.specifier"));
-        }
-
-        HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
-
-        // Look up the module configuration for this request
-        ModuleConfig config =
-            (ModuleConfig) request.getAttribute(Globals.MODULE_KEY);
-        if (config == null) { // Backwards compatibility hack
-            config =
-                (ModuleConfig) pageContext.getServletContext().getAttribute(Globals.MODULE_KEY);
-            InternalUtils.setCurrentModule( config, request );
-        }
-
-        // Calculate the appropriate URL
-        StringBuilder url = new StringBuilder(32);
-        if (forward != null) {
-            ForwardConfig fc = config.findForwardConfig(forward);
-            if (fc == null) {
-                throw new MalformedURLException(messages.getMessage("computeURL.forward", forward));
-            }
-            if (fc.getRedirect()) {
-                redirect = true;
-            }
-            if (fc.getPath().startsWith("/")) {
-                url.append(request.getContextPath());
-                url.append(RequestUtils.forwardURL(request, fc));
-            } else {
-                url.append(fc.getPath());
-            }
-        } else if (href != null) {
-            url.append(href);
-        } else if (action != null) {
-            url.append(RequestUtils.getActionMappingURL(action, pageContext));
-
-        } else /* if (page != null) */ {
-            url.append(request.getContextPath());
-            url.append(RequestUtils.pageURL(request, page));
-        }
-
-        // Add anchor if requested (replacing any existing anchor)
-        if (anchor != null) {
-            String temp = url.toString();
-            int hash = temp.indexOf('#');
-            if (hash >= 0) {
-                url.setLength(hash);
-            }
-            url.append('#');
-            url.append(encodeURL(anchor,encoding));
-        }
-
-        // Add dynamic parameters if requested
-        if ((params != null) && (params.size() > 0)) {
-            addParameters(url,encoding,redirect,params);
-        }
-
-        return (url.toString());
-    }
-
-    //
-    public static void addParameters(StringBuilder url,String encoding,
-                                     boolean redirect,Map params)
-    {
-        String anchor;
-        // Add dynamic parameters if requested
-        if ((params != null) && (params.size() > 0)) {
-
-            // Save any existing anchor
-            String temp = url.toString();
-            int hash = temp.indexOf('#');
-            if (hash >= 0) {
-                anchor = temp.substring(hash + 1);
-                url.setLength(hash);
-                temp = url.toString();
-            } else {
-                anchor = null;
-            }
-
-            // Define the parameter separator
-            String separator = "&amp;";
-            if (redirect) {
-                separator = "&";
-            }
-
-            // Add the required request parameters
-            boolean question = temp.indexOf('?') >= 0;
-            Iterator keys = params.keySet().iterator();
-            while (keys.hasNext()) {
-                String key = (String) keys.next();
-                Object value = params.get(key);
-                if (value == null) {
-                    if (!question) {
-                        url.append('?');
-                        question = true;
-                    } else {
-                        url.append(separator);
-                    }
-                    url.append(encodeURL(key,encoding));
-                    url.append('='); // Interpret null as "no value"
-                } else if (value instanceof String) {
-                    if (!question) {
-                        url.append('?');
-                        question = true;
-                    } else {
-                        url.append(separator);
-                    }
-                    url.append(encodeURL(key,encoding));
-                    url.append('=');
-                    url.append(encodeURL((String) value,encoding));
-                } else if (value instanceof String[]) {
-                    String values[] = (String[]) value;
-                    for (int i = 0; i < values.length; i++) {
-                        if (!question) {
-                            url.append('?');
-                            question = true;
-                        } else {
-                            url.append(separator);
-                        }
-                        url.append(encodeURL(key,encoding));
-                        url.append('=');
-                        url.append(encodeURL(values[i],encoding));
-                    }
-                } else /* Convert other objects to a string */ {
-                    if (!question) {
-                        url.append('?');
-                        question = true;
-                    } else {
-                        url.append(separator);
-                    }
-                    url.append(encodeURL(key,encoding));
-                    url.append('=');
-                    url.append(encodeURL(value.toString(),encoding));
-                }
-            }
-
-            // Re-add the saved anchor (if any)
-            if (anchor != null) {
-                url.append('#');
-                url.append(encodeURL(anchor,encoding));
-            }
-        }
-    }
-
-
-    // @struts : from org.apache.struts.util.RequestUtils RC 1.1
-    // This has been modified from the strut to assume 1.4 because we ship 
-    // with that.
-    public static String encodeURL(String url, String encoding)
-    {
-        String encodedURL = null;
-        try {
-            encodedURL = URLEncoder.encode(url,encoding);
-        }
-        catch (java.io.UnsupportedEncodingException e) {
-            logger.error( "Unsupported encoding:" + encoding, e );
-            // try this in utf-8 and log the exception
-            try {
-                encodedURL = URLEncoder.encode(url,"UTF-8");
-            }
-            catch (java.io.UnsupportedEncodingException ignore) {}
-        }
-        return encodedURL;
-    }
-    
-    /**
-     * Add a parameter to the given URL.
-     * 
-     * @param url the URL to which to append. 
-     * @param paramName the name of the parameter to add.
-     * @param paramVal the value of the parameter to add.
-     * @return the URL, with the given parameter added.
-     */ 
-    public static String addParam(String url, String paramName, String paramVal)
-    {
-        return url + (url.indexOf('?') != -1 ? '&' : '?') + paramName + '=' + paramVal;
-    }
-}
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/util/URLRewriter.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/util/URLRewriter.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/util/URLRewriter.java	(working copy)
@@ -25,6 +25,8 @@
 /**
  * URL rewriter interface.  Offers methods for rewriting URLs/query parameters, and adding URL rewriters
  * to the chain.
+ *
+ * @deprecated Use {@link org.apache.beehive.netui.core.urls.URLRewriter} instead.
  */
 public abstract class URLRewriter
 {
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/util/URLRewriterService.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/util/URLRewriterService.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/util/URLRewriterService.java	(working copy)
@@ -17,16 +17,10 @@
  */
 package org.apache.beehive.netui.pageflow.util;
 
-
-
-//java imports
-
-//internal imports
+import org.apache.beehive.netui.core.urls.MutableURI;
 import org.apache.beehive.netui.pageflow.PageFlowUtils;
 import org.apache.beehive.netui.pageflow.SecurityProtocol;
 
-//external imports
-import javax.servlet.ServletRequest;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
@@ -36,7 +30,9 @@
 
 /**
  * Methods for registering URL rewriters, and for rewriting URLs using registered rewriters.
- */ 
+ *
+ * @deprecated Use {@link org.apache.beehive.netui.core.urls.URLRewriterService} instead.
+ */
 public class URLRewriterService
 {
     private static URLRewriter defaultRewriter = new DefaultURLRewriter();
@@ -62,20 +58,7 @@
      */ 
     public static String rewriteName(ServletContext servletContext, ServletRequest request, String name)
     {
-        URLRewriter rewriter = (URLRewriter) request.getAttribute(URL_REWRITER_KEY);
-        String rewrittenName = null;
-
-        if (rewriter != null)
-        {
-            rewrittenName = rewriter.rewriteName(servletContext, request, name);
-        }
-        else
-        {
-            rewrittenName = defaultRewriter.rewriteName(servletContext, request, name);
-        }
-
-        return rewrittenName;
-
+        return org.apache.beehive.netui.core.urls.URLRewriterService.rewriteName( servletContext, request, name );
     }
 
     /**
@@ -103,7 +86,7 @@
 
     /**
      * Rewrite the given URL, using the registered URLRewriter.
-     * 
+     *
      * @param servletContext the current ServletContext.
      * @param request the current HttpServletRequest.
      * @param response the current HttpServletResponse.
@@ -118,21 +101,40 @@
      * @param doEncode if <code>true</code>, the rewritten URL will be encoded using
      *                 {@link HttpServletResponse#encodeRedirectURL}.
      * @return the rewritten URL.
-     * 
+     *
      * @see #registerURLRewriter
-     */ 
+     */
     public static String rewriteURL(ServletContext servletContext, ServletRequest request, ServletResponse response, String url, String type, boolean doEncode)
     {
-        URLRewriter rewriter = (URLRewriter) request.getAttribute(URL_REWRITER_KEY);
         String rewrittenURL = null;
+        MutableURI mutableUri = null;
+        try {
+            mutableUri = new MutableURI( url );
+            org.apache.beehive.netui.core.urls.URLRewriter.Type tempType =
+                    org.apache.beehive.netui.core.urls.URLRewriter.Type.RESOURCE;
+            boolean needsToBeSecure = false;
 
-        if (rewriter != null)
-        {
-            rewrittenURL = rewriter.rewriteURL(servletContext, request, response, url, type);
+            if ( type.equals( URLRewriter.ACTION_UNSECURE ) )
+            {
+                tempType = org.apache.beehive.netui.core.urls.URLRewriter.Type.ACTION;
+            }
+            else if ( type.equals( URLRewriter.ACTION_SECURE ) )
+            {
+                tempType = org.apache.beehive.netui.core.urls.URLRewriter.Type.ACTION;
+                needsToBeSecure = true;
+            }
+            else if ( type.equals( URLRewriter.RESOURCE_SECURE ) )
+            {
+                needsToBeSecure = true;
+            }
+
+            org.apache.beehive.netui.core.urls.URLRewriterService.rewriteURL( servletContext, request, response,
+                                                                              mutableUri, tempType, needsToBeSecure );
+            rewrittenURL = mutableUri.toString();
         }
-        else
+        catch ( java.net.URISyntaxException e )
         {
-            rewrittenURL = defaultRewriter.rewriteURL(servletContext, request, response, url, type);
+            rewrittenURL = url;
         }
 
         if (doEncode)
@@ -142,18 +144,19 @@
         }
 
         return rewrittenURL;
-
     }
 
     /**
      * Register a URLRewriter in the request.  This rewriter will be used if {@link #rewriteURL} is called.
-     * 
+     *
      * @param request the current HttpServletRequest.
      * @param rewriter the URLRewriter to register.
-     */ 
+     */
     public static void registerURLRewriter(ServletRequest request, URLRewriter rewriter)
     {
         request.setAttribute(URL_REWRITER_KEY, rewriter);
+        org.apache.beehive.netui.core.urls.URLRewriter rewriterWrapper = new OldURLRewriterWrapper(rewriter);
+        org.apache.beehive.netui.core.urls.URLRewriterService.registerURLRewriter(request, rewriterWrapper);
     }
 
     /**
@@ -167,6 +170,8 @@
     {
         URLRewriter rewriter = (URLRewriter) request.getAttribute(URL_REWRITER_KEY);
         request.removeAttribute(URL_REWRITER_KEY);
+        org.apache.beehive.netui.core.urls.URLRewriter rewriterWrapper = new OldURLRewriterWrapper(rewriter);
+        org.apache.beehive.netui.core.urls.URLRewriterService.unregisterURLRewriter(request, rewriterWrapper);
 
         return rewriter;
     }
@@ -188,27 +193,12 @@
      */
     public static String getActionMappingName(String action)
     {
-        String value = action;
-        int question = action.indexOf("?");
-        if (question >= 0) {
-            value = value.substring(0, question);
-        }
-        int slash = value.lastIndexOf("/");
-        int period = value.lastIndexOf(".");
-        if ((period >= 0) && (period > slash)) {
-            value = value.substring(0, period);
-        }
-
-        if (value.startsWith("/")) {
-            return (value);
-        } else {
-            return ("/" + value);
-        }
+        return org.apache.beehive.netui.core.urls.URLRewriterService.getActionMappingName( action );
     }
 
     /**
      * Tell whether a given URI should be written to be secure.
-     * 
+     *
      * @param request the current HttpServletRequest.
      * @param context the current ServletContext.
      * @param uri the URI to check.
@@ -230,22 +220,21 @@
      *                 is unsecure ({@link javax.servlet.http.HttpServletRequest#isSecure} returns
      *                 <code>false</code>).
      *         </ul>
-     */ 
+     */
     public static boolean needsSecure(ServletRequest request, ServletContext context, String uri,
                                       boolean stripContextPath)
     {
-
         //Get the web-app relative path for security check
         String secureCheck = uri;
         if (stripContextPath)
         {
             String contextPath = ((HttpServletRequest)request).getContextPath();
+            if (secureCheck.startsWith(contextPath))
+            {
+                secureCheck = secureCheck.substring(contextPath.length());
+            }
+        }
 
-             if (secureCheck.startsWith(contextPath))
-             {
-                 secureCheck = secureCheck.substring(contextPath.length());
-             }
-         }
         boolean secure = false;
         if (secureCheck.indexOf("?") > -1)
         {
@@ -258,10 +247,13 @@
             secure = request.isSecure();
         }
         else
+        {
             secure = sp.equals(SecurityProtocol.SECURE);
+        }
+
         return secure;
     }
-    
+
     /**
      * Tell whether rewritten form actions should be allowed to have query parameters.  If this returns
      * <code>false</code>, then a form-tag implementation should render query parameters into hidden
@@ -270,7 +262,6 @@
      */
     public static boolean allowParamsOnFormAction(ServletContext servletContext, ServletRequest request)
     {
-        URLRewriter rewriter = (URLRewriter) request.getAttribute(URL_REWRITER_KEY);
-        return (rewriter != null ? rewriter.allowParamsOnFormAction(servletContext, request) : true);
+        return org.apache.beehive.netui.core.urls.URLRewriterService.allowParamsOnFormAction( servletContext, request );
     }
 }
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/util/DefaultURLRewriter.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/util/DefaultURLRewriter.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/util/DefaultURLRewriter.java	(working copy)
@@ -18,10 +18,9 @@
 package org.apache.beehive.netui.pageflow.util;
 
 //internal imports
-import org.apache.beehive.netui.pageflow.PageFlowUtils;
 import org.apache.beehive.netui.pageflow.ServerAdapter;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 import org.apache.beehive.netui.util.FileUtils;
 import org.apache.beehive.netui.util.logging.Logger;
@@ -33,6 +32,9 @@
 import javax.servlet.http.HttpServletResponse;
 
 
+/**
+ * @deprecated Use {@link org.apache.beehive.netui.pageflow.internal.DefaultURLRewriter} instead.
+ */
 public class DefaultURLRewriter extends URLRewriter
 {
     private static final Logger _log = Logger.getInstance( DefaultURLRewriter.class );
@@ -58,7 +60,7 @@
         }
         else
         {
-            ServerAdapter serverAdapter = ContextCache.get(servletContext).getServerAdapter();
+            ServerAdapter serverAdapter = ServerAdapterManager.getServerAdapter(servletContext);
             
             //Need to do default secure/unsecure rewriting
             if ((type.equals(URLRewriter.ACTION_SECURE) || (type.equals(URLRewriter.RESOURCE_SECURE))))
@@ -111,7 +113,7 @@
         {
             // TODO: after we've rewritten this to use mutable URLs (i.e., when it's easier to check for existing
             // parameters, we should check to see if the scope-id param is already there.
-            url = PageflowTagUtils.addParam(url, ScopedServletUtils.SCOPE_ID_PARAM, scopeID);
+            url = InternalUtils.addParam(url, ScopedServletUtils.SCOPE_ID_PARAM, scopeID);
         }
         
         // Continue chaining if there is another
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/util/TemplateHelper.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/util/TemplateHelper.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/util/TemplateHelper.java	(working copy)
@@ -26,8 +26,8 @@
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.ServletContext;
 
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 
 /**
  * Class for creating URLs from parameterized templates.
@@ -565,7 +565,7 @@
             else {
                 // Append the webapp name
                 ServletContext servletContext = InternalUtils.getServletContext(httpRequest);
-                String webAppName = ContextCache.get(servletContext).getServerAdapter().getFullContextPath(httpRequest);
+                String webAppName = ServerAdapterManager.getServerAdapter(servletContext).getFullContextPath(httpRequest);
                 buf = appendEnsureSeparator(buf, webAppName);
 
                 // Append the servlet name (mapping)
@@ -654,7 +654,7 @@
             else {
                 // Append the webapp name
                 ServletContext servletContext = InternalUtils.getServletContext(httpRequest);
-                String webAppName = ContextCache.get(servletContext).getServerAdapter().getFullContextPath(httpRequest);
+                String webAppName = ServerAdapterManager.getServerAdapter(servletContext).getFullContextPath(httpRequest);
                 buf.append(webAppName);
 
                 // Append the servlet name (mapping)
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/SharedFlowController.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/SharedFlowController.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/SharedFlowController.java	(working copy)
@@ -26,8 +26,7 @@
 import javax.servlet.http.HttpSession;
 import javax.servlet.ServletContext;
 
-import org.apache.beehive.netui.pageflow.internal.InternalUtils;
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 import static org.apache.beehive.netui.pageflow.internal.InternalConstants.*;
 
 
@@ -71,7 +70,7 @@
      */
     public void ensureFailover( HttpServletRequest request )
     {
-        ServerAdapter serverAdapter = ContextCache.get( getServletContext() ).getServerAdapter();
+        ServerAdapter serverAdapter = ServerAdapterManager.getServerAdapter( getServletContext() );
         serverAdapter.ensureFailover( SHARED_FLOW_ATTR_PREFIX + getClass().getName(), this, request );
     }
     
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java	(working copy)
@@ -35,15 +35,17 @@
 import org.apache.struts.config.ModuleConfig;
 import org.apache.struts.Globals;
 
+import org.apache.beehive.netui.core.urls.URLRewriterService;
 import org.apache.beehive.netui.script.common.BundleMap;
 import org.apache.beehive.netui.script.common.ImplicitObjectUtil;
 import org.apache.beehive.netui.util.logging.Logger;
 import org.apache.beehive.netui.util.FileUtils;
 import org.apache.beehive.netui.util.ServletUtils;
+import org.apache.beehive.netui.pageflow.internal.DefaultURLRewriter;
 import org.apache.beehive.netui.pageflow.internal.JavaControlUtils;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 
 
 /**
@@ -123,14 +125,19 @@
             //
             // Callback to the server adapter.
             //
-            ServerAdapter serverAdapter = ContextCache.get( _servletContext ).getServerAdapter();
+            ServerAdapter serverAdapter = ServerAdapterManager.getServerAdapter( _servletContext );
             serverAdapter.beginRequest( httpRequest, httpResponse );
             
             //
             // Initialize the ControlBeanContext in the session.
             //
             JavaControlUtils.initializeControlContext( httpRequest, httpResponse, _servletContext );
-            
+
+            //
+            // Register the default URLRewriter
+            //
+            URLRewriterService.registerURLRewriter( request, new DefaultURLRewriter() );
+
             try
             {
                 ModuleConfig prevModuleConfig = RequestUtils.getRequestModuleConfig( httpRequest );
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBean.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBean.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBean.java	(working copy)
@@ -20,13 +20,12 @@
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
 import org.apache.beehive.netui.pageflow.internal.CachedFacesBackingInfo;
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 import org.apache.beehive.netui.util.cache.ClassLevelCache;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
 import javax.servlet.ServletContext;
 import java.util.Map;
 import java.util.Collections;
@@ -58,7 +57,7 @@
         String attr =
                 ScopedServletUtils.getScopedSessionAttrName( InternalConstants.FACES_BACKING_ATTR, unwrappedRequest );
         ServletContext servletContext = InternalUtils.getServletContext( request );
-        ContextCache.get( servletContext ).getServerAdapter().ensureFailover( attr, this, unwrappedRequest );
+        ServerAdapterManager.getServerAdapter( servletContext ).ensureFailover( attr, this, unwrappedRequest );
     }
 
     public String getDisplayName()
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java	(working copy)
@@ -36,7 +36,7 @@
 import org.apache.beehive.netui.pageflow.internal.CachedPageFlowInfo;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 
 import static org.apache.beehive.netui.pageflow.internal.InternalConstants.*;
@@ -204,7 +204,7 @@
         if ( request.getAttribute( DELETING_PAGEFLOW_ATTR ) != this && request.getSession( false ) != null )
         {
             HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
-            ServerAdapter serverAdapter = ContextCache.get( getServletContext() ).getServerAdapter();
+            ServerAdapter serverAdapter = ServerAdapterManager.getServerAdapter( getServletContext() );
         
             //
             // If this is a long-lived page flow, there are two attributes to deal with.
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBeanFactory.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBeanFactory.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBeanFactory.java	(working copy)
@@ -20,7 +20,6 @@
 import static org.apache.beehive.netui.pageflow.internal.InternalConstants.FACES_BACKING_ATTR;
 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
 import org.apache.beehive.netui.pageflow.internal.ContextCache;
-import org.apache.beehive.netui.pageflow.internal.InternalConstants;
 import org.apache.beehive.netui.pageflow.annotations.Jpf;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 import org.apache.beehive.netui.util.FileUtils;
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowContextListener.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowContextListener.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowContextListener.java	(working copy)
@@ -20,9 +20,10 @@
 //java imports
 
 //internal imports
-import org.apache.beehive.netui.pageflow.util.UrlTemplateDescriptor;
 import org.apache.beehive.netui.pageflow.internal.ContextCache;
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
+import org.apache.beehive.netui.pageflow.util.UrlTemplateDescriptor;
 import org.apache.beehive.netui.util.config.ConfigUtil;
 import org.apache.beehive.netui.util.config.ConfigInitializationException;
 import org.apache.beehive.netui.util.logging.Logger;
@@ -95,6 +96,7 @@
         }
         
         ContextCache.init( servletContext );
+        ServerAdapterManager.init( servletContext );
         UrlTemplateDescriptor.getInstance().load( servletContext );
     }
 }
Index: netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowStack.java
===================================================================
--- netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowStack.java	(revision 109213)
+++ netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowStack.java	(working copy)
@@ -22,9 +22,8 @@
 import org.apache.beehive.netui.pageflow.interceptor.InterceptorForward;
 import org.apache.beehive.netui.pageflow.interceptor.ActionInterceptorChain;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
-import org.apache.beehive.netui.pageflow.internal.InternalUtils;
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
-import org.apache.beehive.netui.pageflow.internal.ContextCache;
+import org.apache.beehive.netui.pageflow.internal.ServerAdapterManager;
 
 import javax.servlet.http.HttpSessionBindingListener;
 import javax.servlet.http.HttpSessionBindingEvent;
@@ -207,7 +206,7 @@
     {
         String name =
             ScopedServletUtils.getScopedSessionAttrName( JPF_STACK_ATTR, PageFlowUtils.unwrapMultipart( request ) );
-        ContextCache.get( servletContext ).getServerAdapter().ensureFailover( name, this, request );
+        ServerAdapterManager.getServerAdapter( servletContext ).ensureFailover( name, this, request );
     }
     
     void save( HttpServletRequest request )
Index: netui/src/util/org/apache/beehive/netui/core/urls/URLRewriter.java
===================================================================
--- netui/src/util/org/apache/beehive/netui/core/urls/URLRewriter.java	(revision 0)
+++ netui/src/util/org/apache/beehive/netui/core/urls/URLRewriter.java	(revision 0)
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.netui.core.urls;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+
+/**
+ * Offers methods for rewriting URLs/query parameters.
+ */
+public abstract class URLRewriter
+{
+    /**
+     * Passed to {@link #rewriteURL} for normal (non-resource) and resource, non-secure and
+     * secure URLs.
+     */
+    public enum Type { ACTION, RESOURCE }
+
+    /**
+     * Rewrite the given query parameter name.
+     * 
+     * @param servletContext the current ServletContext.
+     * @param request the current ServletRequest.
+     * @param name the query parameter name to rewrite.
+     * @return the rewritten query parameter name.
+     */
+    public abstract String rewriteName( ServletContext servletContext, ServletRequest request, String name );
+
+    /**
+     * Rewrite the given URL.
+     * 
+     * @param servletContext the current ServletContext.
+     * @param request the current ServletRequest.
+     * @param response the current ServletResponse.
+     * @param url the MutableURI to be rewritten.
+     * @param type the type of URL to be rewritten.  This is one of the following values:
+     *    <ul>
+     *    <li><code>action</code>: a standard (non-resource) URL
+     *    <li><code>resource</code>: a resource (e.g., image) URL
+     *    </ul>
+     * @param needsToBeSecure a flag indicating whether the URL should be secure (SSL required) or not
+     */
+    public abstract void rewriteURL( ServletContext servletContext, ServletRequest request,
+                                     ServletResponse response, MutableURI url, Type type,
+                                     boolean needsToBeSecure );
+
+    /**
+     * Tell whether rewritten form actions should be allowed to have query parameters.  If this returns
+     * <code>false</code>, then a form-tag implementation should render query parameters into hidden
+     * fields on the form instead of allowing them to remain in the URL.
+     * @exclude
+     */
+    public boolean allowParamsOnFormAction( ServletContext servletContext, ServletRequest request )
+    {
+        return false;
+    }
+}

Property changes on: netui/src/util/org/apache/beehive/netui/core/urls/URLRewriter.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: netui/src/util/org/apache/beehive/netui/core/urls/URLRewriterService.java
===================================================================
--- netui/src/util/org/apache/beehive/netui/core/urls/URLRewriterService.java	(revision 0)
+++ netui/src/util/org/apache/beehive/netui/core/urls/URLRewriterService.java	(revision 0)
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.netui.core.urls;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletResponse;
+
+
+/**
+ * Methods for registering URL rewriters, adding URL rewriters
+ * to the chain, and for rewriting URLs using registered rewriters.
+ */
+public class URLRewriterService
+{
+    private static String URL_REWRITERS_KEY = "url_rewriters";
+
+    /**
+     * Rewrite the given parameter name, using the registered URLRewriter.
+     *
+     * @param servletContext the current ServletContext.
+     * @param request        the current ServletRequest.
+     * @param name           the parameter name to rewrite.
+     * @return the rewritten parameter name.
+     */
+    public static String rewriteName( ServletContext servletContext, ServletRequest request, String name )
+    {
+        ArrayList< URLRewriter > rewriters = ( ArrayList< URLRewriter > ) request.getAttribute( URL_REWRITERS_KEY );
+
+        if ( rewriters != null )
+        {
+            for ( URLRewriter rewriter : rewriters )
+            {
+                name = rewriter.rewriteName( servletContext, request, name );
+            }
+        }
+
+        return name;
+    }
+
+    /**
+     * Rewrite the given URL, using the list of registered URLRewriter objects.
+     *
+     * @param servletContext the current ServletContext.
+     * @param request        the current ServletRequest.
+     * @param response       the current ServletResponse.
+     * @param url            the URL to be rewritten.
+     * @param type           the type of URL to be rewritten.  This is one of the following values:
+     *    <ul>
+     *    <li><code>action</code>: a standard (non-resource) URL
+     *    <li><code>resource</code>: a resource (e.g., image) URL
+     *    </ul>
+     * @param needsToBeSecure a flag indicating whether the URL should be secure (SSL required) or not
+     * @see #registerURLRewriter
+     */
+    public static void rewriteURL( ServletContext servletContext, ServletRequest request,
+                                   ServletResponse response, MutableURI url, URLRewriter.Type type,
+                                   boolean needsToBeSecure )
+    {
+        ArrayList< URLRewriter > rewriters = ( ArrayList< URLRewriter > ) request.getAttribute( URL_REWRITERS_KEY );
+
+        if ( rewriters != null )
+        {
+            for ( URLRewriter rewriter : rewriters )
+            {
+                rewriter.rewriteURL( servletContext, request, response, url, type, needsToBeSecure );
+            }
+        }
+    }
+
+    /**
+     * Get the unmodifiable list of URLRewriter objects in the request that will be used if
+     * {@link #rewriteURL} is called.
+     *
+     * @param request  the current ServletRequest.
+     * @return an unmodifiable list of the URLRewriters that have been registered.
+     */
+    public static List< URLRewriter > getURLRewriters( ServletRequest request )
+    {
+        return Collections.unmodifiableList( ( ArrayList< URLRewriter > ) request.getAttribute( URL_REWRITERS_KEY ) );
+    }
+
+    /**
+     * Register a URLRewriter (add to a list) in the request.  It will be added to the end
+     * of a list of URLRewriter objects and will be used if {@link #rewriteURL} is called.
+     *
+     * @param request  the current ServletRequest.
+     * @param rewriter the URLRewriter to register.
+     */
+    public static void registerURLRewriter( ServletRequest request, URLRewriter rewriter )
+    {
+        ArrayList< URLRewriter > rewriters = ( ArrayList< URLRewriter > ) request.getAttribute( URL_REWRITERS_KEY );
+
+        if ( rewriters == null )
+        {
+            rewriters = new ArrayList< URLRewriter >();
+            rewriters.add( rewriter );
+            request.setAttribute( URL_REWRITERS_KEY, rewriters );
+        }
+        else
+        {
+            if ( !rewriters.contains( rewriter ) ) { rewriters.add( rewriter ); }
+        }
+    }
+
+    /**
+     * Register a URLRewriter (add to a list) in the request.  It will be added at the
+     * specified position in this list of URLRewriter objects and will be used if
+     * {@link #rewriteURL} is called.
+     *
+     * @param index    the place to insert the URLRewriter
+     * @param request  the current ServletRequest.
+     * @param rewriter the URLRewriter to register.
+     */
+    public static void registerURLRewriter( int index, ServletRequest request, URLRewriter rewriter )
+    {
+        ArrayList< URLRewriter > rewriters = ( ArrayList< URLRewriter > ) request.getAttribute( URL_REWRITERS_KEY );
+
+        if ( rewriters == null )
+        {
+            rewriters = new ArrayList< URLRewriter >();
+            rewriters.add( rewriter );
+            request.setAttribute( URL_REWRITERS_KEY, rewriters );
+        }
+        else
+        {
+            if ( !rewriters.contains( rewriter ) ) { rewriters.add( index, rewriter ); }
+        }
+    }
+
+    /**
+     * Unregister the URLRewriter (remove from the list) from the request.
+     *
+     * @param request the current ServletRequest.
+     * @param rewriter the URLRewriter to unregister
+     * @see #registerURLRewriter
+     */
+    public static void unregisterURLRewriter( ServletRequest request, URLRewriter rewriter )
+    {
+        if ( rewriter == null ) { return; }
+
+        ArrayList< URLRewriter > rewriters = ( ArrayList< URLRewriter > ) request.getAttribute( URL_REWRITERS_KEY );
+
+        if ( rewriters == null )
+        {
+            return;
+        }
+        else
+        {
+            rewriters.remove( rewriter );
+
+            if ( rewriters.size() == 0 )
+            {
+                request.removeAttribute( URL_REWRITERS_KEY );
+            }
+        }
+    }
+
+    /**
+     * Return the form action converted into an action mapping path.  The
+     * value of the <code>action</code> property is manipulated as follows in
+     * computing the name of the requested mapping:
+     * <ul>
+     * <li>Any filename extension is removed (on the theory that extension
+     * mapping is being used to select the controller servlet).</li>
+     * <li>If the resulting value does not start with a slash, then a
+     * slash is prepended.</li>
+     * </ul>
+     *
+     * @param action the action name to be converted.
+     * @return an action path, suitable for lookup in the Struts configuration file.
+     */
+    public static String getActionMappingName( String action )
+    {
+        String value = action;
+        int question = action.indexOf( "?" );
+        if ( question >= 0 )
+        {
+            value = value.substring( 0, question );
+        }
+        int slash = value.lastIndexOf( "/" );
+        int period = value.lastIndexOf( "." );
+        if ( ( period >= 0 ) && ( period > slash ) )
+        {
+            value = value.substring( 0, period );
+        }
+
+        if ( value.startsWith( "/" ) )
+        {
+            return ( value );
+        }
+        else
+        {
+            return ( "/" + value );
+        }
+    }
+
+    /**
+     * Tell whether rewritten form actions should be allowed to have query parameters.  If this returns
+     * <code>false</code>, then a form-tag implementation should render query parameters into hidden
+     * fields on the form instead of allowing them to remain in the URL.
+     *
+     * @exclude
+     */
+    public static boolean allowParamsOnFormAction( ServletContext servletContext, ServletRequest request )
+    {
+        ArrayList< URLRewriter > rewriters = ( ArrayList< URLRewriter > ) request.getAttribute( URL_REWRITERS_KEY );
+
+        if ( rewriters != null )
+        {
+            for ( URLRewriter rewriter : rewriters )
+            {
+                if ( !rewriter.allowParamsOnFormAction( servletContext, request ) ) { return false; }
+            }
+        }
+
+        return true;
+    }
+}

Property changes on: netui/src/util/org/apache/beehive/netui/core/urls/URLRewriterService.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: netui/src/util/org/apache/beehive/netui/core/urls/MutableURI.java
===================================================================
--- netui/src/util/org/apache/beehive/netui/core/urls/MutableURI.java	(revision 0)
+++ netui/src/util/org/apache/beehive/netui/core/urls/MutableURI.java	(revision 0)
@@ -0,0 +1,825 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.netui.core.urls;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * Class for creating URIs.
+ *
+ * TODO... We need to implement some conditions for opaque URIs like mailto, etc.
+ * TODO... determine what to do about constructor and initialization of path when (path == null) => opaque and URI.getPath() would return "" for non-opaue URIs.
+ */
+public class MutableURI
+{
+    /** Value used to set the port as undefined. */
+    public static final int UNDEFINED_PORT = -1;
+
+    /** Protocol scheme. */
+    private String _scheme;
+
+    /**
+     * User information "may consist of a user name and, optionally,
+     * scheme-specific information about how to gain authorization to
+     * access the server.
+     */
+    private String _userInfo;
+
+    /** Host */
+    private String _host;
+
+    /** Port */
+    private int _port;
+
+    /** Path */
+    private String _path;
+
+    /** Query parameters */
+    private LinkedHashMap< String, ArrayList< String > > _params;
+
+    /** Fragment */
+    private String _fragment;
+
+    /**
+     * Constructs a <code>MutableURI</code>.
+     */
+    public MutableURI()
+    {
+    }
+
+    /**
+     * Constructs a <code>MutableURI</code>.
+     *
+     * @param  uriString the string to be parsed into a URI
+     * @see              java.net.URI#URI(String)
+     */
+    public MutableURI( String uriString ) throws URISyntaxException
+    {
+        assert uriString != null : "The uri cannot be null.";
+
+        if ( uriString == null )
+        {
+            throw new IllegalArgumentException( "The URI cannot be null." );
+        }
+
+        // Parse this url into its component parts
+        URI uri = new URI( uriString );
+        setScheme( uri.getScheme() );
+        setUserInfo( uri.getRawUserInfo() );
+        setHost( uri.getHost() );
+        setPort( uri.getPort() );
+        setPath( uri.getRawPath() );
+        setQuery( uri.getRawQuery() );
+        setFragment( uri.getRawFragment() );
+    }
+
+    /**
+     * Constructs a <code>MutableURI</code>.
+     *
+     * @param scheme the name of the protocol to use
+     * @param userInfo the username and password
+     * @param host the name of the host
+     * @param port the port number on the host
+     * @param path the file on the host
+     * @param query the query part of this URI
+     * @param fragment the fragment part of this URI (internal reference in the URL)
+     */
+    public MutableURI( String scheme, String userInfo, String host, int port,
+                       String path, String query, String fragment )
+    {
+        setScheme( scheme );
+        setUserInfo( userInfo );
+        setHost( host );
+        setPort( port );
+        setPath( path );
+        setQuery( query );
+        setFragment( fragment );
+    }
+
+    /**
+     * Constructs a <code>MutableURI</code>.
+     */
+    public MutableURI( URI uri )
+    {
+        assert uri != null : "The URI cannot be null.";
+
+        if ( uri == null )
+        {
+            throw new IllegalArgumentException( "The URI cannot be null." );
+        }
+
+        setScheme( uri.getScheme() );
+        setUserInfo( uri.getRawUserInfo() );
+        setHost( uri.getHost() );
+        setPort( uri.getPort() );
+        setPath( uri.getRawPath() );
+        setQuery( uri.getRawQuery() );
+        setFragment( uri.getRawFragment() );
+    }
+
+    /**
+     * Constructs a <code>MutableURI</code>.
+     *
+     * <p> This is just a convenience constructor that functions the same as
+     * {@link #MutableURI(java.net.URI)} constructor with
+     * {@link java.net.URL#toURI()} as the argument. </p>
+     *
+     * <p>Note, any URL instance that complies with RFC 2396 can be converted
+     * to a URI. However, some URLs that are not strictly in compliance
+     * can not be converted to a URI. See {@link java.net.URL} </p>
+     *
+     * @exception URISyntaxException if this URL is not formatted strictly
+     *            to RFC2396 and cannot be converted to a URI.
+     * @see        java.net.URL#toURI()
+     */
+    public MutableURI( URL url ) throws URISyntaxException
+    {
+        assert url != null : "The URL cannot be null.";
+
+        if ( url == null )
+        {
+            throw new IllegalArgumentException( "The URL cannot be null." );
+        }
+
+        URI uri = url.toURI();
+        setScheme( uri.getScheme() );
+        setUserInfo( uri.getRawUserInfo() );
+        setHost( uri.getHost() );
+        setPort( uri.getPort() );
+        setPath( uri.getRawPath() );
+        setQuery( uri.getRawQuery() );
+        setFragment( uri.getRawFragment() );
+    }
+
+    /**
+     * Sets the protocol/scheme.
+     *
+     * @param scheme protocol/scheme
+     */
+    public void setScheme( String scheme )
+    {
+        _scheme = null;
+        if ( scheme != null )
+        {
+            scheme = scheme.trim();
+            if ( scheme.length() > 0 )
+            {
+                _scheme = scheme;
+            }
+        }
+    }
+
+    /**
+     * Returns the protocol/scheme. If no protocol was previously set,
+     * returns null.
+     *
+     * @return protocol/scheme
+     */
+    public String getScheme()
+    {
+        return _scheme;
+    }
+
+    /**
+     * Sets the userInfo.
+     *
+     * @param userInfo userInfo
+     */
+    public void setUserInfo( String userInfo )
+    {
+        _userInfo = null;
+        if ( userInfo != null )
+        {
+            userInfo = userInfo.trim();
+            if ( userInfo.length() > 0 )
+            {
+                _userInfo = userInfo;
+            }
+        }
+    }
+
+    /**
+     * Returns the userInfo. If no host was previously set, returns
+     * null.
+     *
+     * @return userInfo
+     */
+    public String getUserInfo()
+    {
+        return _userInfo;
+    }
+
+    /**
+     * Sets the host.
+     *
+     * @param host host
+     */
+    public void setHost( String host )
+    {
+        _host = null;
+        if ( host != null )
+        {
+            host = host.trim();
+            if ( host.length() > 0 )
+            {
+                //
+                // Here's some very minimal support for IPv6 addresses.
+                // If the literal IPv6 address is not enclosed in square brackets
+                // then add them.
+                //
+                boolean needBrackets = ( ( host.indexOf( ':' ) >= 0 )
+                        && !host.startsWith( "[" )
+                        && !host.endsWith( "]" ) );
+
+                if ( needBrackets )
+                {
+                    _host = '[' + host + ']';
+                }
+                else
+                {
+                    _host = host;
+                }
+            }
+        }
+
+        if ( host == null )
+        {
+            setUserInfo( null );
+            setPort( UNDEFINED_PORT );
+        }
+    }
+
+    /**
+     * Returns the host. If no host was previously set, returns
+     * null.
+     *
+     * @return host
+     */
+    public String getHost()
+    {
+        return _host;
+    }
+
+    /**
+     * Sets the port.
+     *
+     * @param port port
+     */
+    public void setPort( int port )
+    {
+        assert ( port >= 0 && port <= 65535 ) || ( port == UNDEFINED_PORT )
+                 : "Invalid port" ;
+
+        if ( ( port > 65535 ) || ( port < 0 && port != UNDEFINED_PORT ) )
+        {
+             throw new IllegalArgumentException( "A port must be between 0 and 65535 or equal to "
+                                                 + UNDEFINED_PORT + ".");
+        }
+
+        _port = port;
+    }
+
+    /**
+     * Returns the port. If no port was previously set, returns
+     * null.
+     *
+     * @return port
+     */
+    public int getPort()
+    {
+        return _port;
+    }
+
+    /**
+     * Sets the path.
+     *
+     * @param path path
+     */
+    public void setPath( String path )
+    {
+        // Note that an empty path is OK
+        if ( path == null )
+        {
+            _path = null;
+            setQuery( null );
+            setFragment( null );
+        }
+        else
+        {
+            _path = path.trim();
+        }
+    }
+
+    /**
+     * Returns the path.
+     *
+     * @return path
+     */
+    public String getPath()
+    {
+        return _path;
+    }
+
+    /**
+     * Sets (and resets) the query string.
+     * This method assumes that the query is already encoded.
+     *
+     * @param query Query string
+     */
+    public void setQuery( String query )
+    {
+        _params = null;
+
+        if ( query == null || query.trim().length() == 0 ) { return; }
+
+        for ( StringTokenizer tok = new StringTokenizer( query.trim(), "&" ); tok.hasMoreElements(); )
+        {
+            String queryItem = tok.nextToken().trim();
+            int eq = queryItem.indexOf( '=' );
+            if ( eq != -1 )
+            {
+                addParameter( queryItem.substring( 0, eq ).trim() , queryItem.substring( eq + 1 ).trim(), true, null );
+            }
+            else
+            {
+                addParameter( queryItem, null, true, null );
+            }
+        }
+    }
+
+    /**
+     * Returns the query string (encoded).
+     *
+     * @param paramSeparator The string used to separate the parameters in the
+     *                       query. (&quot;&amp;&quot; or &quot;&amp;amp;&quot;)
+     * @return encoded query string.
+     */
+    public String getQuery( String paramSeparator )
+    {
+        assert paramSeparator != null;
+        if ( paramSeparator == null || paramSeparator.length() == 0 )
+        {
+            throw new IllegalArgumentException( "Parameter separator cannot be null or empty.");
+        }
+
+        if ( _params == null || _params.isEmpty() ) { return null; }
+
+        StringBuffer query = new StringBuffer( 64 );
+        boolean firstParam = true;
+        for ( String name : _params.keySet() )
+        {
+            for ( String value : _params.get( name ) )
+            {
+                if ( firstParam )
+                {
+                    firstParam = false;
+                }
+                else
+                {
+                    query.append( paramSeparator );
+                }
+
+                query.append( name );
+
+                if ( value != null ) { query.append( '=' ).append( value ); }
+            }
+        }
+
+        return query.toString();
+    }
+
+    /**
+     * Add a parameter for the query string.
+     * <p> If the encoded flag is true then this method assumes that
+     * the name and value do not need encoding or are already encoded
+     * correctly. Otherwise, it translates the name and value with the
+     * character encoding and adds them to the set of parameters for
+     * the query. </p>
+     * <p> Multiple values for the same parameter can be set by
+     * calling this method multiple times with the same name. </p>
+     *
+     * @param name  name
+     * @param value value
+     * @param encoded Flag indicating whether the names and values are
+     *                already encoded.
+     * @param encoding The name of a supported character encoding.
+     */
+    public void addParameter( String name, String value, boolean encoded, String encoding )
+    {
+        if ( name == null )
+        {
+            throw new IllegalArgumentException( "A parameter name may not be null." );
+        }
+
+        if ( !encoded )
+        {
+            name = encode( name, encoding );
+            value = encode( value, encoding );
+        }
+
+        if ( _params == null )
+        {
+            _params = new LinkedHashMap< String, ArrayList< String > >();
+        }
+
+        ArrayList< String > values = _params.get( name );
+        if ( values == null )
+        {
+            values = new ArrayList< String >();
+            _params.put( name, values );
+        }
+
+        values.add( value );
+    }
+
+    /**
+     * Add a separameter to the query string.
+     * <p> If the encoded flag is true then this method assumes that
+     * the name and value do not need encoding or are already encoded
+     * correctly. Otherwise, it translates the name and value with the
+     * character encoding and adds them to the set of parameters for
+     * the query. </p>
+     *
+     * @param newParams the map of new parameters to add to the URI
+     * @param encoded Flag indicating whether the names and values are
+     *                already encoded.
+     * @param encoding The name of a supported character encoding.
+     */
+    public void addParameters( Map newParams, boolean encoded, String encoding )
+    {
+        if ( newParams == null || newParams.size() == 0 )
+        {
+            throw new IllegalArgumentException( "Cannot add null or empty map of parameters." );
+        }
+
+        if ( _params == null )
+        {
+            _params = new LinkedHashMap< String, ArrayList< String > >();
+        }
+
+        Iterator keys = newParams.keySet().iterator();
+        while ( keys.hasNext() )
+        {
+            String name = ( String ) keys.next();
+            String encodedName = name;
+
+            if ( !encoded ) { encodedName = encode( name, encoding ); }
+
+            ArrayList< String > values = _params.get( encodedName );
+            if ( values == null )
+            {
+                values = new ArrayList< String >();
+                _params.put( encodedName, values );
+            }
+
+            Object newValue = newParams.get( name );
+            if ( newValue == null )
+            {
+                values.add( null );
+            }
+            else if ( newValue instanceof String )
+            {
+                addValue( values, ( String ) newValue, encoded, encoding );
+            }
+            else if ( newValue instanceof String[] )
+            {
+                String newValues[] = ( String[] ) newValue;
+                for ( int i = 0; i < newValues.length; i++ )
+                {
+                    addValue( values, newValues[i], encoded, encoding );
+                }
+            }
+            else if ( newValue instanceof List )
+            {
+                Iterator newValues = ( ( List ) newValue ).iterator();
+                while ( newValues.hasNext() )
+                {
+                    addValue( values, newValues.next().toString(), encoded, encoding );
+                }
+            }
+            else /* Convert other objects to a string */
+            {
+                addValue( values, newValue.toString(), encoded, encoding );
+            }
+        }
+    }
+
+    private static void addValue( ArrayList< String > list, String value, boolean encoded, String encoding )
+    {
+        if ( !encoded )
+        {
+            value = encode( value, encoding );
+        }
+
+        list.add( value );
+    }
+
+    /**
+     * Returns the value of the parameter. If the parameter has
+     * several values, returns the first value.
+     *
+     * @param name name of the parameter
+     * @return value of the given parameter name (or just the first in the list
+     *         if there are multiple values for the given name)
+     */
+    public String getParameter( String name )
+    {
+        if ( _params == null ) { return null; }
+
+        ArrayList< String > values = _params.get( name );
+        if ( values != null && values.size() > 0 )
+        {
+            return values.get( 0 );
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the values of the given parameter.
+     *
+     * @param name name of the parameter
+     * @return an unmodifable {@link java.util.List} of values for the given parameter name
+     */
+    public List< String > getParameters( String name )
+    {
+        if ( _params == null )
+        {
+            return Collections.unmodifiableList( new ArrayList< String >( 0 ) );
+        }
+        else
+        {
+            return Collections.unmodifiableList( _params.get( name ) );
+        }
+    }
+
+    /**
+     * Returns an unmodifiable Map of all parameters.
+     *
+     * @return an unmodifiable {@link java.util.Map} of names and values for all parameters
+     */
+    public Map< String, ArrayList< String > > getParameters()
+    {
+        return Collections.unmodifiableMap( _params );
+    }
+
+    /**
+     * Removes the given parameter.
+     *
+     * @param name name
+     */
+    public void removeParameter( String name )
+    {
+        if ( _params == null ) { return; }
+
+        _params.remove( name );
+    }
+
+    /**
+     * Sets the fragment.
+     *
+     * @param fragment fragment
+     */
+    public void setFragment( String fragment )
+    {
+        _fragment = null;
+        if ( fragment != null )
+        {
+            fragment = fragment.trim();
+            if ( fragment.length() > 0 )
+            {
+                _fragment = fragment;
+            }
+        }
+    }
+
+    /**
+     * Returns the fragment.
+     *
+     * @return fragment
+     */
+    public String getFragment()
+    {
+        return _fragment;
+    }
+
+    /**
+     * Tells whether or not this URI is absolute.
+     *
+     * <p> A URI is absolute if, and only if, it has a scheme component. </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this URI is absolute
+     */
+    public boolean isAbsolute() {
+        return getScheme() != null;
+    }
+
+    /**
+     * Returns a string form of this URL.
+     *
+     * @return string
+     */
+    @Override
+    public String toString()
+    {
+        return toString("&");
+    }
+
+    /**
+     * Returns a valid XML string form of this URL.
+     *
+     * @return string
+     */
+    public String toXMLString()
+    {
+        return toString("&amp;");
+    }
+
+    private String toString(String paramSeparator)
+    {
+        StringBuilder buf = new StringBuilder( 128 );
+
+        // Append the scheme
+        if ( getScheme() != null )
+        {
+            buf.append( getScheme() ).append( ':' );
+        }
+
+        // Append the user info, host and, port
+        if ( getHost() != null)
+        {
+            buf.append( "//" );
+
+            if ( getUserInfo() != null )
+            {
+                buf.append( getUserInfo() );
+                buf.append( '@' );
+            }
+
+            buf.append( getHost() );
+
+            if ( getPort() != UNDEFINED_PORT )
+            {
+                buf.append( ':' ).append( getPort() );
+            }
+        }
+
+        // Append the path.
+        if ( getPath() != null )
+        {
+            if ( isAbsolute() )
+            {
+                // absolute URI so
+                appendEnsureSeparator( buf, getPath() );
+            }
+            else
+            {
+                buf.append( getPath() );
+            }
+        }
+
+        // Append the parameters (the query)
+        if ( _params != null && _params.size() > 0 )
+        {
+            buf.append( '?' );
+            buf.append( getQuery( paramSeparator ) );
+        }
+
+        // Append the fragment
+        if ( getFragment() != null && getFragment().length() > 0 )
+        {
+            buf.append( '#' ).append( getFragment() );
+        }
+
+        String url = buf.toString();
+
+        return url;
+    }
+
+    private static void appendEnsureSeparator( StringBuilder buf, String token )
+    {
+        if ( token != null && token.length() > 0 )
+        {
+            if ( buf.charAt( buf.length() - 1 ) != '/' && token.charAt( 0 ) != '/' )
+            {
+                buf.append( '/' );
+            }
+            if ( buf.charAt( buf.length() - 1 ) == '/' && token.charAt( 0 ) == '/' )
+            {
+                token = token.substring( 1 );
+            }
+            buf.append( token );
+        }
+    }
+
+    // @struts : from org.apache.struts.util.RequestUtils RC 1.1
+    // This has been modified from the strut to assume 1.4 because we ship
+    // with that.
+    public static String encode( String url, String encoding )
+    {
+        String encodedURL = null;
+        try
+        {
+            encodedURL = URLEncoder.encode( url, encoding );
+        }
+        catch ( java.io.UnsupportedEncodingException e )
+        {
+            // try utf-8 as a default encoding
+            try
+            {
+                encodedURL = URLEncoder.encode( url, "UTF-8" );
+            }
+            catch ( java.io.UnsupportedEncodingException ignore )
+            {
+            }
+        }
+        return encodedURL;
+    }
+
+    /**
+     * Determines if the passed-in Object is equivalent to this MutableURI.
+     *
+     * @param object the Object to test for equality.
+     * @return true if object is a MutableURI with all values equal to this
+     *         MutableURI, false otherwise
+     */
+    @Override
+    public boolean equals( Object object )
+    {
+        if ( object == this ) { return true; }
+
+        if ( object == null || !object.getClass().equals( this.getClass() ) )
+        {
+            return false;
+        }
+
+        MutableURI testURI = ( MutableURI ) object;
+
+        if ( ( _scheme == testURI.getScheme() || ( _scheme != null && _scheme.equalsIgnoreCase( testURI.getScheme() ) ) ) &&
+                ( _userInfo == testURI.getUserInfo() || ( _userInfo != null && _userInfo.equals( testURI.getUserInfo() ) ) ) &&
+                ( _host == testURI.getHost() || ( _host != null && _host.equalsIgnoreCase( testURI.getHost() ) ) ) &&
+                _port == testURI.getPort() &&
+                ( _path == testURI.getPath() || ( _path != null && _path.equals( testURI.getPath() ) ) ) &&
+                ( _fragment == testURI.getFragment() || ( _fragment != null && _fragment.equals( testURI.getFragment() ) ) ) )
+        {
+            Map< String, ArrayList< String > > testParams = testURI.getParameters();
+
+            if ( ( _params == null && testParams == null ) ||
+                    ( _params != null && _params.equals( testParams ) ) ) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns a hash code value for the object.
+     * <p> Implemented in conjunction with equals() override. </p>
+     * <p> This is a mutable class implying that we're basing the hash
+     * code on the member data that can change. Therefor it's important
+     * not to use this class as a key in a hashtable as it would still
+     * appear with an enumeration but not when calling contains.
+     * I.E. The object could get lost in the hashtable. A call for the
+     * hashcode would return a different value than when it was first
+     * placed in the hashtable. </p>
+     *
+     * <p> With this in mind, we simply return the same value to support
+     * the rules of equality. </p>
+     *
+     * @return a hash code value for this object.
+     */
+    @Override
+    public int hashCode()
+    {
+        return 0;
+    }
+}
+

Property changes on: netui/src/util/org/apache/beehive/netui/core/urls/MutableURI.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: netui/src/util/org/apache/beehive/netui/util/netui.properties
===================================================================
--- netui/src/util/org/apache/beehive/netui/util/netui.properties	(revision 109213)
+++ netui/src/util/org/apache/beehive/netui/util/netui.properties	(working copy)
@@ -56,7 +56,7 @@
 Tags_FormattableParentRequired=Format tags require a parent that is Formattable.
 Tags_EmptyStringFormatException=The value to be formatted by the FormatNumber cannot be an empty string or null.
 Tags_BadParameterType=Parameter {0} cannot be a Map.
-Tags_MalformedURLException=MalformedURLException occured.
+Tags_URISyntaxException=URISyntaxException occured.
 Tags_ExpressionEvaluationFailure=Expression evaluation failed for ''{0}''.
 Tags_IsExpressionFailure=The string ''{0}'' is not an expression : {1}
 Tags_ExpressionEvaluationException=Caught exception evaluating expression ''{0}'': {1}.
@@ -92,6 +92,10 @@
 Tags_Anchor_ForwardError=URL Exception: {0}.  This may be caused because an ActionMapping cannot be found (the page was not accessed through an Action).
 Tags_Form_URLException=The action ''{0}'' for the Form is malformed: {1}
 Tags_Anchor_InvalidAnchorURI=The Anchor URI is invalid; it must be exactly one of {0}
+Tags_Image_URLException=The src ''{0}'' for the Image is malformed: {1}
+Tags_Rollover_Image_URLException=The src ''{0}'' for the rollover Image is malformed: {1}
+Tags_RewriteURL_URLException=The url ''{0}'' for the RewriteURL is malformed: {1}
+Tags_Tree_Node_URLException=The action ''{0}'' for the tree node is malformed: {1}
 Tags_HRefEvalNull=The href expression "{0}" resolved to null.
 Tags_formatDate_Type_Error=The type "{0}" may not be formatted by a formatDate tag.
 Tags_LocaleRequiresLanguage=If you set a country, you must also set a language when specifying a local, defaulting to Locale of Request.  The country set was "{0}"
Index: netui/src/util/org/apache/beehive/netui/util/cache/ServletContextCache.java
===================================================================
--- netui/src/util/org/apache/beehive/netui/util/cache/ServletContextCache.java	(revision 109213)
+++ netui/src/util/org/apache/beehive/netui/util/cache/ServletContextCache.java	(working copy)
@@ -1,42 +0,0 @@
-/*
- * Copyright 2004 The Apache Software Foundation.
- *
- * Licensed 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.
- *
- * $Header:$
- */
-package org.apache.beehive.netui.util.cache;
-
-import javax.servlet.ServletContext;
-
-public abstract class ServletContextCache
-{
-    protected void initInternal( ServletContext servletContext )
-    {
-        servletContext.setAttribute( getKey(), this );
-    }
-    
-    protected static ServletContextCache get( ServletContext servletContext, String key )
-    {
-        ServletContextCache cache = ( ServletContextCache ) servletContext.getAttribute( key );
-        
-        if ( cache == null )
-        {
-            throw new IllegalStateException( "Cache " + key + " was not initialized in the ServletContext." );
-        }
-        
-        return cache;
-    }
-    
-    protected abstract String getKey();
-}
