KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > naming > ldap > Rfc2253Parser


1 package javax.naming.ldap;
2
3 import java.util.List JavaDoc;
4 import java.util.ArrayList JavaDoc;
5
6 import javax.naming.InvalidNameException JavaDoc;
7
8 /*
9  * RFC2253Parser implements a recursive descent parser for a single DN.
10  */

11 final class Rfc2253Parser {
12
13     private final String JavaDoc name; // DN being parsed
14
private final char[] chars; // characters in LDAP name being parsed
15
private final int len; // length of "chars"
16
private int cur = 0; // index of first unconsumed char in "chars"
17

18     /*
19      * Given an LDAP DN in string form, returns a parser for it.
20      */

21     Rfc2253Parser(String JavaDoc name) {
22         this.name = name;
23         len = name.length();
24         chars = name.toCharArray();
25     }
26
27     /*
28      * Parses the DN, returning a List of its RDNs.
29      */

30     // public List<Rdn> getDN() throws InvalidNameException {
31

32     List JavaDoc parseDn() throws InvalidNameException JavaDoc {
33         cur = 0;
34
35         // ArrayList<Rdn> rdns =
36
// new ArrayList<Rdn>(len / 3 + 10); // leave room for growth
37

38         ArrayList JavaDoc rdns =
39         new ArrayList JavaDoc(len / 3 + 10); // leave room for growth
40

41         if (len == 0) {
42         return rdns;
43         }
44
45         rdns.add(doParse(new Rdn JavaDoc()));
46         while (cur < len) {
47         if (chars[cur] == ',' || chars[cur] == ';') {
48             ++cur;
49             rdns.add(0, doParse(new Rdn JavaDoc()));
50         } else {
51             throw new InvalidNameException JavaDoc("Invalid name: " + name);
52         }
53         }
54         return rdns;
55     }
56
57     /*
58      * Parses the DN, if it is known to contain a single RDN.
59      */

60     Rdn JavaDoc parseRdn() throws InvalidNameException JavaDoc {
61         return parseRdn(new Rdn JavaDoc());
62     }
63
64     /*
65      * Parses the DN, if it is known to contain a single RDN.
66      */

67     Rdn JavaDoc parseRdn(Rdn JavaDoc rdn) throws InvalidNameException JavaDoc {
68         rdn = doParse(rdn);
69         if (cur < len) {
70         throw new InvalidNameException JavaDoc("Invalid RDN: " + name);
71         }
72         return rdn;
73     }
74
75     /*
76      * Parses the next RDN and returns it. Throws an exception if
77      * none is found. Leading and trailing whitespace is consumed.
78      */

79      private Rdn JavaDoc doParse(Rdn JavaDoc rdn) throws InvalidNameException JavaDoc {
80
81         while (cur < len) {
82         consumeWhitespace();
83         String JavaDoc attrType = parseAttrType();
84         consumeWhitespace();
85         if (cur >= len || chars[cur] != '=') {
86             throw new InvalidNameException JavaDoc("Invalid name: " + name);
87         }
88         ++cur; // consume '='
89
consumeWhitespace();
90         String JavaDoc value = parseAttrValue();
91         consumeWhitespace();
92
93         rdn.put(attrType, Rdn.unescapeValue(value));
94         if (cur >= len || chars[cur] != '+') {
95             break;
96         }
97         ++cur; // consume '+'
98
}
99         rdn.sort();
100         return rdn;
101     }
102
103     /*
104      * Returns the attribute type that begins at the next unconsumed
105      * char. No leading whitespace is expected.
106      * This routine is more generous than RFC 2253. It accepts
107      * attribute types composed of any nonempty combination of Unicode
108      * letters, Unicode digits, '.', '-', and internal space characters.
109      */

110     private String JavaDoc parseAttrType() throws InvalidNameException JavaDoc {
111
112         final int beg = cur;
113         while (cur < len) {
114         char c = chars[cur];
115         if (Character.isLetterOrDigit(c) ||
116             c == '.' ||
117             c == '-' ||
118             c == ' ') {
119             ++cur;
120         } else {
121             break;
122         }
123         }
124         // Back out any trailing spaces.
125
while ((cur > beg) && (chars[cur - 1] == ' ')) {
126         --cur;
127         }
128
129         if (beg == cur) {
130         throw new InvalidNameException JavaDoc("Invalid name: " + name);
131         }
132         return new String JavaDoc(chars, beg, cur - beg);
133     }
134
135     /*
136      * Returns the attribute value that begins at the next unconsumed
137      * char. No leading whitespace is expected.
138      */

139     private String JavaDoc parseAttrValue() throws InvalidNameException JavaDoc {
140
141         if (cur < len && chars[cur] == '#') {
142         return parseBinaryAttrValue();
143         } else if (cur < len && chars[cur] == '"') {
144         return parseQuotedAttrValue();
145         } else {
146         return parseStringAttrValue();
147         }
148     }
149
150     private String JavaDoc parseBinaryAttrValue() throws InvalidNameException JavaDoc {
151         final int beg = cur;
152         ++cur; // consume '#'
153
while ((cur < len) &&
154             Character.isLetterOrDigit(chars[cur])) {
155         ++cur;
156         }
157         return new String JavaDoc(chars, beg, cur - beg);
158     }
159
160     private String JavaDoc parseQuotedAttrValue() throws InvalidNameException JavaDoc {
161
162         final int beg = cur;
163         ++cur; // consume '"'
164

165         while ((cur < len) && chars[cur] != '"') {
166         if (chars[cur] == '\\') {
167             ++cur; // consume backslash, then what follows
168
}
169         ++cur;
170         }
171         if (cur >= len) { // no closing quote
172
throw new InvalidNameException JavaDoc("Invalid name: " + name);
173         }
174         ++cur; // consume closing quote
175

176         return new String JavaDoc(chars, beg, cur - beg);
177     }
178
179     private String JavaDoc parseStringAttrValue() throws InvalidNameException JavaDoc {
180
181         final int beg = cur;
182         int esc = -1; // index of the most recently escaped character
183

184         while ((cur < len) && !atTerminator()) {
185         if (chars[cur] == '\\') {
186             ++cur; // consume backslash, then what follows
187
esc = cur;
188         }
189         ++cur;
190         }
191         if (cur > len) { // 'twas backslash followed by nothing
192
throw new InvalidNameException JavaDoc("Invalid name: " + name);
193         }
194
195         // Trim off (unescaped) trailing whitespace.
196
int end;
197         for (end = cur; end > beg; end--) {
198         if (!isWhitespace(chars[end - 1]) || (esc == end - 1)) {
199             break;
200         }
201         }
202         return new String JavaDoc(chars, beg, end - beg);
203     }
204
205     private void consumeWhitespace() {
206         while ((cur < len) && isWhitespace(chars[cur])) {
207         ++cur;
208         }
209     }
210
211     /*
212      * Returns true if next unconsumed character is one that terminates
213      * a string attribute value.
214      */

215     private boolean atTerminator() {
216         return (cur < len &&
217             (chars[cur] == ',' ||
218             chars[cur] == ';' ||
219             chars[cur] == '+'));
220     }
221
222     /*
223      * Best guess as to what RFC 2253 means by "whitespace".
224      */

225         private static boolean isWhitespace(char c) {
226         return (c == ' ' || c == '\r');
227         }
228     }
229
Popular Tags