1 /* CompositeName.java -- 2 Copyright (C) 2001, 2005, 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 39 package javax.naming; 40 41 import gnu.java.lang.CPStringBuilder; 42 43 import java.io.IOException; 44 import java.io.ObjectInputStream; 45 import java.io.ObjectOutputStream; 46 import java.io.Serializable; 47 import java.util.Enumeration; 48 import java.util.NoSuchElementException; 49 import java.util.Vector; 50 51 /** 52 * Represents names that may span over several namespaces. For instance, 53 * the composite name http://www.gnu.org/software/classpath/index.html spans 54 * over three namespaces (the protocol http, the web server location 55 * (www.gnu.org) and the index.html location on the server). 56 * 57 * @author Tom Tromey (tromey@redhat.com) 58 */ 59 public class CompositeName implements Name, Cloneable, Serializable 60 { 61 private static final long serialVersionUID = 1667768148915813118L; 62 63 private transient Vector<String> elts; 64 CompositeName()65 public CompositeName () 66 { 67 elts = new Vector<String> (); 68 } 69 CompositeName(Enumeration<String> comps)70 protected CompositeName (Enumeration<String> comps) 71 { 72 elts = new Vector<String> (); 73 try 74 { 75 while (comps.hasMoreElements ()) 76 elts.add (comps.nextElement ()); 77 } 78 catch (NoSuchElementException ignore) 79 { 80 } 81 } 82 CompositeName(String n)83 public CompositeName (String n) throws InvalidNameException 84 { 85 elts = new Vector<String> (); 86 // Parse the string into its components. 87 final char no_quote = 'x'; // Use 'x' to mean no quoting. 88 char quote = no_quote; 89 boolean escaped = false; 90 StringBuilder new_element = new StringBuilder (); 91 for (int i = 0; i < n.length (); ++i) 92 { 93 char c = n.charAt (i); 94 if (escaped) 95 escaped = false; 96 else if (c == '\\') 97 { 98 escaped = true; 99 continue; 100 } 101 else if (quote != no_quote) 102 { 103 if (quote == c) 104 { 105 // The quotes must surround a complete component. 106 if (i + 1 < n.length () && n.charAt (i + 1) != '/') 107 throw new InvalidNameException ("close quote before end of component"); 108 elts.add (new_element.toString ()); 109 new_element.setLength (0); 110 quote = no_quote; 111 continue; 112 } 113 // Otherwise, fall through. 114 } 115 // Quotes are only special at the start of a component. 116 else if (new_element.length () == 0 117 && (c == '\'' || c == '"')) 118 { 119 quote = c; 120 continue; 121 } 122 else if (c == '/') 123 { 124 elts.add (new_element.toString ()); 125 new_element.setLength (0); 126 continue; 127 } 128 129 new_element.append (c); 130 } 131 132 if (new_element.length () != 0) 133 elts.add (new_element.toString ()); 134 135 // Error checking. 136 if (quote != no_quote) 137 throw new InvalidNameException ("unterminated quote"); 138 if (escaped) 139 throw new InvalidNameException ("trailing escape character"); 140 } 141 add(int posn, String comp)142 public Name add (int posn, String comp) throws InvalidNameException 143 { 144 elts.add (posn, comp); 145 return this; 146 } 147 add(String comp)148 public Name add (String comp) throws InvalidNameException 149 { 150 elts.add (comp); 151 return this; 152 } 153 addAll(int posn, Name n)154 public Name addAll (int posn, Name n) throws InvalidNameException 155 { 156 Enumeration<String> e = n.getAll (); 157 try 158 { 159 while (e.hasMoreElements ()) 160 { 161 elts.add (posn, e.nextElement ()); 162 ++posn; 163 } 164 } 165 catch (NoSuchElementException ignore) 166 { 167 } 168 return this; 169 } 170 addAll(Name suffix)171 public Name addAll (Name suffix) throws InvalidNameException 172 { 173 Enumeration<String> e = suffix.getAll (); 174 try 175 { 176 while (e.hasMoreElements ()) 177 elts.add (e.nextElement ()); 178 } 179 catch (NoSuchElementException ignore) 180 { 181 } 182 return this; 183 } 184 clone()185 public Object clone () 186 { 187 return new CompositeName (elts.elements ()); 188 } 189 compareTo(Object obj)190 public int compareTo (Object obj) 191 { 192 if (obj == null || ! (obj instanceof CompositeName)) 193 throw new ClassCastException ("CompositeName.compareTo() expected CompositeName"); 194 CompositeName cn = (CompositeName) obj; 195 int last = Math.min (cn.elts.size (), elts.size ()); 196 for (int i = 0; i < last; ++i) 197 { 198 String f = elts.get (i); 199 int comp = f.compareTo (cn.elts.get (i)); 200 if (comp != 0) 201 return comp; 202 } 203 return elts.size () - cn.elts.size (); 204 } 205 endsWith(Name n)206 public boolean endsWith (Name n) 207 { 208 if (! (n instanceof CompositeName)) 209 return false; 210 CompositeName cn = (CompositeName) n; 211 if (cn.elts.size () > elts.size ()) 212 return false; 213 int delta = elts.size () - cn.elts.size (); 214 for (int i = 0; i < cn.elts.size (); ++i) 215 { 216 if (! cn.elts.get (i).equals (elts.get (delta + i))) 217 return false; 218 } 219 return true; 220 } 221 equals(Object obj)222 public boolean equals (Object obj) 223 { 224 if (! (obj instanceof CompositeName)) 225 return false; 226 CompositeName cn = (CompositeName) obj; 227 return elts.equals (cn.elts); 228 } 229 get(int posn)230 public String get (int posn) 231 { 232 return elts.get (posn); 233 } 234 getAll()235 public Enumeration<String> getAll () 236 { 237 return elts.elements (); 238 } 239 getPrefix(int posn)240 public Name getPrefix (int posn) 241 { 242 CompositeName cn = new CompositeName (); 243 for (int i = 0; i < posn; ++i) 244 cn.elts.add (elts.get (i)); 245 return cn; 246 } 247 getSuffix(int posn)248 public Name getSuffix (int posn) 249 { 250 if (posn > elts.size ()) 251 throw new ArrayIndexOutOfBoundsException (posn); 252 CompositeName cn = new CompositeName (); 253 for (int i = posn; i < elts.size (); ++i) 254 cn.elts.add (elts.get (i)); 255 return cn; 256 } 257 hashCode()258 public int hashCode () 259 { 260 // Specified in documentation. 261 int h = 0; 262 for (int i = 0; i < elts.size (); ++i) 263 h += elts.get (i).hashCode (); 264 return h; 265 } 266 isEmpty()267 public boolean isEmpty () 268 { 269 return elts.isEmpty (); 270 } 271 remove(int posn)272 public Object remove (int posn) throws InvalidNameException 273 { 274 return elts.remove (posn); 275 } 276 size()277 public int size () 278 { 279 return elts.size (); 280 } 281 startsWith(Name n)282 public boolean startsWith (Name n) 283 { 284 if (! (n instanceof CompositeName)) 285 return false; 286 CompositeName cn = (CompositeName) n; 287 if (cn.elts.size () > elts.size ()) 288 return false; 289 for (int i = 0; i < cn.elts.size (); ++i) 290 { 291 if (! cn.elts.get (i).equals (elts.get (i))) 292 return false; 293 } 294 return true; 295 } 296 toString()297 public String toString () 298 { 299 CPStringBuilder result = new CPStringBuilder (); 300 for (int i = 0; i < elts.size (); ++i) 301 { 302 // For simplicity we choose to always quote using escapes and 303 // never quotes. 304 String elt = elts.get (i); 305 if (i > 0 306 || (i == elts.size () - 1 && elt.equals (""))) 307 result.append ('/'); 308 for (int k = 0; k < elt.length (); ++k) 309 { 310 char c = elt.charAt (k); 311 // We must quote 312 // ... a leading quote, 313 if ((k == 0 && (c == '"' || c == '\'')) 314 // ... an escape preceding a meta character, 315 // or at the end of a component, 316 || (c == '\\' 317 && (k == elt.length () - 1 318 || "\\'\"/".indexOf (elt.charAt (k + 1)) != -1)) 319 // ... or a component separator. 320 || c == '/') 321 result.append ('\\'); 322 result.append (c); 323 } 324 } 325 return result.toString (); 326 } 327 readObject(ObjectInputStream s)328 private void readObject(ObjectInputStream s) 329 throws IOException, ClassNotFoundException 330 { 331 int size = s.readInt(); 332 elts = new Vector<String>(size); 333 for (int i = 0; i < size; i++) 334 elts.add((String) s.readObject()); 335 } 336 writeObject(ObjectOutputStream s)337 private void writeObject(ObjectOutputStream s) throws IOException 338 { 339 s.writeInt(elts.size()); 340 for (int i = 0; i < elts.size(); i++) 341 s.writeObject(elts.get(i)); 342 } 343 } 344