001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.naming;
030:
031: import com.caucho.util.L10N;
032:
033: import javax.naming.Context;
034: import javax.naming.InvalidNameException;
035: import javax.naming.Name;
036: import javax.naming.NamingException;
037: import java.util.ArrayList;
038: import java.util.Collections;
039: import java.util.Enumeration;
040:
041: /**
042: * Represents a parsed JNDI name.
043: */
044: public class QName implements Name {
045: private static L10N L = new L10N(QName.class);
046:
047: // The owning root context.
048: protected Context _context;
049:
050: // The name items
051: private ArrayList<String> _items = new ArrayList<String>();
052:
053: /**
054: * Creates a root name based on a context.
055: *
056: * @param context the root context
057: */
058: public QName(Context context) {
059: _context = context;
060: }
061:
062: /**
063: * Creates a new name with a single component.
064: *
065: * @param context the root context
066: * @param first the first name component
067: */
068: public QName(Context context, String first) {
069: _context = context;
070:
071: if (first != null)
072: _items.add(first);
073: }
074:
075: /**
076: * Creates a new name with two components
077: *
078: * @param context the root context
079: * @param first the first name component
080: * @param tail the tail name component
081: */
082: public QName(Context context, String first, String rest) {
083: _context = context;
084:
085: if (first != null)
086: _items.add(first);
087: if (rest != null)
088: _items.add(rest);
089: }
090:
091: /**
092: * Clones the name.
093: */
094: public Object clone() {
095: QName name = new QName(_context);
096:
097: for (int i = 0; i < _items.size(); i++)
098: name._items.add(_items.get(i));
099:
100: return name;
101: }
102:
103: public int size() {
104: return _items.size();
105: }
106:
107: public boolean isEmpty() {
108: return _items.size() == 0;
109: }
110:
111: public Enumeration getAll() {
112: return Collections.enumeration(_items);
113: }
114:
115: public String get(int pos) {
116: if (pos < _items.size())
117: return (String) _items.get(pos);
118: else
119: return null;
120: }
121:
122: public Name getPrefix(int posn) {
123: QName name = new QName(_context);
124:
125: for (int i = 0; i < posn; i++)
126: name._items.add(_items.get(i));
127:
128: return name;
129: }
130:
131: public Name getSuffix(int posn) {
132: Context subcontext = _context;
133:
134: for (int i = 0; i < posn; i++) {
135: String item = (String) _items.get(i);
136: try {
137: Object obj = subcontext.lookup(item);
138: if (obj instanceof Context)
139: subcontext = (Context) obj;
140: else
141: break;
142: } catch (NamingException e) {
143: break;
144: }
145: }
146:
147: QName name = new QName(subcontext);
148: for (int i = posn; i < _items.size(); i++) {
149: String item = (String) _items.get(i);
150:
151: name._items.add(_items.get(i));
152: }
153:
154: return name;
155: }
156:
157: /**
158: * Returns true if the argument is a prefix of the name.
159: *
160: * @param name the Name to start as a prefix.
161: */
162: public boolean startsWith(Name name) {
163: if (name == null)
164: return false;
165:
166: if (size() < name.size())
167: return false;
168:
169: for (int i = 0; i < name.size(); i++) {
170: if (!get(i).equals(name.get(i)))
171: return false;
172: }
173:
174: return true;
175: }
176:
177: public boolean endsWith(Name name) {
178: if (name == null)
179: return false;
180:
181: int nameSize = name.size();
182: if (size() < nameSize)
183: return false;
184:
185: int offset = size() - nameSize;
186: for (int i = 0; i < nameSize; i++)
187: if (!get(i + offset).equals(name.get(i)))
188: return false;
189:
190: return true;
191: }
192:
193: /**
194: * Append a name to the current name.
195: *
196: * @param suffix the name to add as a suffix
197: *
198: * @return the modified name
199: */
200: public Name addAll(Name suffix) throws InvalidNameException {
201: for (int i = 0; i < suffix.size(); i++)
202: _items.add(suffix.get(i));
203:
204: return this ;
205: }
206:
207: /**
208: * Insert a name to the current name.
209: *
210: * @param suffix the name to add as a suffix
211: *
212: * @return the modified name
213: */
214: public Name addAll(int posn, Name suffix)
215: throws InvalidNameException {
216: for (int i = 0; i < suffix.size(); i++)
217: _items.add(posn, suffix.get(i));
218:
219: return this ;
220: }
221:
222: /**
223: * Add a component to the tail of the name, returning the name.
224: *
225: * @param comp the new component to add.
226: *
227: * @return the modified name
228: */
229: public Name add(String comp) throws InvalidNameException {
230: _items.add(comp);
231:
232: return this ;
233: }
234:
235: /**
236: * Add a component at a specific position, returning the name.
237: *
238: * @return the modified name
239: */
240: public Name add(int posn, String comp) throws InvalidNameException {
241: _items.add(posn, comp);
242:
243: return this ;
244: }
245:
246: public Object remove(int posn) throws InvalidNameException {
247: _items.remove(posn);
248:
249: return this ;
250: }
251:
252: /**
253: * Returns the name's hash code.
254: */
255: public int hashCode() {
256: int hashCode = 337;
257:
258: for (int i = size() - 1; i >= 0; i--)
259: hashCode = 65521 * hashCode + get(i).hashCode();
260:
261: return hashCode;
262: }
263:
264: /**
265: * Returns true if the object is an equivalent name.
266: *
267: * @param obj the object to test for equality.
268: */
269: public boolean equals(Object obj) {
270: if (!(obj instanceof Name))
271: return false;
272:
273: Name name = (Name) obj;
274:
275: if (size() != name.size())
276: return false;
277:
278: for (int i = size() - 1; i >= 0; i--) {
279: if (!get(i).equals(name.get(i)))
280: return false;
281: }
282:
283: return true;
284: }
285:
286: /**
287: * Compares the name to another name.
288: *
289: * @return -1 if less than b, 0 if equal, or 1 if greater chan
290: */
291: public int compareTo(Object rawB) {
292: if (!(rawB instanceof Name))
293: return -1;
294:
295: Name b = (Name) rawB;
296:
297: for (int i = 0; i < size(); i++) {
298: if (i >= b.size())
299: return 1;
300:
301: String sa = (String) get(i);
302: String sb = (String) b.get(i);
303:
304: int cmp = sa.compareTo(sb);
305: if (cmp != 0)
306: return cmp;
307: }
308:
309: if (size() == b.size())
310: return 0;
311: else
312: return -1;
313: }
314:
315: /**
316: * Converts the name to a string.
317: */
318: public String toString() {
319: String name = null;
320:
321: for (int i = 0; i < size(); i++) {
322: String str = (String) get(i);
323:
324: if (name != null) {
325: try {
326: name = _context.composeName(str, name);
327: } catch (NamingException e) {
328: name = name + "/" + str;
329: }
330: } else
331: name = str;
332: }
333:
334: return name == null ? "" : name;
335: }
336: }
|