--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/naming/NameImpl.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,730 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.naming;
+
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.NoSuchElementException;
+
+/**
+ * The implementation class for CompoundName and CompositeName.
+ * This class is package private.
+ *
+ * @author Rosanna Lee
+ * @author Scott Seligman
+ * @author Aravindan Ranganathan
+ * @since 1.3
+ */
+
+class NameImpl {
+ private static final byte LEFT_TO_RIGHT = 1;
+ private static final byte RIGHT_TO_LEFT = 2;
+ private static final byte FLAT = 0;
+
+ private Vector components;
+
+ private byte syntaxDirection = LEFT_TO_RIGHT;
+ private String syntaxSeparator = "/";
+ private String syntaxSeparator2 = null;
+ private boolean syntaxCaseInsensitive = false;
+ private boolean syntaxTrimBlanks = false;
+ private String syntaxEscape = "\\";
+ private String syntaxBeginQuote1 = "\"";
+ private String syntaxEndQuote1 = "\"";
+ private String syntaxBeginQuote2 = "'";
+ private String syntaxEndQuote2 = "'";
+ private String syntaxAvaSeparator = null;
+ private String syntaxTypevalSeparator = null;
+
+ // escapingStyle gives the method used at creation time for
+ // quoting or escaping characters in the name. It is set to the
+ // first style of quote or escape encountered if and when the name
+ // is parsed.
+ private static final int STYLE_NONE = 0;
+ private static final int STYLE_QUOTE1 = 1;
+ private static final int STYLE_QUOTE2 = 2;
+ private static final int STYLE_ESCAPE = 3;
+ private int escapingStyle = STYLE_NONE;
+
+ // Returns true if "match" is not null, and n contains "match" at
+ // position i.
+ private final boolean isA(String n, int i, String match) {
+ return (match != null && n.startsWith(match, i));
+ }
+
+ private final boolean isMeta(String n, int i) {
+ return (isA(n, i, syntaxEscape) ||
+ isA(n, i, syntaxBeginQuote1) ||
+ isA(n, i, syntaxBeginQuote2) ||
+ isSeparator(n, i));
+ }
+
+ private final boolean isSeparator(String n, int i) {
+ return (isA(n, i, syntaxSeparator) ||
+ isA(n, i, syntaxSeparator2));
+ }
+
+ private final int skipSeparator(String name, int i) {
+ if (isA(name, i, syntaxSeparator)) {
+ i += syntaxSeparator.length();
+ } else if (isA(name, i, syntaxSeparator2)) {
+ i += syntaxSeparator2.length();
+ }
+ return (i);
+ }
+
+ private final int extractComp(String name, int i, int len, Vector comps)
+ throws InvalidNameException {
+ String beginQuote;
+ String endQuote;
+ boolean start = true;
+ boolean one = false;
+ StringBuffer answer = new StringBuffer(len);
+
+ while (i < len) {
+ // handle quoted strings
+ if (start && ((one = isA(name, i, syntaxBeginQuote1)) ||
+ isA(name, i, syntaxBeginQuote2))) {
+
+ // record choice of quote chars being used
+ beginQuote = one ? syntaxBeginQuote1 : syntaxBeginQuote2;
+ endQuote = one ? syntaxEndQuote1 : syntaxEndQuote2;
+ if (escapingStyle == STYLE_NONE) {
+ escapingStyle = one ? STYLE_QUOTE1 : STYLE_QUOTE2;
+ }
+
+ // consume string until matching quote
+ for (i += beginQuote.length();
+ ((i < len) && !name.startsWith(endQuote, i));
+ i++) {
+ // skip escape character if it is escaping ending quote
+ // otherwise leave as is.
+ if (isA(name, i, syntaxEscape) &&
+ isA(name, i + syntaxEscape.length(), endQuote)) {
+ i += syntaxEscape.length();
+ }
+ answer.append(name.charAt(i)); // copy char
+ }
+
+ // no ending quote found
+ if (i >= len)
+ throw
+ new InvalidNameException(name + ": no close quote");
+// new Exception("no close quote");
+
+ i += endQuote.length();
+
+ // verify that end-quote occurs at separator or end of string
+ if (i == len || isSeparator(name, i)) {
+ break;
+ }
+// throw (new Exception(
+ throw (new InvalidNameException(name +
+ ": close quote appears before end of component"));
+
+ } else if (isSeparator(name, i)) {
+ break;
+
+ } else if (isA(name, i, syntaxEscape)) {
+ if (isMeta(name, i + syntaxEscape.length())) {
+ // if escape precedes meta, consume escape and let
+ // meta through
+ i += syntaxEscape.length();
+ if (escapingStyle == STYLE_NONE) {
+ escapingStyle = STYLE_ESCAPE;
+ }
+ } else if (i + syntaxEscape.length() >= len) {
+ throw (new InvalidNameException(name +
+ ": unescaped " + syntaxEscape + " at end of component"));
+ }
+ } else if (isA(name, i, syntaxTypevalSeparator) &&
+ ((one = isA(name, i+syntaxTypevalSeparator.length(), syntaxBeginQuote1)) ||
+ isA(name, i+syntaxTypevalSeparator.length(), syntaxBeginQuote2))) {
+ // Handle quote occurring after typeval separator
+ beginQuote = one ? syntaxBeginQuote1 : syntaxBeginQuote2;
+ endQuote = one ? syntaxEndQuote1 : syntaxEndQuote2;
+
+ i += syntaxTypevalSeparator.length();
+ answer.append(syntaxTypevalSeparator+beginQuote); // add back
+
+ // consume string until matching quote
+ for (i += beginQuote.length();
+ ((i < len) && !name.startsWith(endQuote, i));
+ i++) {
+ // skip escape character if it is escaping ending quote
+ // otherwise leave as is.
+ if (isA(name, i, syntaxEscape) &&
+ isA(name, i + syntaxEscape.length(), endQuote)) {
+ i += syntaxEscape.length();
+ }
+ answer.append(name.charAt(i)); // copy char
+ }
+
+ // no ending quote found
+ if (i >= len)
+ throw
+ new InvalidNameException(name + ": typeval no close quote");
+
+ i += endQuote.length();
+ answer.append(endQuote); // add back
+
+ // verify that end-quote occurs at separator or end of string
+ if (i == len || isSeparator(name, i)) {
+ break;
+ }
+ throw (new InvalidNameException(name.substring(i) +
+ ": typeval close quote appears before end of component"));
+ }
+
+ answer.append(name.charAt(i++));
+ start = false;
+ }
+
+ if (syntaxDirection == RIGHT_TO_LEFT)
+ comps.insertElementAt(answer.toString(), 0);
+ else
+ comps.addElement(answer.toString());
+ return i;
+ }
+
+ private static boolean getBoolean(Properties p, String name) {
+ return toBoolean(p.getProperty(name));
+ }
+
+ private static boolean toBoolean(String name) {
+ return ((name != null) && name.toLowerCase().equals("true"));
+ }
+
+ private final void recordNamingConvention(Properties p) {
+ String syntaxDirectionStr =
+ p.getProperty("jndi.syntax.direction", "flat");
+ if (syntaxDirectionStr.equals("left_to_right")) {
+ syntaxDirection = LEFT_TO_RIGHT;
+ } else if (syntaxDirectionStr.equals("right_to_left")) {
+ syntaxDirection = RIGHT_TO_LEFT;
+ } else if (syntaxDirectionStr.equals("flat")) {
+ syntaxDirection = FLAT;
+ } else {
+ throw new IllegalArgumentException(syntaxDirectionStr +
+ "is not a valid value for the jndi.syntax.direction property");
+ }
+
+ if (syntaxDirection != FLAT) {
+ syntaxSeparator = p.getProperty("jndi.syntax.separator");
+ syntaxSeparator2 = p.getProperty("jndi.syntax.separator2");
+ if (syntaxSeparator == null) {
+ throw new IllegalArgumentException(
+ "jndi.syntax.separator property required for non-flat syntax");
+ }
+ } else {
+ syntaxSeparator = null;
+ }
+ syntaxEscape = p.getProperty("jndi.syntax.escape");
+
+ syntaxCaseInsensitive = getBoolean(p, "jndi.syntax.ignorecase");
+ syntaxTrimBlanks = getBoolean(p, "jndi.syntax.trimblanks");
+
+ syntaxBeginQuote1 = p.getProperty("jndi.syntax.beginquote");
+ syntaxEndQuote1 = p.getProperty("jndi.syntax.endquote");
+ if (syntaxEndQuote1 == null && syntaxBeginQuote1 != null)
+ syntaxEndQuote1 = syntaxBeginQuote1;
+ else if (syntaxBeginQuote1 == null && syntaxEndQuote1 != null)
+ syntaxBeginQuote1 = syntaxEndQuote1;
+ syntaxBeginQuote2 = p.getProperty("jndi.syntax.beginquote2");
+ syntaxEndQuote2 = p.getProperty("jndi.syntax.endquote2");
+ if (syntaxEndQuote2 == null && syntaxBeginQuote2 != null)
+ syntaxEndQuote2 = syntaxBeginQuote2;
+ else if (syntaxBeginQuote2 == null && syntaxEndQuote2 != null)
+ syntaxBeginQuote2 = syntaxEndQuote2;
+
+ syntaxAvaSeparator = p.getProperty("jndi.syntax.separator.ava");
+ syntaxTypevalSeparator =
+ p.getProperty("jndi.syntax.separator.typeval");
+ }
+
+ NameImpl(Properties syntax) {
+ if (syntax != null) {
+ recordNamingConvention(syntax);
+ }
+ components = new Vector();
+ }
+
+ NameImpl(Properties syntax, String n) throws InvalidNameException {
+ this(syntax);
+
+ boolean rToL = (syntaxDirection == RIGHT_TO_LEFT);
+ boolean compsAllEmpty = true;
+ int len = n.length();
+
+ for (int i = 0; i < len; ) {
+ i = extractComp(n, i, len, components);
+
+ String comp = rToL
+ ? (String)components.firstElement()
+ : (String)components.lastElement();
+ if (comp.length() >= 1) {
+ compsAllEmpty = false;
+ }
+
+ if (i < len) {
+ i = skipSeparator(n, i);
+ if ((i == len) && !compsAllEmpty) {
+ // Trailing separator found. Add an empty component.
+ if (rToL) {
+ components.insertElementAt("", 0);
+ } else {
+ components.addElement("");
+ }
+ }
+ }
+ }
+ }
+
+ NameImpl(Properties syntax, Enumeration comps) {
+ this(syntax);
+
+ // %% comps could shrink in the middle.
+ while (comps.hasMoreElements())
+ components.addElement(comps.nextElement());
+ }
+/*
+ // Determines whether this component needs any escaping.
+ private final boolean escapingNeeded(String comp) {
+ int len = comp.length();
+ for (int i = 0; i < len; i++) {
+ if (i == 0) {
+ if (isA(comp, 0, syntaxBeginQuote1) ||
+ isA(comp, 0, syntaxBeginQuote2)) {
+ return (true);
+ }
+ }
+ if (isSeparator(comp, i)) {
+ return (true);
+ }
+ if (isA(comp, i, syntaxEscape)) {
+ i += syntaxEscape.length();
+ if (i >= len || isMeta(comp, i)) {
+ return (true);
+ }
+ }
+ }
+ return (false);
+ }
+*/
+ private final String stringifyComp(String comp) {
+ int len = comp.length();
+ boolean escapeSeparator = false, escapeSeparator2 = false;
+ String beginQuote = null, endQuote = null;
+ StringBuffer strbuf = new StringBuffer(len);
+
+ // determine whether there are any separators; if so escape
+ // or quote them
+ if (syntaxSeparator != null &&
+ comp.indexOf(syntaxSeparator) >= 0) {
+ if (syntaxBeginQuote1 != null) {
+ beginQuote = syntaxBeginQuote1;
+ endQuote = syntaxEndQuote1;
+ } else if (syntaxBeginQuote2 != null) {
+ beginQuote = syntaxBeginQuote2;
+ endQuote = syntaxEndQuote2;
+ } else if (syntaxEscape != null)
+ escapeSeparator = true;
+ }
+ if (syntaxSeparator2 != null &&
+ comp.indexOf(syntaxSeparator2) >= 0) {
+ if (syntaxBeginQuote1 != null) {
+ if (beginQuote == null) {
+ beginQuote = syntaxBeginQuote1;
+ endQuote = syntaxEndQuote1;
+ }
+ } else if (syntaxBeginQuote2 != null) {
+ if (beginQuote == null) {
+ beginQuote = syntaxBeginQuote2;
+ endQuote = syntaxEndQuote2;
+ }
+ } else if (syntaxEscape != null)
+ escapeSeparator2 = true;
+ }
+
+ // if quoting component,
+ if (beginQuote != null) {
+
+ // start string off with opening quote
+ strbuf = strbuf.append(beginQuote);
+
+ // component is being quoted, so we only need to worry about
+ // escaping end quotes that occur in component
+ for (int i = 0; i < len; ) {
+ if (comp.startsWith(endQuote, i)) {
+ // end-quotes must be escaped when inside a quoted string
+ strbuf.append(syntaxEscape).append(endQuote);
+ i += endQuote.length();
+ } else {
+ // no special treatment required
+ strbuf.append(comp.charAt(i++));
+ }
+ }
+
+ // end with closing quote
+ strbuf.append(endQuote);
+
+ } else {
+
+ // When component is not quoted, add escape for:
+ // 1. leading quote
+ // 2. an escape preceding any meta char
+ // 3. an escape at the end of a component
+ // 4. separator
+
+ // go through characters in component and escape where necessary
+ boolean start = true;
+ for (int i = 0; i < len; ) {
+ // leading quote must be escaped
+ if (start && isA(comp, i, syntaxBeginQuote1)) {
+ strbuf.append(syntaxEscape).append(syntaxBeginQuote1);
+ i += syntaxBeginQuote1.length();
+ } else if (start && isA(comp, i, syntaxBeginQuote2)) {
+ strbuf.append(syntaxEscape).append(syntaxBeginQuote2);
+ i += syntaxBeginQuote2.length();
+ } else
+
+ // Escape an escape preceding meta characters, or at end.
+ // Other escapes pass through.
+ if (isA(comp, i, syntaxEscape)) {
+ if (i + syntaxEscape.length() >= len) {
+ // escape an ending escape
+ strbuf.append(syntaxEscape);
+ } else if (isMeta(comp, i + syntaxEscape.length())) {
+ // escape meta strings
+ strbuf.append(syntaxEscape);
+ }
+ strbuf.append(syntaxEscape);
+ i += syntaxEscape.length();
+ } else
+
+ // escape unescaped separator
+ if (escapeSeparator && comp.startsWith(syntaxSeparator, i)) {
+ // escape separator
+ strbuf.append(syntaxEscape).append(syntaxSeparator);
+ i += syntaxSeparator.length();
+ } else if (escapeSeparator2 &&
+ comp.startsWith(syntaxSeparator2, i)) {
+ // escape separator2
+ strbuf.append(syntaxEscape).append(syntaxSeparator2);
+ i += syntaxSeparator2.length();
+ } else {
+ // no special treatment required
+ strbuf.append(comp.charAt(i++));
+ }
+ start = false;
+ }
+ }
+ return (strbuf.toString());
+ }
+
+ public String toString() {
+ StringBuffer answer = new StringBuffer();
+ String comp;
+ boolean compsAllEmpty = true;
+ int size = components.size();
+
+ for (int i = 0; i < size; i++) {
+ if (syntaxDirection == RIGHT_TO_LEFT) {
+ comp =
+ stringifyComp((String) components.elementAt(size - 1 - i));
+ } else {
+ comp = stringifyComp((String) components.elementAt(i));
+ }
+ if ((i != 0) && (syntaxSeparator != null))
+ answer.append(syntaxSeparator);
+ if (comp.length() >= 1)
+ compsAllEmpty = false;
+ answer = answer.append(comp);
+ }
+ if (compsAllEmpty && (size >= 1) && (syntaxSeparator != null))
+ answer = answer.append(syntaxSeparator);
+ return (answer.toString());
+ }
+
+ public boolean equals(Object obj) {
+ if ((obj != null) && (obj instanceof NameImpl)) {
+ NameImpl target = (NameImpl)obj;
+ if (target.size() == this.size()) {
+ Enumeration mycomps = getAll();
+ Enumeration comps = target.getAll();
+ while (mycomps.hasMoreElements()) {
+ // %% comps could shrink in the middle.
+ String my = (String)mycomps.nextElement();
+ String his = (String)comps.nextElement();
+ if (syntaxTrimBlanks) {
+ my = my.trim();
+ his = his.trim();
+ }
+ if (syntaxCaseInsensitive) {
+ if (!(my.equalsIgnoreCase(his)))
+ return false;
+ } else {
+ if (!(my.equals(his)))
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Compares obj to this NameImpl to determine ordering.
+ * Takes into account syntactic properties such as
+ * elimination of blanks, case-ignore, etc, if relevant.
+ *
+ * Note: using syntax of this NameImpl and ignoring
+ * that of comparison target.
+ */
+ public int compareTo(NameImpl obj) {
+ if (this == obj) {
+ return 0;
+ }
+
+ int len1 = size();
+ int len2 = obj.size();
+ int n = Math.min(len1, len2);
+
+ int index1 = 0, index2 = 0;
+
+ while (n-- != 0) {
+ String comp1 = get(index1++);
+ String comp2 = obj.get(index2++);
+
+ // normalize according to syntax
+ if (syntaxTrimBlanks) {
+ comp1 = comp1.trim();
+ comp2 = comp2.trim();
+ }
+ if (syntaxCaseInsensitive) {
+ comp1 = comp1.toLowerCase();
+ comp2 = comp2.toLowerCase();
+ }
+ int local = comp1.compareTo(comp2);
+ if (local != 0) {
+ return local;
+ }
+ }
+
+ return len1 - len2;
+ }
+
+ public int size() {
+ return (components.size());
+ }
+
+ public Enumeration getAll() {
+ return components.elements();
+ }
+
+ public String get(int posn) {
+ return ((String) components.elementAt(posn));
+ }
+
+ public Enumeration getPrefix(int posn) {
+ if (posn < 0 || posn > size()) {
+ throw new ArrayIndexOutOfBoundsException(posn);
+ }
+ return new NameImplEnumerator(components, 0, posn);
+ }
+
+ public Enumeration getSuffix(int posn) {
+ int cnt = size();
+ if (posn < 0 || posn > cnt) {
+ throw new ArrayIndexOutOfBoundsException(posn);
+ }
+ return new NameImplEnumerator(components, posn, cnt);
+ }
+
+ public boolean isEmpty() {
+ return (components.isEmpty());
+ }
+
+ public boolean startsWith(int posn, Enumeration prefix) {
+ if (posn < 0 || posn > size()) {
+ return false;
+ }
+ try {
+ Enumeration mycomps = getPrefix(posn);
+ while (mycomps.hasMoreElements()) {
+ String my = (String)mycomps.nextElement();
+ String his = (String)prefix.nextElement();
+ if (syntaxTrimBlanks) {
+ my = my.trim();
+ his = his.trim();
+ }
+ if (syntaxCaseInsensitive) {
+ if (!(my.equalsIgnoreCase(his)))
+ return false;
+ } else {
+ if (!(my.equals(his)))
+ return false;
+ }
+ }
+ } catch (NoSuchElementException e) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean endsWith(int posn, Enumeration suffix) {
+ // posn is number of elements in suffix
+ // startIndex is the starting position in this name
+ // at which to start the comparison. It is calculated by
+ // subtracting 'posn' from size()
+ int startIndex = size() - posn;
+ if (startIndex < 0 || startIndex > size()) {
+ return false;
+ }
+ try {
+ Enumeration mycomps = getSuffix(startIndex);
+ while (mycomps.hasMoreElements()) {
+ String my = (String)mycomps.nextElement();
+ String his = (String)suffix.nextElement();
+ if (syntaxTrimBlanks) {
+ my = my.trim();
+ his = his.trim();
+ }
+ if (syntaxCaseInsensitive) {
+ if (!(my.equalsIgnoreCase(his)))
+ return false;
+ } else {
+ if (!(my.equals(his)))
+ return false;
+ }
+ }
+ } catch (NoSuchElementException e) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean addAll(Enumeration comps) throws InvalidNameException {
+ boolean added = false;
+ while (comps.hasMoreElements()) {
+ try {
+ Object comp = comps.nextElement();
+ if (size() > 0 && syntaxDirection == FLAT) {
+ throw new InvalidNameException(
+ "A flat name can only have a single component");
+ }
+ components.addElement(comp);
+ added = true;
+ } catch (NoSuchElementException e) {
+ break; // "comps" has shrunk.
+ }
+ }
+ return added;
+ }
+
+ public boolean addAll(int posn, Enumeration comps)
+ throws InvalidNameException {
+ boolean added = false;
+ for (int i = posn; comps.hasMoreElements(); i++) {
+ try {
+ Object comp = comps.nextElement();
+ if (size() > 0 && syntaxDirection == FLAT) {
+ throw new InvalidNameException(
+ "A flat name can only have a single component");
+ }
+ components.insertElementAt(comp, i);
+ added = true;
+ } catch (NoSuchElementException e) {
+ break; // "comps" has shrunk.
+ }
+ }
+ return added;
+ }
+
+ public void add(String comp) throws InvalidNameException {
+ if (size() > 0 && syntaxDirection == FLAT) {
+ throw new InvalidNameException(
+ "A flat name can only have a single component");
+ }
+ components.addElement(comp);
+ }
+
+ public void add(int posn, String comp) throws InvalidNameException {
+ if (size() > 0 && syntaxDirection == FLAT) {
+ throw new InvalidNameException(
+ "A flat name can only zero or one component");
+ }
+ components.insertElementAt(comp, posn);
+ }
+
+ public Object remove(int posn) {
+ Object r = components.elementAt(posn);
+ components.removeElementAt(posn);
+ return r;
+ }
+
+ public int hashCode() {
+ int hash = 0;
+ for (Enumeration e = getAll(); e.hasMoreElements();) {
+ String comp = (String)e.nextElement();
+ if (syntaxTrimBlanks) {
+ comp = comp.trim();
+ }
+ if (syntaxCaseInsensitive) {
+ comp = comp.toLowerCase();
+ }
+
+ hash += comp.hashCode();
+ }
+ return hash;
+ }
+}
+
+final
+class NameImplEnumerator implements Enumeration {
+ Vector vector;
+ int count;
+ int limit;
+
+ NameImplEnumerator(Vector v, int start, int lim) {
+ vector = v;
+ count = start;
+ limit = lim;
+ }
+
+ public boolean hasMoreElements() {
+ return count < limit;
+ }
+
+ public Object nextElement() {
+ if (count < limit) {
+ return vector.elementAt(count++);
+ }
+ throw new NoSuchElementException("NameImplEnumerator");
+ }
+}