You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mm...@apache.org on 2007/10/25 15:38:13 UTC
svn commit: r588233 [4/5] - in /myfaces/portlet-bridge/trunk: ./ api/
api/src/ api/src/main/ api/src/main/java/ api/src/main/java/javax/
api/src/main/java/javax/portlet/ api/src/main/java/javax/portlet/faces/
api/src/main/java/javax/portlet/faces/compo...
Added: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/HTTPUtils.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/HTTPUtils.java?rev=588233&view=auto
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/HTTPUtils.java (added)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/HTTPUtils.java Thu Oct 25 06:38:05 2007
@@ -0,0 +1,791 @@
+/* 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.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;
+ 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);
+ }
+
+ SimpleStringBuffer url = new SimpleStringBuffer(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();
+ SimpleStringBuffer out = new SimpleStringBuffer(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)
+ {
+ SimpleStringBuffer buff = new SimpleStringBuffer(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;
+
+ SimpleStringBuffer buff = new SimpleStringBuffer(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 = TextUtils.globalReplace(string, "\n", "");
+ string = TextUtils.globalReplace(string, "\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();
+ }
+}
Added: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java?rev=588233&view=auto
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java (added)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java Thu Oct 25 06:38:05 2007
@@ -0,0 +1,502 @@
+/* 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.util;
+
+import java.io.UnsupportedEncodingException;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A class encapsulating an HTTP query string.
+ */
+public final class QueryString
+{
+ private String mQueryString;
+ private String mCharacterEncoding;
+ private Map mParameterMap;
+ private List mParameterList;
+ private List mParameterNames;
+
+ /**
+ * Construct a <code>QueryString</code> from a pre-encoded string.
+ */
+ public QueryString(String queryString, String characterEncoding)
+ {
+ mQueryString = queryString;
+ mCharacterEncoding = characterEncoding;
+ }
+
+ /**
+ * Makes a copy of an existing <code>QueryString</code>.
+ */
+ public QueryString(QueryString source)
+ {
+ mQueryString = source.mQueryString;
+ mCharacterEncoding = source.mCharacterEncoding;
+ if (source.mParameterList != null)
+ {
+ mParameterList = new ArrayList(source.mParameterList);
+ }
+ }
+
+ /**
+ * Constructs an empty query string (parameters may be added later).
+ */
+ public QueryString(String characterEncoding)
+ {
+ mCharacterEncoding = characterEncoding;
+ }
+
+ /**
+ * Constructs a query string from an old-fashioned array of PRE-ENCODED name-value pairs
+ */
+ public QueryString(String[][] args, String characterEncoding)
+ {
+ this(characterEncoding);
+ for (String[] element : args)
+ {
+ addParameter(element[0], element[1], true);
+ }
+ }
+
+ /**
+ * Constructs a query string from a list of PRE-ENCODED name-value pairs
+ */
+ public QueryString(List params, String characterEncoding)
+ {
+ this(characterEncoding);
+
+ Iterator pairs = params.iterator();
+ while (pairs.hasNext())
+ {
+ String[] pair = (String[]) pairs.next();
+ addParameter(pair[0], pair[1], true);
+ }
+ }
+
+ /**
+ * Converts this object into an encoded query string.
+ */
+ @Override
+ public String toString()
+ {
+ // Use appendTo to concatenate the parameters together
+ if (mQueryString == null)
+ {
+ appendTo(new SimpleStringBuffer(200));
+ }
+ return mQueryString;
+ }
+
+ /**
+ * Appends the contents of this object to the given buffer in encoded query string form.
+ *
+ * @param buff
+ * the buffer to append to
+ */
+ public void appendTo(SimpleStringBuffer buff)
+ {
+ // If we don't have a cached query string yet, generate it
+ if (mQueryString == null)
+ {
+ // Remember the start position in the buffer, so that we can also
+ // cache the
+ // concatenated string in mQueryString
+ int startPos = buff.length();
+ Iterator i;
+ if (mParameterList != null && (i = mParameterList.iterator()).hasNext())
+ {
+ Parameter param = (Parameter) i.next();
+ buff.append(param.getEncodedName()).append('=').append(param.getEncodedValue());
+ while (i.hasNext())
+ {
+ param = (Parameter) i.next();
+ buff.append('&').append(param.getEncodedName()).append('=')
+ .append(param.getEncodedValue());
+ }
+ mQueryString = buff.substring(startPos);
+ }
+ // If we don't have any parameters at all, cache the empty string
+ else
+ {
+ mQueryString = "";
+ }
+ }
+ // If we have a cached query string, reuse it
+ else
+ {
+ buff.append(mQueryString);
+ }
+ }
+
+ public Enumeration getParameterNames()
+ {
+ initParameterMap();
+ return Collections.enumeration(mParameterNames);
+ }
+
+ public String getParameter(String name)
+ {
+ initParameterMap();
+ List values = (List) mParameterMap.get(name);
+ return values == null ? null : ((Parameter) values.get(0)).getValue();
+ }
+
+ public Enumeration getParameterValues(String name)
+ {
+ initParameterMap();
+ List params = (List) mParameterMap.get(name);
+ if (params == null)
+ {
+ return Collections.enumeration(Collections.EMPTY_LIST);
+ }
+ List values = new ArrayList(params.size());
+ Iterator i = params.iterator();
+ Parameter param;
+ while (i.hasNext())
+ {
+ param = (Parameter) i.next();
+ values.add(param.getValue());
+ }
+ return Collections.enumeration(values);
+ }
+
+ public void addParameter(String name, String value)
+ {
+ addParameter(name, value, false);
+ }
+
+ public void addParameter(String name, String value, boolean isEncoded)
+ {
+ if (value == null)
+ {
+ return;
+ }
+ initParameterList();
+
+ // Invalidate the query string
+ mQueryString = null;
+
+ // Update the parameter list
+ Parameter param = new Parameter(name, value, isEncoded);
+ mParameterList.add(param);
+
+ // Update the parameter map if it is initialized
+ if (mParameterMap != null)
+ {
+ String decodedName = param.getName();
+ List values = (List) mParameterMap.get(decodedName);
+ if (values == null)
+ {
+ values = new ArrayList(4);
+ mParameterMap.put(decodedName, values);
+ // Only add UNIQUE parameter names (preserving order)
+ mParameterNames.add(decodedName);
+ }
+ values.add(param);
+ }
+ }
+
+ public void setParameter(String name, String value)
+ {
+ setParameter(name, value, false);
+ }
+
+ public void setParameter(String name, String value, boolean isEncoded)
+ {
+ if (value == null)
+ {
+ removeParameter(name, isEncoded);
+ return;
+ }
+ initParameterMap();
+
+ // Invalidate the query string
+ mQueryString = null;
+
+ // Update the map
+ Parameter param = new Parameter(name, value, isEncoded);
+ String decodedName = param.getName();
+ List values = (List) mParameterMap.get(decodedName);
+ if (values == null)
+ {
+ values = new ArrayList(4);
+ mParameterMap.put(decodedName, values);
+ // Only add UNIQUE parameter names (preserving order)
+ mParameterNames.add(decodedName);
+ mParameterList.add(param);
+ }
+ else
+ {
+ values.clear();
+
+ // First, replace the existing occurence of the parameter
+ int i = mParameterList.indexOf(param);
+ mParameterList.set(i, param);
+
+ // Now, remove any subsequent occurrences
+ int j;
+ while ((j = mParameterList.lastIndexOf(param)) > i)
+ {
+ mParameterList.remove(j);
+ }
+ }
+ values.add(param);
+ }
+
+ public String removeParameter(String name)
+ {
+ return removeParameter(name, false);
+ }
+
+ public String removeParameter(String name, boolean isEncoded)
+ {
+ initParameterList();
+
+ // Invalidate the query string
+ mQueryString = null;
+
+ // Create a template parameter for comparisons, so that we can avoid
+ // decoding all parameter names in the list
+ Parameter templateParam = new Parameter(name, "", isEncoded);
+
+ // Update the parameter list
+ Iterator i = mParameterList.iterator();
+ Parameter param = null, firstParam = null;
+ while (i.hasNext())
+ {
+ param = (Parameter) i.next();
+ // Compare the parameter with our template (only the template name
+ // will
+ // be encoded / decoded if necessary)
+ if (templateParam.equals(param))
+ {
+ if (firstParam == null)
+ {
+ firstParam = param;
+ }
+ i.remove();
+ }
+ }
+
+ // Update the map, if it is initialized and we found a parameter
+ if (mParameterMap != null && firstParam != null)
+ {
+ String decodedName = templateParam.getName();
+ List values = (List) mParameterMap.remove(decodedName);
+ if (values != null)
+ {
+ mParameterNames.remove(decodedName);
+ }
+ }
+
+ return firstParam == null ? null : isEncoded ? firstParam.getEncodedValue()
+ : firstParam.getValue();
+ }
+
+ private void initParameterMap()
+ {
+ if (mParameterMap == null)
+ {
+ initParameterList();
+
+ mParameterMap = new HashMap(30);
+ mParameterNames = new ArrayList(30);
+ if (mParameterList.size() == 0)
+ {
+ return;
+ }
+ String decodedName;
+ Parameter param;
+ List values;
+ Iterator i = mParameterList.iterator();
+ while (i.hasNext())
+ {
+ param = (Parameter) i.next();
+ decodedName = param.getName();
+ values = (List) mParameterMap.get(decodedName);
+ if (values == null)
+ {
+ values = new ArrayList(4);
+ mParameterMap.put(decodedName, values);
+ // Only add UNIQUE parameter names (preserving order)
+ mParameterNames.add(decodedName);
+ }
+ values.add(param);
+ }
+ }
+ }
+
+ private void initParameterList()
+ {
+ if (mParameterList == null)
+ {
+ mParameterList = new ArrayList(30);
+ int length;
+ if (mQueryString == null || (length = mQueryString.length()) == 0)
+ {
+ return;
+ }
+ Parameter param;
+ int lastPos = 0, nextPos, sepPos;
+ do
+ {
+ nextPos = mQueryString.indexOf('&', lastPos);
+ if (nextPos == -1)
+ {
+ nextPos = length;
+ }
+ sepPos = mQueryString.indexOf('=', lastPos);
+ if (sepPos != -1 && sepPos < nextPos)
+ {
+ param = new Parameter(mQueryString.substring(lastPos, sepPos),
+ mQueryString.substring(sepPos + 1, nextPos), true);
+ }
+ else
+ {
+ param = new Parameter(mQueryString.substring(lastPos, nextPos), "", true);
+ }
+ mParameterList.add(param);
+ lastPos = nextPos + 1;
+ } while (nextPos < length);
+ }
+ }
+
+ private class Parameter
+ {
+ private String mName;
+ private String mEncodedName;
+
+ private String mValue;
+ private String mEncodedValue;
+
+ public Parameter(String name, String value, boolean encoded)
+ {
+ if (encoded)
+ {
+ mEncodedName = name;
+ mEncodedValue = value;
+ }
+ else
+ {
+ mName = name;
+ mValue = value;
+ }
+ }
+
+ public String getName()
+ {
+ if (mName == null)
+ {
+ try
+ {
+ mName = HTTPUtils.decode(mEncodedName, mCharacterEncoding);
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ handleUnsupportedEncoding();
+ }
+ }
+ return mName;
+ }
+
+ public String getEncodedName()
+ {
+ if (mEncodedName == null)
+ {
+ try
+ {
+ mEncodedName = HTTPUtils.encode(mName, mCharacterEncoding);
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ handleUnsupportedEncoding();
+ }
+ }
+ return mEncodedName;
+ }
+
+ public String getValue()
+ {
+ if (mValue == null)
+ {
+ try
+ {
+ mValue = HTTPUtils.decode(mEncodedValue, mCharacterEncoding);
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ handleUnsupportedEncoding();
+ }
+ }
+ return mValue;
+ }
+
+ public String getEncodedValue()
+ {
+ if (mEncodedValue == null)
+ {
+ try
+ {
+ mEncodedValue = HTTPUtils.encode(mValue, mCharacterEncoding);
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ handleUnsupportedEncoding();
+ }
+ }
+ return mEncodedValue;
+ }
+
+ /**
+ * Compares two parameters for name equality.
+ *
+ * Attempts not to invoke any lazy encoding or decoding in the passed in parameter - only in
+ * this one.
+ */
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o == null || !(o instanceof Parameter))
+ {
+ return false;
+ }
+ Parameter p1 = (Parameter) o;
+ return p1.mName != null && getName().equals(p1.mName) || p1.mEncodedName != null
+ && getEncodedName().equals(p1.mEncodedName);
+ }
+ }
+
+ private void handleUnsupportedEncoding()
+ {
+ throw new IllegalArgumentException(
+ new SimpleStringBuffer(100)
+ .append(
+ "Unrecognized character encoding \"")
+ .append(mCharacterEncoding)
+ .append('"').toString());
+ }
+}
Added: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/SimpleStringBuffer.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/SimpleStringBuffer.java?rev=588233&view=auto
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/SimpleStringBuffer.java (added)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/SimpleStringBuffer.java Thu Oct 25 06:38:05 2007
@@ -0,0 +1,530 @@
+/* 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.util;
+
+/**
+ * A non synchronized StringBuffer object that mimmicks the functionality of java.lang.StringBuffer.
+ */
+public final class SimpleStringBuffer
+{
+ private char mValue[];
+ private int mLength;
+
+ public SimpleStringBuffer()
+ {
+ this(16);
+ }
+
+ public SimpleStringBuffer(int length)
+ {
+ mValue = new char[length];
+ }
+
+ public SimpleStringBuffer(String str)
+ {
+ this(str.length() + 16);
+ append(str);
+ }
+
+ /**
+ * Returns the length (character count) of this string buffer.
+ *
+ * @return the number of characters in this string buffer.
+ */
+ public int length()
+ {
+ return mLength;
+ }
+
+ /**
+ * Returns the current capacity of the String buffer. The capacity is the amount of storage
+ * available for newly inserted characters; beyond which an allocation will occur.
+ *
+ * @return the current capacity of this string buffer.
+ */
+ public int capacity()
+ {
+ return mValue.length;
+ }
+
+ /**
+ * Ensures that the capacity of the buffer is at least equal to the specified minimum. If the
+ * current capacity of this string buffer is less than the argument, then a new internal buffer is
+ * allocated with greater capacity. The new capacity is the larger of:
+ * <ul>
+ * <li>The <code>minimumCapacity</code> argument.
+ * <li>Twice the old capacity, plus <code>2</code>.
+ * </ul>
+ * If the <code>minimumCapacity</code> argument is nonpositive, this method takes no action and
+ * simply returns.
+ *
+ * @param minimumCapacity
+ * the minimum desired capacity.
+ */
+ public void ensureCapacity(int minimumCapacity)
+ {
+ if (minimumCapacity > mValue.length)
+ {
+ int newCapacity = (mValue.length + 1) * 2;
+ if (minimumCapacity > newCapacity)
+ {
+ newCapacity = minimumCapacity;
+ }
+
+ char newValue[] = new char[newCapacity];
+ System.arraycopy(mValue, 0, newValue, 0, mLength);
+ mValue = newValue;
+
+ // Debug Facility that dumps the stack trace when
+ // the buffer grows allowing sizing to be tweaked!
+ // SHOULD BE COMMENTED OUT
+ // printStackTrace(new Throwable());
+ }
+ }
+
+ public void setLength(int newLength)
+ {
+ if (newLength < 0)
+ {
+ throw new StringIndexOutOfBoundsException(newLength);
+ }
+
+ if (newLength > mValue.length)
+ {
+ ensureCapacity(newLength);
+ }
+
+ if (mLength < newLength)
+ {
+ for (; mLength < newLength; mLength++)
+ {
+ mValue[mLength] = '\0';
+ }
+ }
+ else
+ {
+ mLength = newLength;
+ }
+ }
+
+ public char charAt(int index)
+ {
+ if (index < 0 || index >= mLength)
+ {
+ throw new StringIndexOutOfBoundsException(index);
+ }
+ return mValue[index];
+ }
+
+ public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
+ {
+ if (srcBegin < 0 || srcBegin >= mLength)
+ {
+ throw new StringIndexOutOfBoundsException(srcBegin);
+ }
+
+ if (srcEnd < 0 || srcEnd > mLength)
+ {
+ throw new StringIndexOutOfBoundsException(srcEnd);
+ }
+
+ if (srcBegin < srcEnd)
+ {
+ System.arraycopy(mValue, srcBegin, dst, dstBegin, srcEnd - srcBegin);
+ }
+ }
+
+ public void setCharAt(int index, char ch)
+ {
+ if (index < 0 || index >= mLength)
+ {
+ throw new StringIndexOutOfBoundsException(index);
+ }
+ mValue[index] = ch;
+ }
+
+ public SimpleStringBuffer append(Object obj)
+ {
+ return append(String.valueOf(obj));
+ }
+
+ public SimpleStringBuffer append(String str)
+ {
+ if (str == null)
+ {
+ str = String.valueOf(str);
+ }
+
+ int len = str.length();
+ int newcount = mLength + len;
+ if (newcount > mValue.length)
+ {
+ ensureCapacity(newcount);
+ }
+ str.getChars(0, len, mValue, mLength);
+ mLength = newcount;
+ return this;
+ }
+
+ public SimpleStringBuffer append(char[] str)
+ {
+ int len = str.length;
+ int newcount = mLength + len;
+ if (newcount > mValue.length)
+ {
+ ensureCapacity(newcount);
+ }
+ System.arraycopy(str, 0, mValue, mLength, len);
+ mLength = newcount;
+ return this;
+ }
+
+ public SimpleStringBuffer append(char[] str, int offset, int len)
+ {
+ int newcount = mLength + len;
+ if (newcount > mValue.length)
+ {
+ ensureCapacity(newcount);
+ }
+ System.arraycopy(str, offset, mValue, mLength, len);
+ mLength = newcount;
+ return this;
+ }
+
+ public SimpleStringBuffer append(boolean b)
+ {
+ return append(String.valueOf(b));
+ }
+
+ public SimpleStringBuffer append(char c)
+ {
+ int newcount = mLength + 1;
+ if (newcount > mValue.length)
+ {
+ ensureCapacity(newcount);
+ }
+ mValue[mLength++] = c;
+ return this;
+ }
+
+ /**
+ */
+ public SimpleStringBuffer append(int i)
+ {
+ return append(String.valueOf(i));
+ }
+
+ /**
+ */
+ public SimpleStringBuffer append(long l)
+ {
+ return append(String.valueOf(l));
+ }
+
+ /**
+ */
+ public SimpleStringBuffer append(float f)
+ {
+ return append(String.valueOf(f));
+ }
+
+ /**
+ */
+ public SimpleStringBuffer append(double d)
+ {
+ return append(String.valueOf(d));
+ }
+
+ /**
+ */
+ public SimpleStringBuffer insert(int offset, Object obj)
+ {
+ return insert(offset, String.valueOf(obj));
+ }
+
+ /**
+ */
+ public SimpleStringBuffer insert(int offset, String str)
+ {
+ if (offset < 0 || offset > mLength)
+ {
+ throw new StringIndexOutOfBoundsException();
+ }
+ int len = str.length();
+ int newcount = mLength + len;
+ if (newcount > mValue.length)
+ {
+ ensureCapacity(newcount);
+ }
+ System.arraycopy(mValue, offset, mValue, offset + len, mLength - offset);
+ str.getChars(0, len, mValue, offset);
+ mLength = newcount;
+ return this;
+ }
+
+ /**
+ */
+ public SimpleStringBuffer insert(int offset, char[] str)
+ {
+ if (offset < 0 || offset > mLength)
+ {
+ throw new StringIndexOutOfBoundsException();
+ }
+ int len = str.length;
+ int newcount = mLength + len;
+ if (newcount > mValue.length)
+ {
+ ensureCapacity(newcount);
+ }
+ System.arraycopy(mValue, offset, mValue, offset + len, mLength - offset);
+ System.arraycopy(str, 0, mValue, offset, len);
+ mLength = newcount;
+ return this;
+ }
+
+ /**
+ */
+ public SimpleStringBuffer insert(int offset, boolean b)
+ {
+ return insert(offset, String.valueOf(b));
+ }
+
+ /**
+ */
+ public SimpleStringBuffer insert(int offset, char c)
+ {
+ int newcount = mLength + 1;
+ if (newcount > mValue.length)
+ {
+ ensureCapacity(newcount);
+ }
+ System.arraycopy(mValue, offset, mValue, offset + 1, mLength - offset);
+ mValue[offset] = c;
+ mLength = newcount;
+ return this;
+ }
+
+ /**
+ */
+ public SimpleStringBuffer insert(int offset, int i)
+ {
+ return insert(offset, String.valueOf(i));
+ }
+
+ /**
+ */
+ public SimpleStringBuffer insert(int offset, long l)
+ {
+ return insert(offset, String.valueOf(l));
+ }
+
+ /**
+ */
+ public SimpleStringBuffer insert(int offset, float f)
+ {
+ return insert(offset, String.valueOf(f));
+ }
+
+ /**
+ */
+ public SimpleStringBuffer insert(int offset, double d)
+ {
+ return insert(offset, String.valueOf(d));
+ }
+
+ /**
+ * Removes the characters in a substring of this <code>
+ * SimpleStringBuffer</code>. The substring
+ * begins at the specified <code>start</code> and extends to the character at index
+ * <code>end</code> - 1 or to the end of the SimpleStringBuffer if no such character exists. If
+ * start is equal to end, no changes are made.
+ *
+ * @param start -
+ * the beginning index, inclusive
+ * @param end -
+ * the ending index, exclusive
+ *
+ * @return This simple string buffer
+ * @exception StringIndexOutOfBoundsException -
+ * if start is negative, greater than <code>length()</code>, or greater than
+ * <code>end</code>.
+ *
+ */
+ public SimpleStringBuffer delete(int start, int end)
+ {
+ if (start < 0)
+ {
+ throw new StringIndexOutOfBoundsException(start);
+ }
+ if (end > mLength)
+ {
+ end = mLength;
+ }
+ if (start > end)
+ {
+ throw new StringIndexOutOfBoundsException();
+ }
+ int numChars = end - start;
+ if (numChars > 0)
+ {
+ System.arraycopy(mValue, start + numChars, mValue, start, mLength - end);
+ mLength -= numChars;
+ }
+ return this;
+ }
+
+ /**
+ * Removes the character at the specified position in this <code>SimpleStringBuffer</code>
+ * (shortening the <code>SimpleStringBuffer</code> by one character).
+ *
+ * @param index -
+ * index of the character to remove
+ *
+ * @return This simple string buffer
+ * @exception StringIndexOutOfBoundsException -
+ * if the <code>index</code> is negative or greater than or equal to
+ * <code>length()</code>.
+ *
+ */
+ public SimpleStringBuffer deleteCharAt(int index)
+ {
+ if (index < 0 || index >= mLength)
+ {
+ throw new StringIndexOutOfBoundsException();
+ }
+ System.arraycopy(mValue, index + 1, mValue, index, mLength - index - 1);
+ mLength--;
+ return this;
+ }
+
+ /**
+ * Replaces the characters in a substring of this <code>SimpleStringBuffer</code> with
+ * characters in the specified String. The substring begins at the specified start and extends to
+ * the character at index <code>end</code> - 1 or to the end of the
+ * <code>SimpleStringBuffer</code> if no such character exists. First the characters in the
+ * substring are removed and then the specified String is inserted at start. (The
+ * <code>SimpleStringBuffer</code> will be lengthened to accommodate the specified String if
+ * necessary.)
+ *
+ * @param start -
+ * the beginning index, inclusive
+ * @param end -
+ * the ending index, exclusive
+ * @param str -
+ * string that will replace previous contents
+ *
+ * @return This simple string buffer
+ * @exception StringIndexOutOfBoundsException -
+ * if start is negative, greater than <code>length()</code>, or greater than
+ * <code>end</code>.
+ *
+ */
+ public SimpleStringBuffer replace(int start, int end, String str)
+ {
+ if (start < 0)
+ {
+ throw new StringIndexOutOfBoundsException(start);
+ }
+ if (end > mLength)
+ {
+ end = mLength;
+ }
+ if (start > end)
+ {
+ throw new StringIndexOutOfBoundsException();
+ }
+
+ int numChars = str.length();
+ int newLength = mLength + numChars - (end - start);
+
+ if (newLength > mValue.length)
+ {
+ ensureCapacity(newLength);
+ }
+ System.arraycopy(mValue, end, mValue, start + numChars, mLength - end);
+
+ str.getChars(0, numChars, mValue, start);
+ mLength = newLength;
+
+ return this;
+ }
+
+ /**
+ * Returns a new <code>String</code> that contains a subsequence of characters currently
+ * contained in this <code>SimpleStringBuffer</code>.The substring begins at the specified
+ * index and extends to the end of the <code>StringBuffer</code>.
+ *
+ * @param start
+ * The beginning index, inclusive.
+ * @return The new string.
+ * @exception StringIndexOutOfBoundsException
+ * if <code>start</code> is less than zero, or greater than the length of this
+ * <code>StringBuffer</code>.
+ */
+ public String substring(int start)
+ {
+ return substring(start, mLength);
+ }
+
+ /**
+ * Returns a new <code>String</code> that contains a subsequence of characters currently
+ * contained in this <code>SimpleStringBuffer</code>. The substring begins at the specified
+ * <code>start</code> and extends to the character at index <code>end -
+ * 1</code>.
+ *
+ * @param start
+ * The beginning index, inclusive.
+ * @param end
+ * The ending index, exclusive.
+ * @return The new string.
+ * @exception StringIndexOutOfBoundsException
+ * if <code>start</code> or <code>end</code> are negative or greater than
+ * <code>length()</code>, or <code>start</code> is greater than <code>end</code>.
+ */
+ public String substring(int start, int end)
+ {
+ if (start < 0)
+ {
+ throw new StringIndexOutOfBoundsException(start);
+ }
+ if (end > mLength)
+ {
+ throw new StringIndexOutOfBoundsException(end);
+ }
+ if (start > end)
+ {
+ throw new StringIndexOutOfBoundsException(end - start);
+ }
+ return new String(mValue, start, end - start);
+ }
+
+ /**
+ */
+ @Override
+ public String toString()
+ {
+ return new String(getValue(), 0, length());
+ }
+
+ public char[] getValue()
+ {
+ return mValue;
+ }
+}
Added: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/TextUtils.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/TextUtils.java?rev=588233&view=auto
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/TextUtils.java (added)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/TextUtils.java Thu Oct 25 06:38:05 2007
@@ -0,0 +1,102 @@
+/* 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.util;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+// TODO once we figure out which class is shipped with the 2.0 container
+// we'll be using that class instead
+// Borrowed from oracle.portlet.utils
+
+public class TextUtils
+{
+
+ public static final String getString(ResourceBundle bundle, String key, Object[] args)
+ {
+ return formatMessage(bundle.getString(key), args);
+ }
+
+ public static final String getString(ResourceBundle bundle, String key)
+ {
+ return formatMessage(bundle.getString(key), null);
+ }
+
+ public static final String formatMessage(String message, Object[] args)
+ {
+ if (args != null)
+ {
+ return MessageFormat.format(message, args);
+ }
+ else
+ {
+ return message;
+ }
+ }
+
+ /**
+ * Provides the "global substring search and replace" functionality missing from the JDK.
+ *
+ * @param orig
+ * the original string to process
+ * @param search
+ * the substring to search for in <code>orig</code>
+ * @param replace
+ * the string to replace all occurrences of <code>search</code> with
+ * @return copy of <code>orig</code> with all occurrences of <code>search</code> replaced by
+ * <code>replace</code>
+ */
+ public static final String globalReplace(String orig, String search, String replace)
+ {
+ // OPTIMIZATION: Return original string if it doesn't contain the search
+ // string
+ int searchLen = search.length();
+ if (searchLen == 0)
+ {
+ return orig;
+ }
+ int nextPos = orig.indexOf(search);
+ if (nextPos == -1)
+ {
+ return orig;
+ }
+ int origLen = orig.length();
+ int startPos = 0;
+ SimpleStringBuffer result = new SimpleStringBuffer(origLen + 100);
+
+ // Use 'do' loop, because we know the search string occurs at least once
+ do
+ {
+ if (nextPos > startPos)
+ {
+ result.append(orig.substring(startPos, nextPos));
+ }
+ result.append(replace);
+ startPos = nextPos + searchLen;
+ } while (startPos < origLen && (nextPos = orig.indexOf(search, startPos)) != -1);
+
+ if (startPos < origLen)
+ {
+ result.append(orig.substring(startPos));
+ }
+
+ return result.toString();
+ }
+}
Added: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/URLUtils.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/URLUtils.java?rev=588233&view=auto
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/URLUtils.java (added)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/URLUtils.java Thu Oct 25 06:38:05 2007
@@ -0,0 +1,146 @@
+/* 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.util;
+
+public class URLUtils
+{
+
+ /**
+ * Borrowed from package oracle.adfinternal.view.faces.share.url.EncoderUtils
+ */
+ public static String appendURLArguments(StringBuffer buffer, String baseURL,
+ String[] keysAndValues)
+ {
+
+ // Bug 1814825: the anchor has to stay on the end.
+ int anchorIndex = baseURL.indexOf('#');
+
+ if (anchorIndex >= 0)
+ {
+ buffer.append(baseURL.substring(0, anchorIndex));
+ }
+ else
+ {
+ buffer.append(baseURL);
+ }
+
+ boolean queryAppended = baseURL.indexOf('?') >= 0;
+
+ for (int i = 0; i < keysAndValues.length; i += 2)
+ {
+ String value = keysAndValues[i + 1];
+ if (value != null)
+ {
+ // only append '?' at start if the URL doesn't already contain
+ // arguments
+ if (!queryAppended)
+ {
+ queryAppended = true;
+ buffer.append('?');
+ }
+ else
+ {
+ buffer.append('&');
+ }
+
+ buffer.append(keysAndValues[i]);
+ buffer.append('=');
+ buffer.append(value);
+ }
+ }
+
+ String beforeEncode = buffer.toString();
+ return beforeEncode;
+ }
+
+ /**
+ * Borrowed from package oracle.adfinternal.view.faces.share.url.EncoderUtils
+ */
+ public static String appendURLArguments(String baseURL, String[] keysAndValues)
+ {
+ // buffer length = base + separators + keys + values
+ int bufferLength = baseURL.length() + keysAndValues.length;
+ for (int i = 0; i < keysAndValues.length; i += 2)
+ {
+ String value = keysAndValues[i + 1];
+ if (value != null)
+ {
+ bufferLength += keysAndValues[i].length() + value.length();
+ }
+ }
+
+ StringBuffer buffer = new StringBuffer(bufferLength);
+
+ return appendURLArguments(buffer, baseURL, keysAndValues);
+ }
+
+ public static String convertFromRelative(String currentPath, String relativeLoc)
+ throws IllegalArgumentException
+ {
+ // determine if and how many levels we must walk up the currentPath
+ int levels = 0;
+ int i = 0, length = relativeLoc.length();
+ while (i + 1 < length)
+ {
+ if (relativeLoc.charAt(i) != '.')
+ {
+ break;
+ }
+ else if (relativeLoc.charAt(i) == '.' && relativeLoc.charAt(i + 1) == '/')
+ {
+ // no new level but prune the ./
+ i += 2;
+ }
+ else if (i + 2 < length && relativeLoc.charAt(i) == '.' && relativeLoc.charAt(i + 1) == '.'
+ && relativeLoc.charAt(i + 2) == '/')
+ {
+ levels += 1;
+ i += 3;
+ }
+ }
+
+ StringBuffer sb = new StringBuffer(currentPath);
+ if (currentPath.endsWith("/"))
+ {
+ sb = sb.deleteCharAt(currentPath.length() - 1);
+ }
+ for (int j = 0; j < levels; j++)
+ {
+ int loc = sb.lastIndexOf("/");
+ if (loc < 0)
+ {
+ throw new IllegalArgumentException("Location: " + relativeLoc
+ + "Can't be made relative to: " + currentPath);
+ }
+ sb = sb.delete(loc, sb.length());
+ }
+
+ // now sb should contain root path without trailing / so add one
+ sb = sb.append("/");
+
+ // now add the portion of the relativeLoc that doesn't contain
+ // the relative references
+ sb = sb.append(relativeLoc.substring(i));
+
+ return sb.toString();
+
+ }
+
+}
Added: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/config/WebConfigurationProcessor.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/config/WebConfigurationProcessor.java?rev=588233&view=auto
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/config/WebConfigurationProcessor.java (added)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/config/WebConfigurationProcessor.java Thu Oct 25 06:38:05 2007
@@ -0,0 +1,252 @@
+/* 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.util.config;
+
+import java.io.StringReader;
+
+import java.util.Vector;
+
+import javax.portlet.PortletContext;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class WebConfigurationProcessor
+{
+
+ private static final String WEB_XML_PATH = "/WEB-INF/web.xml";
+
+ private Vector mMappings = null;
+
+ /**
+ * <p>
+ * When instantiated, the web.xml of the current application will be scanned looking for a
+ * references to the <code>FacesServlet</code>. <code>isFacesServletPresent()</code> will
+ * return the appropriate value based on the scan.
+ * </p>
+ *
+ * @param context
+ * the <code>ServletContext</code> for the application of interest
+ */
+ public WebConfigurationProcessor(PortletContext context)
+ {
+
+ if (context != null)
+ {
+ scanForFacesMappings(context);
+ }
+
+ } // END WebXmlProcessor
+
+ public Vector getFacesMappings()
+ {
+
+ return mMappings;
+
+ } // END getFacesMappings
+
+ /**
+ * <p>
+ * Parse the web.xml for the current application and scan for a FacesServlet entry, if found, set
+ * the <code>facesServletPresent</code> property to true.
+ *
+ * @param context
+ * the ServletContext instance for this application
+ */
+ private void scanForFacesMappings(PortletContext context)
+ {
+
+ SAXParserFactory factory = getSAXFactory();
+ try
+ {
+ SAXParser parser = factory.newSAXParser();
+ parser.parse(context.getResourceAsStream(WEB_XML_PATH), new WebXmlHandler());
+ }
+ catch (Exception e)
+ {
+ // TODO add logging
+ // Do nothing
+ ;
+ }
+
+ } // END scanForFacesMappings
+
+ /**
+ * <p>
+ * Return a <code>SAXParserFactory</code> instance that is non-validating and is namespace
+ * aware.
+ * </p>
+ *
+ * @return configured <code>SAXParserFactory</code>
+ */
+ private SAXParserFactory getSAXFactory()
+ {
+
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setValidating(false);
+ factory.setNamespaceAware(true);
+ return factory;
+
+ } // END getConfiguredFactory
+
+ /**
+ * <p>
+ * A simple SAX handler to process the elements of interested within a web application's
+ * deployment descriptor.
+ * </p>
+ */
+ private class WebXmlHandler extends DefaultHandler
+ {
+
+ private static final String SERVLET_ELEMENT = "servlet";
+ private static final String SERVLET_NAME_ELEMENT = "servlet-name";
+ private static final String SERVLET_CLASS_ELEMENT = "servlet-class";
+ private static final String SERVLET_MAPPING_ELEMENT = "servlet-mapping";
+ private static final String URL_PATTERN_ELEMENT = "url-pattern";
+ private static final String FACES_SERVLET_DATA = "javax.faces.webapp.FacesServlet";
+
+ private boolean mInServletElement = false;
+ private boolean mInServletNameElement = false;
+ private boolean mInServletClassElement = false;
+
+ private boolean mInServletMappingElement = false;
+ private boolean mInURLPatternElement = false;
+
+ private String mName = null;
+ private String mClass = null;
+
+ private String mFacesServletName = null;
+ private StringBuffer mContent;
+
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId) throws SAXException
+ {
+
+ return new InputSource(new StringReader(""));
+
+ } // END resolveEntity
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException
+ {
+
+ boolean parseContent = false;
+
+ if (SERVLET_ELEMENT.equals(localName))
+ {
+ mInServletElement = true;
+ }
+ else if (SERVLET_MAPPING_ELEMENT.equals(localName))
+ {
+ mInServletMappingElement = true;
+ }
+ else if (mInServletElement)
+ {
+ if (SERVLET_CLASS_ELEMENT.equals(localName))
+ {
+ mInServletClassElement = parseContent = true;
+ }
+ else if (SERVLET_NAME_ELEMENT.equals(localName))
+ {
+ mInServletNameElement = parseContent = true;
+ }
+ }
+ else if (mInServletMappingElement)
+ {
+ if (URL_PATTERN_ELEMENT.equals(localName))
+ {
+ mInURLPatternElement = parseContent = true;
+ }
+ else if (SERVLET_NAME_ELEMENT.equals(localName))
+ {
+ mInServletNameElement = parseContent = true;
+ }
+ }
+ if (parseContent)
+ {
+ mContent = new StringBuffer();
+ }
+
+ } // END startElement
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException
+ {
+
+ if (mContent != null)
+ {
+ mContent.append(ch, start, length);
+ }
+
+ } // END characters
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException
+ {
+
+ if (mInServletClassElement)
+ {
+ mClass = mContent.toString().trim();
+ mInServletClassElement = false;
+ }
+ else if (mInServletNameElement)
+ {
+ mName = mContent.toString().trim();
+ mInServletNameElement = false;
+ }
+ else if (mInURLPatternElement)
+ {
+ if (mInServletMappingElement && mName != null && mFacesServletName != null
+ && mName.equals(mFacesServletName))
+ {
+ if (mMappings == null)
+ {
+ mMappings = new Vector();
+ }
+ mMappings.add(mContent.toString().trim());
+ }
+ mInURLPatternElement = false;
+ }
+ else if (SERVLET_ELEMENT.equals(localName))
+ {
+ if (mName != null && mClass != null && mClass.equals(FACES_SERVLET_DATA))
+ {
+ mFacesServletName = mName;
+ }
+ mInServletElement = false;
+ }
+ else if (SERVLET_MAPPING_ELEMENT.equals(localName))
+ {
+ mInServletMappingElement = false;
+ }
+
+ mContent = null;
+
+ } // END endElement
+
+ } // END WebXmlHandler
+
+}
Added: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/LocalesIterator.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/LocalesIterator.java?rev=588233&view=auto
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/LocalesIterator.java (added)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/LocalesIterator.java Thu Oct 25 06:38:05 2007
@@ -0,0 +1,48 @@
+/* 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.util.map;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+public class LocalesIterator implements Iterator
+{
+ private Enumeration mLocales;
+
+ public LocalesIterator(Enumeration locales)
+ {
+ mLocales = locales;
+ }
+
+ public boolean hasNext()
+ {
+ return mLocales.hasMoreElements();
+ }
+
+ public Object next()
+ {
+ return mLocales.nextElement();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+}
Added: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletAbstractMap.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletAbstractMap.java?rev=588233&view=auto
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletAbstractMap.java (added)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletAbstractMap.java Thu Oct 25 06:38:05 2007
@@ -0,0 +1,340 @@
+/* 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.util.map;
+
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * Helper class for different portlet external context maps
+ */
+public abstract class PortletAbstractMap implements Map
+{
+ static final String ILLEGAL_ARGUMENT = "Only supported in a portlet environment";
+
+ private Set mKeySet;
+ private Collection mValues;
+ private Set mEntrySet;
+
+ public void clear()
+ {
+ List names = new ArrayList();
+ for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
+ {
+ names.add(e.nextElement());
+ }
+
+ for (Iterator it = names.iterator(); it.hasNext();)
+ {
+ removeAttribute((String) it.next());
+ }
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return getAttribute(key.toString()) != null;
+ }
+
+ public boolean containsValue(Object findValue)
+ {
+ if (findValue == null)
+ {
+ return false;
+ }
+
+ for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
+ {
+ Object value = getAttribute((String) e.nextElement());
+ if (findValue.equals(value))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public Set entrySet()
+ {
+ return mEntrySet != null ? mEntrySet : (mEntrySet = new EntrySet());
+ }
+
+ public Object get(Object key)
+ {
+ return getAttribute(key.toString());
+ }
+
+ public boolean isEmpty()
+ {
+ return !getAttributeNames().hasMoreElements();
+ }
+
+ public Set keySet()
+ {
+ return mKeySet != null ? mKeySet : (mKeySet = new KeySet());
+ }
+
+ public Object put(Object key, Object value)
+ {
+ String localKey = key.toString();
+ Object retval = getAttribute(localKey);
+ setAttribute(localKey, value);
+ return retval;
+ }
+
+ public void putAll(Map t)
+ {
+ for (Iterator it = t.entrySet().iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ setAttribute(entry.getKey().toString(), entry.getValue());
+ }
+ }
+
+ public Object remove(Object key)
+ {
+ String localKey = key.toString();
+ Object retval = getAttribute(localKey);
+ removeAttribute(localKey);
+ return retval;
+ }
+
+ public int size()
+ {
+ int size = 0;
+ for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
+ {
+ size++;
+ e.nextElement();
+ }
+ return size;
+ }
+
+ public Collection values()
+ {
+ return mValues != null ? mValues : (mValues = new Values());
+ }
+
+ protected abstract Object getAttribute(String key);
+
+ protected abstract void setAttribute(String key, Object value);
+
+ protected abstract void removeAttribute(String key);
+
+ protected abstract Enumeration getAttributeNames();
+
+ private class KeySet extends AbstractSet
+ {
+ @Override
+ public Iterator iterator()
+ {
+ return new KeyIterator();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return PortletAbstractMap.this.isEmpty();
+ }
+
+ @Override
+ public int size()
+ {
+ return PortletAbstractMap.this.size();
+ }
+
+ @Override
+ public boolean contains(Object o)
+ {
+ return containsKey(o);
+ }
+
+ @Override
+ public boolean remove(Object o)
+ {
+ return PortletAbstractMap.this.remove(o) != null;
+ }
+
+ @Override
+ public void clear()
+ {
+ PortletAbstractMap.this.clear();
+ }
+ }
+
+ private class KeyIterator implements Iterator
+ {
+ protected final Enumeration mEnum = getAttributeNames();
+ protected Object mKey;
+
+ public void remove()
+ {
+ if (mKey == null)
+ {
+ throw new NoSuchElementException();
+ }
+ PortletAbstractMap.this.remove(mKey);
+ }
+
+ public boolean hasNext()
+ {
+ return mEnum.hasMoreElements();
+ }
+
+ public Object next()
+ {
+ return mKey = mEnum.nextElement();
+ }
+ }
+
+ private class Values extends KeySet
+ {
+ @Override
+ public Iterator iterator()
+ {
+ return new ValuesIterator();
+ }
+
+ @Override
+ public boolean contains(Object o)
+ {
+ return containsValue(o);
+ }
+
+ @Override
+ public boolean remove(Object o)
+ {
+ if (o == null)
+ {
+ return false;
+ }
+
+ for (Iterator it = iterator(); it.hasNext();)
+ {
+ if (o.equals(it.next()))
+ {
+ it.remove();
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ private class ValuesIterator extends KeyIterator
+ {
+ @Override
+ public Object next()
+ {
+ super.next();
+ return get(mKey);
+ }
+ }
+
+ private class EntrySet extends KeySet
+ {
+ @Override
+ public Iterator iterator()
+ {
+ return new EntryIterator();
+ }
+
+ @Override
+ public boolean contains(Object o)
+ {
+ if (!(o instanceof Entry))
+ {
+ return false;
+ }
+
+ Entry entry = (Entry) o;
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+ if (key == null || value == null)
+ {
+ return false;
+ }
+
+ return value.equals(get(key));
+ }
+
+ @Override
+ public boolean remove(Object o)
+ {
+ if (!(o instanceof Entry))
+ {
+ return false;
+ }
+
+ Entry entry = (Entry) o;
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+ if (key == null || value == null || !value.equals(get(key)))
+ {
+ return false;
+ }
+
+ return PortletAbstractMap.this.remove(((Entry) o).getKey()) != null;
+ }
+ }
+
+ private class EntryIterator extends KeyIterator
+ {
+ @Override
+ public Object next()
+ {
+ super.next();
+ return new EntrySetEntry(mKey);
+ }
+ }
+
+ private class EntrySetEntry implements Entry
+ {
+ private final Object mKey;
+
+ public EntrySetEntry(Object currentKey)
+ {
+ mKey = currentKey;
+ }
+
+ public Object getKey()
+ {
+ return mKey;
+ }
+
+ public Object getValue()
+ {
+ return get(mKey);
+ }
+
+ public Object setValue(Object value)
+ {
+ return put(mKey, value);
+ }
+ }
+}
Added: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletApplicationMap.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletApplicationMap.java?rev=588233&view=auto
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletApplicationMap.java (added)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletApplicationMap.java Thu Oct 25 06:38:05 2007
@@ -0,0 +1,88 @@
+/* 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.util.map;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletContext;
+
+/**
+ * Map of portlet context attributes
+ */
+public class PortletApplicationMap extends PortletAbstractMap
+{
+ private final PortletContext mPortletContext;
+
+ public PortletApplicationMap(Object context)
+ {
+ if (context instanceof PortletContext)
+ {
+ mPortletContext = (PortletContext) context;
+ }
+ else
+ {
+ throw new IllegalArgumentException(ILLEGAL_ARGUMENT);
+ }
+ }
+
+ @Override
+ public Object getAttribute(String key)
+ {
+ if (mPortletContext != null)
+ {
+ return mPortletContext.getAttribute(key);
+ }
+ else
+ {
+ throw new IllegalArgumentException(ILLEGAL_ARGUMENT);
+ }
+ }
+
+ @Override
+ public void setAttribute(String key, Object value)
+ {
+ if (mPortletContext != null)
+ {
+ mPortletContext.setAttribute(key, value);
+ }
+ }
+
+ @Override
+ public void removeAttribute(String key)
+ {
+ if (mPortletContext != null)
+ {
+ mPortletContext.removeAttribute(key);
+ }
+ }
+
+ @Override
+ public Enumeration getAttributeNames()
+ {
+ if (mPortletContext != null)
+ {
+ return mPortletContext.getAttributeNames();
+ }
+ else
+ {
+ throw new IllegalArgumentException(ILLEGAL_ARGUMENT);
+ }
+ }
+}
Added: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletInitParameterMap.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletInitParameterMap.java?rev=588233&view=auto
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletInitParameterMap.java (added)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletInitParameterMap.java Thu Oct 25 06:38:05 2007
@@ -0,0 +1,82 @@
+/* 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.util.map;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletContext;
+
+/**
+ * Map of portlet context init params
+ */
+public class PortletInitParameterMap extends PortletAbstractMap
+{
+ private final PortletContext mPortletContext;
+
+ public PortletInitParameterMap(Object context)
+ {
+ if (context instanceof PortletContext)
+ {
+ mPortletContext = (PortletContext) context;
+ }
+ else
+ {
+ throw new IllegalArgumentException(ILLEGAL_ARGUMENT);
+ }
+ }
+
+ @Override
+ public Object getAttribute(String key)
+ {
+ if (mPortletContext != null)
+ {
+ return mPortletContext.getInitParameter(key);
+ }
+ else
+ {
+ throw new IllegalArgumentException(ILLEGAL_ARGUMENT);
+ }
+ }
+
+ @Override
+ public void setAttribute(String key, Object value)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void removeAttribute(String key)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Enumeration getAttributeNames()
+ {
+ if (mPortletContext != null)
+ {
+ return mPortletContext.getInitParameterNames();
+ }
+ else
+ {
+ throw new IllegalArgumentException(ILLEGAL_ARGUMENT);
+ }
+ }
+}