001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.tools.wsdlto.frontend.jaxws.customization;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.net.URI;
023: import java.net.URISyntaxException;
024: import java.util.ArrayList;
025: import java.util.List;
026: import java.util.Map;
027: import java.util.logging.Logger;
028:
029: import javax.xml.stream.XMLStreamException;
030: import javax.xml.stream.XMLStreamReader;
031:
032: import org.w3c.dom.Document;
033: import org.w3c.dom.Element;
034: import org.w3c.dom.Node;
035: import org.w3c.dom.NodeList;
036:
037: import org.xml.sax.InputSource;
038:
039: import org.apache.cxf.common.i18n.Message;
040: import org.apache.cxf.common.logging.LogUtils;
041: import org.apache.cxf.common.util.StringUtils;
042: import org.apache.cxf.helpers.DOMUtils;
043: import org.apache.cxf.helpers.MapNamespaceContext;
044: import org.apache.cxf.resource.URIResolver;
045: import org.apache.cxf.tools.common.ToolConstants;
046: import org.apache.cxf.tools.common.ToolContext;
047: import org.apache.cxf.tools.common.ToolException;
048: import org.apache.cxf.tools.util.StAXUtil;
049: import org.apache.cxf.tools.util.URIParserUtil;
050: import org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.ProcessorUtil;
051:
052: public final class CustomizationParser {
053: // For WSDL1.1
054: private static final Logger LOG = LogUtils
055: .getL7dLogger(CustomizationParser.class);
056:
057: private ToolContext env;
058: private final List<Element> jaxwsBindings = new ArrayList<Element>();
059: private final List<InputSource> jaxbBindings = new ArrayList<InputSource>();
060:
061: private Element handlerChains;
062: private Element wsdlNode;
063: private String wsdlURL;
064:
065: private CustomNodeSelector nodeSelector = new CustomNodeSelector();
066:
067: public CustomizationParser() {
068: jaxwsBindings.clear();
069: jaxbBindings.clear();
070: }
071:
072: public Element getHandlerChains() {
073: return this .handlerChains;
074: }
075:
076: public void parse(ToolContext pe) {
077: this .env = pe;
078: String[] bindingFiles;
079: try {
080: this .wsdlURL = URIParserUtil.getAbsoluteURI((String) env
081: .get(ToolConstants.CFG_WSDLURL));
082: this .wsdlNode = this .getTargetNode(this .wsdlURL);
083: bindingFiles = (String[]) env
084: .get(ToolConstants.CFG_BINDING);
085: if (bindingFiles == null) {
086: return;
087: }
088: } catch (ClassCastException e) {
089: bindingFiles = new String[1];
090: bindingFiles[0] = (String) env
091: .get(ToolConstants.CFG_BINDING);
092: }
093:
094: for (int i = 0; i < bindingFiles.length; i++) {
095: try {
096: addBinding(bindingFiles[i]);
097: } catch (XMLStreamException xse) {
098: Message msg = new Message("STAX_PARSER_ERROR", LOG);
099: throw new ToolException(msg, xse);
100: }
101: }
102:
103: for (Element element : jaxwsBindings) {
104: nodeSelector.addNamespaces(element);
105: internalizeBinding(element, "");
106: }
107: buildHandlerChains();
108: }
109:
110: public Element getTargetNode(String wsdlLoc) {
111: Document doc = null;
112: InputStream ins = null;
113: try {
114: URIResolver resolver = new URIResolver(wsdlLoc);
115: ins = resolver.getInputStream();
116: } catch (IOException e1) {
117: throw new ToolException(e1);
118: }
119:
120: try {
121: doc = DOMUtils.readXml(ins);
122: } catch (Exception e) {
123: Message msg = new Message("CAN_NOT_READ_AS_ELEMENT", LOG,
124: new Object[] { wsdlLoc });
125: throw new ToolException(msg, e);
126: }
127:
128: if (doc != null) {
129: return doc.getDocumentElement();
130: }
131: return null;
132: }
133:
134: private void buildHandlerChains() {
135:
136: for (Element jaxwsBinding : jaxwsBindings) {
137: NodeList nl = jaxwsBinding.getElementsByTagNameNS(
138: ToolConstants.HANDLER_CHAINS_URI,
139: ToolConstants.HANDLER_CHAINS);
140: if (nl.getLength() == 0) {
141: continue;
142: }
143: // take the first one, anyway its 1 handler-config per customization
144: this .handlerChains = (Element) nl.item(0);
145: return;
146: }
147:
148: }
149:
150: private Node[] getAnnotationNodes(final Node node) {
151: Node[] nodes = new Node[2];
152:
153: Node annotationNode = nodeSelector.queryNode(node,
154: "//xsd:annotation");
155:
156: if (annotationNode == null) {
157: annotationNode = node.getOwnerDocument().createElementNS(
158: ToolConstants.SCHEMA_URI, "annotation");
159: }
160:
161: nodes[0] = annotationNode;
162:
163: Node appinfoNode = nodeSelector.queryNode(annotationNode,
164: "//xsd:appinfo");
165:
166: if (appinfoNode == null) {
167: appinfoNode = node.getOwnerDocument().createElementNS(
168: ToolConstants.SCHEMA_URI, "appinfo");
169: annotationNode.appendChild(appinfoNode);
170: }
171: nodes[1] = appinfoNode;
172: return nodes;
173: }
174:
175: private void appendJaxbVersion(final Element schemaElement) {
176: String jaxbPrefix = schemaElement
177: .lookupPrefix(ToolConstants.NS_JAXB_BINDINGS);
178: if (jaxbPrefix == null) {
179: schemaElement.setAttribute("xmlns:jaxb",
180: ToolConstants.NS_JAXB_BINDINGS);
181: schemaElement.setAttribute("jaxb:version", "2.0");
182: }
183: }
184:
185: protected void copyAllJaxbDeclarations(final Node schemaNode,
186: final Element jaxwsBindingNode) {
187: Element jaxbBindingElement = getJaxbBindingElement(jaxwsBindingNode);
188: appendJaxbVersion((Element) schemaNode);
189: if (jaxbBindingElement != null) {
190: copyAllJaxbDeclarations(nodeSelector.queryNode(schemaNode,
191: jaxbBindingElement.getAttribute("node")),
192: jaxbBindingElement);
193: return;
194: }
195:
196: Node[] embededNodes = getAnnotationNodes(schemaNode);
197: Node annotationNode = embededNodes[0];
198: Node appinfoNode = embededNodes[1];
199:
200: NodeList childNodes = jaxwsBindingNode.getChildNodes();
201: for (int i = 0; i < childNodes.getLength(); i++) {
202: Node childNode = childNodes.item(i);
203: if (!isJaxbBindings(childNode)
204: || isJaxbBindingsElement(childNode)) {
205: continue;
206: }
207:
208: final Node jaxbNode = childNode;
209:
210: Node cloneNode = ProcessorUtil.cloneNode(schemaNode
211: .getOwnerDocument(), jaxbNode, true);
212: appinfoNode.appendChild(cloneNode);
213: }
214:
215: if (schemaNode.getChildNodes().getLength() > 0) {
216: schemaNode.insertBefore(annotationNode, schemaNode
217: .getChildNodes().item(0));
218: } else {
219: schemaNode.appendChild(annotationNode);
220: }
221: }
222:
223: protected void internalizeBinding(Element bindings,
224: String expression) {
225: if (bindings.getAttributeNode("wsdlLocation") != null) {
226: expression = "/";
227: }
228:
229: if (isGlobaleBindings(bindings)) {
230: String pfx = wsdlNode.getPrefix();
231: if (pfx == null) {
232: pfx = "";
233: } else {
234: pfx += ":";
235: }
236:
237: nodeSelector.addNamespaces(wsdlNode);
238: Node node = nodeSelector.queryNode(wsdlNode, "//" + pfx
239: + "definitions");
240: copyBindingsToWsdl(node, bindings, nodeSelector
241: .getNamespaceContext());
242: }
243:
244: if (isJAXWSBindings(bindings)
245: && bindings.getAttributeNode("node") != null) {
246: expression = expression + "/"
247: + bindings.getAttribute("node");
248:
249: nodeSelector.addNamespaces(bindings);
250:
251: Node node = nodeSelector.queryNode(wsdlNode, expression);
252: if (node == null) {
253: throw new ToolException(new Message("NODE_NOT_EXISTS",
254: LOG, new Object[] { expression }));
255: }
256:
257: if (hasJaxbBindingDeclaration(bindings)) {
258: copyAllJaxbDeclarations(node, bindings);
259: } else {
260: copyBindingsToWsdl(node, bindings, nodeSelector
261: .getNamespaceContext());
262: }
263: }
264:
265: Element[] children = getChildElements(bindings,
266: ToolConstants.NS_JAXWS_BINDINGS);
267: for (int i = 0; i < children.length; i++) {
268: if (children[i].getNodeType() == Node.ELEMENT_NODE) {
269: internalizeBinding(children[i], expression);
270: }
271: }
272: }
273:
274: private void copyBindingsToWsdl(Node node, Node bindings,
275: MapNamespaceContext ctx) {
276: if (bindings.getNamespaceURI().equals(
277: ToolConstants.JAXWS_BINDINGS.getNamespaceURI())) {
278: bindings.setPrefix("jaxws");
279: }
280:
281: for (Map.Entry<String, String> ent : ctx.getUsedNamespaces()
282: .entrySet()) {
283: if (node.lookupNamespaceURI(ent.getKey()) == null) {
284: node.getOwnerDocument().getDocumentElement()
285: .setAttribute("xmlns:" + ent.getKey(),
286: ent.getValue());
287: }
288:
289: }
290:
291: for (int i = 0; i < bindings.getChildNodes().getLength(); i++) {
292: Node childNode = bindings.getChildNodes().item(i);
293: if (childNode.getNodeType() == Element.ELEMENT_NODE
294: && childNode.getNamespaceURI().equals(
295: ToolConstants.JAXWS_BINDINGS
296: .getNamespaceURI())) {
297: childNode.setPrefix("jaxws");
298: }
299: }
300:
301: Node cloneNode = ProcessorUtil.cloneNode(node
302: .getOwnerDocument(), bindings, true);
303: Node firstChild = DOMUtils.getChild(node, "jaxws:bindings");
304: if (firstChild == null
305: && cloneNode.getNodeName().indexOf("bindings") == -1) {
306: wsdlNode.setAttribute("xmlns:jaxws",
307: ToolConstants.JAXWS_BINDINGS.getNamespaceURI());
308: Element jaxwsBindingElement = node.getOwnerDocument()
309: .createElement("jaxws:bindings");
310: node.appendChild(jaxwsBindingElement);
311: firstChild = jaxwsBindingElement;
312: }
313:
314: if (firstChild == null
315: && cloneNode.getNodeName().indexOf("bindings") > -1) {
316: firstChild = node;
317: if (wsdlNode.getAttributeNode("xmls:jaxws") == null) {
318: wsdlNode.setAttribute("xmlns:jaxws",
319: ToolConstants.JAXWS_BINDINGS.getNamespaceURI());
320: }
321: }
322:
323: Element cloneEle = (Element) cloneNode;
324: cloneEle.removeAttribute("node");
325: for (int i = 0; i < cloneNode.getChildNodes().getLength(); i++) {
326: Node child = cloneNode.getChildNodes().item(i);
327: if (child.getNodeType() == Element.ELEMENT_NODE) {
328: Element childElement = (Element) child;
329: Node attrNode = childElement.getAttributeNode("node");
330: if (attrNode != null) {
331: cloneNode.removeChild(child);
332: }
333:
334: }
335: }
336: firstChild.appendChild(cloneNode);
337: }
338:
339: private boolean isGlobaleBindings(Element binding) {
340:
341: boolean globleNode = binding.getNamespaceURI().equals(
342: ToolConstants.NS_JAXWS_BINDINGS)
343: && binding.getLocalName().equals("package")
344: || binding.getLocalName().equals("enableAsyncMapping")
345: || binding.getLocalName().equals(
346: "enableAdditionalSOAPHeaderMapping")
347: || binding.getLocalName().equals("enableWrapperStyle")
348: || binding.getLocalName().equals("enableMIMEContent");
349: Node parentNode = binding.getParentNode();
350: if (parentNode instanceof Element) {
351: Element ele = (Element) parentNode;
352: if (ele.getAttributeNode("wsdlLocation") != null
353: && globleNode) {
354: return true;
355: }
356:
357: }
358: return false;
359:
360: }
361:
362: private Element[] getChildElements(Element parent, String nsUri) {
363: List<Element> a = new ArrayList<Element>();
364: NodeList children = parent.getChildNodes();
365: for (int i = 0; i < children.getLength(); i++) {
366: Node item = children.item(i);
367: if (!(item instanceof Element)) {
368: continue;
369: }
370: if (nsUri.equals(item.getNamespaceURI())) {
371: a.add((Element) item);
372: }
373: }
374: return (Element[]) a.toArray(new Element[a.size()]);
375: }
376:
377: private void addBinding(String bindingFile)
378: throws XMLStreamException {
379: InputSource is = new InputSource(bindingFile);
380: XMLStreamReader reader = StAXUtil
381: .createFreshXMLStreamReader(is);
382:
383: StAXUtil.toStartTag(reader);
384:
385: if (isValidJaxwsBindingFile(bindingFile, reader)) {
386: Element root = null;
387: try {
388: URIResolver resolver = new URIResolver(bindingFile);
389: root = DOMUtils.readXml(resolver.getInputStream())
390: .getDocumentElement();
391: } catch (Exception e1) {
392: Message msg = new Message("CAN_NOT_READ_AS_ELEMENT",
393: LOG, new Object[] { bindingFile });
394: throw new ToolException(msg, e1);
395: }
396: String wsdlLocation = root.getAttribute("wsdlLocation");
397: URI wsdlURI = null;
398: try {
399: wsdlURI = new URI(wsdlLocation);
400: } catch (URISyntaxException e) {
401: Message msg = new Message(
402: "JAXWSBINDINGS_WSDLLOC_ERROR", LOG,
403: new Object[] { wsdlLocation });
404: throw new ToolException(msg);
405: }
406:
407: if (!wsdlURI.isAbsolute()) {
408: try {
409: URI baseURI = new URI(bindingFile);
410: wsdlURI = baseURI.resolve(wsdlURI);
411: } catch (URISyntaxException e) {
412: Message msg = new Message("NOT_URI", LOG,
413: new Object[] { bindingFile });
414: throw new ToolException(msg, e);
415: }
416:
417: }
418:
419: URI normalizedURL = null;
420: if (this .wsdlURL != null) {
421: normalizedURL = URI.create(this .wsdlURL).normalize();
422: }
423:
424: if (wsdlURI.normalize().equals(normalizedURL)) {
425: jaxwsBindings.add(root);
426: } else {
427: String wsdl = (String) env
428: .get(ToolConstants.CFG_WSDLURL);
429: Message msg = new Message("NOT_POINTTO_URL", LOG,
430: new Object[] { bindingFile, wsdl });
431: throw new ToolException(msg);
432: }
433: } else if (isValidJaxbBindingFile(reader)) {
434: jaxbBindings.add(is);
435: } else {
436: Message msg = new Message("UNKNOWN_BINDING_FILE", LOG,
437: bindingFile);
438: throw new ToolException(msg);
439: }
440: }
441:
442: private boolean isValidJaxbBindingFile(XMLStreamReader reader) {
443: if (ToolConstants.JAXB_BINDINGS.equals(reader.getName())) {
444: return true;
445: }
446: return false;
447: }
448:
449: private boolean isValidJaxwsBindingFile(String bindingLocation,
450: XMLStreamReader reader) {
451: if (ToolConstants.JAXWS_BINDINGS.equals(reader.getName())) {
452: String wsdlLocation = reader.getAttributeValue(null,
453: "wsdlLocation");
454: if (!StringUtils.isEmpty(wsdlLocation)) {
455: return true;
456: }
457: }
458: return false;
459:
460: }
461:
462: protected void setWSDLNode(final Element node) {
463: this .wsdlNode = node;
464: }
465:
466: public Node getWSDLNode() {
467: return this .wsdlNode;
468: }
469:
470: private boolean isJAXWSBindings(Node bindings) {
471: return ToolConstants.NS_JAXWS_BINDINGS.equals(bindings
472: .getNamespaceURI())
473: && "bindings".equals(bindings.getLocalName());
474: }
475:
476: private boolean isJaxbBindings(Node bindings) {
477: return ToolConstants.NS_JAXB_BINDINGS.equals(bindings
478: .getNamespaceURI());
479: }
480:
481: private boolean isJaxbBindingsElement(Node bindings) {
482: return "bindings".equals(bindings.getLocalName());
483: }
484:
485: protected Element getJaxbBindingElement(final Element bindings) {
486: NodeList list = bindings.getElementsByTagNameNS(
487: ToolConstants.NS_JAXB_BINDINGS, "bindings");
488: if (list.getLength() > 0) {
489: return (Element) list.item(0);
490: }
491: return null;
492: }
493:
494: protected boolean hasJaxbBindingDeclaration(Node bindings) {
495: NodeList childNodes = bindings.getChildNodes();
496: for (int i = 0; i < childNodes.getLength(); i++) {
497: Node childNode = childNodes.item(i);
498: if (isJaxbBindings(childNode)) {
499: return true;
500: }
501: }
502: return false;
503: }
504:
505: public Element getCustomizedWSDLElement() {
506: return this .wsdlNode;
507: }
508:
509: public List<InputSource> getJaxbBindings() {
510: return this .jaxbBindings;
511: }
512:
513: public static JAXWSBinding mergeJawsBinding(JAXWSBinding binding1,
514: JAXWSBinding binding2) {
515: if (binding1 != null && binding2 != null) {
516: if (binding2.isEnableAsyncMapping()) {
517: binding1.setEnableAsyncMapping(true);
518: }
519: if (binding2.isEnableWrapperStyle()) {
520: binding1.setEnableWrapperStyle(true);
521: }
522: if (binding2.isEnableMime()) {
523: binding1.setEnableMime(true);
524: }
525:
526: if (binding2.getJaxwsClass() != null) {
527: binding1.setJaxwsClass(binding2.getJaxwsClass());
528: }
529:
530: if (binding2.getJaxwsPara() != null) {
531: binding1.setJaxwsPara(binding2.getJaxwsPara());
532: }
533: return binding1;
534: }
535:
536: return binding1 == null ? binding2 : binding1;
537: }
538:
539: }
|