- /*
- * @(#)NameImpl.java 1.9 03/12/19
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
- 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
- * @version 1.9 03/12/19
- * @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");
- }
- }
-