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