Author: rich Date: Tue Nov 30 23:13:42 2004 New Revision: 109310 URL: http://svn.apache.org/viewcvs?view=rev&rev=109310 Log: Missed these files in my last checkin...
Added: incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/ incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/ incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/MutableURI.java (contents, props changed) incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/URLRewriter.java (contents, props changed) incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/URLRewriterService.java (contents, props changed) Added: incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/MutableURI.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/MutableURI.java?view=auto&rev=109310 ============================================================================== --- (empty file) +++ incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/MutableURI.java Tue Nov 30 23:13:42 2004 @@ -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 + * [EMAIL PROTECTED] #MutableURI(java.net.URI)} constructor with + * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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. ("&" or "&amp;") + * @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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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("&"); + } + + 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; + } +} + Added: incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/URLRewriter.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/URLRewriter.java?view=auto&rev=109310 ============================================================================== --- (empty file) +++ incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/URLRewriter.java Tue Nov 30 23:13:42 2004 @@ -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 [EMAIL PROTECTED] #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; + } +} Added: incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/URLRewriterService.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/URLRewriterService.java?view=auto&rev=109310 ============================================================================== --- (empty file) +++ incubator/beehive/trunk/netui/src/util/org/apache/beehive/netui/core/urls/URLRewriterService.java Tue Nov 30 23:13:42 2004 @@ -0,0 +1,244 @@ +/* + * 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 org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils; + +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 = getRewriters( request ); + + 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 = getRewriters( request ); + + 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 + * [EMAIL PROTECTED] #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( getRewriters( request ) ); + } + + /** + * 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 [EMAIL PROTECTED] #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 = getRewriters( request ); + + 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 + * [EMAIL PROTECTED] #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 = getRewriters( request ); + + 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 ); } + } + } + + private static ArrayList< URLRewriter > getRewriters( ServletRequest request ) + { + return ( ArrayList< URLRewriter > ) ScopedServletUtils.getScopedRequestAttribute( URL_REWRITERS_KEY, request ); + } + + /** + * 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 = getRewriters( request ); + + 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 = getRewriters( request ); + + if ( rewriters != null ) + { + for ( URLRewriter rewriter : rewriters ) + { + if ( !rewriter.allowParamsOnFormAction( servletContext, request ) ) { return false; } + } + } + + return true; + } +}
