001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: *
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /**
020: * @author Alexei Y. Zakharov
021: * @version $Revision: 1.1.2.4 $
022: */package org.apache.harmony.jndi.provider.dns;
023:
024: import java.util.Enumeration;
025: import java.util.Vector; // import java.util.logging.Level;
026: import javax.naming.InvalidNameException;
027: import javax.naming.Name;
028:
029: import org.apache.harmony.jndi.internal.nls.Messages;
030:
031: /**
032: * Represents the name in Domain Name System. The most significant part is the
033: * rightmost part of string representation.
034: *
035: * TODO add escapes checking for name components (?)
036: */
037: public class DNSName implements Name, Cloneable {
038:
039: private static final long serialVersionUID = -5931312723719884197L;
040:
041: private Vector<String> components;
042:
043: /**
044: * Constructs an empty DNS name.
045: */
046: public DNSName() {
047: super ();
048: components = new Vector<String>();
049: }
050:
051: /**
052: * Constructs new DNS name with given components.
053: *
054: * @param compVect
055: * the vector of name components
056: */
057: DNSName(Vector<String> compVect) {
058: components = compVect;
059: }
060:
061: /**
062: * @return size of this name
063: * @see javax.naming.Name#size()
064: */
065: public int size() {
066: return components.size();
067: }
068:
069: /**
070: * @return <code>true</code> if this name is empty
071: * @see javax.naming.Name#isEmpty()
072: */
073: public boolean isEmpty() {
074: return components.isEmpty();
075: }
076:
077: /**
078: * @return <code>true</code> if this name is an absolute DNS name, i.e.
079: * starts with empty label
080: */
081: public boolean isAbsolute() {
082: if (components.size() > 0) {
083: String el0 = components.get(0);
084:
085: if (el0 != null && el0.length() == 0) {
086: return true;
087: }
088: }
089: return false;
090: }
091:
092: /**
093: * Returns clone of the current name.
094: *
095: * @see java.lang.Object#clone()
096: */
097: @Override
098: public Object clone() {
099: Vector<String> compClone = new Vector<String>();
100: Enumeration<String> compEnum = this .components.elements();
101:
102: while (compEnum.hasMoreElements()) {
103: compClone.addElement(compEnum.nextElement());
104: }
105: return new DNSName(compClone);
106: }
107:
108: /**
109: * Removes component with specified number.
110: *
111: * @param posn
112: * index of component to remove
113: * @throws ArrayIndexOutOfBoundsException
114: * if <code>posn</code> index is out of range
115: * @see javax.naming.Name#remove(int)
116: */
117: public Object remove(int posn) throws InvalidNameException {
118: return components.remove(posn);
119: }
120:
121: /**
122: * Compares the specified name with the current name. It checks all
123: * components beginning at the most significant one. The method
124: * <code>compareToIgnoreCase</code> of underlying <code>String</code>
125: * object will be used for the real comparison of components. If two names
126: * have different sizes and the longer name begins with the shorter name
127: * then the longer name will be "bigger" than shorter.
128: *
129: * @param name
130: * the name to compare with
131: * @return negative number; zero or positive number
132: * @throws ClassCastException
133: * if the <code>name</code> has class other than
134: * <code>DNSName</code>
135: * @throws NullPointerException
136: * if the <code>name</code> is null
137: * @see javax.naming.Name#compareTo(java.lang.Object)
138: * @see java.lang.String#compareToIgnoreCase(java.lang.String)
139: */
140: public int compareTo(Object name) {
141: DNSName nameToCompareWith = null;
142: Enumeration<String> enum1;
143: Enumeration<String> enum2;
144:
145: if (name == null) {
146: // jndi.2E=The name is null
147: throw new NullPointerException(Messages
148: .getString("jndi.2E")); //$NON-NLS-1$
149: }
150: if (!(name instanceof DNSName)) {
151: // jndi.2F=Given name is not an instance of DNSName class
152: throw new ClassCastException(Messages.getString("jndi.2F")); //$NON-NLS-1$
153: }
154: nameToCompareWith = (DNSName) name;
155: enum1 = this .getAll();
156: enum2 = nameToCompareWith.getAll();
157: while (enum1.hasMoreElements()) {
158: String comp1 = enum1.nextElement();
159: String comp2;
160: int k;
161:
162: if (!enum2.hasMoreElements()) {
163: return 1;
164: }
165: comp2 = enum2.nextElement();
166: k = comp1.compareToIgnoreCase(comp2);
167: if (k != 0) {
168: return k;
169: }
170: }
171: if (enum2.hasMoreElements()) {
172: return -1;
173: }
174: return 0;
175: }
176:
177: /**
178: * @param posn
179: * index of the component to return
180: * @return name component at index <code>posn</code>
181: * @throws ArrayIndexOutOfBoundsException
182: * if <code>posn</code> index is out of range
183: * @see javax.naming.Name#get(int)
184: */
185: public String get(int posn) {
186: return components.elementAt(posn);
187: }
188:
189: /**
190: * Returns all components of the current name.
191: *
192: * @return enumeration of strings
193: * @see javax.naming.Name#getAll()
194: */
195: public Enumeration<String> getAll() {
196: return components.elements();
197: }
198:
199: /**
200: * @param posn
201: * index to stop at
202: * @return a <code>DNSName</code> object that consists of components of
203: * the current name with indexes from <code>0</code> to and not
204: * including <code>posn</code>.
205: * @throws ArrayIndexOutOfBoundsException
206: * if <code>posn</code> index is out of range
207: * @see javax.naming.Name#getPrefix(int)
208: */
209: public Name getPrefix(int posn) {
210: Vector<String> prefix = new Vector<String>();
211:
212: for (int i = 0; i < posn; i++) {
213: prefix.addElement(components.elementAt(i));
214: }
215: return new DNSName(prefix);
216: }
217:
218: /**
219: * @param posn
220: * index to start at
221: * @return a <code>DNSName</code> object that consists of components of
222: * the current name with indexes from <code>posn</code> to and not
223: * including <code>#size()</code>.
224: * @throws ArrayIndexOutOfBoundsException
225: * if <code>posn</code> index is out of range
226: * @see javax.naming.Name#getSuffix(int)
227: */
228: public Name getSuffix(int posn) {
229: Vector<String> prefix = new Vector<String>();
230:
231: for (int i = posn; i < components.size(); i++) {
232: prefix.addElement(components.elementAt(i));
233: }
234: return new DNSName(prefix);
235: }
236:
237: /**
238: * Checks if the current name ends with the given name. Returns
239: * <code>false</code> if the given name is <code>null</code> or not an
240: * instance of <code>DNSName</code> class.
241: *
242: * @param name
243: * the name to compare the end of the current message with
244: * @return <code>true</code> or <code>false</code>
245: * @see javax.naming.Name#endsWith(javax.naming.Name)
246: */
247: public boolean endsWith(Name name) {
248: int k = -1;
249: int len1;
250: int len2;
251:
252: if (name == null) {
253: return false;
254: }
255: if (!(name instanceof DNSName)) {
256: return false;
257: }
258: len1 = this .size();
259: len2 = name.size();
260: if (len1 == len2) {
261: try {
262: k = this .compareTo(name);
263: } catch (ClassCastException e) {
264: // impossible case
265: // ProviderMgr.logger.log(Level.SEVERE, "impossible case", e);
266: }
267: } else if (len1 > len2) {
268: Name suffix = this .getSuffix(len1 - len2);
269:
270: k = suffix.compareTo(name);
271: }
272: return (k == 0 ? true : false);
273: }
274:
275: /**
276: * Checks if the current name starts with the given name. Returns
277: * <code>false</code> if the given name is <code>null</code> or not an
278: * instance of <code>DNSName</code> class.
279: *
280: * @param name
281: * the name to compare the beginning of the current message with
282: * @return <code>true</code> or <code>false</code>
283: * @see javax.naming.Name#startsWith(javax.naming.Name)
284: */
285: public boolean startsWith(Name name) {
286: int k = -1;
287: int len1;
288: int len2;
289:
290: if (name == null) {
291: return false;
292: }
293: if (!(name instanceof DNSName)) {
294: return false;
295: }
296: len1 = this .size();
297: len2 = name.size();
298: if (len1 == len2) {
299: try {
300: k = this .compareTo(name);
301: } catch (ClassCastException e) {
302: // impossible case
303: // ProviderMgr.logger.log(Level.SEVERE, "impossible error", e);
304: }
305: } else if (len1 > len2) {
306: Name prefix = this .getPrefix(len2);
307:
308: k = prefix.compareTo(name);
309: }
310: return (k == 0 ? true : false);
311: }
312:
313: /**
314: * Adds the given component to the list of components at the specified
315: * index.
316: *
317: * @param posn
318: * an index to insert at
319: * @param comp
320: * the component to insert
321: * @return updated name (<code>this</code> object)
322: * @throws InvalidNameException
323: * if the given string can't be used as a DNS name component
324: * @throws ArrayIndexOutOfBoundsException
325: * if <code>posn</code> index is out of range
326: * @see javax.naming.Name#add(int, java.lang.String)
327: */
328: public Name add(int posn, String comp) throws InvalidNameException {
329: if (!componentIsOk(comp)) {
330: // jndi.30={0} can't be used as a component for DNS name
331: throw new InvalidNameException(Messages.getString(
332: "jndi.30", comp)); //$NON-NLS-1$
333: }
334: components.insertElementAt(comp, posn);
335: return this ;
336: }
337:
338: /**
339: * Adds the given component to the end of the current name.
340: *
341: * @param comp
342: * the component to insert
343: * @return updated name (<code>this</code> object)
344: * @throws InvalidNameException
345: * if the given string can't be used as a DNS name component
346: * @see javax.naming.Name#add(java.lang.String)
347: */
348: public Name add(String comp) throws InvalidNameException {
349: if (!componentIsOk(comp)) {
350: // jndi.30={0} can't be used as a component for DNS name
351: throw new InvalidNameException(Messages.getString(
352: "jndi.30", comp));//$NON-NLS-1$
353: }
354: components.addElement(comp);
355: return this ;
356: }
357:
358: /**
359: * Add given components to the current name. The order is preserved.
360: *
361: * @param posn
362: * the index at which given components should be added
363: * @param name
364: * components this name should be added
365: * @return <code>this</code> object
366: * @throws InvalidNameException
367: * if the name given is not an instance of <code>DNSName</code>
368: * class
369: * @see javax.naming.Name#addAll(int, javax.naming.Name)
370: */
371: public Name addAll(int posn, Name name) throws InvalidNameException {
372: Vector<String> newComps;
373:
374: if (!(name instanceof DNSName)) {
375: // jndi.31=Given name is not an instance of DNSName class
376: throw new InvalidNameException(Messages
377: .getString("jndi.31")); //$NON-NLS-1$
378: }
379: newComps = ((DNSName) name).components;
380: components.addAll(posn, newComps);
381: return this ;
382: }
383:
384: /**
385: * Add given components to the end of current name. The order is preserved.
386: *
387: * @param name
388: * components this name should be added
389: * @return <code>this</code> object
390: * @throws InvalidNameException
391: * if the name given is not an instance of <code>DNSName</code>
392: * class
393: * @see javax.naming.Name#addAll(javax.naming.Name)
394: */
395: public Name addAll(Name name) throws InvalidNameException {
396: Vector<String> newComps;
397:
398: if (!(name instanceof DNSName)) {
399: // jndi.31=Given name is not an instance of DNSName class
400: throw new InvalidNameException(Messages
401: .getString("jndi.31")); //$NON-NLS-1$
402: }
403: newComps = ((DNSName) name).components;
404: components.addAll(newComps);
405: return this ;
406: }
407:
408: /**
409: * Returns the string representation of this DNS name.
410: *
411: * @return DNS name in string form
412: */
413: @Override
414: public String toString() {
415: StringBuffer sb = new StringBuffer();
416:
417: for (int i = components.size() - 1; i >= 0; i--) {
418: String comp = components.elementAt(i);
419: if (sb.length() > 0 || i == 0) {
420: sb.append('.');
421: }
422: if (comp.length() > 0) {
423: sb.append(comp);
424: }
425: }
426: return sb.toString();
427: }
428:
429: /**
430: * Checks if the given string is a correct DNS name component.
431: *
432: * @param comp
433: * the string component to check
434: * @return <code>true</code> or <code>false</code>
435: */
436: static boolean componentIsOk(String comp) {
437: if (comp.indexOf(".") != -1 || comp.length() > //$NON-NLS-1$
438: ProviderConstants.LABEL_MAX_CHARS) {
439: return false;
440: }
441: return true;
442: }
443: }
|