You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rave.apache.org by zh...@apache.org on 2011/04/01 02:29:38 UTC
svn commit: r1087520 [4/35] - in
/incubator/rave/donations/ogce-gadget-container: ./ config/
config/shindig-1.1-BETA5/ config/shindig-2.0.0/ db-cleaner/ examples/
examples/src/ examples/src/main/ examples/src/main/java/
examples/src/main/java/cgl/ exam...
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Text.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Text.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Text.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Text.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,789 @@
+package cgl.shindig.common;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Properties;
+
+/**
+ * This Class provides some text related utilities
+ */
+public class Text {
+
+ /**
+ * Hidden constructor.
+ */
+ private Text() {
+ }
+
+ /**
+ * used for the md5
+ */
+ public static final char[] hexTable = "0123456789abcdef".toCharArray();
+
+ /**
+ * Calculate an MD5 hash of the string given.
+ *
+ * @param data the data to encode
+ * @param enc the character encoding to use
+ * @return a hex encoded string of the md5 digested input
+ */
+ public static String md5(String data, String enc)
+ throws UnsupportedEncodingException {
+ try {
+ return digest("MD5", data.getBytes(enc));
+ } catch (NoSuchAlgorithmException e) {
+ throw new InternalError("MD5 digest not available???");
+ }
+ }
+
+ /**
+ * Calculate an MD5 hash of the string given using 'utf-8' encoding.
+ *
+ * @param data the data to encode
+ * @return a hex encoded string of the md5 digested input
+ */
+ public static String md5(String data) {
+ try {
+ return md5(data, "utf-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new InternalError("UTF8 digest not available???");
+ }
+ }
+
+ /**
+ * Digest the plain string using the given algorithm.
+ *
+ * @param algorithm The alogrithm for the digest. This algorithm must be
+ * supported by the MessageDigest class.
+ * @param data The plain text String to be digested.
+ * @param enc The character encoding to use
+ * @return The digested plain text String represented as Hex digits.
+ * @throws java.security.NoSuchAlgorithmException if the desired algorithm is not supported by
+ * the MessageDigest class.
+ * @throws java.io.UnsupportedEncodingException if the encoding is not supported
+ */
+ public static String digest(String algorithm, String data, String enc)
+ throws NoSuchAlgorithmException, UnsupportedEncodingException {
+
+ return digest(algorithm, data.getBytes(enc));
+ }
+
+ /**
+ * Digest the plain string using the given algorithm.
+ *
+ * @param algorithm The alogrithm for the digest. This algorithm must be
+ * supported by the MessageDigest class.
+ * @param data the data to digest with the given algorithm
+ * @return The digested plain text String represented as Hex digits.
+ * @throws java.security.NoSuchAlgorithmException if the desired algorithm is not supported by
+ * the MessageDigest class.
+ */
+ public static String digest(String algorithm, byte[] data)
+ throws NoSuchAlgorithmException {
+
+ MessageDigest md = MessageDigest.getInstance(algorithm);
+ byte[] digest = md.digest(data);
+ StringBuffer res = new StringBuffer(digest.length * 2);
+ for (int i = 0; i < digest.length; i++) {
+ byte b = digest[i];
+ res.append(hexTable[(b >> 4) & 15]);
+ res.append(hexTable[b & 15]);
+ }
+ return res.toString();
+ }
+
+ /**
+ * returns an array of strings decomposed of the original string, split at
+ * every occurance of 'ch'. if 2 'ch' follow each other with no intermediate
+ * characters, empty "" entries are avoided.
+ *
+ * @param str the string to decompose
+ * @param ch the character to use a split pattern
+ * @return an array of strings
+ */
+ public static String[] explode(String str, int ch) {
+ return explode(str, ch, false);
+ }
+
+ /**
+ * returns an array of strings decomposed of the original string, split at
+ * every occurance of 'ch'.
+ *
+ * @param str the string to decompose
+ * @param ch the character to use a split pattern
+ * @param respectEmpty if <code>true</code>, empty elements are generated
+ * @return an array of strings
+ */
+ public static String[] explode(String str, int ch, boolean respectEmpty) {
+ if (str == null || str.length() == 0) {
+ return new String[0];
+ }
+
+ ArrayList strings = new ArrayList();
+ int pos;
+ int lastpos = 0;
+
+ // add snipples
+ while ((pos = str.indexOf(ch, lastpos)) >= 0) {
+ if (pos - lastpos > 0 || respectEmpty) {
+ strings.add(str.substring(lastpos, pos));
+ }
+ lastpos = pos + 1;
+ }
+ // add rest
+ if (lastpos < str.length()) {
+ strings.add(str.substring(lastpos));
+ } else if (respectEmpty && lastpos == str.length()) {
+ strings.add("");
+ }
+
+ // return stringarray
+ return (String[]) strings.toArray(new String[strings.size()]);
+ }
+
+ /**
+ * Concatenates all strings in the string array using the specified delimiter.
+ * @param arr
+ * @param delim
+ * @return the concatenated string
+ */
+ public static String implode(String[] arr, String delim) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) {
+ buf.append(delim);
+ }
+ buf.append(arr[i]);
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Replaces all occurences of <code>oldString</code> in <code>text</code>
+ * with <code>newString</code>.
+ *
+ * @param text
+ * @param oldString old substring to be replaced with <code>newString</code>
+ * @param newString new substring to replace occurences of <code>oldString</code>
+ * @return a string
+ */
+ public static String replace(String text, String oldString, String newString) {
+ if (text == null || oldString == null || newString == null) {
+ throw new IllegalArgumentException("null argument");
+ }
+ int pos = text.indexOf(oldString);
+ if (pos == -1) {
+ return text;
+ }
+ int lastPos = 0;
+ StringBuffer sb = new StringBuffer(text.length());
+ while (pos != -1) {
+ sb.append(text.substring(lastPos, pos));
+ sb.append(newString);
+ lastPos = pos + oldString.length();
+ pos = text.indexOf(oldString, lastPos);
+ }
+ if (lastPos < text.length()) {
+ sb.append(text.substring(lastPos));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Replaces illegal XML characters in the given string by their corresponding
+ * predefined entity references.
+ *
+ * @param text text to be escaped
+ * @return a string
+ */
+ public static String encodeIllegalXMLCharacters(String text) {
+ if (text == null) {
+ throw new IllegalArgumentException("null argument");
+ }
+ StringBuffer buf = null;
+ int length = text.length();
+ int pos = 0;
+ for (int i = 0; i < length; i++) {
+ int ch = text.charAt(i);
+ switch (ch) {
+ case '<':
+ case '>':
+ case '&':
+ case '"':
+ case '\'':
+ if (buf == null) {
+ buf = new StringBuffer();
+ }
+ if (i > 0) {
+ buf.append(text.substring(pos, i));
+ }
+ pos = i + 1;
+ break;
+ default:
+ continue;
+ }
+ if (ch == '<') {
+ buf.append("<");
+ } else if (ch == '>') {
+ buf.append(">");
+ } else if (ch == '&') {
+ buf.append("&");
+ } else if (ch == '"') {
+ buf.append(""");
+ } else if (ch == '\'') {
+ buf.append("'");
+ }
+ }
+ if (buf == null) {
+ return text;
+ } else {
+ if (pos < length) {
+ buf.append(text.substring(pos));
+ }
+ return buf.toString();
+ }
+ }
+
+ /**
+ * The list of characters that are not encoded by the <code>escape()</code>
+ * and <code>unescape()</code> METHODS. They contains the characters as
+ * defined 'unreserved' in section 2.3 of the RFC 2396 'URI generic syntax':
+ * <p/>
+ * <pre>
+ * unreserved = alphanum | mark
+ * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+ * </pre>
+ */
+ public static BitSet URISave;
+
+ /**
+ * Same as {@link #URISave} but also contains the '/'
+ */
+ public static BitSet URISaveEx;
+
+ static {
+ URISave = new BitSet(256);
+ int i;
+ for (i = 'a'; i <= 'z'; i++) {
+ URISave.set(i);
+ }
+ for (i = 'A'; i <= 'Z'; i++) {
+ URISave.set(i);
+ }
+ for (i = '0'; i <= '9'; i++) {
+ URISave.set(i);
+ }
+ URISave.set('-');
+ URISave.set('_');
+ URISave.set('.');
+ URISave.set('!');
+ URISave.set('~');
+ URISave.set('*');
+ URISave.set('\'');
+ URISave.set('(');
+ URISave.set(')');
+
+ URISaveEx = (BitSet) URISave.clone();
+ URISaveEx.set('/');
+ }
+
+ /**
+ * Does an URL encoding of the <code>string</code> using the
+ * <code>escape</code> character. The characters that don't need encoding
+ * are those defined 'unreserved' in section 2.3 of the 'URI generic syntax'
+ * RFC 2396, but without the escape character.
+ *
+ * @param string the string to encode.
+ * @param escape the escape character.
+ * @return the escaped string
+ * @throws NullPointerException if <code>string</code> is <code>null</code>.
+ */
+ public static String escape(String string, char escape) {
+ return escape(string, escape, false);
+ }
+
+ /**
+ * Does an URL encoding of the <code>string</code> using the
+ * <code>escape</code> character. The characters that don't need encoding
+ * are those defined 'unreserved' in section 2.3 of the 'URI generic syntax'
+ * RFC 2396, but without the escape character. If <code>isPath</code> is
+ * <code>true</code>, additionally the slash '/' is ignored, too.
+ *
+ * @param string the string to encode.
+ * @param escape the escape character.
+ * @param isPath if <code>true</code>, the string is treated as path
+ * @return the escaped string
+ * @throws NullPointerException if <code>string</code> is <code>null</code>.
+ */
+ public static String escape(String string, char escape, boolean isPath) {
+ try {
+ BitSet validChars = isPath ? URISaveEx : URISave;
+ byte[] bytes = string.getBytes("utf-8");
+ StringBuffer out = new StringBuffer(bytes.length);
+ for (int i = 0; i < bytes.length; i++) {
+ int c = bytes[i] & 0xff;
+ if (validChars.get(c) && c != escape) {
+ out.append((char) c);
+ } else {
+ out.append(escape);
+ out.append(hexTable[(c >> 4) & 0x0f]);
+ out.append(hexTable[(c) & 0x0f]);
+ }
+ }
+ return out.toString();
+ } catch (UnsupportedEncodingException e) {
+ throw new InternalError(e.toString());
+ }
+ }
+
+ /**
+ * Does a URL encoding of the <code>string</code>. The characters that
+ * don't need encoding are those defined 'unreserved' in section 2.3 of
+ * the 'URI generic syntax' RFC 2396.
+ *
+ * @param string the string to encode
+ * @return the escaped string
+ * @throws NullPointerException if <code>string</code> is <code>null</code>.
+ */
+ public static String escape(String string) {
+ return escape(string, '%');
+ }
+
+ /**
+ * Does a URL encoding of the <code>path</code>. The characters that
+ * don't need encoding are those defined 'unreserved' in section 2.3 of
+ * the 'URI generic syntax' RFC 2396. In contrast to the
+ * {@link #escape(String)} method, not the entire path string is escaped,
+ * but every individual part (i.e. the slashes are not escaped).
+ *
+ * @param path the path to encode
+ * @return the escaped path
+ * @throws NullPointerException if <code>path</code> is <code>null</code>.
+ */
+ public static String escapePath(String path) {
+ return escape(path, '%', true);
+ }
+
+ /**
+ * Does a URL decoding of the <code>string</code> using the
+ * <code>escape</code> character. Please note that in opposite to the
+ * {@link java.net.URLDecoder} it does not transform the + into spaces.
+ *
+ * @param string the string to decode
+ * @param escape the escape character
+ * @return the decoded string
+ * @throws NullPointerException if <code>string</code> is <code>null</code>.
+ * @throws IllegalArgumentException if the 2 characters following the escape
+ * character do not represent a hex-number
+ * or if not enough characters follow an
+ * escape character
+ */
+ public static String unescape(String string, char escape) {
+ try {
+ byte[] utf8 = string.getBytes("utf-8");
+
+ // Check whether escape occurs at invalid position
+ if ((utf8.length >= 1 && utf8[utf8.length - 1] == escape) ||
+ (utf8.length >= 2 && utf8[utf8.length - 2] == escape)) {
+ throw new IllegalArgumentException("Premature end of escape sequence at end of input");
+ }
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream(utf8.length);
+ for (int k = 0; k < utf8.length; k++) {
+ byte b = utf8[k];
+ if (b == escape) {
+ out.write((decodeDigit(utf8[++k]) << 4) + decodeDigit(utf8[++k]));
+ }
+ else {
+ out.write(b);
+ }
+ }
+
+ return new String(out.toByteArray(), "utf-8");
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new InternalError(e.toString());
+ }
+ }
+
+ /**
+ * Does a URL decoding of the <code>string</code>. Please note that in
+ * opposite to the {@link java.net.URLDecoder} it does not transform the +
+ * into spaces.
+ *
+ * @param string the string to decode
+ * @return the decoded string
+ * @throws NullPointerException if <code>string</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if not enough character follow an
+ * escape character
+ * @throws IllegalArgumentException if the 2 characters following the escape
+ * character do not represent a hex-number.
+ */
+ public static String unescape(String string) {
+ return unescape(string, '%');
+ }
+
+ /**
+ * Escapes all illegal JCR name characters of a string.
+ * The encoding is loosely modeled after URI encoding, but only encodes
+ * the characters it absolutely needs to in order to make the resulting
+ * string a valid JCR name.
+ * Use {@link #unescapeIllegalJcrChars(String)} for decoding.
+ * <p/>
+ * QName EBNF:<br>
+ * <xmp>
+ * simplename ::= onecharsimplename | twocharsimplename | threeormorecharname
+ * onecharsimplename ::= (* Any Unicode character except: '.', '/', ':', '[', ']', '*', '|' or any whitespace character *)
+ * twocharsimplename ::= '.' onecharsimplename | onecharsimplename '.' | onecharsimplename onecharsimplename
+ * threeormorecharname ::= nonspace string nonspace
+ * string ::= char | string char
+ * char ::= nonspace | ' '
+ * nonspace ::= (* Any Unicode character except: '/', ':', '[', ']', '*', '|' or any whitespace character *)
+ * </xmp>
+ *
+ * @param name the name to escape
+ * @return the escaped name
+ */
+ public static String escapeIllegalJcrChars(String name) {
+ StringBuffer buffer = new StringBuffer(name.length() * 2);
+ for (int i = 0; i < name.length(); i++) {
+ char ch = name.charAt(i);
+ if (ch == '%' || ch == '/' || ch == ':' || ch == '[' || ch == ']'
+ || ch == '*' || ch == '|'
+ || (ch == '.' && name.length() < 3)
+ || (ch == ' ' && (i == 0 || i == name.length() - 1))
+ || ch == '\t' || ch == '\r' || ch == '\n') {
+ buffer.append('%');
+ buffer.append(Character.toUpperCase(Character.forDigit(ch / 16, 16)));
+ buffer.append(Character.toUpperCase(Character.forDigit(ch % 16, 16)));
+ } else {
+ buffer.append(ch);
+ }
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Escapes all illegal XPath search characters of a string.
+ * <p>Example:<br>
+ * A search string like 'test?' will run into a ParseException
+ * documented in http://issues.apache.org/jira/browse/JCR-1248
+ *
+ * @param s the string to encode
+ * @return the escaped string
+ */
+ public static String escapeIllegalXpathSearchChars(String s) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(s.substring(0, (s.length() - 1)));
+ char c = s.charAt(s.length() - 1);
+ // NOTE: keep this in sync with _ESCAPED_CHAR below!
+ if (c == '!' || c == '(' || c == ':' || c == '^'
+ || c == '[' || c == ']' || c == '\"' || c == '{'
+ || c == '}' || c == '?') {
+ sb.append('\\');
+ }
+ sb.append(c);
+ return sb.toString();
+ }
+
+ /**
+ * Unescapes previously escaped jcr chars.
+ * <p/>
+ * Please note, that this does not exactly the same as the url related
+ * {@link #unescape(String)}, since it handles the byte-encoding
+ * differently.
+ *
+ * @param name the name to unescape
+ * @return the unescaped name
+ */
+ public static String unescapeIllegalJcrChars(String name) {
+ StringBuffer buffer = new StringBuffer(name.length());
+ int i = name.indexOf('%');
+ while (i > -1 && i + 2 < name.length()) {
+ buffer.append(name.toCharArray(), 0, i);
+ int a = Character.digit(name.charAt(i + 1), 16);
+ int b = Character.digit(name.charAt(i + 2), 16);
+ if (a > -1 && b > -1) {
+ buffer.append((char) (a * 16 + b));
+ name = name.substring(i + 3);
+ } else {
+ buffer.append('%');
+ name = name.substring(i + 1);
+ }
+ i = name.indexOf('%');
+ }
+ buffer.append(name);
+ return buffer.toString();
+ }
+
+ /**
+ * Returns the name part of the path. If the given path is already a name
+ * (i.e. contains no slashes) it is returned.
+ *
+ * @param path the path
+ * @return the name part or <code>null</code> if <code>path</code> is <code>null</code>.
+ */
+ public static String getName(String path) {
+ return getName(path, '/');
+ }
+
+ /**
+ * Returns the name part of the path, delimited by the given <code>delim</code>.
+ * If the given path is already a name (i.e. contains no <code>delim</code>
+ * characters) it is returned.
+ *
+ * @param path the path
+ * @param delim the delimiter
+ * @return the name part or <code>null</code> if <code>path</code> is <code>null</code>.
+ */
+ public static String getName(String path, char delim) {
+ return path == null
+ ? null
+ : path.substring(path.lastIndexOf(delim) + 1);
+ }
+
+ /**
+ * Same as {@link #getName(String)} but adding the possibility
+ * to pass paths that end with a trailing '/'
+ *
+ * @see #getName(String)
+ */
+ public static String getName(String path, boolean ignoreTrailingSlash) {
+ if (ignoreTrailingSlash && path != null && path.endsWith("/") && path.length() > 1) {
+ path = path.substring(0, path.length()-1);
+ }
+ return getName(path);
+ }
+
+ /**
+ * Returns the namespace prefix of the given <code>qname</code>. If the
+ * prefix is missing, an empty string is returned. Please note, that this
+ * method does not validate the name or prefix.
+ * </p>
+ * the qname has the format: qname := [prefix ':'] local;
+ *
+ * @param qname a qualified name
+ * @return the prefix of the name or "".
+ *
+ * @see #getLocalName(String)
+ *
+ * @throws NullPointerException if <code>qname</code> is <code>null</code>
+ */
+ public static String getNamespacePrefix(String qname) {
+ int pos = qname.indexOf(':');
+ return pos >=0 ? qname.substring(0, pos) : "";
+ }
+
+ /**
+ * Returns the local name of the given <code>qname</code>. Please note, that
+ * this method does not validate the name.
+ * </p>
+ * the qname has the format: qname := [prefix ':'] local;
+ *
+ * @param qname a qualified name
+ * @return the localname
+ *
+ * @see #getNamespacePrefix(String)
+ *
+ * @throws NullPointerException if <code>qname</code> is <code>null</code>
+ */
+ public static String getLocalName(String qname) {
+ int pos = qname.indexOf(':');
+ return pos >=0 ? qname.substring(pos+1) : qname;
+ }
+
+ /**
+ * Determines, if two paths denote hierarchical siblins.
+ *
+ * @param p1 first path
+ * @param p2 second path
+ * @return true if on same level, false otherwise
+ */
+ public static boolean isSibling(String p1, String p2) {
+ int pos1 = p1.lastIndexOf('/');
+ int pos2 = p2.lastIndexOf('/');
+ return (pos1 == pos2 && pos1 >= 0 && p1.regionMatches(0, p2, 0, pos1));
+ }
+
+ /**
+ * Determines if the <code>descendant</code> path is hierarchical a
+ * descendant of <code>path</code>.
+ *
+ * @param path the current path
+ * @param descendant the potential descendant
+ * @return <code>true</code> if the <code>descendant</code> is a descendant;
+ * <code>false</code> otherwise.
+ */
+ public static boolean isDescendant(String path, String descendant) {
+ String pattern = path.endsWith("/") ? path : path + "/";
+ return !pattern.equals(descendant) &&
+ descendant.startsWith(pattern);
+ }
+
+ /**
+ * Determines if the <code>descendant</code> path is hierarchical a
+ * descendant of <code>path</code> or equal to it.
+ *
+ * @param path the path to check
+ * @param descendant the potential descendant
+ * @return <code>true</code> if the <code>descendant</code> is a descendant
+ * or equal; <code>false</code> otherwise.
+ */
+ public static boolean isDescendantOrEqual(String path, String descendant) {
+ if (path.equals(descendant)) {
+ return true;
+ } else {
+ String pattern = path.endsWith("/") ? path : path + "/";
+ return descendant.startsWith(pattern);
+ }
+ }
+
+ /**
+ * Returns the n<sup>th</sup> relative parent of the path, where n=level.
+ * <p>Example:<br>
+ * <code>
+ * Text.getRelativeParent("/foo/bar/test", 1) == "/foo/bar"
+ * </code>
+ *
+ * @param path the path of the page
+ * @param level the level of the parent
+ */
+ public static String getRelativeParent(String path, int level) {
+ int idx = path.length();
+ while (level > 0) {
+ idx = path.lastIndexOf('/', idx - 1);
+ if (idx < 0) {
+ return "";
+ }
+ level--;
+ }
+ return (idx == 0) ? "/" : path.substring(0, idx);
+ }
+
+ /**
+ * Same as {@link #getRelativeParent(String, int)} but adding the possibility
+ * to pass paths that end with a trailing '/'
+ *
+ * @see #getRelativeParent(String, int)
+ */
+ public static String getRelativeParent(String path, int level, boolean ignoreTrailingSlash) {
+ if (ignoreTrailingSlash && path.endsWith("/") && path.length() > 1) {
+ path = path.substring(0, path.length()-1);
+ }
+ return getRelativeParent(path, level);
+ }
+
+ /**
+ * Returns the n<sup>th</sup> absolute parent of the path, where n=level.
+ * <p>Example:<br>
+ * <code>
+ * Text.getAbsoluteParent("/foo/bar/test", 1) == "/foo/bar"
+ * </code>
+ *
+ * @param path the path of the page
+ * @param level the level of the parent
+ */
+ public static String getAbsoluteParent(String path, int level) {
+ int idx = 0;
+ int len = path.length();
+ while (level >= 0 && idx < len) {
+ idx = path.indexOf('/', idx + 1);
+ if (idx < 0) {
+ idx = len;
+ }
+ level--;
+ }
+ return level >= 0 ? "" : path.substring(0, idx);
+ }
+
+ /**
+ * Performs variable replacement on the given string value.
+ * Each <code>${...}</code> sequence within the given value is replaced
+ * with the value of the named parser variable. If a variable is not found
+ * in the properties an IllegalArgumentException is thrown unless
+ * <code>ignoreMissing</code> is <code>true</code>. In the later case, the
+ * missing variable is replaced by the empty string.
+ *
+ * @param value the original value
+ * @param ignoreMissing if <code>true</code>, missing variables are replaced
+ * by the empty string.
+ * @return value after variable replacements
+ * @throws IllegalArgumentException if the replacement of a referenced
+ * variable is not found
+ */
+ public static String replaceVariables(Properties variables, String value,
+ boolean ignoreMissing)
+ throws IllegalArgumentException {
+ StringBuffer result = new StringBuffer();
+
+ // Value:
+ // +--+-+--------+-+-----------------+
+ // | |p|--> |q|--> |
+ // +--+-+--------+-+-----------------+
+ int p = 0, q = value.indexOf("${"); // Find first ${
+ while (q != -1) {
+ result.append(value.substring(p, q)); // Text before ${
+ p = q;
+ q = value.indexOf("}", q + 2); // Find }
+ if (q != -1) {
+ String variable = value.substring(p + 2, q);
+ String replacement = variables.getProperty(variable);
+ if (replacement == null) {
+ if (ignoreMissing) {
+ replacement = "";
+ } else {
+ throw new IllegalArgumentException(
+ "Replacement not found for ${" + variable + "}.");
+ }
+ }
+ result.append(replacement);
+ p = q + 1;
+ q = value.indexOf("${", p); // Find next ${
+ }
+ }
+ result.append(value.substring(p, value.length())); // Trailing text
+
+ return result.toString();
+ }
+
+ private static byte decodeDigit(byte b) {
+ if (b >= 0x30 && b <= 0x39) {
+ return (byte) (b - 0x30);
+ }
+ else if (b >= 0x41 && b <= 0x46) {
+ return (byte) (b - 0x37);
+ }
+ else if (b >= 0x61 && b <= 0x66) {
+ return (byte) (b - 0x57);
+ }
+ else {
+ throw new IllegalArgumentException("Escape sequence is not hexadecimal: " + (char)b);
+ }
+ }
+
+}
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Uri.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Uri.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Uri.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Uri.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,357 @@
+/*
+ * 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 cgl.shindig.common;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+* Represents a Uniform Resource Identifier (URI) reference as defined by <a
+* href="http://tools.ietf.org/html/rfc3986">RFC 3986</a>.
+*
+* Assumes that all url components are UTF-8 encoded.
+*/
+public final class Uri {
+ private final String text;
+ private final String scheme;
+ private final String authority;
+ private final String path;
+ private final String query;
+ private final String fragment;
+
+ private final Map<String, List<String>> queryParameters;
+
+ private static UriParser parser = new DefaultUriParser();
+
+ @Inject(optional = true)
+ public static void setUriParser(UriParser uriParser) {
+ parser = uriParser;
+ }
+
+ Uri(UriBuilder builder) {
+ scheme = builder.getScheme();
+ authority = builder.getAuthority();
+ path = builder.getPath();
+ query = builder.getQuery();
+ fragment = builder.getFragment();
+ queryParameters
+ = Collections.unmodifiableMap(Maps.newLinkedHashMap(builder.getQueryParameters()));
+
+ StringBuilder out = new StringBuilder();
+
+ if (scheme != null) {
+ out.append(scheme).append(':');
+ }
+ if (authority != null) {
+ out.append("//").append(authority);
+ }
+ if (path != null) {
+ out.append(path);
+ }
+ if (query != null) {
+ out.append('?').append(query);
+ }
+ if (fragment != null) {
+ out.append('#').append(fragment);
+ }
+ text = out.toString();
+ }
+
+ /**
+ * Produces a new Uri from a text representation.
+ *
+ * @param text The text uri.
+ * @return A new Uri, parsed into components.
+ */
+ public static Uri parse(String text) {
+ return parser.parse(text);
+ }
+
+ /**
+ * Convert a java.net.URI to a Uri.
+ */
+ public static Uri fromJavaUri(URI uri) {
+ if (uri.isOpaque()) {
+ throw new IllegalArgumentException("No support for opaque Uris " + uri.toString());
+ }
+ return new UriBuilder()
+ .setScheme(uri.getScheme())
+ .setAuthority(uri.getRawAuthority())
+ .setPath(uri.getRawPath())
+ .setQuery(uri.getRawQuery())
+ .setFragment(uri.getRawFragment())
+ .toUri();
+ }
+
+ /**
+ * @return a java.net.URI equal to this Uri.
+ */
+ public URI toJavaUri() {
+ try {
+ return new URI(toString());
+ } catch (URISyntaxException e) {
+ // Shouldn't ever happen.
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Derived from Harmony
+ * Resolves a given url relative to this url. Resolution rules are the same as for
+ * {@code java.net.URI.resolve(URI)}
+ */
+ public Uri resolve(Uri relative) {
+ if (relative == null) {
+ return null;
+ }
+ if (relative.isAbsolute()) {
+ return relative;
+ }
+
+ UriBuilder result;
+ if (StringUtils.isEmpty(relative.path) && relative.scheme == null
+ && relative.authority == null && relative.query == null
+ && relative.fragment != null) {
+ // if the relative URI only consists of fragment,
+ // the resolved URI is very similar to this URI,
+ // except that it has the fragement from the relative URI.
+ result = new UriBuilder(this);
+ result.setFragment(relative.fragment);
+ } else if (relative.scheme != null) {
+ result = new UriBuilder(relative);
+ } else if (relative.authority != null) {
+ // if the relative URI has authority,
+ // the resolved URI is almost the same as the relative URI,
+ // except that it has the scheme of this URI.
+ result = new UriBuilder(relative);
+ result.setScheme(scheme);
+ } else {
+ // since relative URI has no authority,
+ // the resolved URI is very similar to this URI,
+ // except that it has the query and fragment of the relative URI,
+ // and the path is different.
+ result = new UriBuilder(this);
+ result.setFragment(relative.fragment);
+ result.setQuery(relative.query);
+ String relativePath = (relative.path == null) ? "" : relative.path;
+ if (relativePath.startsWith("/")) { //$NON-NLS-1$
+ result.setPath(relativePath);
+ } else {
+ // resolve a relative reference
+ int endindex = path.lastIndexOf('/') + 1;
+ result.setPath(normalizePath(path.substring(0, endindex) + relativePath));
+ }
+ }
+ Uri resolved = result.toUri();
+ validate(resolved);
+ return resolved;
+ }
+
+ private static void validate(Uri uri) {
+ if (StringUtils.isEmpty(uri.authority) &&
+ StringUtils.isEmpty(uri.path) &&
+ StringUtils.isEmpty(uri.query)) {
+ throw new IllegalArgumentException("Invalid scheme-specific part");
+ }
+ }
+
+ /**
+ * Dervived from harmony
+ * normalize path, and return the resulting string
+ */
+ private static String normalizePath(String path) {
+ // count the number of '/'s, to determine number of segments
+ int index = -1;
+ int pathlen = path.length();
+ int size = 0;
+ if (pathlen > 0 && path.charAt(0) != '/') {
+ size++;
+ }
+ while ((index = path.indexOf('/', index + 1)) != -1) {
+ if (index + 1 < pathlen && path.charAt(index + 1) != '/') {
+ size++;
+ }
+ }
+
+ String[] seglist = new String[size];
+ boolean[] include = new boolean[size];
+
+ // break the path into segments and store in the list
+ int current = 0;
+ int index2 = 0;
+ index = (pathlen > 0 && path.charAt(0) == '/') ? 1 : 0;
+ while ((index2 = path.indexOf('/', index + 1)) != -1) {
+ seglist[current++] = path.substring(index, index2);
+ index = index2 + 1;
+ }
+
+ // if current==size, then the last character was a slash
+ // and there are no more segments
+ if (current < size) {
+ seglist[current] = path.substring(index);
+ }
+
+ // determine which segments get included in the normalized path
+ for (int i = 0; i < size; i++) {
+ include[i] = true;
+ if (seglist[i].equals("..")) { //$NON-NLS-1$
+ int remove = i - 1;
+ // search back to find a segment to remove, if possible
+ while (remove > -1 && !include[remove]) {
+ remove--;
+ }
+ // if we find a segment to remove, remove it and the ".."
+ // segment
+ if (remove > -1 && !seglist[remove].equals("..")) { //$NON-NLS-1$
+ include[remove] = false;
+ include[i] = false;
+ }
+ } else if (seglist[i].equals(".")) { //$NON-NLS-1$
+ include[i] = false;
+ }
+ }
+
+ // put the path back together
+ StringBuilder newpath = new StringBuilder();
+ if (path.startsWith("/")) { //$NON-NLS-1$
+ newpath.append('/');
+ }
+
+ for (int i = 0; i < seglist.length; i++) {
+ if (include[i]) {
+ newpath.append(seglist[i]);
+ newpath.append('/');
+ }
+ }
+
+ // if we used at least one segment and the path previously ended with
+ // a slash and the last segment is still used, then delete the extra
+ // trailing '/'
+ if (!path.endsWith("/") && seglist.length > 0 //$NON-NLS-1$
+ && include[seglist.length - 1]) {
+ newpath.deleteCharAt(newpath.length() - 1);
+ }
+
+ String result = newpath.toString();
+
+ // check for a ':' in the first segment if one exists,
+ // prepend "./" to normalize
+ index = result.indexOf(':');
+ index2 = result.indexOf('/');
+ if (index != -1 && (index < index2 || index2 == -1)) {
+ newpath.insert(0, "./"); //$NON-NLS-1$
+ result = newpath.toString();
+ }
+ return result;
+ }
+
+ /**
+ * @return True if the Uri is absolute.
+ */
+ public boolean isAbsolute() {
+ return scheme != null && authority != null;
+ }
+
+ /**
+ * @return The scheme part of the uri, or null if none was specified.
+ */
+ public String getScheme() {
+ return scheme;
+ }
+
+ /**
+ * @return The authority part of the uri, or null if none was specified.
+ */
+ public String getAuthority() {
+ return authority;
+ }
+
+ /**
+ * @return The path part of the uri, or null if none was specified.
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * @return The query part of the uri, or null if none was specified.
+ */
+ public String getQuery() {
+ return query;
+ }
+
+ /**
+ * @return The query part of the uri, separated into component parts.
+ */
+ public Map<String, List<String>> getQueryParameters() {
+ return queryParameters;
+ }
+
+ /**
+ * @return All query parameters with the given name.
+ */
+ public Collection<String> getQueryParameters(String name) {
+ return queryParameters.get(name);
+ }
+
+ /**
+ * @return The first query parameter value with the given name.
+ */
+ public String getQueryParameter(String name) {
+ Collection<String> values = queryParameters.get(name);
+ if (values == null || values.isEmpty()) {
+ return null;
+ }
+ return values.iterator().next();
+ }
+
+ /**
+ * @return The uri fragment.
+ */
+ public String getFragment() {
+ return fragment;
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+
+ @Override
+ public int hashCode() {
+ return text.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {return true;}
+ if (!(obj instanceof Uri)) {return false;}
+ return Objects.equal(text, ((Uri)obj).text);
+ }
+}
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/UriBuilder.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/UriBuilder.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/UriBuilder.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/UriBuilder.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,289 @@
+/*
+ * 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 cgl.shindig.common;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Constructs Uris from inputs.
+ *
+ * Note that the builder will only automatically encode query parameters that are added. Other
+ * parameters must be encoded explicitly.
+ */
+public class UriBuilder {
+ private static final Pattern QUERY_PATTERN = Pattern.compile("([^&=]+)=([^&=]*)");
+
+ private String scheme;
+ private String authority;
+ private String path;
+ private String query;
+ private String fragment;
+ private final Map<String, List<String>> queryParameters;
+
+
+ /**
+ * Construct a new builder from an existing uri.
+ */
+ public UriBuilder(Uri uri) {
+ scheme = uri.getScheme();
+ authority = uri.getAuthority();
+ path = uri.getPath();
+ query = uri.getQuery();
+ fragment = uri.getFragment();
+
+ queryParameters = Maps.newLinkedHashMap(uri.getQueryParameters());
+ }
+
+ /**
+ * Create an empty builder.
+ */
+ public UriBuilder() {
+ queryParameters = Maps.newLinkedHashMap();
+ }
+
+ /**
+ * Construct a builder by parsing a string.
+ */
+ public static UriBuilder parse(String text) {
+ return new UriBuilder(Uri.parse(text));
+ }
+
+ /**
+ * Convert the builder to a Uri.
+ */
+ public Uri toUri() {
+ return new Uri(this);
+ }
+
+ /**
+ * @return The scheme part of the uri, or null if none was specified.
+ */
+ public String getScheme() {
+ return scheme;
+ }
+
+ public UriBuilder setScheme(String scheme) {
+ this.scheme = scheme;
+ return this;
+ }
+
+ /**
+ * @return The authority part of the uri, or null if none was specified.
+ */
+ public String getAuthority() {
+ return authority;
+ }
+
+ public UriBuilder setAuthority(String authority) {
+ this.authority = authority;
+ return this;
+ }
+
+ /**
+ * @return The path part of the uri, or null if none was specified.
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * Sets the path component of the Uri.
+ */
+ public UriBuilder setPath(String path) {
+ this.path = path;
+ return this;
+ }
+
+ /**
+ * @return The query part of the uri, or null if none was specified.
+ */
+ public String getQuery() {
+ if (query == null) {
+ query = joinParameters(queryParameters);
+ }
+ return query;
+ }
+
+ /**
+ * Assigns the specified query string as the query portion of the uri, automatically decoding
+ * parameters to populate the parameter map for calls to getParameter.
+ */
+ public UriBuilder setQuery(String query) {
+ queryParameters.clear();
+ queryParameters.putAll(splitParameters(query));
+ this.query = query;
+ return this;
+ }
+
+ public UriBuilder addQueryParameter(String name, String value) {
+ query = null;
+ List<String> params = queryParameters.get(name);
+ if (params == null) {
+ params = Lists.newArrayList();
+ queryParameters.put(name, params);
+ }
+ params.add(value);
+ return this;
+ }
+
+ public UriBuilder addQueryParameters(Map<String, String> parameters) {
+ query = null;
+ for (Map.Entry<String, String> entry : parameters.entrySet()) {
+ addQueryParameter(entry.getKey(), entry.getValue());
+ }
+ return this;
+ }
+
+ /**
+ * Force overwrites a given query parameter with the given value.
+ */
+ public UriBuilder putQueryParameter(String name, String... values) {
+ query = null;
+ queryParameters.put(name, Lists.newArrayList(values));
+ return this;
+ }
+
+ /**
+ * Force overwrites a given query parameter with the given value.
+ */
+ public UriBuilder putQueryParameter(String name, Iterable<String> values) {
+ query = null;
+ queryParameters.put(name, Lists.newArrayList(values));
+ return this;
+ }
+
+ /**
+ * Removes a query parameter.
+ */
+ public UriBuilder removeQueryParameter(String name) {
+ query = null;
+ queryParameters.remove(name);
+ return this;
+ }
+
+ /**
+ * @return The queryParameters part of the uri, separated into component parts.
+ */
+ public Map<String, List<String>> getQueryParameters() {
+ return queryParameters;
+ }
+
+ /**
+ * @return All queryParameters parameters with the given name.
+ */
+ public List<String> getQueryParameters(String name) {
+ return queryParameters.get(name);
+ }
+
+ /**
+ * @return The first queryParameters parameter value with the given name.
+ */
+ public String getQueryParameter(String name) {
+ Collection<String> values = queryParameters.get(name);
+ if (values == null || values.isEmpty()) {
+ return null;
+ }
+ return values.iterator().next();
+ }
+
+ /**
+ * @return The queryParameters fragment.
+ */
+ public String getFragment() {
+ return fragment;
+ }
+
+ public UriBuilder setFragment(String fragment) {
+ this.fragment = fragment;
+ return this;
+ }
+
+ /**
+ * Utility method for joining key / value pair parameters into a url-encoded string.
+ */
+ static String joinParameters(Map<String, List<String>> query) {
+ if (query.isEmpty()) {
+ return null;
+ }
+ StringBuilder buf = new StringBuilder();
+ boolean firstDone = false;
+ for (Map.Entry<String, List<String>> entry : query.entrySet()) {
+ String name = Utf8UrlCoder.encode(entry.getKey());
+ for (String value : entry.getValue()) {
+ if (firstDone) {
+ buf.append('&');
+ }
+ firstDone = true;
+
+ buf.append(name)
+ .append('=')
+ .append(Utf8UrlCoder.encode(value));
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Utility method for splitting a parameter string into key / value pairs.
+ */
+ public static Map<String, List<String>> splitParameters(String query) {
+ if (query == null) {
+ return Collections.emptyMap();
+ }
+ Map<String, List<String>> params = Maps.newHashMap();
+ Matcher paramMatcher = QUERY_PATTERN.matcher(query);
+ while (paramMatcher.find()) {
+ String name = Utf8UrlCoder.decode(paramMatcher.group(1));
+ String value = Utf8UrlCoder.decode(paramMatcher.group(2));
+ List<String> values = params.get(name);
+ if (values == null) {
+ values = Lists.newArrayList();
+ params.put(name, values);
+ }
+ values.add(value);
+ }
+ return Collections.unmodifiableMap(params);
+ }
+
+ @Override
+ public String toString() {
+ return toUri().toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return toUri().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {return true;}
+ if (!(obj instanceof UriBuilder)) {return false;}
+
+ return toString().equals(obj.toString());
+ }
+}
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/UriParser.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/UriParser.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/UriParser.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/UriParser.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,32 @@
+/*
+ * 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 cgl.shindig.common;
+
+/**
+ * An injectable interface for parsing Uris out of String text.
+ */
+public interface UriParser {
+ /**
+ * Produces a new Uri from a text representation.
+ *
+ * @param text The text uri.
+ * @return A new Uri, parsed into components.
+ */
+ public Uri parse(String text);
+}
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Utf8UrlCoder.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Utf8UrlCoder.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Utf8UrlCoder.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Utf8UrlCoder.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,47 @@
+/*
+ * 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 cgl.shindig.common;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+/**
+ * Performs url encoding / decoding with forced utf-8. Automatically takes care
+ * of boilerplate exception handling.
+ */
+public class Utf8UrlCoder {
+
+ public static String encode(String input) {
+ try {
+ return URLEncoder.encode(input, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String decode(String input) {
+ try {
+ return URLDecoder.decode(input, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Util.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Util.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Util.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/Util.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,35 @@
+/**
+ *
+ */
+package cgl.shindig.common;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+/**
+ * @author gerald
+ *
+ */
+public class Util {
+ public static boolean isEmpty(String str) {
+ return str == null || str.length() == 0;
+ }
+}
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/X509CertUtil.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/X509CertUtil.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/X509CertUtil.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/common/X509CertUtil.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,52 @@
+/**
+ *
+ */
+package cgl.shindig.common;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import java.security.cert.X509Certificate;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * @author gerald
+ *
+ */
+public class X509CertUtil {
+ public static String extractCN(X509Certificate cert) {
+ X500Principal principal = cert.getSubjectX500Principal();
+ String rfc2253dn = principal.getName(X500Principal.RFC2253);
+ String parts[] = rfc2253dn.split(",");
+ for (int i = 0; i < parts.length; ++i) {
+ String part = parts[i];
+ String keyvalue[] = part.split("=");
+ if (keyvalue == null || keyvalue.length != 2)
+ continue;
+ String key = keyvalue[0], value = keyvalue[1];
+ if (key.equalsIgnoreCase("CN")) {
+ return value;
+ }
+ }
+ return null;
+ }
+}
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/AccessManagerConfig.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/AccessManagerConfig.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/AccessManagerConfig.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/AccessManagerConfig.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,45 @@
+package cgl.shindig.config;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+/**
+ * Access manager configuration. This bean configuration class
+ * is used to create configured access manager objects.
+ * <p>
+ * This class is currently only used to assign a static type to
+ * more generic bean configuration information.
+ *
+ * @see SecurityConfig#getAccessManagerConfig()
+ */
+public class AccessManagerConfig extends BeanConfig {
+
+ /**
+ * Creates an access manager configuration object from the
+ * given bean configuration.
+ *
+ * @param config bean configuration
+ */
+ public AccessManagerConfig(BeanConfig config) {
+ super(config);
+ }
+
+}
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/BeanConfig.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/BeanConfig.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/BeanConfig.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/BeanConfig.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,270 @@
+package cgl.shindig.config;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import org.apache.commons.collections.BeanMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Properties;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Collections;
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * Bean configuration class. BeanConfig instances contain the class name
+ * and property information required to instantiate a class that conforms
+ * with the JavaBean conventions.
+ */
+public class BeanConfig<T> {
+
+ private static Logger log = LoggerFactory.getLogger(BeanConfig.class);
+
+ private static final Map<String, String> DEPRECATIONS;
+
+ static {
+ try {
+ Map<String, String> temp = new HashMap<String, String>();
+ Properties props = new Properties();
+ InputStream in = BeanConfig.class.getResourceAsStream("deprecated-classes.properties");
+ if (in!=null) {
+ try {
+ props.load(in);
+ } finally {
+ in.close();
+ }
+ }
+ for (Map.Entry<Object, Object> entry : props.entrySet()) {
+ temp.put(entry.getKey().toString(), entry.getValue().toString());
+ }
+ DEPRECATIONS = Collections.unmodifiableMap(temp);
+ } catch (IOException e) {
+ throw new InternalError("failed to read deprecated classes");
+ }
+ }
+
+ /** The default class loader used by all instances of this class */
+ private static ClassLoader defaultClassLoader =
+ BeanConfig.class.getClassLoader();
+
+ /**
+ * The current class loader used by this instance to create instances of
+ * configured classes.
+ */
+ private ClassLoader classLoader = getDefaultClassLoader();
+
+ /**
+ * The class name of the configured bean.
+ */
+ private final String className;
+
+ /**
+ * The initial properties of the configured bean.
+ */
+ private final Properties properties;
+
+ /**
+ * Flag to validate the configured bean property names against
+ * the configured bean class. By default this is <code>true</code>
+ * to prevent incorrect property names. However, in some cases this
+ * validation should not be performed as client classes may access
+ * the configuration parameters directly through the
+ * {@link #getParameters()} method.
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/JCR-1920">JCR-1920</a>
+ */
+ private boolean validate = true;
+
+ /**
+ * Creates a bean configuration. Note that a copy of the given
+ * bean properties is stored as a part of the created configuration
+ * object. Thus the caller is free to modify the given properties
+ * once the configuration object has been created.
+ *
+ * @param className class name of the bean
+ * @param properties initial properties of the bean
+ */
+ public BeanConfig(String className, Properties properties) {
+ if (DEPRECATIONS.containsKey(className)) {
+ String replacement = DEPRECATIONS.get(className);
+ log.info("{} is deprecated. Please use {} instead", className, replacement);
+ className = replacement;
+ }
+ this.className = className;
+ this.properties = (Properties) properties.clone();
+ }
+
+ /**
+ * Copies a bean configuration.
+ *
+ * @param config the configuration to be copied
+ */
+ public BeanConfig(BeanConfig config) {
+ this(config.getClassName(), config.getParameters());
+ }
+
+ /**
+ * Allows subclasses to control whether the configured bean property
+ * names should be validated.
+ *
+ * @param validate flag to validate the configured property names
+ */
+ protected void setValidate(boolean validate) {
+ this.validate = validate;
+ }
+
+ /**
+ * Returns the class name of the configured bean.
+ *
+ * @return class name of the bean
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * Returns the initial properties of the configured bean.
+ *
+ * @return initial properties of the bean
+ */
+ public Properties getParameters() {
+ return properties;
+ }
+
+ /**
+ * Creates a new instance of the configured bean class.
+ *
+ * @return new bean instance
+ * @throws ConfigurationException on bean configuration errors
+ */
+ public Object newInstance() throws ConfigurationException {
+ try {
+ // Instantiate the object using the default constructor
+ Class<?> objectClass =
+ Class.forName(getClassName(), true, getClassLoader());
+ Object object = objectClass.newInstance();
+
+ // Set all configured bean properties
+ BeanMap map = new BeanMap(object);
+ for (Object key : map.keySet()) {
+ String value = properties.getProperty(key.toString());
+ if (value != null) {
+ map.put(key, value);
+ }
+ }
+
+ if (validate) {
+ // Check that no invalid property names were configured
+ for (Object key : properties.keySet()) {
+ if (!map.containsKey(key)
+ && properties.getProperty(key.toString()) != null) {
+ String msg =
+ "Configured class " + object.getClass().getName()
+ + " does not contain the property " + key
+ + ". Please fix the repository configuration.";
+ log.error(msg);
+ throw new ConfigurationException(msg);
+ }
+ }
+ }
+
+ return (T) object;
+ } catch (ClassNotFoundException e) {
+ throw new ConfigurationException(
+ "Configured bean implementation class " + getClassName()
+ + " was not found.", e);
+ } catch (InstantiationException e) {
+ throw new ConfigurationException(
+ "Configured bean implementation class " + getClassName()
+ + " can not be instantiated.", e);
+ } catch (IllegalAccessException e) {
+ throw new ConfigurationException(
+ "Configured bean implementation class " + getClassName()
+ + " is protected.", e);
+ }
+ }
+
+ //---------- Configurable class loader support ----------------------------
+
+ /**
+ * Returns the current <code>ClassLoader</code> used to instantiate objects
+ * in the {@link #newInstance()} method.
+ *
+ * @see #newInstance()
+ * @see #setClassLoader(ClassLoader)
+ * @see #getDefaultClassLoader()
+ * @see #setDefaultClassLoader(ClassLoader)
+ */
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ /**
+ * Sets the <code>ClassLoader</code> used to instantiate objects in the
+ * {@link #newInstance()} method.
+ *
+ * @param classLoader The class loader to set on this instance. If this is
+ * <code>null</code> the system class loader will be used, which may
+ * lead to unexpected class loading failures.
+ *
+ * @see #newInstance()
+ * @see #getClassLoader()
+ * @see #getDefaultClassLoader()
+ * @see #setDefaultClassLoader(ClassLoader)
+ */
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ /**
+ * Returns the current <code>ClassLoader</code> used for new instances of
+ * this class as the loader used to instantiate objects in the
+ * {@link #newInstance()} method.
+ *
+ * @see #newInstance()
+ * @see #getClassLoader()
+ * @see #setClassLoader(ClassLoader)
+ * @see #setDefaultClassLoader(ClassLoader)
+ */
+ public static ClassLoader getDefaultClassLoader() {
+ return defaultClassLoader;
+ }
+
+ /**
+ * Sets the <code>ClassLoader</code> used for new instances of this class as
+ * the loader to instantiate objects in the {@link #newInstance()} method.
+ *
+ * @param classLoader The class loader to set as the default class loader.
+ * If this is <code>null</code> the system class loader will be used,
+ * which may lead to unexpected class loading failures.
+ *
+ * @see #newInstance()
+ * @see #getClassLoader()
+ * @see #setClassLoader(ClassLoader)
+ * @see #getDefaultClassLoader()
+ */
+ public static void setDefaultClassLoader(ClassLoader classLoader) {
+ defaultClassLoader = classLoader;
+ }
+}
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/ConfigurationException.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/ConfigurationException.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/ConfigurationException.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/ConfigurationException.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,48 @@
+package cgl.shindig.config;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+/**
+ * Exception class used for configuration errors.
+ */
+public class ConfigurationException extends Exception {
+
+ /**
+ * Creates a configuration exception.
+ *
+ * @param message configuration message
+ */
+ public ConfigurationException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a configuration exception that is caused by another exception.
+ *
+ * @param message configuration error message
+ * @param cause root cause of the configuration error
+ */
+ public ConfigurationException(String message, Exception cause) {
+ super(message, cause);
+ }
+
+}
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/ConfigurationParser.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/ConfigurationParser.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/ConfigurationParser.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/ConfigurationParser.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,320 @@
+package cgl.shindig.config;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+// import org.apache.jackrabbit.util.Text;
+
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.commons.configuration.SubnodeConfiguration;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.commons.configuration.tree.ConfigurationNode;
+
+
+public class ConfigurationParser {
+
+ /** Name of the bean parameter configuration element. */
+ public static final String PARAM_ELEMENT = "param";
+
+ /** Name of the bean implementation class configuration attribute. */
+ public static final String CLASS_ATTRIBUTE = "class";
+
+ /** Name of the bean parameter name configuration attribute. */
+ public static final String NAME_ATTRIBUTE = "name";
+
+ /** Name of the bean parameter value configuration attribute. */
+ public static final String VALUE_ATTRIBUTE = "value";
+
+ /**
+ * The configuration parser variables. These name-value pairs
+ * are used to substitute <code>${...}</code> variable references
+ * with context-dependent values in the configuration.
+ *
+ * @see #replaceVariables(String)
+ */
+ private final Properties variables;
+
+ /**
+ * Creates a new configuration parser with the given parser variables.
+ *
+ * @param variables parser variables
+ */
+ public ConfigurationParser(Properties variables) {
+ this.variables = variables;
+ }
+
+ /**
+ * Returns the variables.
+ * @return the variables.
+ */
+ public Properties getVariables() {
+ return variables;
+ }
+
+ protected BeanConfig parseBeanConfig(HierarchicalConfiguration parent, String name)
+ throws ConfigurationException {
+ // Bean configuration element
+ HierarchicalConfiguration config = getSubConfig(parent, name);
+
+ // Bean implementation class
+ String className = getAttribute(config, CLASS_ATTRIBUTE);
+
+ // Bean properties
+ Properties properties = parseParameters(config);
+
+ return new BeanConfig(className, properties);
+ }
+
+ /**
+ * Parses a named bean configuration from the given element.
+ * Bean configuration uses the following format:
+ * <pre>
+ * <BeanName class="...">
+ * <param name="..." value="..."/>
+ * ...
+ * </BeanName>
+ * </pre>
+ * <p>
+ * The returned bean configuration object contains the configured
+ * class name and configuration parameters. Variable replacement
+ * is performed on the parameter values.
+ *
+ * @param element
+ * @return bean configuration,
+ * @throws ConfigurationException if the configuration element does not
+ * exist or is broken
+ */
+ protected BeanConfig parseBeanConfig(HierarchicalConfiguration element)
+ throws ConfigurationException {
+ // Bean implementation class
+ String className = getAttribute(element, CLASS_ATTRIBUTE);
+
+ // Bean properties
+ Properties properties = parseParameters(element);
+
+ return new BeanConfig(className, properties);
+ }
+
+ /**
+ * Parses the configuration parameters of the given element.
+ * Parameters are stored as
+ * <code><param name="..." value="..."/></code>
+ * child elements. This method parses all param elements,
+ * performs {@link #replaceVariables(String) variable replacement}
+ * on parameter values, and returns the resulting name-value pairs.
+ *
+ * @param element configuration element
+ * @return configuration parameters
+ * @throws ConfigurationException if a <code>param</code> element does
+ * not contain the <code>name</code> and
+ * <code>value</code> attributes
+ */
+ protected Properties parseParameters(HierarchicalConfiguration config)
+ throws ConfigurationException {
+ Properties parameters = new Properties();
+
+ List params = config.configurationsAt(PARAM_ELEMENT);
+ for(Iterator it = params.iterator(); it.hasNext();) {
+ // HierarchicalConfiguration sub = (HierarchicalConfiguration)it.next();
+ SubnodeConfiguration sub = (SubnodeConfiguration)it.next();
+
+ String name = null;
+ String value = null;
+ // String name = sub.getString("@" + NAME_ATTRIBUTE);
+ // String value = sub.getString("@" + VALUE_ATTRIBUTE);
+ List nameAtts = sub.getRootNode().getAttributes(NAME_ATTRIBUTE);
+ List valueAtts = sub.getRootNode().getAttributes(VALUE_ATTRIBUTE);
+ if (nameAtts != null && nameAtts.size() > 0) {
+ ConfigurationNode nameAttNode = (ConfigurationNode)nameAtts.get(0);
+ name = (String)nameAttNode.getValue();
+ }
+ if (valueAtts != null && valueAtts.size() > 0) {
+ ConfigurationNode valueAttNode = (ConfigurationNode)valueAtts.get(0);
+ value = (String)valueAttNode.getValue();
+ }
+
+ if (name == null && value != null) {
+ throw new ConfigurationException("Parameter name not set");
+ } else if (name != null && value == null) {
+ throw new ConfigurationException("Parameter value not set");
+ } else if (name == null && value == null) {
+ throw new ConfigurationException("Parameter name and value not set");
+ }
+ parameters.put(name.trim(), replaceVariables(value));
+ }
+ return parameters;
+ }
+
+ /**
+ * Performs variable replacement on the given string value.
+ * Each <code>${...}</code> sequence within the given value is replaced
+ * with the value of the named parser variable. The replacement is not
+ * done if the named variable does not exist.
+ *
+ * @param value original value
+ * @return value after variable replacements
+ * @throws ConfigurationException if the replacement of a referenced
+ * variable is not found
+ */
+ protected String replaceVariables(String value)
+ throws ConfigurationException {
+ try {
+ // return Text.replaceVariables(variables, value, false);
+ return value;
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Parses the given XML document and returns the DOM root element.
+ * A custom entity resolver is used to make the included configuration
+ * file DTD available using the specified public identifiers.
+ *
+ * @see ConfigurationEntityResolver
+ * @param xml xml document
+ * @param validate wheter the XML should be validated
+ * @return root element
+ * @throws ConfigurationException if the configuration document could
+ * not be read or parsed
+ */
+ protected HierarchicalConfiguration parseXML(InputStream xml, boolean validate)
+ throws ConfigurationException {
+ try {
+ XMLConfiguration config = new XMLConfiguration();
+ config.setValidating(validate);
+ config.load(xml);
+ return config;
+ } catch (Exception e) {
+ throw new ConfigurationException(
+ "Configuration file could not be read.", e);
+ }
+ }
+
+ /**
+ * Returns the named child of the given parent element.
+ *
+ * @param parent parent element
+ * @param name name of the child element
+ * @return named child element
+ * @throws ConfigurationException
+ * @throws ConfigurationException if the child element is not found
+ */
+ protected HierarchicalConfiguration getSubConfig(HierarchicalConfiguration parent, String name)
+ throws ConfigurationException {
+ return getSubConfig(parent, name, true);
+ }
+
+ /**
+ * Returns the named child of the given parent element.
+ *
+ * @param parent parent element
+ * @param name name of the child element
+ * @param required indicates if the child element is required
+ * @return named child element, or <code>null</code> if not found and
+ * <code>required</code> is <code>false</code>.
+ * @throws ConfigurationException if the child element is not found and
+ * <code>required</code> is <code>true</code>;
+ * or if more than one element with this name exists.
+ */
+ protected HierarchicalConfiguration getSubConfig(
+ HierarchicalConfiguration parent, String name, boolean required)
+ throws ConfigurationException {
+
+ List subs = parent.configurationsAt(name);
+ if (subs.size() > 1) {
+ throw new ConfigurationException(
+ "Duplicate configuration element " + name + " in "
+ + parent.toString() + ".");
+ }
+ if (required && subs.size() == 0) {
+ throw new ConfigurationException(
+ "Configuration element " + name + " not found in "
+ + parent.toString() + ".");
+ }
+ return (HierarchicalConfiguration)subs.get(0);
+ }
+
+ /**
+ * Returns the value of the named attribute of the given element.
+ *
+ * @param element element
+ * @param name attribute name
+ * @return attribute value
+ * @throws ConfigurationException if the attribute is not found
+ */
+ protected String getAttribute(HierarchicalConfiguration config, String name)
+ throws ConfigurationException {
+ // String attribute = config.getString("@" + name);
+ SubnodeConfiguration xmlconfig = (SubnodeConfiguration)config;
+ ConfigurationNode rootNode = xmlconfig.getRootNode();
+ String rootNodeName = rootNode.getName();
+ List atts = rootNode.getAttributes(name);
+ String attribute = null;
+ // Object obj = config.getProperty(name);
+ if (atts != null && atts.size() > 0) {
+ attribute = (String)((ConfigurationNode)atts.get(0)).getValue();
+ }
+ System.out.println("attribute is:" + attribute);
+ if (attribute != null) {
+ return attribute;
+ } else {
+ throw new ConfigurationException(
+ "Configuration attribute " + name + " not found in "
+ + config.toString() + ".\n" + rootNodeName);
+ }
+ }
+
+ /**
+ * Returns the value of the named attribute of the given element.
+ * If the attribute is not found, then the given default value is returned.
+ *
+ * @param element element
+ * @param name attribute name
+ * @param def default value
+ * @return attribute value, or the default value
+ */
+ protected String getAttribute(HierarchicalConfiguration config, String name, String def) {
+ String attribute = null;
+ Object obj = config.getProperty(name);
+ if (obj != null) {
+ if (obj instanceof Collection) {
+ attribute = (String)((Collection)obj).iterator().next();
+ } else {
+ attribute = (String)obj;
+ }
+ }
+
+ if (attribute != null) {
+ return attribute;
+ } else {
+ return def;
+ }
+ }
+}
+
Added: incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/LoginModuleConfig.java
URL: http://svn.apache.org/viewvc/incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/LoginModuleConfig.java?rev=1087520&view=auto
==============================================================================
--- incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/LoginModuleConfig.java (added)
+++ incubator/rave/donations/ogce-gadget-container/ishindig-webapp/src/main/java/cgl/shindig/config/LoginModuleConfig.java Fri Apr 1 00:29:22 2011
@@ -0,0 +1,55 @@
+package cgl.shindig.config;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import javax.security.auth.spi.LoginModule;
+
+public class LoginModuleConfig extends BeanConfig {
+
+ public static final String PARAM_ANONYMOUS_ID = "anonymousId";
+
+ public static final String PARAM_ADMIN_ID = "adminId";
+
+ public static final String PARAM_PRINCIPAL_PROVIDER_CLASS = "principalProvider";
+
+ /**
+ * Creates an access manager configuration object from the
+ * given bean configuration.
+ *
+ * @param config bean configuration
+ */
+ public LoginModuleConfig(BeanConfig config) {
+ super(config);
+ setValidate(false); // JCR-1920
+ }
+
+ public LoginModule getLoginModule() throws ConfigurationException {
+ Object result = newInstance();
+ if (result instanceof LoginModule) {
+ return (LoginModule) result;
+ } else {
+ throw new ConfigurationException("Invalid login module implementation class "
+ + getClassName() + ".");
+ }
+ }
+}
+