|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package javax.naming; |
|
|
|
import java.util.Locale; |
|
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<String> 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 |
|
|
|
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 |
|
|
|
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<String> comps) |
|
throws InvalidNameException { |
|
String beginQuote; |
|
String endQuote; |
|
boolean start = true; |
|
boolean one = false; |
|
StringBuffer answer = new StringBuffer(len); |
|
|
|
while (i < len) { |
|
|
|
if (start && ((one = isA(name, i, syntaxBeginQuote1)) || |
|
isA(name, i, syntaxBeginQuote2))) { |
|
|
|
|
|
beginQuote = one ? syntaxBeginQuote1 : syntaxBeginQuote2; |
|
endQuote = one ? syntaxEndQuote1 : syntaxEndQuote2; |
|
if (escapingStyle == STYLE_NONE) { |
|
escapingStyle = one ? STYLE_QUOTE1 : STYLE_QUOTE2; |
|
} |
|
|
|
|
|
for (i += beginQuote.length(); |
|
((i < len) && !name.startsWith(endQuote, i)); |
|
i++) { |
|
// skip escape character if it is escaping ending quote |
|
|
|
if (isA(name, i, syntaxEscape) && |
|
isA(name, i + syntaxEscape.length(), endQuote)) { |
|
i += syntaxEscape.length(); |
|
} |
|
answer.append(name.charAt(i)); |
|
} |
|
|
|
|
|
if (i >= len) |
|
throw |
|
new InvalidNameException(name + ": no close quote"); |
|
// new Exception("no close quote"); |
|
|
|
i += endQuote.length(); |
|
|
|
|
|
if (i == len || isSeparator(name, i)) { |
|
break; |
|
} |
|
|
|
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 |
|
|
|
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))) { |
|
|
|
beginQuote = one ? syntaxBeginQuote1 : syntaxBeginQuote2; |
|
endQuote = one ? syntaxEndQuote1 : syntaxEndQuote2; |
|
|
|
i += syntaxTypevalSeparator.length(); |
|
answer.append(syntaxTypevalSeparator+beginQuote); |
|
|
|
|
|
for (i += beginQuote.length(); |
|
((i < len) && !name.startsWith(endQuote, i)); |
|
i++) { |
|
// skip escape character if it is escaping ending quote |
|
|
|
if (isA(name, i, syntaxEscape) && |
|
isA(name, i + syntaxEscape.length(), endQuote)) { |
|
i += syntaxEscape.length(); |
|
} |
|
answer.append(name.charAt(i)); |
|
} |
|
|
|
|
|
if (i >= len) |
|
throw |
|
new InvalidNameException(name + ": typeval no close quote"); |
|
|
|
i += endQuote.length(); |
|
answer.append(endQuote); |
|
|
|
|
|
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(Locale.ENGLISH).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 |
|
? components.firstElement() |
|
: components.lastElement(); |
|
if (comp.length() >= 1) { |
|
compsAllEmpty = false; |
|
} |
|
|
|
if (i < len) { |
|
i = skipSeparator(n, i); |
|
if ((i == len) && !compsAllEmpty) { |
|
|
|
if (rToL) { |
|
components.insertElementAt("", 0); |
|
} else { |
|
components.addElement(""); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
NameImpl(Properties syntax, Enumeration<String> comps) { |
|
this(syntax); |
|
|
|
|
|
while (comps.hasMoreElements()) |
|
components.addElement(comps.nextElement()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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 |
|
|
|
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 (beginQuote != null) { |
|
|
|
|
|
strbuf = strbuf.append(beginQuote); |
|
|
|
// component is being quoted, so we only need to worry about |
|
|
|
for (int i = 0; i < len; ) { |
|
if (comp.startsWith(endQuote, i)) { |
|
|
|
strbuf.append(syntaxEscape).append(endQuote); |
|
i += endQuote.length(); |
|
} else { |
|
|
|
strbuf.append(comp.charAt(i++)); |
|
} |
|
} |
|
|
|
|
|
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 |
|
|
|
|
|
boolean start = true; |
|
for (int i = 0; i < len; ) { |
|
|
|
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. |
|
|
|
if (isA(comp, i, syntaxEscape)) { |
|
if (i + syntaxEscape.length() >= len) { |
|
|
|
strbuf.append(syntaxEscape); |
|
} else if (isMeta(comp, i + syntaxEscape.length())) { |
|
|
|
strbuf.append(syntaxEscape); |
|
} |
|
strbuf.append(syntaxEscape); |
|
i += syntaxEscape.length(); |
|
} else |
|
|
|
|
|
if (escapeSeparator && comp.startsWith(syntaxSeparator, i)) { |
|
|
|
strbuf.append(syntaxEscape).append(syntaxSeparator); |
|
i += syntaxSeparator.length(); |
|
} else if (escapeSeparator2 && |
|
comp.startsWith(syntaxSeparator2, i)) { |
|
|
|
strbuf.append(syntaxEscape).append(syntaxSeparator2); |
|
i += syntaxSeparator2.length(); |
|
} else { |
|
|
|
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(components.elementAt(size - 1 - i)); |
|
} else { |
|
comp = stringifyComp(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<String> mycomps = getAll(); |
|
Enumeration<String> comps = target.getAll(); |
|
while (mycomps.hasMoreElements()) { |
|
|
|
String my = mycomps.nextElement(); |
|
String his = 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; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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++); |
|
|
|
|
|
if (syntaxTrimBlanks) { |
|
comp1 = comp1.trim(); |
|
comp2 = comp2.trim(); |
|
} |
|
|
|
int local; |
|
if (syntaxCaseInsensitive) { |
|
local = comp1.compareToIgnoreCase(comp2); |
|
} else { |
|
local = comp1.compareTo(comp2); |
|
} |
|
|
|
if (local != 0) { |
|
return local; |
|
} |
|
} |
|
|
|
return len1 - len2; |
|
} |
|
|
|
public int size() { |
|
return (components.size()); |
|
} |
|
|
|
public Enumeration<String> getAll() { |
|
return components.elements(); |
|
} |
|
|
|
public String get(int posn) { |
|
return components.elementAt(posn); |
|
} |
|
|
|
public Enumeration<String> getPrefix(int posn) { |
|
if (posn < 0 || posn > size()) { |
|
throw new ArrayIndexOutOfBoundsException(posn); |
|
} |
|
return new NameImplEnumerator(components, 0, posn); |
|
} |
|
|
|
public Enumeration<String> 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<String> prefix) { |
|
if (posn < 0 || posn > size()) { |
|
return false; |
|
} |
|
try { |
|
Enumeration<String> mycomps = getPrefix(posn); |
|
while (mycomps.hasMoreElements()) { |
|
String my = mycomps.nextElement(); |
|
String his = 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<String> 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 |
|
|
|
int startIndex = size() - posn; |
|
if (startIndex < 0 || startIndex > size()) { |
|
return false; |
|
} |
|
try { |
|
Enumeration<String> mycomps = getSuffix(startIndex); |
|
while (mycomps.hasMoreElements()) { |
|
String my = mycomps.nextElement(); |
|
String his = 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<String> comps) throws InvalidNameException { |
|
boolean added = false; |
|
while (comps.hasMoreElements()) { |
|
try { |
|
String 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; |
|
} |
|
} |
|
return added; |
|
} |
|
|
|
public boolean addAll(int posn, Enumeration<String> comps) |
|
throws InvalidNameException { |
|
boolean added = false; |
|
for (int i = posn; comps.hasMoreElements(); i++) { |
|
try { |
|
String 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; |
|
} |
|
} |
|
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<String> e = getAll(); e.hasMoreElements();) { |
|
String comp = e.nextElement(); |
|
if (syntaxTrimBlanks) { |
|
comp = comp.trim(); |
|
} |
|
if (syntaxCaseInsensitive) { |
|
comp = comp.toLowerCase(Locale.ENGLISH); |
|
} |
|
|
|
hash += comp.hashCode(); |
|
} |
|
return hash; |
|
} |
|
} |
|
|
|
final |
|
class NameImplEnumerator implements Enumeration<String> { |
|
Vector<String> vector; |
|
int count; |
|
int limit; |
|
|
|
NameImplEnumerator(Vector<String> v, int start, int lim) { |
|
vector = v; |
|
count = start; |
|
limit = lim; |
|
} |
|
|
|
public boolean hasMoreElements() { |
|
return count < limit; |
|
} |
|
|
|
public String nextElement() { |
|
if (count < limit) { |
|
return vector.elementAt(count++); |
|
} |
|
throw new NoSuchElementException("NameImplEnumerator"); |
|
} |
|
} |