jtaylor 02/04/16 09:49:38
Modified: src/java/org/apache/turbine DynamicURI.java
Log:
No longer uses java.net.URLEncoder, use StringBuffer more effectively. A couple
of times faster and fewer object creations. There is probably room for more
optimization, any improvement is probably worthwhile since this is a real
hotspot.
Revision Changes Path
1.6 +285 -194 jakarta-turbine-3/src/java/org/apache/turbine/DynamicURI.java
Index: DynamicURI.java
===================================================================
RCS file: /home/cvs/jakarta-turbine-3/src/java/org/apache/turbine/DynamicURI.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- DynamicURI.java 5 Mar 2002 01:32:34 -0000 1.5
+++ DynamicURI.java 16 Apr 2002 16:49:38 -0000 1.6
@@ -54,14 +54,11 @@
* <http://www.apache.org/>.
*/
-import org.apache.turbine.RunData;
-import java.net.URLEncoder;
+import java.util.BitSet;
import java.util.Enumeration;
import java.util.Vector;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.turbine.Turbine;
-import org.apache.turbine.ParameterParser;
/**
* This creates a Dynamic URI for use within the Turbine system
@@ -84,7 +81,8 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Jon S. Stevens</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Jason van Zyl</a>
* @author <a href="mailto:[EMAIL PROTECTED]">John McNally</a>
- * @version $Id: DynamicURI.java,v 1.5 2002/03/05 01:32:34 jon Exp $
+ * @author <a href="mailto:[EMAIL PROTECTED]">James Taylor</a>
+ * @version $Id: DynamicURI.java,v 1.6 2002/04/16 16:49:38 jtaylor Exp $
*/
public class DynamicURI
{
@@ -141,7 +139,7 @@
*
* @param data A Turbine RunData object.
*/
- public DynamicURI( RunData data )
+ public DynamicURI(RunData data)
{
init(data);
}
@@ -160,8 +158,8 @@
* @param data A Turbine RunData object.
* @param screen A String with the name of a screen.
*/
- public DynamicURI( RunData data,
- String screen )
+ public DynamicURI(RunData data,
+ String screen)
{
this(data);
setScreen(screen);
@@ -174,11 +172,11 @@
* @param screen A String with the name of a screen.
* @param action A String with the name of an action.
*/
- public DynamicURI( RunData data,
- String screen,
- String action )
+ public DynamicURI(RunData data,
+ String screen,
+ String action)
{
- this( data, screen );
+ this(data, screen);
setAction(action);
}
@@ -190,12 +188,12 @@
* @param action A String with the name of an action.
* @param redirect True if it should redirect.
*/
- public DynamicURI( RunData data,
- String screen,
- String action,
- boolean redirect )
+ public DynamicURI(RunData data,
+ String screen,
+ String action,
+ boolean redirect)
{
- this( data, screen, action );
+ this(data, screen, action);
this.redirect = redirect;
}
@@ -206,11 +204,11 @@
* @param screen A String with the name of a screen.
* @param redirect True if it should redirect.
*/
- public DynamicURI( RunData data,
- String screen,
- boolean redirect )
+ public DynamicURI(RunData data,
+ String screen,
+ boolean redirect)
{
- this( data, screen );
+ this(data, screen);
this.redirect = redirect;
}
@@ -220,19 +218,19 @@
* @param data A Turbine RunData object.
* @param redirect True if it should redirect.
*/
- public DynamicURI( RunData data,
- boolean redirect )
+ public DynamicURI(RunData data,
+ boolean redirect)
{
- this( data );
+ this(data);
this.redirect = redirect;
}
/**
* Initialize with a RunData object
*
- * @param RunData
+ * @param data
*/
- public void init( RunData data )
+ public void init(RunData data)
{
this.data = data;
this.res = data.getResponse();
@@ -250,23 +248,23 @@
* @param name A String with the name to add.
* @param value A String with the value to add.
*/
- protected void add ( int type,
+ protected void add(int type,
String name,
- String value )
+ String value)
{
Object[] tmp = new Object[2];
tmp[0] = (Object) data.getParameters().convertAndTrim(name);
tmp[1] = (Object) value;
switch (type)
{
- case PATH_INFO:
- this.pathInfo.addElement ( tmp );
- this.hasPathInfo = true;
- break;
- case QUERY_DATA:
- this.queryData.addElement ( tmp );
- this.hasQueryData = true;
- break;
+ case PATH_INFO:
+ this.pathInfo.addElement(tmp);
+ this.hasPathInfo = true;
+ break;
+ case QUERY_DATA:
+ this.queryData.addElement(tmp);
+ this.hasQueryData = true;
+ break;
}
}
@@ -283,21 +281,21 @@
* @param type Type (P or Q) of insertion.
* @param pp A ParameterParser.
*/
- protected void add( int type,
- ParameterParser pp )
+ protected void add(int type,
+ ParameterParser pp)
{
Enumeration e = pp.keys();
- while ( e.hasMoreElements() )
+ while (e.hasMoreElements())
{
- String key = (String)e.nextElement();
- if ( !key.equalsIgnoreCase(Turbine.ACTION) &&
- !key.equalsIgnoreCase(Turbine.SCREEN) &&
- !key.equalsIgnoreCase(Turbine.TEMPLATE) )
+ String key = (String) e.nextElement();
+ if (!key.equalsIgnoreCase(Turbine.ACTION) &&
+ !key.equalsIgnoreCase(Turbine.SCREEN) &&
+ !key.equalsIgnoreCase(Turbine.TEMPLATE))
{
String[] values = pp.getStrings(key);
- for ( int i=0; i<values.length; i++ )
+ for (int i = 0; i < values.length; i++)
{
- add( type, key, values[i] );
+ add(type, key, values[i]);
}
}
}
@@ -309,9 +307,9 @@
* @param name A String with the name to add.
* @param value An Object with the value to add.
*/
- public DynamicURI addPathInfo ( String name, Object value )
+ public DynamicURI addPathInfo(String name, Object value)
{
- add ( PATH_INFO, name, value.toString() );
+ add(PATH_INFO, name, value.toString());
return this;
}
@@ -321,9 +319,9 @@
* @param name A String with the name to add.
* @param value A String with the value to add.
*/
- public DynamicURI addPathInfo ( String name, String value )
+ public DynamicURI addPathInfo(String name, String value)
{
- add ( PATH_INFO, name, value );
+ add(PATH_INFO, name, value);
return this;
}
@@ -333,9 +331,9 @@
* @param name A String with the name to add.
* @param value A double with the value to add.
*/
- public DynamicURI addPathInfo ( String name, double value )
+ public DynamicURI addPathInfo(String name, double value)
{
- add ( PATH_INFO, name, Double.toString(value) );
+ add(PATH_INFO, name, Double.toString(value));
return this;
}
@@ -345,9 +343,9 @@
* @param name A String with the name to add.
* @param value An int with the value to add.
*/
- public DynamicURI addPathInfo ( String name, int value )
+ public DynamicURI addPathInfo(String name, int value)
{
- add ( PATH_INFO, name, new Integer(value).toString() );
+ add(PATH_INFO, name, new Integer(value).toString());
return this;
}
@@ -357,9 +355,9 @@
* @param name A String with the name to add.
* @param value A long with the value to add.
*/
- public DynamicURI addPathInfo ( String name, long value )
+ public DynamicURI addPathInfo(String name, long value)
{
- add ( PATH_INFO, name, new Long(value).toString() );
+ add(PATH_INFO, name, new Long(value).toString());
return this;
}
@@ -369,9 +367,9 @@
*
* @param pp A ParameterParser.
*/
- public DynamicURI addPathInfo ( ParameterParser pp )
+ public DynamicURI addPathInfo(ParameterParser pp)
{
- add ( PATH_INFO, pp );
+ add(PATH_INFO, pp);
return this;
}
@@ -381,9 +379,9 @@
* @param name A String with the name to add.
* @param value An Object with the value to add.
*/
- public DynamicURI addQueryData ( String name, Object value )
+ public DynamicURI addQueryData(String name, Object value)
{
- add ( QUERY_DATA, name, value.toString() );
+ add(QUERY_DATA, name, value.toString());
return this;
}
@@ -393,9 +391,9 @@
* @param name A String with the name to add.
* @param value A String with the value to add.
*/
- public DynamicURI addQueryData ( String name, String value )
+ public DynamicURI addQueryData(String name, String value)
{
- add ( QUERY_DATA, name, value );
+ add(QUERY_DATA, name, value);
return this;
}
@@ -405,9 +403,9 @@
* @param name A String with the name to add.
* @param value A double with the value to add.
*/
- public DynamicURI addQueryData ( String name, double value )
+ public DynamicURI addQueryData(String name, double value)
{
- add ( QUERY_DATA, name, Double.toString(value) );
+ add(QUERY_DATA, name, Double.toString(value));
return this;
}
@@ -417,9 +415,9 @@
* @param name A String with the name to add.
* @param value An int with the value to add.
*/
- public DynamicURI addQueryData ( String name, int value )
+ public DynamicURI addQueryData(String name, int value)
{
- add ( QUERY_DATA, name, new Integer(value).toString() );
+ add(QUERY_DATA, name, new Integer(value).toString());
return this;
}
@@ -429,9 +427,9 @@
* @param name A String with the name to add.
* @param value A long with the value to add.
*/
- public DynamicURI addQueryData ( String name, long value )
+ public DynamicURI addQueryData(String name, long value)
{
- add ( QUERY_DATA, name, new Long(value).toString() );
+ add(QUERY_DATA, name, new Long(value).toString());
return this;
}
@@ -441,9 +439,9 @@
*
* @param pp A ParameterParser.
*/
- public DynamicURI addQueryData ( ParameterParser pp )
+ public DynamicURI addQueryData(ParameterParser pp)
{
- add ( QUERY_DATA, pp );
+ add(QUERY_DATA, pp);
return this;
}
@@ -463,7 +461,7 @@
* @param name A String with the name for the anchor.
* @return The anchor as a <A HREF="">name</A>.
*/
- public String getA( String name )
+ public String getA(String name)
{
return new StringBuffer("<a href=\"")
.append(this.toString())
@@ -479,7 +477,7 @@
*
* @return A String with the script name.
*/
- public String getScriptName ()
+ public String getScriptName()
{
return data.getScriptName();
}
@@ -489,7 +487,7 @@
*
* @return A String with the server name.
*/
- public String getServerName ()
+ public String getServerName()
{
return data.getServerName();
}
@@ -499,7 +497,7 @@
*
* @return A String with the server port.
*/
- public int getServerPort ()
+ public int getServerPort()
{
return data.getServerPort();
}
@@ -533,48 +531,48 @@
* @param type Type (P or Q) of removal.
* @param name A String with the name to be removed.
*/
- protected void remove ( int type,
- String name )
+ protected void remove(int type,
+ String name)
{
try
{
switch (type)
{
- case PATH_INFO:
- for (Enumeration e = this.pathInfo.elements() ;
- e.hasMoreElements() ;)
- {
- Object[] tmp = (Object[]) e.nextElement();
- if ( data.getParameters().convertAndTrim(name)
- .equals ( (String)tmp[0] ) )
+ case PATH_INFO:
+ for (Enumeration e = this.pathInfo.elements();
+ e.hasMoreElements();)
{
- this.pathInfo.removeElement ( tmp );
+ Object[] tmp = (Object[]) e.nextElement();
+ if (data.getParameters().convertAndTrim(name)
+ .equals((String) tmp[0]))
+ {
+ this.pathInfo.removeElement(tmp);
+ }
}
- }
- if ( hasPathInfo && this.pathInfo.size() == 0 )
- {
- this.hasPathInfo = false;
- }
- break;
- case QUERY_DATA:
- for (Enumeration e = this.queryData.elements() ;
- e.hasMoreElements() ;)
- {
- Object[] tmp = (Object[]) e.nextElement();
- if ( data.getParameters().convertAndTrim(name)
- .equals ( (String)tmp[0] ) )
+ if (hasPathInfo && this.pathInfo.size() == 0)
{
- this.queryData.removeElement ( tmp );
+ this.hasPathInfo = false;
}
- }
- if ( hasQueryData && this.queryData.size() == 0 )
- {
- this.hasQueryData = false;
- }
- break;
+ break;
+ case QUERY_DATA:
+ for (Enumeration e = this.queryData.elements();
+ e.hasMoreElements();)
+ {
+ Object[] tmp = (Object[]) e.nextElement();
+ if (data.getParameters().convertAndTrim(name)
+ .equals((String) tmp[0]))
+ {
+ this.queryData.removeElement(tmp);
+ }
+ }
+ if (hasQueryData && this.queryData.size() == 0)
+ {
+ this.hasQueryData = false;
+ }
+ break;
}
}
- catch ( Exception e )
+ catch (Exception e)
{
}
}
@@ -582,7 +580,7 @@
/**
* Removes all the path info elements.
*/
- public void removePathInfo ()
+ public void removePathInfo()
{
this.pathInfo.removeAllElements();
this.hasPathInfo = false;
@@ -593,15 +591,15 @@
*
* @param name A String with the name to be removed.
*/
- public void removePathInfo ( String name )
+ public void removePathInfo(String name)
{
- remove ( PATH_INFO, name );
+ remove(PATH_INFO, name);
}
/**
* Removes all the query string elements.
*/
- public void removeQueryData ()
+ public void removeQueryData()
{
this.queryData.removeAllElements();
this.hasQueryData = false;
@@ -612,9 +610,9 @@
*
* @param name A String with the name to be removed.
*/
- public void removeQueryData ( String name )
+ public void removeQueryData(String name)
{
- remove ( QUERY_DATA, name );
+ remove(QUERY_DATA, name);
}
/**
@@ -624,36 +622,39 @@
* @param data A Vector of key/value arrays.
* @return A String with the URL encoded data.
*/
- protected String renderPathInfo ( Vector data )
+ protected String renderPathInfo(Vector data)
{
- String key = null;
- String value = null;
- String tmp = null;
StringBuffer out = new StringBuffer();
+
+ renderPathInfo(data, out);
+
+ return out.toString();
+ }
+
+ /**
+ * This method takes a Vector of key/value arrays and writes it to the
+ * supplied StringBuffer as encoded path info.
+ *
+ * @param data A Vector of key/value arrays.
+ * @param out Buffer to which encoded path info is written
+ */
+ protected void renderPathInfo(Vector data, StringBuffer out)
+ {
Enumeration keys = data.elements();
- while(keys.hasMoreElements())
+
+ while (keys.hasMoreElements())
{
Object[] stuff = (Object[]) keys.nextElement();
- key = URLEncoder.encode((String)stuff[0]);
- tmp = (String) stuff[1];
- if (tmp == null || tmp.length() == 0)
- {
- value = "null";
- }
- else
- {
- value = URLEncoder.encode(tmp);
- }
if (out.length() > 0)
{
- out.append ( "/" );
+ out.append("/");
}
- out.append ( key );
- out.append ( "/" );
- out.append ( value );
+
+ writeEncoded((String) stuff[0], out);
+ out.append("/");
+ writeEncoded((String) stuff[1], out);
}
- return out.toString();
}
/**
@@ -663,36 +664,39 @@
* @param data A Vector of key/value arrays.
* @return A String with the URL encoded data.
*/
- protected String renderQueryString ( Vector data )
+ protected String renderQueryString(Vector data)
{
- String key = null;
- String value = null;
- String tmp = null;
StringBuffer out = new StringBuffer();
+
+ renderQueryString(data, out);
+
+ return out.toString();
+ }
+
+ /**
+ * This method takes a Vector of key/value arrays and writes it to the
+ * provided StringBuffer in encoded query string format.
+ *
+ * @param data A Vector of key/value arrays.
+ * @param out Buffer to which encoded query string is written.
+ */
+ protected void renderQueryString(Vector data, StringBuffer out)
+ {
Enumeration keys = data.elements();
- while(keys.hasMoreElements())
+
+ while (keys.hasMoreElements())
{
Object[] stuff = (Object[]) keys.nextElement();
- key = URLEncoder.encode((String) stuff[0]);
- tmp = (String) stuff[1];
- if (tmp == null || tmp.length() == 0)
- {
- value = "null";
- }
- else
- {
- value = URLEncoder.encode(tmp);
- }
- if ( out.length() > 0)
+ if (out.length() > 0)
{
- out.append ( "&" );
+ out.append("&");
}
- out.append ( key );
- out.append ( "=" );
- out.append ( value );
+
+ writeEncoded((String) stuff[0], out);
+ out.append("=");
+ writeEncoded((String) stuff[1], out);
}
- return out.toString();
}
/**
@@ -704,9 +708,9 @@
* @param action A String with the action value.
* @return A DynamicURI (self).
*/
- public DynamicURI setAction ( String action )
+ public DynamicURI setAction(String action)
{
- add ( PATH_INFO, Turbine.ACTION, action );
+ add(PATH_INFO, Turbine.ACTION, action);
return this;
}
@@ -716,12 +720,12 @@
* <p>By default it adds the information to the path_info instead
* of the query data.
*
- * @param action A String with the screen value.
+ * @param screen A String with the screen value.
* @return A DynamicURI (self).
*/
- public DynamicURI setScreen ( String screen )
+ public DynamicURI setScreen(String screen)
{
- add ( PATH_INFO, Turbine.SCREEN, screen );
+ add(PATH_INFO, Turbine.SCREEN, screen);
return this;
}
@@ -760,7 +764,7 @@
* if true, the scheme, domain, and port will not be included in the
* String representation of this uri..
*
- * @param b a <code>boolean</code>
+ * @param b a <code>boolean</code>
* @return a <code>DynamicURI</code> (self)
*/
public DynamicURI setRelative(boolean b)
@@ -783,7 +787,7 @@
/**
* Can be used to disable url rewriting.
*
- * @param b a <code>boolean</code>
+ * @param b a <code>boolean</code>
* @return a <code>DynamicURI</code> (self)
*/
public DynamicURI setEncodeUrl(boolean b)
@@ -825,44 +829,44 @@
public String toString()
{
StringBuffer output = new StringBuffer();
- if (!isRelative)
+ if (!isRelative())
{
- output.append ( getServerScheme() );
- output.append ( "://" );
- output.append ( getServerName() );
- if ( (getServerScheme().equals(HTTP) && getServerPort() != 80)
- || (getServerScheme().equals(HTTPS) && getServerPort() != 443)
- )
+ output.append(getServerScheme());
+ output.append("://");
+ output.append(getServerName());
+ if ((getServerScheme().equals(HTTP) && getServerPort() != 80)
+ || (getServerScheme().equals(HTTPS) && getServerPort() != 443))
{
- output.append (':');
- output.append ( getServerPort() );
+ output.append(':');
+ output.append(getServerPort());
}
}
- output.append ( getScriptName() );
- if ( this.hasPathInfo )
+ output.append(getScriptName());
+
+ if (this.hasPathInfo)
{
- output.append ('/');
- output.append ( renderPathInfo(this.pathInfo) );
+ output.append('/');
+ renderPathInfo(this.pathInfo, output);
}
- if ( this.hasQueryData )
+ if (this.hasQueryData)
{
- output.append ('?');
- output.append ( renderQueryString(this.queryData) );
+ output.append('?');
+ renderQueryString(this.queryData, output);
}
// There seems to be a bug in Apache JServ 1.0 where the
// session id is not appended to the end of the url when a
// cookie has not been set.
- if ( this.res != null && encodeUrl )
+ if (this.res != null && isEncodeUrl())
{
- if ( this.redirect )
+ if (this.redirect)
{
- return res.encodeRedirectURL (output.toString());
+ return res.encodeRedirectURL(output.toString());
}
else
{
- return res.encodeURL (output.toString());
+ return res.encodeURL(output.toString());
}
}
else
@@ -894,7 +898,7 @@
* would not.
*
* @param data A Turbine RunData object.
- * @param boolean to determine absolute vs. relative links.
+ * @param isAbsolute to determine absolute vs. relative links.
* @return A String with the URL representing the RunData.
*/
public static String toString(RunData data, boolean isAbsolute)
@@ -904,32 +908,119 @@
if (isAbsolute)
{
- output.append (data.getServerScheme());
- output.append ( "://" );
- output.append (data.getServerName());
-
- if ( (data.getServerScheme().equals(HTTP) &&
- data.getServerPort() != 80) ||
- (data.getServerScheme().equals(HTTPS) &&
- data.getServerPort() != 443) )
+ output.append(data.getServerScheme());
+ output.append("://");
+ output.append(data.getServerName());
+
+ if ((data.getServerScheme().equals(HTTP) &&
+ data.getServerPort() != 80) ||
+ (data.getServerScheme().equals(HTTPS) &&
+ data.getServerPort() != 443))
{
- output.append (':');
- output.append (data.getServerPort());
+ output.append(':');
+ output.append(data.getServerPort());
}
}
- output.append (data.getScriptName());
+ output.append(data.getScriptName());
- if ( request.getPathInfo() != null )
+ if (request.getPathInfo() != null)
{
output.append(request.getPathInfo());
}
- if ( request.getQueryString() != null )
+ if (request.getQueryString() != null)
{
- output.append ('?');
- output.append (request.getQueryString());
+ output.append('?');
+ output.append(request.getQueryString());
}
return output.toString();
+ }
+
+ /**
+ * URL encodes <code>in</code> and writes it to <code>out</code>. If the
+ * string is null, 'null' will be written.
+ *
+ * @param in String to write.
+ * @param out Buffer to write to.
+ */
+ protected static final void writeEncoded(String in, StringBuffer out)
+ {
+ if (in == null || in.length() == 0)
+ {
+ out.append("null");
+ return;
+ }
+
+ // This is the most expensive operation:
+
+ byte[] bytes = in.getBytes();
+
+ for (int i = 0; i < bytes.length; i++)
+ {
+ char c = (char) bytes[i];
+
+ if ( safe[ c ] )
+ {
+ out.append(c);
+ }
+ else if (c == ' ')
+ {
+ out.append('+');
+ }
+ else
+ {
+ byte toEscape = bytes[i];
+ out.append('%');
+ int low = (int) (toEscape & 0x0f);
+ int high = (int) ((toEscape & 0xf0) >> 4);
+ out.append(hexadecimal[high]);
+ out.append(hexadecimal[low]);
+ }
+ }
+ }
+
+ // ------------------------------------- private constants for url encoding
+
+ /**
+ * Array mapping hexadecimal values to the corresponding ASCII characters.
+ */
+ private static final char[] hexadecimal =
+ {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+ /**
+ * Characters that need not be encoded. This is much faster than using a
+ * BitSet, and for such a small array the space cost seems justified.
+ */
+ private static boolean[] safe = new boolean[ 255 ];
+
+ /** Static initializer for {@link #safe} */
+ static
+ {
+ for (int i = 'a'; i <= 'z'; i++)
+ {
+ safe[ i ] = true;
+ }
+ for (int i = 'A'; i <= 'Z'; i++)
+ {
+ safe[ i ] = true;
+ }
+ for (int i = '0'; i <= '9'; i++)
+ {
+ safe[ i ] = true;
+ }
+
+ safe['-'] = true;
+ safe['_'] = true;
+ safe['.'] = true;
+ safe['!'] = true;
+ safe['~'] = true;
+ safe['*'] = true;
+ safe['\''] = true;
+ safe['('] = true;
+ safe[')'] = true;
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>