CompositeName.java 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /* CompositeName.java --
  2. Copyright (C) 2001, 2005, 2006 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package javax.naming;
  32. import gnu.java.lang.CPStringBuilder;
  33. import java.io.IOException;
  34. import java.io.ObjectInputStream;
  35. import java.io.ObjectOutputStream;
  36. import java.io.Serializable;
  37. import java.util.Enumeration;
  38. import java.util.NoSuchElementException;
  39. import java.util.Vector;
  40. /**
  41. * Represents names that may span over several namespaces. For instance,
  42. * the composite name http://www.gnu.org/software/classpath/index.html spans
  43. * over three namespaces (the protocol http, the web server location
  44. * (www.gnu.org) and the index.html location on the server).
  45. *
  46. * @author Tom Tromey (tromey@redhat.com)
  47. */
  48. public class CompositeName implements Name, Cloneable, Serializable
  49. {
  50. private static final long serialVersionUID = 1667768148915813118L;
  51. private transient Vector<String> elts;
  52. public CompositeName ()
  53. {
  54. elts = new Vector<String> ();
  55. }
  56. protected CompositeName (Enumeration<String> comps)
  57. {
  58. elts = new Vector<String> ();
  59. try
  60. {
  61. while (comps.hasMoreElements ())
  62. elts.add (comps.nextElement ());
  63. }
  64. catch (NoSuchElementException ignore)
  65. {
  66. }
  67. }
  68. public CompositeName (String n) throws InvalidNameException
  69. {
  70. elts = new Vector<String> ();
  71. // Parse the string into its components.
  72. final char no_quote = 'x'; // Use 'x' to mean no quoting.
  73. char quote = no_quote;
  74. boolean escaped = false;
  75. StringBuilder new_element = new StringBuilder ();
  76. for (int i = 0; i < n.length (); ++i)
  77. {
  78. char c = n.charAt (i);
  79. if (escaped)
  80. escaped = false;
  81. else if (c == '\\')
  82. {
  83. escaped = true;
  84. continue;
  85. }
  86. else if (quote != no_quote)
  87. {
  88. if (quote == c)
  89. {
  90. // The quotes must surround a complete component.
  91. if (i + 1 < n.length () && n.charAt (i + 1) != '/')
  92. throw new InvalidNameException ("close quote before end of component");
  93. elts.add (new_element.toString ());
  94. new_element.setLength (0);
  95. quote = no_quote;
  96. continue;
  97. }
  98. // Otherwise, fall through.
  99. }
  100. // Quotes are only special at the start of a component.
  101. else if (new_element.length () == 0
  102. && (c == '\'' || c == '"'))
  103. {
  104. quote = c;
  105. continue;
  106. }
  107. else if (c == '/')
  108. {
  109. elts.add (new_element.toString ());
  110. new_element.setLength (0);
  111. continue;
  112. }
  113. new_element.append (c);
  114. }
  115. if (new_element.length () != 0)
  116. elts.add (new_element.toString ());
  117. // Error checking.
  118. if (quote != no_quote)
  119. throw new InvalidNameException ("unterminated quote");
  120. if (escaped)
  121. throw new InvalidNameException ("trailing escape character");
  122. }
  123. public Name add (int posn, String comp) throws InvalidNameException
  124. {
  125. elts.add (posn, comp);
  126. return this;
  127. }
  128. public Name add (String comp) throws InvalidNameException
  129. {
  130. elts.add (comp);
  131. return this;
  132. }
  133. public Name addAll (int posn, Name n) throws InvalidNameException
  134. {
  135. Enumeration<String> e = n.getAll ();
  136. try
  137. {
  138. while (e.hasMoreElements ())
  139. {
  140. elts.add (posn, e.nextElement ());
  141. ++posn;
  142. }
  143. }
  144. catch (NoSuchElementException ignore)
  145. {
  146. }
  147. return this;
  148. }
  149. public Name addAll (Name suffix) throws InvalidNameException
  150. {
  151. Enumeration<String> e = suffix.getAll ();
  152. try
  153. {
  154. while (e.hasMoreElements ())
  155. elts.add (e.nextElement ());
  156. }
  157. catch (NoSuchElementException ignore)
  158. {
  159. }
  160. return this;
  161. }
  162. public Object clone ()
  163. {
  164. return new CompositeName (elts.elements ());
  165. }
  166. public int compareTo (Object obj)
  167. {
  168. if (obj == null || ! (obj instanceof CompositeName))
  169. throw new ClassCastException ("CompositeName.compareTo() expected CompositeName");
  170. CompositeName cn = (CompositeName) obj;
  171. int last = Math.min (cn.elts.size (), elts.size ());
  172. for (int i = 0; i < last; ++i)
  173. {
  174. String f = elts.get (i);
  175. int comp = f.compareTo (cn.elts.get (i));
  176. if (comp != 0)
  177. return comp;
  178. }
  179. return elts.size () - cn.elts.size ();
  180. }
  181. public boolean endsWith (Name n)
  182. {
  183. if (! (n instanceof CompositeName))
  184. return false;
  185. CompositeName cn = (CompositeName) n;
  186. if (cn.elts.size () > elts.size ())
  187. return false;
  188. int delta = elts.size () - cn.elts.size ();
  189. for (int i = 0; i < cn.elts.size (); ++i)
  190. {
  191. if (! cn.elts.get (i).equals (elts.get (delta + i)))
  192. return false;
  193. }
  194. return true;
  195. }
  196. public boolean equals (Object obj)
  197. {
  198. if (! (obj instanceof CompositeName))
  199. return false;
  200. CompositeName cn = (CompositeName) obj;
  201. return elts.equals (cn.elts);
  202. }
  203. public String get (int posn)
  204. {
  205. return elts.get (posn);
  206. }
  207. public Enumeration<String> getAll ()
  208. {
  209. return elts.elements ();
  210. }
  211. public Name getPrefix (int posn)
  212. {
  213. CompositeName cn = new CompositeName ();
  214. for (int i = 0; i < posn; ++i)
  215. cn.elts.add (elts.get (i));
  216. return cn;
  217. }
  218. public Name getSuffix (int posn)
  219. {
  220. if (posn > elts.size ())
  221. throw new ArrayIndexOutOfBoundsException (posn);
  222. CompositeName cn = new CompositeName ();
  223. for (int i = posn; i < elts.size (); ++i)
  224. cn.elts.add (elts.get (i));
  225. return cn;
  226. }
  227. public int hashCode ()
  228. {
  229. // Specified in documentation.
  230. int h = 0;
  231. for (int i = 0; i < elts.size (); ++i)
  232. h += elts.get (i).hashCode ();
  233. return h;
  234. }
  235. public boolean isEmpty ()
  236. {
  237. return elts.isEmpty ();
  238. }
  239. public Object remove (int posn) throws InvalidNameException
  240. {
  241. return elts.remove (posn);
  242. }
  243. public int size ()
  244. {
  245. return elts.size ();
  246. }
  247. public boolean startsWith (Name n)
  248. {
  249. if (! (n instanceof CompositeName))
  250. return false;
  251. CompositeName cn = (CompositeName) n;
  252. if (cn.elts.size () > elts.size ())
  253. return false;
  254. for (int i = 0; i < cn.elts.size (); ++i)
  255. {
  256. if (! cn.elts.get (i).equals (elts.get (i)))
  257. return false;
  258. }
  259. return true;
  260. }
  261. public String toString ()
  262. {
  263. CPStringBuilder result = new CPStringBuilder ();
  264. for (int i = 0; i < elts.size (); ++i)
  265. {
  266. // For simplicity we choose to always quote using escapes and
  267. // never quotes.
  268. String elt = elts.get (i);
  269. if (i > 0
  270. || (i == elts.size () - 1 && elt.equals ("")))
  271. result.append ('/');
  272. for (int k = 0; k < elt.length (); ++k)
  273. {
  274. char c = elt.charAt (k);
  275. // We must quote
  276. // ... a leading quote,
  277. if ((k == 0 && (c == '"' || c == '\''))
  278. // ... an escape preceding a meta character,
  279. // or at the end of a component,
  280. || (c == '\\'
  281. && (k == elt.length () - 1
  282. || "\\'\"/".indexOf (elt.charAt (k + 1)) != -1))
  283. // ... or a component separator.
  284. || c == '/')
  285. result.append ('\\');
  286. result.append (c);
  287. }
  288. }
  289. return result.toString ();
  290. }
  291. private void readObject(ObjectInputStream s)
  292. throws IOException, ClassNotFoundException
  293. {
  294. int size = s.readInt();
  295. elts = new Vector<String>(size);
  296. for (int i = 0; i < size; i++)
  297. elts.add((String) s.readObject());
  298. }
  299. private void writeObject(ObjectOutputStream s) throws IOException
  300. {
  301. s.writeInt(elts.size());
  302. for (int i = 0; i < elts.size(); i++)
  303. s.writeObject(elts.get(i));
  304. }
  305. }