You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mf...@apache.org on 2010/05/20 23:25:43 UTC
svn commit: r946793 - in
/myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite:
common/util/HTTPUtils.java tests/chapter_6/section_6_1_3_1/Tests.java
Author: mfreedman
Date: Thu May 20 21:25:43 2010
New Revision: 946793
URL: http://svn.apache.org/viewvc?rev=946793&view=rev
Log:
Fixed issues with URL encoding tests: i.e. use url encoder based on latest rfc AND made sure that all URL compares took into account that the portlet container can return XML & in their results.
Added:
myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite/common/util/HTTPUtils.java
Modified:
myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite/tests/chapter_6/section_6_1_3_1/Tests.java
Added: myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite/common/util/HTTPUtils.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite/common/util/HTTPUtils.java?rev=946793&view=auto
==============================================================================
--- myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite/common/util/HTTPUtils.java (added)
+++ myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite/common/util/HTTPUtils.java Thu May 20 21:25:43 2010
@@ -0,0 +1,786 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ *
+ */
+
+package org.apache.myfaces.portlet.faces.testsuite.common.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * This class contains various utility methods for encoding and decoding URIs <code>String</code>
+ * using the set of characters allowed in a URI, as defined in <a
+ * href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396 - "Uniform Resource Identifiers (URI):
+ * Generic Syntax"</a>.
+ *
+ * The method does not suffer from the limitations of the <code>java.net.URLEncoder</code> in that
+ * it provides control over the character encoding used for character to byte conversions and is
+ * capable of encoding characters that are encoded by a sequence of several bytes.
+ * <p>
+ *
+ * To convert a <code>String</code>, each character is examined in turn:
+ * <ul>
+ * <li>The ASCII characters '<code>a</code>' through '<code>z</code>', '<code>A</code>'
+ * through '<code>Z</code>', and '<code>0</code>' through '<code>9</code>' remain the
+ * same.
+ * <li>Additional 'mark characters', i.e. '<code>-</code>', '<code>_</code>', '<code>.</code>', '<code>!</code>', '<code>~</code>', '<code>*</code>', '<code>'</code>' , '<code>(</code>', '<code>)</code>',
+ * remain the same.
+ * <li>The space character '<code> </code>' is converted into a plus sign '<code>+</code>'.
+ * <li>All other characters are converted into a sequence of bytes using the specified character
+ * encoding, and each of these bytes is then encoded as a string "<code>%<i>xy</i></code>",
+ * where <i>xy</i> is the two-digit hexadecimal representation of the byte value.
+ * </ul>
+ */
+public class HTTPUtils
+{
+ // An array mapping characters to booleans. True means the character can be
+ // included without Hex encoding
+ private static final boolean[] sValidChar = new boolean[128];
+
+ // An array mapping 4 bit values to uppercase Hex digits to speed things up
+ // a bit
+ private static final char[] sHexLookup = new char[16];
+
+ // Lookup arrays used during base64 encoding/decoding
+ private static char[] sCharLookup;
+ private static byte[] sByteLookup;
+
+ // Static initializer block
+ static
+ {
+ // First initialize sValidChar
+ // Allow lower case alphabetic characters
+ for (char c = 'a'; c <= 'z'; c++)
+ {
+ sValidChar[c] = true;
+ }
+ // Allow upper case alphabetic characters
+ for (char c = 'A'; c <= 'Z'; c++)
+ {
+ sValidChar[c] = true;
+ }
+ // Allow numeric characters
+ for (char c = '0'; c <= '9'; c++)
+ {
+ sValidChar[c] = true;
+ }
+ // Allow various 'mark' characters
+ sValidChar['-'] = true;
+ sValidChar['_'] = true;
+ sValidChar['.'] = true;
+ sValidChar['~'] = true;
+ sValidChar['\''] = true;
+
+
+ // Also initialize the sHexLookup table
+ for (byte b = 0; b < 16; b++)
+ {
+ sHexLookup[b] = Character.toUpperCase(Character.forDigit(b, 16));
+ }
+
+ // Populate arrays for base64 encoding/decoding
+ sCharLookup = new char[64];
+ sByteLookup = new byte[127];
+
+ byte i = 0;
+ char c;
+ for (c = 'A'; c <= 'Z'; c++)
+ {
+ sCharLookup[i] = c;
+ sByteLookup[c] = i++;
+ }
+ for (c = 'a'; c <= 'z'; c++)
+ {
+ sCharLookup[i] = c;
+ sByteLookup[c] = i++;
+ }
+ for (c = '0'; c <= '9'; c++)
+ {
+ sCharLookup[i] = c;
+ sByteLookup[c] = i++;
+ }
+ sCharLookup[i] = '+';
+ sByteLookup['+'] = i++;
+ sCharLookup[i] = '/';
+ sByteLookup['/'] = i;
+ // Signal EOF with -1 (It's safe because the other bytes are only 6
+ // bits)
+ sByteLookup['='] = -1;
+ }
+
+ /**
+ * Returns the date format used for expiry times in type zero (Netscape) cookies.
+ *
+ * Also used as the date format for portlet session expiries. Creates a new instance, so thread
+ * safe.
+ *
+ * @return the date format used for expiry times in type zero (Netscape) cookies
+ */
+ public static DateFormat getCookieDateFormat()
+ {
+ DateFormat format = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z", Locale.US);
+ // Cookies use GMT Time zone by convention (Rule Britania!)
+ format.setTimeZone(TimeZone.getTimeZone("GMT"));
+ return format;
+ }
+
+ /**
+ * Build a fully qualified URL from the pieces provided.
+ *
+ * This method does not call any encoding methods, so the path argument has to be properly
+ * encoded.
+ *
+ * @param scheme
+ * server protocol.
+ * @param host
+ * server name.
+ * @param port
+ * server port.
+ * @param path
+ * properly encoded relative URL.
+ * @throws IllegalArgumentException
+ * if scheme, host or port is null.
+ */
+ public static String buildUrlAsString(String scheme, String host, int port, String path)
+ {
+ if (scheme == null || scheme.equals("") || host == null || host.equals("") || port == 0)
+ {
+ throw new IllegalArgumentException("Cannot build a URL using following scheme: " + scheme
+ + " host: " + host + " port: " + port + " path: " + path);
+ }
+
+ StringBuilder url = new StringBuilder(200);
+
+ url.append(scheme).append("://").append(host);
+
+ // check for protocol default port number
+ if (scheme.equalsIgnoreCase("http") && port != 80 || scheme.equalsIgnoreCase("https")
+ && port != 443)
+ {
+ url.append(":").append(port);
+ }
+
+ if (path != null)
+ {
+ url.append(path);
+ }
+
+ return url.toString();
+ }
+
+ /**
+ * Encodes a String using the set of characters allowed in a URI.
+ *
+ * @param value
+ * <code>String</code> to be translated.
+ * @param encoding
+ * the Java alias for the character encoding to be used to convert non-ASCII characters
+ * into bytes (e.g. <code>"UTF8"</code>).
+ * @return the translated <code>String</code>.
+ * @exception UnsupportedEncodingException
+ * if the given encoding is not a recognised character encoding.
+ */
+ public static String encode(String value, String encoding) throws UnsupportedEncodingException
+ {
+ // Create a buffer that is roughly 1.5 times bigger than the value to
+ // account for possible expansion of the resulting encoded string
+ int len = value.length();
+ StringBuilder out = new StringBuilder(len * 3 / 2);
+
+ for (int charIndex = 0; charIndex < len; charIndex++)
+ {
+ char aChar = value.charAt(charIndex);
+ if (aChar <= 127 && sValidChar[aChar])
+ {
+ out.append(aChar);
+ }
+ else if (aChar == ' ')
+ {
+ out.append('+');
+ }
+ else
+ {
+ byte[] charBytes = String.valueOf(aChar).getBytes(encoding);
+ // For each byte to encode this character, write a '%',
+ // followed by a 2 digit uppercase hex representation of the
+ // byte value
+ for (byte element : charBytes)
+ {
+ out.append('%');
+ // Convert into two Hex digits (and don't worry about the
+ // sign bit, unlike Integer.toHexString()
+ out.append(sHexLookup[(element & 0xF0) >> 4]);
+ out.append(sHexLookup[element & 0x0F]);
+ }
+ }
+ }
+ // The result string should be encodable in pure ASCII
+ return out.toString();
+ }
+
+ /**
+ * Encodes a String using the set of characters allowed in a URI. This method encodes a multibyte
+ * string in UTF8
+ *
+ * @param value
+ * <code>String</code> to be translated.
+ * @return the translated <code>String</code>.
+ */
+ public static String encodeUTF(String value)
+ {
+ String encodedValue = null;
+ try
+ {
+ encodedValue = encode(value, "UTF8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ // TODO - error handling
+ // should never happen for this method because the
+ // character encoding is constant
+ }
+ return encodedValue;
+ }
+
+ /**
+ * Decodes an encoded String.
+ *
+ * @param value
+ * <code>String</code> to be translated.
+ * @param encoding
+ * the Java alias for the character encoding to be used to convert byte sequences into
+ * characters(e.g. <code>"UTF8"</code>).
+ * @return the translated <code>String</code>.
+ * @exception UnsupportedEncodingException
+ * if the given encoding is not a recognised character encoding.
+ */
+ public static String decode(String value, String encoding) throws UnsupportedEncodingException
+ {
+ // optimization!
+ // determine if decoding is actually required
+ if (!needsDecoding(value))
+ {
+ return value;
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ int charIndex = 0;
+ int length = value.length();
+ while (charIndex < length)
+ {
+ char aChar = value.charAt(charIndex);
+ if (aChar == '%')
+ {
+ do
+ {
+ int byteVal = Character.digit(value.charAt(charIndex + 1), 16) << 4
+ | Character.digit(value.charAt(charIndex + 2), 16);
+ bos.write(byteVal);
+ charIndex += 3;
+ } while (charIndex < length && (aChar = value.charAt(charIndex)) == '%');
+ }
+ else
+ {
+ if (aChar == '+')
+ {
+ bos.write(' ');
+ }
+ else
+ {
+ bos.write(aChar);
+ }
+ charIndex++;
+ }
+ }
+ return bos.toString(encoding);
+ }
+
+ /**
+ * Decodes an encoded UTF8 String.
+ *
+ * @param value
+ * <code>String</code> to be translated.
+ * @return the translated <code>String</code>.
+ */
+ public static String decodeUTF(String value)
+ {
+ String decodedValue = null;
+ try
+ {
+ decodedValue = decode(value, "UTF8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ // TODO - error handling
+ // should never happen for this method because the
+ // character encoding is constant
+ }
+ return decodedValue;
+ }
+
+ /**
+ * Determines whether the given HTTP status code denotes a client or server error. According to
+ * the HTTP 1.1 spec, the codes have the following categories:
+ * <ul>
+ * <li> 1xx - Informational (new in HTTP/1.1)
+ * <li> 2xx - Success
+ * <li> 3xx - Redirection
+ * <li> 4xx - Client Error
+ * <li> 5xx - Server Error
+ * </ul>
+ *
+ * @param statusCode
+ * an HTTP response status code
+ * @return true if the given status code denotes a client or server error
+ */
+ public static boolean isErrorStatusCode(int statusCode)
+ {
+ return statusCode >= 400 && statusCode < 600;
+ }
+
+ /**
+ * Determine if a value needs to be decoded using HTTPUtils.decode()
+ *
+ * This method assumes that a value is encoded. As such, the existence of '%' (leading character
+ * of an encoded sequence) or '+' (sometimes used to replace <space> characters indicates that
+ * decoding IS required.
+ */
+ public static final boolean needsDecoding(String token)
+ {
+ if (token == null)
+ {
+ return false;
+ }
+
+ return token.indexOf('+') != -1 || token.indexOf('%') != -1;
+ }
+
+ /**
+ * Extracts a cookie value from a list of cookies based on the name.
+ *
+ * @param cookieName
+ * Name of the cookie to search for.
+ * @param cookies
+ * List of cookies of the form "name1=value1; name2=value2; ...; nameN=valueN".
+ * @return The cookie value stored as a String object. null if cookie not found.
+ */
+ public static String getCookie(String cookieName, String cookies)
+ {
+ return getParameterValue(cookieName, cookies);
+ }
+
+ /**
+ * Extracts a parameter value from a list of parameters based on the name.
+ *
+ * @param paramName
+ * name of the parameter to search forn
+ * @param params
+ * list of parameters as a String of the form: "name1=value1; name2=value2; ...;
+ * nameN=valueN".
+ * @return the parameter value or <code>null</code> if not found
+ */
+ protected static String getParameterValue(String paramName, String params)
+ {
+ int paramNameLen;
+ int paramsLen;
+
+ // Obvious error in arguments?
+ if (paramName == null || (paramNameLen = paramName.length()) == 0)
+ {
+ return null;
+ }
+
+ if (params == null || (paramsLen = params.length()) == 0)
+ {
+ return null;
+ }
+
+ // Try to extract the parameter from the list of parameters
+ // Parameters are defined in a string of the form
+ // name1=value1; name2=value2; ...; nameN=valueN
+ //
+ // The following parse copies the behaviour of
+ // wpugcinb_GetCookieInNewBuffer in /m/wwg/src/wpu.c
+ // and
+ // wpdsesgcv_get_cookie_value in /m/wwg/src/wpdses.c
+ //
+
+ int index = 0;
+
+ for (;;)
+ {
+ // First, eat all the white spaces
+ while (params.charAt(index) == ' ' && index < paramsLen)
+ {
+ index++;
+ }
+
+ if (params.startsWith(paramName, index))
+ {
+ int equalsIndex = params.indexOf('=', index);
+
+ if (equalsIndex != -1)
+ {
+ int i = equalsIndex - 1;
+
+ while (params.charAt(i) == ' ' && i > index)
+ {
+ i--;
+ }
+
+ if (paramNameLen == i - index + 1)
+ {
+ // We've found our parameter
+
+ // Move 1 char past '='
+ int beginIndex = equalsIndex + 1;
+
+ // Check for empty parameter - if so return ""
+ if (beginIndex == paramsLen)
+ {
+ return "";
+ }
+
+ // Find end of token
+ int endIndex = params.indexOf(';', beginIndex);
+ if (endIndex == -1)
+ {
+ endIndex = paramsLen - 1;
+ }
+ else
+ {
+ // Check for empty parameter - if so return ""
+ if (beginIndex == endIndex)
+ {
+ return "";
+ }
+ endIndex--;
+ }
+ // Eat white spaces out in front
+ while (params.charAt(beginIndex) == ' ' && beginIndex < endIndex)
+ {
+ beginIndex++;
+ }
+
+ // Eat white spaces out at end
+ while (params.charAt(endIndex) == ' ' && endIndex > beginIndex)
+ {
+ endIndex--;
+ }
+
+ // Please note that substring takes the endIndex and
+ // subtracts 1
+ // from it. Since our endIndex points to where we want
+ // it to be,
+ // we need to add 1 to it so that everything works out.
+ String paramValue = params.substring(beginIndex, endIndex + 1);
+
+ // check for empty cookie - if so return ""
+ if (0 == paramValue.length())
+ {
+ return "";
+ }
+
+ return paramValue;
+ }
+ }
+ }
+
+ // no match - advance to next parameter
+ index = params.indexOf(';', index);
+
+ // Check for end cases
+ if (index == -1) // no more tokens
+ {
+ return null;
+ }
+ if (index == paramsLen - 1) // nothing following last ';'
+ {
+ return null;
+ }
+
+ index++;
+ }
+ }
+
+ /**
+ * Converts a Java Locale to a String in the format specified for the Accept-Language and xml:lang
+ * attribute, i.e. <a href="http://www.ietf.org/rfc/rfc1766.txt">RFC 1766</a>.
+ */
+ public static String toHTTPLocale(Locale locale)
+ {
+ String language = locale.getLanguage();
+ String country = locale.getCountry();
+ String variant = locale.getVariant();
+ if (country.length() > 0 || variant.length() > 0)
+ {
+ StringBuilder buff = new StringBuilder(20).append(language).append('-')
+ .append(country);
+ if (variant.length() > 0)
+ {
+ buff.append('-').append(variant);
+ }
+ return buff.toString();
+ }
+ else
+ {
+ return language;
+ }
+ }
+
+ /**
+ * Sets a cookie value in a list of cookies based on the name. If the cookie value is null, the
+ * cookie is removed from the list.
+ *
+ * @param cookieName
+ * Name of the cookie to set.
+ * @param cookieValue
+ * Value of the cookie to set.
+ * @param cookies
+ * List of cookies of the form "name1=value1; name2=value2; ...; nameN=valueN".
+ * @return The new cookie string.
+ */
+ public static String setCookie(String cookieName, String cookieValue, String cookies)
+ {
+ int cookieNameLen;
+ int cookiesLen;
+ String newCookies = cookies;
+
+ // Obvious error in arguments?
+ if (cookieName == null || (cookieNameLen = cookieName.length()) == 0)
+ {
+ return cookies;
+ }
+
+ if (cookies == null || (cookiesLen = cookies.length()) == 0)
+ {
+ if (cookieValue != null)
+ {
+ newCookies = cookieName + "=" + cookieValue;
+ }
+ }
+ else
+ {
+ int index = 0;
+
+ // Set the cookie in the list of cookies
+ // Cookie is a string of the form
+ // name1=value1; name2=value2; ...; nameN=valueN
+ //
+
+ for (;;)
+ {
+ // First, eat all the white spaces
+ while (index < cookiesLen && cookies.charAt(index) == ' ')
+ {
+ index++;
+ }
+
+ if (cookies.startsWith(cookieName, index))
+ {
+ int equalsIndex = cookies.indexOf('=', index);
+
+ if (equalsIndex != -1)
+ {
+ int i = equalsIndex - 1;
+
+ while (cookies.charAt(i) == ' ' && i > index)
+ {
+ i--;
+ }
+
+ if (cookieNameLen == i - index + 1)
+ {
+ // We've found our cookie
+
+ // Move 1 char past '='
+ int beginIndex = equalsIndex + 1;
+
+ // Find end of token
+ int endIndex = cookies.indexOf(';', beginIndex);
+ if (endIndex == -1)
+ {
+ endIndex = cookiesLen - 1;
+ }
+ else
+ {
+ endIndex--;
+ }
+
+ if (cookieValue == null)
+ {
+ newCookies = cookies.substring(0, index) + cookies.substring(endIndex + 1);
+ }
+ else
+ {
+ newCookies = cookies.substring(0, beginIndex) + cookieValue
+ + cookies.substring(endIndex + 1);
+ }
+
+ return newCookies;
+ }
+ }
+ }
+
+ // no match - advance to next cookie
+ index = cookies.indexOf(';', index);
+
+ // Check for end cases
+ if (index == -1 || // no more tokens
+ index == cookiesLen - 1) // nothing following last
+ // ';'
+ {
+ if (cookieValue != null)
+ {
+ if (newCookies.length() != 0)
+ {
+ newCookies = newCookies + ";";
+ }
+ newCookies = newCookies + cookieName + "=" + cookieValue;
+ }
+ return newCookies;
+ }
+
+ index++;
+ }
+ }
+
+ return newCookies;
+ }
+
+ /**
+ * Base64 encodes the supplied bytes array, using the standard base 64 encoding algorithm.
+ *
+ * @param bytes
+ * The byte array to encode
+ * @return The base 64 encoded string representing the byte array
+ */
+ public static String base64Encode(byte[] bytes)
+ {
+
+ /*
+ * The base 64 encoding algorithm works as follows:
+ *
+ * Divide the input bytes stream into blocks of 3 bytes. Divide the 24 bits of a 3-byte block
+ * into 4 groups of 6 bits. Map each group of 6 bits to 1 printable character, based on the
+ * 6-bit value. If the last 3-byte block has only 1 byte of input data, pad 2 bytes of zero
+ * (\x0000). After encoding it as a normal block, override the last 2 characters with 2 equal
+ * signs (==), so the decoding process knows 2 bytes of zero were padded. If the last 3-byte
+ * block has only 2 bytes of input data, pad 1 byte of zero (\x00). After encoding it as a
+ * normal block, override the last 1 character with 1 equal signs (=), so the decoding process
+ * knows 1 byte of zero was padded.
+ */
+
+ int i = 0;
+ int bytesToWrite = bytes.length;
+
+ StringBuilder buff = new StringBuilder(bytes.length * 4 / 3);
+
+ while (bytesToWrite >= 3)
+ {
+ buff.append(sCharLookup[bytes[i] >>> 2 & 63]);
+
+ buff.append(sCharLookup[((bytes[i] & 3) << 4) + (bytes[i + 1] >>> 4 & 15)]);
+ buff.append(sCharLookup[((bytes[i + 1] & 15) << 2) + (bytes[i + 2] >>> 6 & 3)]);
+ buff.append(sCharLookup[bytes[i + 2] & 63]);
+
+ bytesToWrite -= 3;
+ i = i + 3;
+ }
+ switch (bytesToWrite)
+ {
+ case 2:
+ buff.append(sCharLookup[bytes[i] >>> 2 & 63]);
+ buff.append(sCharLookup[((bytes[i] & 3) << 4) + (bytes[i + 1] >>> 4 & 15)]);
+ buff.append(sCharLookup[((bytes[i + 1] & 15) << 2)]);
+ buff.append('=');
+ break;
+ case 1:
+ buff.append(sCharLookup[bytes[i] >> 2 & 63]);
+ buff.append(sCharLookup[(bytes[i] & 3) << 4]);
+ buff.append('=');
+ buff.append('=');
+ }
+ return buff.toString();
+ }
+
+ /**
+ * Decodes the supplied base 64 encoded string into its original byte array, using the standard
+ * base 64 decoding algorithm.
+ *
+ * @param string
+ * The base 64 encoded string to decode
+ * @return The decoded byte array
+ */
+ public static byte[] base64Decode(String string)
+ {
+ // Blocks of encoded data may have newline characters which
+ // must be ignored
+ string = string.replace("\n", "");
+ string = string.replace("\r", "");
+
+ char[] chars = string.toCharArray();
+ int i = 0;
+ int charsToWrite = chars.length;
+ ByteArrayOutputStream buff = new ByteArrayOutputStream(chars.length);
+ byte[] b = new byte[4];
+ while (charsToWrite >= 4)
+ {
+ try
+ {
+ // If we can't get one complete byte, then something has gone
+ // wrong
+ if ((b[0] = sByteLookup[chars[i++]]) == -1 || (b[1] = sByteLookup[chars[i++]]) == -1)
+ {
+ throw new IllegalArgumentException(string);
+ }
+ buff.write(b[0] << 2 | b[1] >>> 4);
+ if ((b[2] = sByteLookup[chars[i++]]) == -1)
+ {
+ charsToWrite -= 4;
+ break;
+ }
+ buff.write(b[1] << 4 | b[2] >>> 2);
+ if ((b[3] = sByteLookup[chars[i++]]) == -1)
+ {
+ charsToWrite -= 4;
+ break;
+ }
+ buff.write(b[2] << 6 | b[3]);
+ charsToWrite -= 4;
+ }
+ // If any of the byte lookups go out of bounds, this can't be a
+ // valid base 64 encoding
+ catch (ArrayIndexOutOfBoundsException aiobe)
+ {
+ throw new IllegalArgumentException(string);
+ }
+ }
+ // If we have any odd characters at the end, then something has gone
+ // wrong
+ if (charsToWrite > 0)
+ {
+ throw new IllegalArgumentException(string);
+ }
+ return buff.toByteArray();
+ }
+}
Modified: myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite/tests/chapter_6/section_6_1_3_1/Tests.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite/tests/chapter_6/section_6_1_3_1/Tests.java?rev=946793&r1=946792&r2=946793&view=diff
==============================================================================
--- myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite/tests/chapter_6/section_6_1_3_1/Tests.java (original)
+++ myfaces/portlet-bridge/testsuite/trunk/src/main/java/org/apache/myfaces/portlet/faces/testsuite/tests/chapter_6/section_6_1_3_1/Tests.java Thu May 20 21:25:43 2010
@@ -23,9 +23,6 @@ package org.apache.myfaces.portlet.faces
import java.io.Reader;
import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.net.URLEncoder;
-
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Locale;
@@ -67,6 +64,7 @@ import org.apache.myfaces.portlet.faces.
import org.apache.myfaces.portlet.faces.testsuite.common.Constants;
import org.apache.myfaces.portlet.faces.testsuite.common.portlet.wrapper.ActionRequestDecorator;
import org.apache.myfaces.portlet.faces.testsuite.common.portlet.wrapper.RenderRequestDecorator;
+import org.apache.myfaces.portlet.faces.testsuite.common.util.HTTPUtils;
public class Tests
@@ -233,17 +231,31 @@ public class Tests
final String PORTLET_RENDER_TEST_STRING =
"portlet:render?param1=value1¶m2=value2";
+ final String PORTLET_RENDER_TEST_STRING_XMLENCODED =
+ "portlet:render?param1=value1&param2=value2";
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext extCtx = ctx.getExternalContext();
- String bridgeEncoded =
- extCtx.encodeActionURL(PORTLET_RENDER_TEST_STRING);
-
RenderResponse response = (RenderResponse) extCtx.getResponse();
PortletURL portletURL = response.createRenderURL();
portletURL.setParameter("param1", "value1");
portletURL.setParameter("param2", "value2");
String portletEncoded = portletURL.toString();
+
+ // PortletContainers can return "URLs" with strict XML encoding -- as the bridge
+ // encoding depends on what is past in to it -- make sure we send in a string
+ // with the same encoding as compare string.
+ String bridgeEncoded = null;
+ if (isStrictXhtmlEncoded(portletEncoded))
+ {
+ bridgeEncoded =
+ extCtx.encodeActionURL(PORTLET_RENDER_TEST_STRING_XMLENCODED);
+ }
+ else
+ {
+ bridgeEncoded =
+ extCtx.encodeActionURL(PORTLET_RENDER_TEST_STRING);
+ }
if (bridgeEncoded.equals(portletEncoded))
{
@@ -272,18 +284,33 @@ public class Tests
final String PORTLET_ACTION_TEST_STRING =
"portlet:action?param1=value1¶m2=value2";
+ final String PORTLET_ACTION_TEST_STRING_XMLENCODED =
+ "portlet:action?param1=value1&param2=value2";
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext extCtx = ctx.getExternalContext();
- String bridgeEncoded =
- extCtx.encodeActionURL(PORTLET_ACTION_TEST_STRING);
-
RenderResponse response = (RenderResponse) extCtx.getResponse();
PortletURL portletURL = response.createActionURL();
portletURL.setParameter("param1", "value1");
portletURL.setParameter("param2", "value2");
String portletEncoded = portletURL.toString();
+ // PortletContainers can return "URLs" with strict XML encoding -- as the bridge
+ // encoding depends on what is past in to it -- make sure we send in a string
+ // with the same encoding as compare string.
+ String bridgeEncoded = null;
+ if (isStrictXhtmlEncoded(portletEncoded))
+ {
+ bridgeEncoded =
+ extCtx.encodeActionURL(PORTLET_ACTION_TEST_STRING_XMLENCODED);
+ }
+ else
+ {
+ bridgeEncoded =
+ extCtx.encodeActionURL(PORTLET_ACTION_TEST_STRING);
+ }
+
+
if (bridgeEncoded.equals(portletEncoded))
{
testRunner.setTestResult(true,
@@ -1123,7 +1150,7 @@ public class Tests
final String FOREIGNEXTERNALURL_TEST_STRING = "http://www.apache.org";
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext extCtx = ctx.getExternalContext();
- if (extCtx.encodeResourceURL(FOREIGNEXTERNALURL_TEST_STRING).equals(((PortletResponse) extCtx.getResponse()).encodeURL(FOREIGNEXTERNALURL_TEST_STRING)))
+ if (extCtx.encodeResourceURL(FOREIGNEXTERNALURL_TEST_STRING).equals(((PortletResponse) extCtx.getResponse()).encodeURL(FOREIGNEXTERNALURL_TEST_STRING).replace("&", "&")))
{
testRunner.setTestResult(true,
"encodeResourceURL correctly encoded a foreign external URL.");
@@ -1162,7 +1189,7 @@ public class Tests
try
{
verifyString =
- FOREIGNEXTERNALURL_BACKLINK_VERIFY_STRING + URLEncoder.encode(actionURL,
+ FOREIGNEXTERNALURL_BACKLINK_VERIFY_STRING + HTTPUtils.encode(actionURL,
"UTF-8");
}
catch (UnsupportedEncodingException e)
@@ -1171,8 +1198,10 @@ public class Tests
"Failed because couldn't UTF-8 encode backLink parameter.");
return Constants.TEST_FAILED;
}
-
- if (extCtx.encodeResourceURL(FOREIGNEXTERNALURL_BACKLINK_TEST_STRING).equals(((PortletResponse) extCtx.getResponse()).encodeURL(verifyString)))
+
+ // According to bridge rules since string passed in isn't xml strict encoded the result won't be as well
+ // So ensure compares match by stripping from the one generated by the portlet container (if it exists)
+ if (extCtx.encodeResourceURL(FOREIGNEXTERNALURL_BACKLINK_TEST_STRING).equals(((PortletResponse) extCtx.getResponse()).encodeURL(verifyString).replace("&", "&")))
{
testRunner.setTestResult(true,
"encodeResourceURL correctly encoded a foreign external URL with a backLink.");
@@ -1202,7 +1231,7 @@ public class Tests
ExternalContext extCtx = ctx.getExternalContext();
if (extCtx.encodeResourceURL(RELATIVEURL_TEST_STRING).equals(((PortletResponse) extCtx.getResponse()).encodeURL(extCtx.getRequestContextPath() +
- RELATIVEURL_VERIFY_STRING)))
+ RELATIVEURL_VERIFY_STRING).replace("&", "&")))
{
testRunner.setTestResult(true,
"encodeResourceURL correctly encoded a resource referenced by a relative path.");
@@ -1242,7 +1271,7 @@ public class Tests
{
verifyString =
extCtx.getRequestContextPath() + RELATIVEURL_BACKLINK_VERIFY_STRING +
- URLEncoder.encode(actionURL, "UTF-8");
+ HTTPUtils.encode(actionURL, "UTF-8");
}
catch (UnsupportedEncodingException e)
{
@@ -1251,7 +1280,9 @@ public class Tests
return Constants.TEST_FAILED;
}
- if (extCtx.encodeResourceURL(RELATIVEURL_BACKLINK_TEST_STRING).equals(((PortletResponse) extCtx.getResponse()).encodeURL(verifyString)))
+ // According to bridge rules since string passed in isn't xml strict encoded the result won't be as well
+ // So ensure compares match by stripping from the one generated by the portlet container (if it exists)
+ if (extCtx.encodeResourceURL(RELATIVEURL_BACKLINK_TEST_STRING).equals(((PortletResponse) extCtx.getResponse()).encodeURL(verifyString).replace("&", "&")))
{
testRunner.setTestResult(true,
"encodeResourceURL correctly encoded a relative URL with a backLink.");
@@ -1281,7 +1312,7 @@ public class Tests
ExternalContext extCtx = ctx.getExternalContext();
if (extCtx.encodeResourceURL(URL_TEST_STRING).equals(((PortletResponse) extCtx.getResponse()).encodeURL(extCtx.getRequestContextPath() +
- URL_TEST_STRING)))
+ URL_TEST_STRING).replace("&", "&")))
{
testRunner.setTestResult(true,
"encodeResourceURL correctly encoded a resource referenced by a context path relative path.");
@@ -1321,7 +1352,7 @@ public class Tests
{
verifyString =
extCtx.getRequestContextPath() + URL_BACKLINK_VERIFY_STRING +
- URLEncoder.encode(actionURL, "UTF-8");
+ HTTPUtils.encode(actionURL, "UTF-8");
}
catch (UnsupportedEncodingException e)
{
@@ -1329,8 +1360,9 @@ public class Tests
"Failed because couldn't UTF-8 encode backLink parameter.");
return Constants.TEST_FAILED;
}
-
- if (extCtx.encodeResourceURL(URL_BACKLINK_TEST_STRING).equals(((PortletResponse) extCtx.getResponse()).encodeURL(verifyString)))
+ // According to bridge rules since string passed in isn't xml strict encoded the result won't be as well
+ // So ensure compares match by stripping from the one generated by the portlet container (if it exists)
+ if (extCtx.encodeResourceURL(URL_BACKLINK_TEST_STRING).equals(((PortletResponse) extCtx.getResponse()).encodeURL(verifyString).replace("&", "&")))
{
testRunner.setTestResult(true,
"encodeResourceURL correctly encoded an URL with a backLink.");
@@ -1402,7 +1434,7 @@ public class Tests
try
{
verifyString =
- URL_VIEWLINK_BACKLINK_VERIFY_STRING + URLEncoder.encode(actionURL,
+ URL_VIEWLINK_BACKLINK_VERIFY_STRING + HTTPUtils.encode(actionURL,
"UTF-8");
}
catch (UnsupportedEncodingException e)