Frames | No Frames |
1: /* GnuName.java -- implementation of the javax.naming.Name 2: Copyright (C) 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package gnu.javax.naming.ictxImpl.trans; 39: 40: import java.util.Enumeration; 41: import java.util.NoSuchElementException; 42: 43: import javax.naming.InvalidNameException; 44: import javax.naming.Name; 45: 46: /** 47: * The implementation of the {@link Name}. 48: * 49: * @author Audrius Meskauskas 50: */ 51: public class GnuName 52: implements Name 53: { 54: /** 55: * The enumeration to traverse over name components. 56: */ 57: class GnuNameEnum 58: implements Enumeration 59: { 60: /** 61: * Get the new enumeration that enumerates from the given position forward 62: * 63: * @param position the position of the first name component to enumerate (0 64: * means first element) 65: */ 66: GnuNameEnum(int position) 67: { 68: nxt = from + position; 69: } 70: 71: /** 72: * The position of the next enumeration component to be returned or -1 if 73: * the end has been reached. 74: */ 75: int nxt; 76: 77: /** 78: * Check if there are more elements in this enumeration. 79: */ 80: public boolean hasMoreElements() 81: { 82: return nxt >= 0; 83: } 84: 85: /** 86: * Return the next element or throw a NoSuchElementException if there is no 87: * any. 88: */ 89: public Object nextElement() 90: { 91: if (nxt < 0) 92: throw new NoSuchElementException(); 93: Object r = content[nxt++]; 94: 95: if (nxt - from == length) 96: nxt = - 1; 97: 98: return r; 99: } 100: } 101: 102: private static final long serialVersionUID = - 3617482732056931635L; 103: 104: /** 105: * The hashcode 106: */ 107: int hash; 108: 109: /** 110: * The content buffer of the name. This buffer may be shared, so the array 111: * member content should never be modified. 112: */ 113: String[] content; 114: 115: /** 116: * The place, inclusive, where the name content starts in the content buffer. 117: */ 118: int from; 119: 120: /** 121: * The length of the name. 122: */ 123: int length; 124: 125: /** 126: * Creates the unitialised name. 127: */ 128: protected GnuName() 129: { 130: 131: } 132: 133: /** 134: * Creates the name, containing from the given chain of the atomic components. 135: * 136: * @param name the array, containing the name components. 137: */ 138: public GnuName(String[] name) 139: { 140: this(name, 0, name.length); 141: } 142: 143: /** 144: * Creates the name that uses the given portion of the array for its 145: * components. 146: */ 147: public GnuName(String[] buffer, int useFrom, int useLength) 148: { 149: content = buffer; 150: from = useFrom; 151: length = useLength; 152: } 153: 154: /** 155: * Inserts the given <code>String</code> component to this <code>Name</code> 156: * at the given index. The method modifies the current <code>Name</code> and 157: * then returns it. 158: * 159: * @exception ArrayIndexOutOfBoundsException if the given index is smaller 160: * then zero or greater then or equal to <code>size()</code>. 161: * @exception InvalidNameException if the given <code>String</code> is not a 162: * valid component for this <code>Name</code>. 163: */ 164: public Name add(int posn, String comp) throws InvalidNameException 165: { 166: String[] nc = new String[content.length + 1]; 167: System.arraycopy(content, from, nc, 0, posn); 168: nc[posn] = comp; 169: System.arraycopy(content, from + posn, nc, posn + 1, length - posn); 170: 171: content = nc; 172: from = 0; 173: length = content.length; 174: hash = 0; 175: return this; 176: } 177: 178: /** 179: * Adds the given <code>String</code> component to the end of this 180: * <code>Name</code>. The method modifies the current <code>Name</code> 181: * and then returns it. 182: * 183: * @exception InvalidNameException if the given <code>String</code> is not a 184: * valid component for this <code>Name</code>. 185: */ 186: public Name add(String comp) throws InvalidNameException 187: { 188: String[] nc = new String[content.length + 1]; 189: System.arraycopy(content, from, nc, 0, length); 190: nc[nc.length - 1] = comp; 191: 192: content = nc; 193: from = 0; 194: length = content.length; 195: hash = 0; 196: return this; 197: } 198: 199: /** 200: * Inserts all the components of the given <code>Name</code> to this 201: * <code>Name</code> at the given index. Components after this index (if 202: * any) are shifted up. The method modifies the current <code>Name</code> 203: * and then returns it. 204: * 205: * @exception ArrayIndexOutOfBoundsException if the given index is smaller 206: * then zero or greater then or equal to <code>size()</code>. 207: * @exception InvalidNameException if any of the given components is not a 208: * valid component for this <code>Name</code>. 209: */ 210: public Name addAll(int posn, Name n) throws InvalidNameException 211: { 212: String[] nc = new String[length + n.size()]; 213: System.arraycopy(content, from, nc, 0, posn); 214: 215: int i = posn; 216: for (int p = 0; p < n.size(); i++, p++) 217: nc[i] = n.get(p); 218: 219: System.arraycopy(content, from + posn, nc, i, length - posn); 220: 221: length = length + n.size(); 222: hash = 0; 223: content = nc; 224: return this; 225: } 226: 227: /** 228: * Adds all the components of the given <code>Name</code> to the end of this 229: * <code>Name</code>. The method modifies the current <code>Name</code> 230: * and then returns it. 231: * 232: * @exception InvalidNameException if any of the given components is not a 233: * valid component for this <code>Name</code>. 234: */ 235: public Name addAll(Name suffix) throws InvalidNameException 236: { 237: String[] nc = new String[length + suffix.size()]; 238: System.arraycopy(content, from, nc, 0, length); 239: 240: for (int i = length, p = 0; i < nc.length; i++, p++) 241: nc[i] = suffix.get(p); 242: 243: length = length + suffix.size(); 244: hash = 0; 245: content = nc; 246: return this; 247: } 248: 249: /** 250: * Compares the given object to this <code>Name</code>. Returns a negative 251: * value if the given <code>Object</code> is smaller then this 252: * <code>Name</code>, a positive value if the <code>Object</code> is 253: * bigger, and zero if the are equal. If the <code>Object</code> is not of a 254: * class that can be compared to the class of this <code>Name</code> then a 255: * <code>ClassCastException</code> is thrown. Note that it is not guaranteed 256: * that <code>Name</code>s implemented in different classes can be 257: * compared. The definition of smaller, bigger and equal is up to the actual 258: * implementing class. 259: */ 260: public int compareTo(Object obj) 261: { 262: Name n = (Name) obj; 263: 264: int l = Math.min(length, n.size()); 265: int c; 266: 267: for (int i = 0; i < l; i++) 268: { 269: c = content[from + i].compareTo(n.get(i)); 270: if (c != 0) 271: return c; 272: } 273: return length - n.size(); 274: } 275: 276: /** 277: * Returns <code>true</code> if this <code>Name</code> ends with the 278: * components of the given <code>Name</code>, <code>false</code> 279: * otherwise. 280: */ 281: public boolean endsWith(Name n) 282: { 283: if (n.size() > length) 284: return false; 285: 286: int ofs = length - n.size() + from; 287: 288: for (int i = 0; i < n.size(); i++, ofs++) 289: if (! content[ofs].equals(n.get(i))) 290: return false; 291: 292: return true; 293: } 294: 295: /** 296: * Gets the component at the given index. 297: * 298: * @exception ArrayIndexOutOfBoundsException if the given index is smaller 299: * then zero or greater then or equal to <code>size()</code>. 300: */ 301: public String get(int posn) 302: { 303: return content[from + posn]; 304: } 305: 306: /** 307: * Returns a non-null (but possibly empty) <code>Enumeration</code> of the 308: * components of the <code>Name</code> as <code>String</code>s. 309: */ 310: public Enumeration getAll() 311: { 312: return new GnuNameEnum(0); 313: } 314: 315: /** 316: * Returns the components till the given index as a <code>Name</code>. The 317: * returned <code>Name</code> can be modified without changing the original. 318: * 319: * @param posn the ending position, exclusive 320: * @exception ArrayIndexOutOfBoundsException if the given index is smaller 321: * then zero or greater then or equal to <code>size()</code>. 322: */ 323: public Name getPrefix(int posn) 324: { 325: return new GnuName(content, from, posn); 326: } 327: 328: /** 329: * Returns the components from the given index till the end as a 330: * <code>Name</code>. The returned <code>Name</code> can be modified 331: * without changing the original. 332: * 333: * @param posn the starting position, inclusive. If it is equal to the size of 334: * the name, the empty name is returned. 335: * @exception ArrayIndexOutOfBoundsException if the given index is smaller 336: * then zero or greater then or equal to <code>size()</code>. 337: */ 338: public Name getSuffix(int posn) 339: { 340: return new GnuName(content, from + posn, length - posn); 341: } 342: 343: /** 344: * Returns <code>true</code> if the number of components of this 345: * <code>Name</code> is zero, <code>false</code> otherwise. 346: */ 347: public boolean isEmpty() 348: { 349: return length == 0; 350: } 351: 352: /** 353: * Removes the component at the given index from this <code>Name</code>. 354: * The method modifies the current <code>Name</code> and then returns it. 355: * 356: * @exception InvalidNameException if the name size reduces below zero. 357: */ 358: public Object remove(int posn) throws InvalidNameException 359: { 360: if (length == 0) 361: throw new InvalidNameException("negative size"); 362: else 363: { 364: length--; 365: if (posn == 0) 366: from++; 367: else if (posn < length) 368: { 369: String[] nc = new String[length]; 370: System.arraycopy(content, from, nc, 0, posn); 371: System.arraycopy(content, from + posn + 1, nc, posn, length - posn); 372: content = nc; 373: from = 0; 374: } 375: } 376: hash = 0; 377: return this; 378: } 379: 380: /** 381: * Returns the number of components of this <code>Name</code>. The returned 382: * number can be zero. 383: */ 384: public int size() 385: { 386: return length; 387: } 388: 389: /** 390: * Returns <code>true</code> if this <code>Name</code> starts with the 391: * components of the given <code>Name</code>, <code>false</code> 392: * otherwise. 393: */ 394: public boolean startsWith(Name n) 395: { 396: if (n.size() > length) 397: return false; 398: 399: for (int i = 0; i < n.size(); i++) 400: if (! content[from + i].equals(n.get(i))) 401: return false; 402: 403: return true; 404: } 405: 406: /** 407: * Returns a clone of this <code>Name</code>. It will be a deep copy of all 408: * the components of the <code>Name</code> so that changes to components of 409: * the components does not change the component in this <code>Name</code>. 410: */ 411: public Object clone() 412: { 413: return new GnuName(content, from, length); 414: } 415: 416: /** 417: * The name is equal to other name if they contents are equal. 418: */ 419: public boolean equals(Object arg0) 420: { 421: if (this == arg0) 422: return true; 423: else if (arg0 instanceof Name) 424: { 425: Name n = (Name) arg0; 426: if (length != n.size()) 427: return false; 428: 429: for (int i = 0; i < length; i++) 430: if (! content[from + i].equals(n.get(i))) 431: return false; 432: return true; 433: } 434: else 435: return false; 436: } 437: 438: /** 439: * Overridden to make consistent with equals. 440: */ 441: public int hashCode() 442: { 443: if (hash == 0 && length > 0) 444: { 445: int s = 0; 446: for (int i = from; i < from + length; i++) 447: s ^= content[i].hashCode(); 448: hash = s; 449: } 450: return hash; 451: } 452: 453: /** 454: * Get the string representation, separating the name components by slashes 455: */ 456: public String toString() 457: { 458: StringBuffer b = new StringBuffer(); 459: for (int i = 0; i < length; i++) 460: { 461: b.append(get(i)); 462: if (i < length - 1) 463: b.append('/'); 464: } 465: return b.toString(); 466: } 467: }