View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.ws.commons.schema.utils;
21  
22  import org.apache.ws.commons.schema.constants.Constants;
23  
24  import org.w3c.dom.Element;
25  import org.w3c.dom.Node;
26  
27  import javax.xml.namespace.NamespaceContext;
28  
29  import java.io.Serializable;
30  import java.util.*;
31  
32  /**
33   * Implementation of {@link NamespaceContext}, which is based on a DOM node.
34   */
35  public class NodeNamespaceContext implements NamespacePrefixList, Serializable {
36      private static final Collection XML_NS_PREFIX_COLLECTION = Collections.singletonList(Constants.XML_NS_PREFIX);
37      private static final Collection XMLNS_ATTRIBUTE_COLLECTION = Collections.singletonList(Constants.XMLNS_ATTRIBUTE);
38      
39      private static final boolean DOM_LEVEL_3;
40      
41      static {
42          boolean level3 = false;
43          try {
44              Class cls = Class.forName("org.w3c.dom.UserDataHandler", false, Node.class.getClassLoader());
45              Node.class.getMethod("getUserData", new Class[]{String.class});
46              Node.class.getMethod("setUserData", new Class[]{String.class, Object.class, cls});
47              level3 = true;
48          } catch (Throwable e) {
49              level3 = false;
50          }
51          DOM_LEVEL_3 = level3;
52      }
53      
54      
55      
56      private final Map declarations;
57      private String[] prefixes;
58  
59      /**
60       * Creates a new instance with the given nodes context.
61       */
62      private NodeNamespaceContext(Map decls) {
63          declarations = decls;
64      }
65      
66      public static String getNamespacePrefix(Element el, String ns) {
67          if (DOM_LEVEL_3) {
68              return getNamespacePrefixDomLevel3(el, ns);
69          }
70          return getNamespaceContext(el).getPrefix(ns);
71      }
72      private static String getNamespacePrefixDomLevel3(Element el, String ns) {
73          return el.lookupPrefix(ns);
74      }
75      
76      
77      public static String getNamespaceURI(Element el, String pfx) {
78          if ("xml".equals(pfx)) {
79              return "http://www.w3.org/XML/1998/namespace";
80          } else  if ("xmlns".equals(pfx)) {
81              return "http://www.w3.org/2000/xmlns/";
82          }
83          if (DOM_LEVEL_3) {
84              return getNamespaceURIDomLevel3(el, pfx);
85          }
86          return getNamespaceContext(el).getNamespaceURI(pfx);
87      }
88      private static String getNamespaceURIDomLevel3(Element el, String pfx) {
89          if ("".equals(pfx)) {
90              pfx = null;
91          }
92          return el.lookupNamespaceURI(pfx);
93      }
94      
95      public static NodeNamespaceContext getNamespaceContext(Node pNode) {
96          final Map declarations = new HashMap();
97          new PrefixCollector() {
98              protected void declare(String pPrefix, String pNamespaceURI) {
99                  declarations.put(pPrefix, pNamespaceURI);
100             }
101         }.searchAllPrefixDeclarations(pNode);
102         return new NodeNamespaceContext(declarations);
103     }
104 
105     public String getNamespaceURI(String pPrefix) {
106         if (pPrefix == null) {
107             throw new IllegalArgumentException("The prefix must not be null.");
108         }
109         if (Constants.XML_NS_PREFIX.equals(pPrefix)) {
110             return Constants.XML_NS_URI;
111         }
112         if (Constants.XMLNS_ATTRIBUTE.equals(pPrefix)) {
113             return Constants.XMLNS_ATTRIBUTE_NS_URI;
114         }
115         final String uri = (String) declarations.get(pPrefix);
116         return uri == null ? Constants.NULL_NS_URI : uri;
117     }
118 
119     public String getPrefix(String pNamespaceURI) {
120         if (pNamespaceURI == null) {
121             throw new IllegalArgumentException("The namespace URI must not be null.");
122         }
123         if (Constants.XML_NS_URI.equals(pNamespaceURI)) {
124             return Constants.XML_NS_PREFIX;
125         }
126         if (Constants.XMLNS_ATTRIBUTE_NS_URI.equals(pNamespaceURI)) {
127             return Constants.XMLNS_ATTRIBUTE;
128         }
129         for (Iterator iter = declarations.entrySet().iterator();  iter.hasNext();  ) {
130             Map.Entry entry = (Map.Entry) iter.next();
131             if (pNamespaceURI.equals(entry.getValue())) {
132                 return (String) entry.getKey();
133             }
134         }
135         return null;
136     }
137 
138     public Iterator getPrefixes(String pNamespaceURI) {
139         if (pNamespaceURI == null) {
140             throw new IllegalArgumentException("The namespace URI must not be null.");
141         }
142         if (Constants.XML_NS_URI.equals(pNamespaceURI)) {
143             return XML_NS_PREFIX_COLLECTION.iterator();
144         }
145         if (Constants.XMLNS_ATTRIBUTE_NS_URI.equals(pNamespaceURI)) {
146             return XMLNS_ATTRIBUTE_COLLECTION.iterator();
147         }
148         final List list = new ArrayList();
149         for (Iterator iter = declarations.entrySet().iterator();  iter.hasNext();  ) {
150             Map.Entry entry = (Map.Entry) iter.next();
151             if (pNamespaceURI.equals(entry.getValue())) {
152                 list.add(entry.getKey());
153             }
154         }
155         return list.iterator();
156     }
157 
158     public String[] getDeclaredPrefixes() {
159         if (prefixes == null) {
160             Collection keys = declarations.keySet();
161             prefixes = (String[]) keys.toArray(new String[keys.size()]);
162         }
163         return prefixes;
164     }
165 }