Sorry for the reformatting folks -- it is unintentional -- all the meat is down at the end.
On Tue, 2002-04-16 at 12:49, [EMAIL PROTECTED] wrote: > 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]> > > -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
