View Javadoc

1   /*
2    * Copyright 2005-2012 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.soap.axiom;
18  
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  import javax.xml.namespace.QName;
24  import javax.xml.stream.XMLStreamConstants;
25  
26  import org.springframework.util.Assert;
27  import org.springframework.xml.namespace.QNameUtils;
28  
29  import org.apache.axiom.om.OMAttribute;
30  import org.apache.axiom.om.OMContainer;
31  import org.apache.axiom.om.OMElement;
32  import org.apache.axiom.om.OMFactory;
33  import org.apache.axiom.om.OMNamespace;
34  import org.xml.sax.Attributes;
35  import org.xml.sax.ContentHandler;
36  import org.xml.sax.Locator;
37  import org.xml.sax.SAXException;
38  import org.xml.sax.ext.LexicalHandler;
39  
40  /**
41   * Specific SAX {@link ContentHandler} and {@link LexicalHandler} that adds the resulting AXIOM OMElement to a specified
42   * parent element when <code>endDocument</code> is called. Used for returing <code>SAXResult</code>s from Axiom
43   * elements.
44   *
45   * @author Arjen Poutsma
46   * @since 1.0.0
47   */
48  class AxiomHandler implements ContentHandler, LexicalHandler {
49  
50      private final OMFactory factory;
51  
52      private final List<OMContainer> elements = new ArrayList<OMContainer>();
53  
54      private Map<String, String> namespaces = new HashMap<String, String>();
55  
56      private final OMContainer container;
57  
58      private int charactersType = XMLStreamConstants.CHARACTERS;
59  
60      AxiomHandler(OMContainer container, OMFactory factory) {
61          Assert.notNull(container, "'container' must not be null");
62          Assert.notNull(factory, "'factory' must not be null");
63          this.factory = factory;
64          this.container = container;
65      }
66  
67      private OMContainer getParent() {
68          if (!elements.isEmpty()) {
69              return elements.get(elements.size() - 1);
70          }
71          else {
72              return container;
73          }
74      }
75  
76      public void startPrefixMapping(String prefix, String uri) throws SAXException {
77          namespaces.put(prefix, uri);
78      }
79  
80      public void endPrefixMapping(String prefix) throws SAXException {
81          namespaces.remove(prefix);
82      }
83  
84      public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
85          OMContainer parent = getParent();
86          OMNamespace ns = factory.createOMNamespace(uri, QNameUtils.toQName(uri, qName).getPrefix());
87          OMElement element = factory.createOMElement(localName, ns, parent);
88          for (Map.Entry<String, String> entry : namespaces.entrySet()) {
89              String prefix = entry.getKey();
90              if (prefix.length() == 0) {
91                  element.declareDefaultNamespace((String) entry.getValue());
92              }
93              else {
94                  element.declareNamespace((String) entry.getValue(), prefix);
95              }
96          }
97          for (int i = 0; i < atts.getLength(); i++) {
98              QName attrName = QNameUtils.toQName(atts.getURI(i), atts.getQName(i));
99              String value = atts.getValue(i);
100             if (!atts.getQName(i).startsWith("xmlns")) {
101                 OMNamespace namespace = factory.createOMNamespace(attrName.getNamespaceURI(), attrName.getPrefix());
102                 OMAttribute attribute = factory.createOMAttribute(attrName.getLocalPart(), namespace, value);
103                 element.addAttribute(attribute);
104             }
105         }
106 
107         elements.add(element);
108     }
109 
110     public void endElement(String uri, String localName, String qName) throws SAXException {
111         elements.remove(elements.size() - 1);
112     }
113 
114     public void characters(char ch[], int start, int length) throws SAXException {
115         String data = new String(ch, start, length);
116         OMContainer parent = getParent();
117         factory.createOMText(parent, data, charactersType);
118     }
119 
120     public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
121         charactersType = XMLStreamConstants.SPACE;
122         characters(ch, start, length);
123         charactersType = XMLStreamConstants.CHARACTERS;
124     }
125 
126     public void processingInstruction(String target, String data) throws SAXException {
127         OMContainer parent = getParent();
128         factory.createOMProcessingInstruction(parent, target, data);
129     }
130 
131     public void comment(char ch[], int start, int length) throws SAXException {
132         String content = new String(ch, start, length);
133         OMContainer parent = getParent();
134         factory.createOMComment(parent, content);
135     }
136 
137     public void startCDATA() throws SAXException {
138         charactersType = XMLStreamConstants.CDATA;
139     }
140 
141     public void endCDATA() throws SAXException {
142         charactersType = XMLStreamConstants.CHARACTERS;
143     }
144 
145     public void startEntity(String name) throws SAXException {
146         if (!isPredefinedEntityReference(name)) {
147             charactersType = XMLStreamConstants.ENTITY_REFERENCE;
148         }
149     }
150 
151     public void endEntity(String name) throws SAXException {
152         charactersType = XMLStreamConstants.CHARACTERS;
153     }
154 
155     private boolean isPredefinedEntityReference(String name) {
156         return "lt".equals(name) || "gt".equals(name) || "amp".equals(name) || "quot".equals(name) ||
157                 "apos".equals(name);
158     }
159 
160     /*
161     * Unsupported
162     */
163 
164     public void setDocumentLocator(Locator locator) {
165     }
166 
167     public void startDocument() throws SAXException {
168     }
169 
170     public void endDocument() throws SAXException {
171     }
172 
173     public void skippedEntity(String name) throws SAXException {
174     }
175 
176     public void startDTD(String name, String publicId, String systemId) throws SAXException {
177     }
178 
179     public void endDTD() throws SAXException {
180     }
181 }