UrlEncoded fix from Jürg Lehni to use JDK 1.4 methods if available and

switch back to JDK 1.3 methods otherwise. Methods renamed to encode()
and decode(), respectively.
This commit is contained in:
hns 2004-09-15 11:15:44 +00:00
parent fad94431e0
commit 71aeea336e
5 changed files with 97 additions and 34 deletions

View file

@ -1070,7 +1070,7 @@ public final class Application implements IPathElement, Runnable {
composeHref(elem, b, 0);
if (actionName != null) {
b.append(UrlEncoded.smartEncode(actionName, charset));
b.append(UrlEncoded.encode(actionName, charset));
}
return b.toString();
@ -1098,7 +1098,7 @@ public final class Application implements IPathElement, Runnable {
// append ourselves
String ename = getElementName(elem);
if (ename != null) {
b.append(UrlEncoded.smartEncode(ename, charset));
b.append(UrlEncoded.encode(ename, charset));
b.append("/");
}
}

View file

@ -123,12 +123,12 @@ public class RequestPath {
}
for (int i=start; i<ids.size(); i++) {
buffer.append(UrlEncoded.smartEncode(ids.get(i).toString(), app.charset));
buffer.append(UrlEncoded.encode(ids.get(i).toString(), app.charset));
buffer.append("/");
}
if (action != null) {
buffer.append(UrlEncoded.smartEncode(action, app.charset));
buffer.append(UrlEncoded.encode(action, app.charset));
}
return buffer.toString();

View file

@ -657,7 +657,7 @@ public final class Skin {
break;
case ENCODE_URL:
buffer.append(UrlEncoded.smartEncode(text, app.charset));
buffer.append(UrlEncoded.encode(text, app.charset));
break;

View file

@ -737,7 +737,7 @@ public abstract class AbstractServletClient extends HttpServlet {
pathbuffer.append('/');
}
pathbuffer.append(UrlEncoded.smartDecode(token, defaultEncoding));
pathbuffer.append(UrlEncoded.decode(token, defaultEncoding));
}
// append trailing "/" if it is contained in original URI

View file

@ -16,43 +16,84 @@
package helma.util;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.net.URLCodec;
import java.io.UnsupportedEncodingException;
import java.util.BitSet;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* A subclass of Jakarta Commons Codec URLCodec that offers
* lazy encode/decode methods that only returns a new String
* if actual work had to be done for encoding/decoding.
* This is because URLCodec is a bit inefficient (e.g. it
* preallocates buffers and stuff for each call to encode/decode),
* and we call it often with short strings that don't need encoding.
* A proxy to java.net.URLEncoder which only encodes when there is actual work
* to do. This is necessary because URLEncoder is quite inefficient (e.g. it
* preallocates buffers and stuff), and we call it often with short string that
* don't need encoding.
*/
public final class UrlEncoded extends URLCodec {
public final class UrlEncoded {
// Java 1.4 encode method to use instead of deprecated 1.3 version.
private static Method encode = null;
private static Method decode = null;
// Initialize the encode and decode variables with the 1.4 methods if
// available.
// this code was adapted from org.apache.struts.utils.RequestUtils and
// org.apache.velocity.tools.view.tools.LinkTool
static {
try {
// get version of encode method with two String args
Class[] args = new Class[] { String.class, String.class };
encode = URLEncoder.class.getMethod("encode", args);
decode = URLDecoder.class.getMethod("decode", args);
} catch (NoSuchMethodException e) {
System.err.println("UrlEncoded: Can't find JDK 1.4 encode and decode methods. Using JDK 1.3 versions.");
}
}
/**
* URL-encode a string using the given encoding, or return it
* unchanged if no encoding was necessary.
*
* @param str The string to be URL-encoded
* URL-encodes a string using the given encoding, or return it unchanged if
* no encoding was necessary.
* This method uses the new URLEncoder.encode() method from java 1.4 if
* available, otherwise the old deprecated version is used. Reflection is
* used to find the appropriate method; if the reflection operations throw
* exceptions other than UnsupportedEncodingException, it returns the url
* encoded with the old URLEncoder.encode() method.
*
* @param str The string to be URL-encoded
* @param encoding the encoding to use
* @return the URL-encoded string, or str if no encoding necessary
*/
public static String smartEncode(String str, String encoding)
throws UnsupportedEncodingException {
public static String encode(String str, String encoding)
throws UnsupportedEncodingException {
int l = str.length();
boolean needsSpaceEncoding = false;
BitSet urlsafe = WWW_FORM_URL;
System.out.println(str);
for (int i = 0; i < l; i++) {
char c = str.charAt(i);
if (c == ' ') {
needsSpaceEncoding = true;
} else if (!urlsafe.get(c)) {
return new URLCodec().encode(str, encoding);
} else if (!(((c >= 'a') && (c <= 'z'))
|| ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')))) {
if (encode != null) {
try {
return (String) encode.invoke(null, new Object[] { str,
encoding });
} catch (IllegalAccessException e) {
// don't keep trying if we get one of these
encode = null;
System.err.println("UrlEncoded: Can't access JDK 1.4 encode method ("
+ e + "). Using deprecated version from now on.");
} catch (InvocationTargetException e) {
// this can only be a UnsupportedEncodingException:
Throwable ex = e.getTargetException();
if (ex instanceof UnsupportedEncodingException)
throw (UnsupportedEncodingException) ex;
}
}
return URLEncoder.encode(str);
}
}
@ -64,20 +105,42 @@ public final class UrlEncoded extends URLCodec {
}
/**
* URL-decode a string using the given encoding,
* or return it unchanged if no encoding was necessary.
*
* @param str The string to be URL-decoded
* URL-decode a string using the given encoding, or return it unchanged if
* no encoding was necessary.
* This method uses the new URLDecoder.decode() method from java 1.4 if
* available, otherwise the old deprecated version is used. Reflection is
* used to find the appropriate method; if the reflection operations throw
* exceptions other than UnsupportedEncodingException, it returns the url
* decoded with the old URLDecoder.decode() method.
*
* @param str The string to be URL-decoded
* @param encoding the encoding to use
* @return the URL-decoded string, or str if no decoding necessary
*/
public static String smartDecode(String str, String encoding)
throws DecoderException, UnsupportedEncodingException {
public static String decode(String str, String encoding)
throws UnsupportedEncodingException {
if ((str.indexOf('+') == -1) && (str.indexOf('%') == -1)) {
return str;
} else {
return new URLCodec().decode(str, encoding);
if (decode != null) {
try {
return (String) decode.invoke(null, new Object[] { str,
encoding });
} catch (IllegalAccessException e) {
// don't keep trying if we get one of these
decode = null;
System.err.println("UrlEncoded: Can't access JDK 1.4 decode method ("
+ e + "). Using deprecated version from now on.");
} catch (InvocationTargetException e) {
// this can only be a UnsupportedEncodingException:
Throwable ex = e.getTargetException();
if (ex instanceof UnsupportedEncodingException)
throw (UnsupportedEncodingException) ex;
}
}
return URLDecoder.decode(str);
}
}
}
}