1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xerces" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, International
  53. * Business Machines, Inc., http://www.apache.org. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package com.sun.org.apache.xerces.internal.dom;
  58. import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  59. import com.sun.org.apache.xerces.internal.util.URI;
  60. import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  61. import org.w3c.dom.Attr;
  62. import org.w3c.dom.DOMException;
  63. import org.w3c.dom.TypeInfo;
  64. /**
  65. * ElementNSImpl inherits from ElementImpl and adds namespace support.
  66. * <P>
  67. * The qualified name is the node name, and we store localName which is also
  68. * used in all queries. On the other hand we recompute the prefix when
  69. * necessary.
  70. * @author Elena litani, IBM
  71. * @author Neeraj Bajaj, Sun Microsystems
  72. * @version $Id: ElementNSImpl.java,v 1.41 2004/01/29 20:59:52 elena Exp $
  73. */
  74. public class ElementNSImpl
  75. extends ElementImpl {
  76. //
  77. // Constants
  78. //
  79. /** Serialization version. */
  80. static final long serialVersionUID = -9142310625494392642L;
  81. static final String xmlURI = "http://www.w3.org/XML/1998/namespace";
  82. //
  83. // Data
  84. //
  85. /** DOM2: Namespace URI. */
  86. protected String namespaceURI;
  87. /** DOM2: localName. */
  88. protected String localName;
  89. protected ElementNSImpl() {
  90. super();
  91. }
  92. /**
  93. * DOM2: Constructor for Namespace implementation.
  94. */
  95. protected ElementNSImpl(CoreDocumentImpl ownerDocument,
  96. String namespaceURI,
  97. String qualifiedName)
  98. throws DOMException
  99. {
  100. super(ownerDocument, qualifiedName);
  101. setName(namespaceURI, qualifiedName);
  102. }
  103. private void setName(String namespaceURI, String qname) {
  104. String prefix;
  105. // DOM Level 3: namespace URI is never empty string.
  106. this.namespaceURI = namespaceURI;
  107. if (namespaceURI != null) {
  108. //convert the empty string to 'null'
  109. this.namespaceURI = (namespaceURI.length() == 0) ? null : namespaceURI;
  110. }
  111. int colon1, colon2 ;
  112. //NAMESPACE_ERR:
  113. //1. if the qualified name is 'null' it is malformed.
  114. //2. or if the qualifiedName is null and the namespaceURI is different from null,
  115. // We dont need to check for namespaceURI != null, if qualified name is null throw DOMException.
  116. if(qname == null){
  117. String msg =
  118. DOMMessageFormatter.formatMessage(
  119. DOMMessageFormatter.DOM_DOMAIN,
  120. "NAMESPACE_ERR",
  121. null);
  122. throw new DOMException(DOMException.NAMESPACE_ERR, msg);
  123. }
  124. else{
  125. colon1 = qname.indexOf(':');
  126. colon2 = qname.lastIndexOf(':');
  127. }
  128. ownerDocument().checkNamespaceWF(qname, colon1, colon2);
  129. if (colon1 < 0) {
  130. // there is no prefix
  131. localName = qname;
  132. ownerDocument().checkQName(null, localName);
  133. if (qname.equals("xmlns")
  134. && (namespaceURI == null
  135. || !namespaceURI.equals(NamespaceContext.XMLNS_URI))
  136. || (namespaceURI!=null && namespaceURI.equals(NamespaceContext.XMLNS_URI)
  137. && !qname.equals("xmlns"))) {
  138. String msg =
  139. DOMMessageFormatter.formatMessage(
  140. DOMMessageFormatter.DOM_DOMAIN,
  141. "NAMESPACE_ERR",
  142. null);
  143. throw new DOMException(DOMException.NAMESPACE_ERR, msg);
  144. }
  145. }//there is a prefix
  146. else {
  147. prefix = qname.substring(0, colon1);
  148. //NAMESPACE_ERR:
  149. //1. if the qualifiedName has a prefix and the namespaceURI is null,
  150. //2. or if the qualifiedName has a prefix that is "xml" and the namespaceURI
  151. //is different from " http://www.w3.org/XML/1998/namespace"
  152. if( namespaceURI == null || ( prefix.equals("xml") && !namespaceURI.equals(NamespaceContext.XML_URI) )){
  153. String msg =
  154. DOMMessageFormatter.formatMessage(
  155. DOMMessageFormatter.DOM_DOMAIN,
  156. "NAMESPACE_ERR",
  157. null);
  158. throw new DOMException(DOMException.NAMESPACE_ERR, msg);
  159. }
  160. localName = qname.substring(colon2 + 1);
  161. ownerDocument().checkQName(prefix, localName);
  162. ownerDocument().checkDOMNSErr(prefix, namespaceURI);
  163. }
  164. }
  165. // when local name is known
  166. protected ElementNSImpl(CoreDocumentImpl ownerDocument,
  167. String namespaceURI, String qualifiedName,
  168. String localName)
  169. throws DOMException
  170. {
  171. super(ownerDocument, qualifiedName);
  172. this.localName = localName;
  173. this.namespaceURI = namespaceURI;
  174. }
  175. // for DeferredElementImpl
  176. protected ElementNSImpl(CoreDocumentImpl ownerDocument,
  177. String value) {
  178. super(ownerDocument, value);
  179. }
  180. // Support for DOM Level 3 renameNode method.
  181. // Note: This only deals with part of the pb. CoreDocumentImpl
  182. // does all the work.
  183. void rename(String namespaceURI, String qualifiedName)
  184. {
  185. if (needsSyncData()) {
  186. synchronizeData();
  187. }
  188. this.name = qualifiedName;
  189. setName(namespaceURI, qualifiedName);
  190. reconcileDefaultAttributes();
  191. }
  192. /**
  193. * NON-DOM: resets this node and sets specified values for the node
  194. *
  195. * @param ownerDocument
  196. * @param namespaceURI
  197. * @param qualifiedName
  198. * @param localName
  199. */
  200. protected void setValues (CoreDocumentImpl ownerDocument,
  201. String namespaceURI, String qualifiedName,
  202. String localName){
  203. // remove children first
  204. firstChild = null;
  205. previousSibling = null;
  206. nextSibling = null;
  207. fNodeListCache = null;
  208. // set owner document
  209. attributes = null;
  210. super.flags = 0;
  211. setOwnerDocument(ownerDocument);
  212. // synchronizeData will initialize attributes
  213. needsSyncData(true);
  214. super.name = qualifiedName;
  215. this.localName = localName;
  216. this.namespaceURI = namespaceURI;
  217. }
  218. //
  219. // Node methods
  220. //
  221. //
  222. //DOM2: Namespace methods.
  223. //
  224. /**
  225. * Introduced in DOM Level 2. <p>
  226. *
  227. * The namespace URI of this node, or null if it is unspecified.<p>
  228. *
  229. * This is not a computed value that is the result of a namespace lookup based on
  230. * an examination of the namespace declarations in scope. It is merely the
  231. * namespace URI given at creation time.<p>
  232. *
  233. * For nodes created with a DOM Level 1 method, such as createElement
  234. * from the Document interface, this is null.
  235. * @since WD-DOM-Level-2-19990923
  236. */
  237. public String getNamespaceURI()
  238. {
  239. if (needsSyncData()) {
  240. synchronizeData();
  241. }
  242. return namespaceURI;
  243. }
  244. /**
  245. * Introduced in DOM Level 2. <p>
  246. *
  247. * The namespace prefix of this node, or null if it is unspecified. <p>
  248. *
  249. * For nodes created with a DOM Level 1 method, such as createElement
  250. * from the Document interface, this is null. <p>
  251. *
  252. * @since WD-DOM-Level-2-19990923
  253. */
  254. public String getPrefix()
  255. {
  256. if (needsSyncData()) {
  257. synchronizeData();
  258. }
  259. int index = name.indexOf(':');
  260. return index < 0 ? null : name.substring(0, index);
  261. }
  262. /**
  263. * Introduced in DOM Level 2. <p>
  264. *
  265. * Note that setting this attribute changes the nodeName attribute, which holds the
  266. * qualified name, as well as the tagName and name attributes of the Element
  267. * and Attr interfaces, when applicable.<p>
  268. *
  269. * @param prefix The namespace prefix of this node, or null(empty string) if it is unspecified.
  270. *
  271. * @exception INVALID_CHARACTER_ERR
  272. * Raised if the specified
  273. * prefix contains an invalid character.
  274. * @exception DOMException
  275. * @since WD-DOM-Level-2-19990923
  276. */
  277. public void setPrefix(String prefix)
  278. throws DOMException
  279. {
  280. if (needsSyncData()) {
  281. synchronizeData();
  282. }
  283. if (ownerDocument().errorChecking) {
  284. if (isReadOnly()) {
  285. String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
  286. throw new DOMException(
  287. DOMException.NO_MODIFICATION_ALLOWED_ERR,
  288. msg);
  289. }
  290. if (prefix != null && prefix.length() != 0) {
  291. if (!CoreDocumentImpl.isXMLName(prefix,ownerDocument().isXML11Version())) {
  292. String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
  293. throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
  294. }
  295. if (namespaceURI == null || prefix.indexOf(':') >=0) {
  296. String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
  297. throw new DOMException(DOMException.NAMESPACE_ERR, msg);
  298. } else if (prefix.equals("xml")) {
  299. if (!namespaceURI.equals(xmlURI)) {
  300. String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
  301. throw new DOMException(DOMException.NAMESPACE_ERR, msg);
  302. }
  303. }
  304. }
  305. }
  306. // update node name with new qualifiedName
  307. if (prefix !=null && prefix.length() != 0) {
  308. name = prefix + ":" + localName;
  309. }
  310. else {
  311. name = localName;
  312. }
  313. }
  314. /**
  315. * Introduced in DOM Level 2. <p>
  316. *
  317. * Returns the local part of the qualified name of this node.
  318. * @since WD-DOM-Level-2-19990923
  319. */
  320. public String getLocalName()
  321. {
  322. if (needsSyncData()) {
  323. synchronizeData();
  324. }
  325. return localName;
  326. }
  327. /**
  328. * DOM Level 3 WD - Experimental.
  329. * Retrieve baseURI
  330. */
  331. public String getBaseURI() {
  332. if (needsSyncData()) {
  333. synchronizeData();
  334. }
  335. //Absolute base URI is computed according to XML Base (http://www.w3.org/TR/xmlbase/#granularity)
  336. //1. the base URI specified by an xml:base attribute on the element, if one exists
  337. if (attributes != null) {
  338. Attr attrNode = (Attr)attributes.getNamedItemNS("http://www.w3.org/XML/1998/namespace", "base");
  339. if (attrNode != null) {
  340. String uri = attrNode.getNodeValue();
  341. if (uri.length() != 0 ) {// attribute value is always empty string
  342. try {
  343. uri = new URI(uri).toString();
  344. }
  345. catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e){
  346. // REVISIT: what should happen in this case?
  347. return null;
  348. }
  349. return uri;
  350. }
  351. }
  352. }
  353. //2.the base URI of the element's parent element within the document or external entity,
  354. //if one exists
  355. String parentElementBaseURI = (this.parentNode() != null) ? this.parentNode().getBaseURI() : null ;
  356. //base URI of parent element is not null
  357. if(parentElementBaseURI != null){
  358. try {
  359. //return valid absolute base URI
  360. return new URI(parentElementBaseURI).toString();
  361. }
  362. catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e){
  363. // REVISIT: what should happen in this case?
  364. return null;
  365. }
  366. }
  367. //3. the base URI of the document entity or external entity containing the element
  368. String baseURI = (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null ;
  369. if(baseURI != null){
  370. try {
  371. //return valid absolute base URI
  372. return new URI(baseURI).toString();
  373. }
  374. catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e){
  375. // REVISIT: what should happen in this case?
  376. return null;
  377. }
  378. }
  379. return null;
  380. }
  381. /**
  382. * NON-DOM: setting type used by the DOM parser
  383. * @see NodeImpl#setReadOnly
  384. */
  385. public void setType(TypeInfo type) {
  386. this.type = type;
  387. }
  388. }