1 /* 2 * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.xml.namespace; 27 28 import java.io.Serializable; 29 import javax.xml.XMLConstants; 30 import jdk.xml.internal.SecuritySupport; 31 32 /** 33 * <p><code>QName</code> represents a <strong>qualified name</strong> 34 * as defined in the XML specifications: <a 35 * href="http://www.w3.org/TR/xmlschema-2/#QName">XML Schema Part2: 36 * Datatypes specification</a>, <a 37 * href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces 38 * in XML</a>, <a 39 * href="http://www.w3.org/XML/xml-names-19990114-errata">Namespaces 40 * in XML Errata</a>.</p> 41 * 42 * <p>The value of a <code>QName</code> contains a <strong>Namespace 43 * URI</strong>, <strong>local part</strong> and 44 * <strong>prefix</strong>.</p> 45 * 46 * <p>The prefix is included in <code>QName</code> to retain lexical 47 * information <strong><em>when present</em></strong> in an {@link 48 * javax.xml.transform.Source XML input source}. The prefix is 49 * <strong><em>NOT</em></strong> used in {@link #equals(Object) 50 * QName.equals(Object)} or to compute the {@link #hashCode() 51 * QName.hashCode()}. Equality and the hash code are defined using 52 * <strong><em>only</em></strong> the Namespace URI and local part.</p> 53 * 54 * <p>If not specified, the Namespace URI is set to {@link 55 * javax.xml.XMLConstants#NULL_NS_URI XMLConstants.NULL_NS_URI}. 56 * If not specified, the prefix is set to {@link 57 * javax.xml.XMLConstants#DEFAULT_NS_PREFIX 58 * XMLConstants.DEFAULT_NS_PREFIX}.</p> 59 * 60 * <p><code>QName</code> is immutable.</p> 61 * 62 * @author Jeff Suttor 63 * @see <a href="http://www.w3.org/TR/xmlschema-2/#QName"> 64 * XML Schema Part2: Datatypes specification</a> 65 * @see <a href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames"> 66 * Namespaces in XML</a> 67 * @see <a href="http://www.w3.org/XML/xml-names-19990114-errata"> 68 * Namespaces in XML Errata</a> 69 * @since 1.5 70 */ 71 72 public class QName implements Serializable { 73 // tests show that the ID is the same from JDK 1.5 through JDK 9 74 private static final long serialVersionUID = -9120448754896609940L; 75 76 /** 77 * <p>Namespace URI of this <code>QName</code>.</p> 78 */ 79 private final String namespaceURI; 80 81 /** 82 * <p>local part of this <code>QName</code>.</p> 83 */ 84 private final String localPart; 85 86 /** 87 * <p>prefix of this <code>QName</code>.</p> 88 */ 89 private final String prefix; 90 91 /** 92 * <p><code>QName</code> constructor specifying the Namespace URI 93 * and local part.</p> 94 * 95 * <p>If the Namespace URI is <code>null</code>, it is set to 96 * {@link javax.xml.XMLConstants#NULL_NS_URI 97 * XMLConstants.NULL_NS_URI}. This value represents no 98 * explicitly defined Namespace as defined by the <a 99 * href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces 100 * in XML</a> specification. This action preserves compatible 101 * behavior with QName 1.0. Explicitly providing the {@link 102 * javax.xml.XMLConstants#NULL_NS_URI 103 * XMLConstants.NULL_NS_URI} value is the preferred coding 104 * style.</p> 105 * 106 * <p>If the local part is <code>null</code> an 107 * <code>IllegalArgumentException</code> is thrown. 108 * A local part of "" is allowed to preserve 109 * compatible behavior with QName 1.0. </p> 110 * 111 * <p>When using this constructor, the prefix is set to {@link 112 * javax.xml.XMLConstants#DEFAULT_NS_PREFIX 113 * XMLConstants.DEFAULT_NS_PREFIX}.</p> 114 * 115 * <p>The Namespace URI is not validated as a 116 * <a href="http://www.ietf.org/rfc/rfc2396.txt">URI reference</a>. 117 * The local part is not validated as a 118 * <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a> 119 * as specified in <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces 120 * in XML</a>.</p> 121 * 122 * @param namespaceURI Namespace URI of the <code>QName</code> 123 * @param localPart local part of the <code>QName</code> 124 * 125 * @throws IllegalArgumentException When <code>localPart</code> is 126 * <code>null</code> 127 * 128 * @see #QName(String namespaceURI, String localPart, String 129 * prefix) QName(String namespaceURI, String localPart, String 130 * prefix) 131 */ 132 public QName(final String namespaceURI, final String localPart) { 133 this(namespaceURI, localPart, XMLConstants.DEFAULT_NS_PREFIX); 134 } 135 136 /** 137 * <p><code>QName</code> constructor specifying the Namespace URI, 138 * local part and prefix.</p> 139 * 140 * <p>If the Namespace URI is <code>null</code>, it is set to 141 * {@link javax.xml.XMLConstants#NULL_NS_URI 142 * XMLConstants.NULL_NS_URI}. This value represents no 143 * explicitly defined Namespace as defined by the <a 144 * href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces 145 * in XML</a> specification. This action preserves compatible 146 * behavior with QName 1.0. Explicitly providing the {@link 147 * javax.xml.XMLConstants#NULL_NS_URI 148 * XMLConstants.NULL_NS_URI} value is the preferred coding 149 * style.</p> 150 * 151 * <p>If the local part is <code>null</code> an 152 * <code>IllegalArgumentException</code> is thrown. 153 * A local part of "" is allowed to preserve 154 * compatible behavior with QName 1.0. </p> 155 * 156 * <p>If the prefix is <code>null</code>, an 157 * <code>IllegalArgumentException</code> is thrown. Use {@link 158 * javax.xml.XMLConstants#DEFAULT_NS_PREFIX 159 * XMLConstants.DEFAULT_NS_PREFIX} to explicitly indicate that no 160 * prefix is present or the prefix is not relevant.</p> 161 * 162 * <p>The Namespace URI is not validated as a 163 * <a href="http://www.ietf.org/rfc/rfc2396.txt">URI reference</a>. 164 * The local part and prefix are not validated as a 165 * <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a> 166 * as specified in <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces 167 * in XML</a>.</p> 168 * 169 * @param namespaceURI Namespace URI of the <code>QName</code> 170 * @param localPart local part of the <code>QName</code> 171 * @param prefix prefix of the <code>QName</code> 172 * 173 * @throws IllegalArgumentException When <code>localPart</code> 174 * or <code>prefix</code> is <code>null</code> 175 */ 176 public QName(String namespaceURI, String localPart, String prefix) { 177 178 // map null Namespace URI to default 179 // to preserve compatibility with QName 1.0 180 if (namespaceURI == null) { 181 this.namespaceURI = XMLConstants.NULL_NS_URI; 182 } else { 183 this.namespaceURI = namespaceURI; 184 } 185 186 // local part is required. 187 // "" is allowed to preserve compatibility with QName 1.0 188 if (localPart == null) { 189 throw new IllegalArgumentException( 190 "local part cannot be \"null\" when creating a QName"); 191 } 192 this.localPart = localPart; 193 194 // prefix is required 195 if (prefix == null) { 196 throw new IllegalArgumentException( 197 "prefix cannot be \"null\" when creating a QName"); 198 } 199 this.prefix = prefix; 200 } 201 202 /** 203 * <p><code>QName</code> constructor specifying the local part.</p> 204 * 205 * <p>If the local part is <code>null</code> an 206 * <code>IllegalArgumentException</code> is thrown. 207 * A local part of "" is allowed to preserve 208 * compatible behavior with QName 1.0. </p> 209 * 210 * <p>When using this constructor, the Namespace URI is set to 211 * {@link javax.xml.XMLConstants#NULL_NS_URI 212 * XMLConstants.NULL_NS_URI} and the prefix is set to {@link 213 * javax.xml.XMLConstants#DEFAULT_NS_PREFIX 214 * XMLConstants.DEFAULT_NS_PREFIX}.</p> 215 * 216 * <p><em>In an XML context, all Element and Attribute names exist 217 * in the context of a Namespace. Making this explicit during the 218 * construction of a <code>QName</code> helps prevent hard to 219 * diagnosis XML validity errors. The constructors {@link 220 * #QName(String namespaceURI, String localPart) QName(String 221 * namespaceURI, String localPart)} and 222 * {@link #QName(String namespaceURI, String localPart, String prefix)} 223 * are preferred.</em></p> 224 * 225 * <p>The local part is not validated as a 226 * <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a> 227 * as specified in <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces 228 * in XML</a>.</p> 229 * 230 * @param localPart local part of the <code>QName</code> 231 * 232 * @throws IllegalArgumentException When <code>localPart</code> is 233 * <code>null</code> 234 * 235 * @see #QName(String namespaceURI, String localPart) QName(String 236 * namespaceURI, String localPart) 237 * @see #QName(String namespaceURI, String localPart, String 238 * prefix) QName(String namespaceURI, String localPart, String 239 * prefix) 240 */ 241 public QName(String localPart) { 242 this( 243 XMLConstants.NULL_NS_URI, 244 localPart, 245 XMLConstants.DEFAULT_NS_PREFIX); 246 } 247 248 /** 249 * <p>Get the Namespace URI of this <code>QName</code>.</p> 250 * 251 * @return Namespace URI of this <code>QName</code> 252 */ 253 public String getNamespaceURI() { 254 return namespaceURI; 255 } 256 257 /** 258 * <p>Get the local part of this <code>QName</code>.</p> 259 * 260 * @return local part of this <code>QName</code> 261 */ 262 public String getLocalPart() { 263 return localPart; 264 } 265 266 /** 267 * <p>Get the prefix of this <code>QName</code>.</p> 268 * 269 * <p>The prefix assigned to a <code>QName</code> might 270 * <strong><em>NOT</em></strong> be valid in a different 271 * context. For example, a <code>QName</code> may be assigned a 272 * prefix in the context of parsing a document but that prefix may 273 * be invalid in the context of a different document.</p> 274 * 275 * @return prefix of this <code>QName</code> 276 */ 277 public String getPrefix() { 278 return prefix; 279 } 280 281 /** 282 * <p>Test this <code>QName</code> for equality with another 283 * <code>Object</code>.</p> 284 * 285 * <p>If the <code>Object</code> to be tested is not a 286 * <code>QName</code> or is <code>null</code>, then this method 287 * returns <code>false</code>.</p> 288 * 289 * <p>Two <code>QName</code>s are considered equal if and only if 290 * both the Namespace URI and local part are equal. This method 291 * uses <code>String.equals()</code> to check equality of the 292 * Namespace URI and local part. The prefix is 293 * <strong><em>NOT</em></strong> used to determine equality.</p> 294 * 295 * <p>This method satisfies the general contract of {@link 296 * java.lang.Object#equals(Object) Object.equals(Object)}</p> 297 * 298 * @param objectToTest the <code>Object</code> to test for 299 * equality with this <code>QName</code> 300 * @return <code>true</code> if the given <code>Object</code> is 301 * equal to this <code>QName</code> else <code>false</code> 302 */ 303 public final boolean equals(Object objectToTest) { 304 if (objectToTest == this) { 305 return true; 306 } 307 308 if (objectToTest == null || !(objectToTest instanceof QName)) { 309 return false; 310 } 311 312 QName qName = (QName) objectToTest; 313 314 return localPart.equals(qName.localPart) 315 && namespaceURI.equals(qName.namespaceURI); 316 } 317 318 /** 319 * <p>Generate the hash code for this <code>QName</code>.</p> 320 * 321 * <p>The hash code is calculated using both the Namespace URI and 322 * the local part of the <code>QName</code>. The prefix is 323 * <strong><em>NOT</em></strong> used to calculate the hash 324 * code.</p> 325 * 326 * <p>This method satisfies the general contract of {@link 327 * java.lang.Object#hashCode() Object.hashCode()}.</p> 328 * 329 * @return hash code for this <code>QName</code> <code>Object</code> 330 */ 331 public final int hashCode() { 332 return namespaceURI.hashCode() ^ localPart.hashCode(); 333 } 334 335 /** 336 * <p><code>String</code> representation of this 337 * <code>QName</code>.</p> 338 * 339 * <p>The commonly accepted way of representing a <code>QName</code> 340 * as a <code>String</code> was 341 * <a href="http://jclark.com/xml/xmlns.htm">defined</a> 342 * by James Clark. Although this is not a <em>standard</em> 343 * specification, it is in common use, e.g. {@link 344 * javax.xml.transform.Transformer#setParameter(String name, Object value)}. 345 * This implementation represents a <code>QName</code> as: 346 * "{" + Namespace URI + "}" + local part. If the Namespace URI 347 * <code>.equals(XMLConstants.NULL_NS_URI)</code>, only the 348 * local part is returned. An appropriate use of this method is 349 * for debugging or logging for human consumption.</p> 350 * 351 * <p>Note the prefix value is <strong><em>NOT</em></strong> 352 * returned as part of the <code>String</code> representation.</p> 353 * 354 * <p>This method satisfies the general contract of {@link 355 * java.lang.Object#toString() Object.toString()}.</p> 356 * 357 * @return <code>String</code> representation of this <code>QName</code> 358 */ 359 public String toString() { 360 if (namespaceURI.equals(XMLConstants.NULL_NS_URI)) { 361 return localPart; 362 } else { 363 return "{" + namespaceURI + "}" + localPart; 364 } 365 } 366 367 /** 368 * <p><code>QName</code> derived from parsing the formatted 369 * <code>String</code>.</p> 370 * 371 * <p>If the <code>String</code> is <code>null</code> or does not conform to 372 * {@link #toString() QName.toString()} formatting, an 373 * <code>IllegalArgumentException</code> is thrown.</p> 374 * 375 * <p><em>The <code>String</code> <strong>MUST</strong> be in the 376 * form returned by {@link #toString() QName.toString()}.</em></p> 377 * 378 * <p>The commonly accepted way of representing a <code>QName</code> 379 * as a <code>String</code> was 380 * <a href="http://jclark.com/xml/xmlns.htm">defined</a> 381 * by James Clark. Although this is not a <em>standard</em> 382 * specification, it is in common use, e.g. {@link 383 * javax.xml.transform.Transformer#setParameter(String name, Object value)}. 384 * This implementation parses a <code>String</code> formatted 385 * as: "{" + Namespace URI + "}" + local part. If the Namespace 386 * URI <code>.equals(XMLConstants.NULL_NS_URI)</code>, only the 387 * local part should be provided.</p> 388 * 389 * <p>The prefix value <strong><em>CANNOT</em></strong> be 390 * represented in the <code>String</code> and will be set to 391 * {@link javax.xml.XMLConstants#DEFAULT_NS_PREFIX 392 * XMLConstants.DEFAULT_NS_PREFIX}.</p> 393 * 394 * <p>This method does not do full validation of the resulting 395 * <code>QName</code>. 396 * <p>The Namespace URI is not validated as a 397 * <a href="http://www.ietf.org/rfc/rfc2396.txt">URI reference</a>. 398 * The local part is not validated as a 399 * <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a> 400 * as specified in 401 * <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML</a>.</p> 402 * 403 * @param qNameAsString <code>String</code> representation 404 * of the <code>QName</code> 405 * 406 * @throws IllegalArgumentException When <code>qNameAsString</code> is 407 * <code>null</code> or malformed 408 * 409 * @return <code>QName</code> corresponding to the given <code>String</code> 410 * @see #toString() QName.toString() 411 */ 412 public static QName valueOf(String qNameAsString) { 413 414 // null is not valid 415 if (qNameAsString == null) { 416 throw new IllegalArgumentException( 417 "cannot create QName from \"null\" or \"\" String"); 418 } 419 420 // "" local part is valid to preserve compatible behavior with QName 1.0 421 if (qNameAsString.length() == 0) { 422 return new QName( 423 XMLConstants.NULL_NS_URI, 424 qNameAsString, 425 XMLConstants.DEFAULT_NS_PREFIX); 426 } 427 428 // local part only? 429 if (qNameAsString.charAt(0) != '{') { 430 return new QName( 431 XMLConstants.NULL_NS_URI, 432 qNameAsString, 433 XMLConstants.DEFAULT_NS_PREFIX); 434 } 435 436 // Namespace URI improperly specified? 437 if (qNameAsString.startsWith("{" + XMLConstants.NULL_NS_URI + "}")) { 438 throw new IllegalArgumentException( 439 "Namespace URI .equals(XMLConstants.NULL_NS_URI), " 440 + ".equals(\"" + XMLConstants.NULL_NS_URI + "\"), " 441 + "only the local part, " 442 + "\"" 443 + qNameAsString.substring(2 + XMLConstants.NULL_NS_URI.length()) 444 + "\", " 445 + "should be provided."); 446 } 447 448 // Namespace URI and local part specified 449 int endOfNamespaceURI = qNameAsString.indexOf('}'); 450 if (endOfNamespaceURI == -1) { 451 throw new IllegalArgumentException( 452 "cannot create QName from \"" 453 + qNameAsString 454 + "\", missing closing \"}\""); 455 } 456 return new QName( 457 qNameAsString.substring(1, endOfNamespaceURI), 458 qNameAsString.substring(endOfNamespaceURI + 1), 459 XMLConstants.DEFAULT_NS_PREFIX); 460 } 461 }