001: package org.objectweb.celtix.tools.extensions.jaxws;
002:
003: import java.io.*;
004: import java.net.*;
005: import java.util.*;
006: import java.util.logging.Logger;
007:
008: import javax.wsdl.Binding;
009: import javax.wsdl.BindingOperation;
010: import javax.wsdl.Definition;
011: import javax.wsdl.Operation;
012: import javax.wsdl.PortType;
013: import javax.wsdl.WSDLException;
014: import javax.xml.parsers.DocumentBuilder;
015: import javax.xml.parsers.DocumentBuilderFactory;
016: import javax.xml.parsers.FactoryConfigurationError;
017: import javax.xml.parsers.ParserConfigurationException;
018: import javax.xml.stream.XMLStreamException;
019: import javax.xml.stream.XMLStreamReader;
020:
021: import org.w3c.dom.Element;
022: import org.w3c.dom.Node;
023: import org.w3c.dom.NodeList;
024: import org.xml.sax.ErrorHandler;
025: import org.xml.sax.InputSource;
026: import org.xml.sax.SAXException;
027: import org.xml.sax.SAXParseException;
028:
029: import org.objectweb.celtix.common.i18n.Message;
030: import org.objectweb.celtix.common.logging.LogUtils;
031: import org.objectweb.celtix.common.util.StringUtils;
032: import org.objectweb.celtix.tools.common.ProcessorEnvironment;
033: import org.objectweb.celtix.tools.common.ToolConstants;
034: import org.objectweb.celtix.tools.common.ToolException;
035: import org.objectweb.celtix.tools.utils.ProcessorUtil;
036: import org.objectweb.celtix.tools.utils.StAXUtil;
037:
038: public final class CustomizationParser {
039: private static final Logger LOG = LogUtils
040: .getL7dLogger(CustomizationParser.class);
041: private static CustomizationParser parser;
042: private ProcessorEnvironment env;
043: private final Set<Element> jaxwsBindings = new HashSet<Element>();
044: private Definition definition;
045: private final Map<BindingsNode, JAXWSBinding> definitionExtensions;
046: private final Map<BindingsNode, JAXWSBinding> portTypeExtensions;
047: private final Map<BindingsNode, JAXWSBinding> operationExtensions;
048: private Element handlerChains;
049:
050: private CustomizationParser() {
051: definitionExtensions = new HashMap<BindingsNode, JAXWSBinding>();
052: portTypeExtensions = new HashMap<BindingsNode, JAXWSBinding>();
053: operationExtensions = new HashMap<BindingsNode, JAXWSBinding>();
054:
055: }
056:
057: public static CustomizationParser getInstance() {
058: if (parser == null) {
059: parser = new CustomizationParser();
060: }
061: return parser;
062: }
063:
064: public void clean() {
065: jaxwsBindings.clear();
066: definitionExtensions.clear();
067: portTypeExtensions.clear();
068: operationExtensions.clear();
069:
070: }
071:
072: public Element getHandlerChains() {
073: return this .handlerChains;
074: }
075:
076: public JAXWSBinding getDefinitionExtension() {
077: if (definitionExtensions.size() > 0) {
078: return definitionExtensions.values().iterator().next();
079: } else {
080: return null;
081: }
082: }
083:
084: public JAXWSBinding getPortTypeExtension(String portTypeName) {
085: Collection<BindingsNode> bindingNodes = portTypeExtensions
086: .keySet();
087: JAXWSBinding jaxwsBinding = null;
088: for (BindingsNode bindingNode : bindingNodes) {
089: if (portTypeName.equals(bindingNode.getNodeName())) {
090: jaxwsBinding = portTypeExtensions.get(bindingNode);
091: break;
092: }
093: }
094: if (jaxwsBinding == null) {
095: jaxwsBinding = getDefinitionExtension();
096: }
097: return jaxwsBinding;
098: }
099:
100: public JAXWSBinding getPortTypeOperationExtension(
101: String portTypeName, String operationName) {
102: Collection<BindingsNode> bindingNodes = operationExtensions
103: .keySet();
104: JAXWSBinding jaxwsBinding = null;
105: for (BindingsNode bindingNode : bindingNodes) {
106: if (matchOperation(bindingNode.getXPathExpression(),
107: portTypeName, operationName)) {
108: jaxwsBinding = operationExtensions.get(bindingNode);
109: break;
110: }
111: }
112: if (jaxwsBinding == null) {
113: jaxwsBinding = getPortTypeExtension(portTypeName);
114: }
115:
116: return jaxwsBinding;
117: }
118:
119: private boolean matchOperation(String xpathExpression,
120: String portTypeName, String operationName) {
121: String regex = ".*" + wrapper(portTypeName) + ".*"
122: + wrapper(operationName) + ".*";
123: return xpathExpression.matches(regex);
124: }
125:
126: public void parse(ProcessorEnvironment pe, Definition def) {
127: this .env = pe;
128: this .definition = def;
129: String[] bindingFiles;
130: try {
131: bindingFiles = (String[]) env
132: .get(ToolConstants.CFG_BINDING);
133: } catch (ClassCastException e) {
134: bindingFiles = new String[1];
135: bindingFiles[0] = (String) env
136: .get(ToolConstants.CFG_BINDING);
137: }
138:
139: for (int i = 0; i < bindingFiles.length; i++) {
140: try {
141: addBinding(bindingFiles[i]);
142: } catch (XMLStreamException xse) {
143: Message msg = new Message("STAX_PASER_ERROR", LOG);
144: throw new ToolException(msg, xse);
145: }
146: }
147:
148: for (Element jaxwsBinding : jaxwsBindings) {
149: buildTargetNodeMap(jaxwsBinding, "/");
150: }
151:
152: buildHandlerChains();
153: }
154:
155: private void buildHandlerChains() {
156: for (Element jaxwsBinding : jaxwsBindings) {
157: NodeList nl = jaxwsBinding.getElementsByTagNameNS(
158: ToolConstants.HANDLER_CHAINS_URI,
159: ToolConstants.HANDLER_CHAINS);
160: if (nl.getLength() == 0) {
161: continue;
162: }
163: //take the first one, anyway its 1 handler-config per customization
164: this .handlerChains = (Element) nl.item(0);
165: return;
166: }
167: }
168:
169: private void buildTargetNodeMap(Element bindings, String expression) {
170: if (bindings.getAttributeNode("wsdlLocation") != null) {
171: expression = "/";
172: }
173:
174: if (isJAXWSBindings(bindings)
175: && bindings.getAttributeNode("node") != null) {
176: expression = expression + "/"
177: + bindings.getAttribute("node");
178: try {
179: evaluateBindingsNode(bindings, expression);
180: } catch (WSDLException we) {
181: Message msg = new Message(
182: "PARSE_BININDINGFILE_EXCEPTION", LOG);
183: throw new ToolException(msg, we);
184: }
185: }
186:
187: Element[] children = getChildElements(bindings,
188: ToolConstants.NS_JAXWS_BINDINGS);
189: for (int i = 0; i < children.length; i++) {
190: buildTargetNodeMap(children[i], expression);
191: }
192: }
193:
194: private Element[] getChildElements(Element parent, String nsUri) {
195: List<Element> a = new ArrayList<Element>();
196: NodeList children = parent.getChildNodes();
197: for (int i = 0; i < children.getLength(); i++) {
198: Node item = children.item(i);
199: if (!(item instanceof Element)) {
200: continue;
201: }
202: if (nsUri.equals(item.getNamespaceURI())) {
203: a.add((Element) item);
204: }
205: }
206: return (Element[]) a.toArray(new Element[a.size()]);
207: }
208:
209: private boolean isJAXWSBindings(Node bindings) {
210: return ToolConstants.NS_JAXWS_BINDINGS.equals(bindings
211: .getNamespaceURI())
212: && "bindings".equals(bindings.getLocalName());
213: }
214:
215: private void addBinding(String bindingFile)
216: throws XMLStreamException {
217: String bindingLocation = ProcessorUtil.absolutize(ProcessorUtil
218: .getFileOrURLName(bindingFile));
219:
220: InputSource is = new InputSource(bindingLocation);
221: XMLStreamReader reader = StAXUtil
222: .createFreshXMLStreamReader(is);
223:
224: StAXUtil.toStartTag(reader);
225:
226: if (isValidJaxwsBindingFile(bindingFile, reader)) {
227: Element root = parse(is);
228: jaxwsBindings.add(root);
229: } else if (isValidJaxbBindingFile(reader)) {
230: env.addJaxbBindingFile(bindingFile, is);
231: } else {
232: Message msg = new Message("UNKONW_BINDING_FILE", LOG,
233: bindingFile);
234: throw new ToolException(msg);
235: }
236: }
237:
238: private boolean isValidJaxbBindingFile(XMLStreamReader reader) {
239: if (ToolConstants.JAXB_BINDINGS.equals(reader.getName())) {
240: return true;
241: }
242: return false;
243: }
244:
245: private boolean isValidJaxwsBindingFile(String bindingLocation,
246: XMLStreamReader reader) {
247: try {
248: if (ToolConstants.JAXWS_BINDINGS.equals(reader.getName())) {
249: String wsdlURL = (String) env
250: .get(ToolConstants.CFG_WSDLURL);
251: wsdlURL = ProcessorUtil.absolutize(ProcessorUtil
252: .getFileOrURLName(wsdlURL));
253: String wsdlLocation = reader.getAttributeValue(null,
254: "wsdlLocation");
255: if (StringUtils.isFileExist(bindingLocation)
256: && !StringUtils.isFileAbsolute(wsdlLocation)) {
257: String basedir = new File(bindingLocation)
258: .getParent();
259: wsdlLocation = new File(basedir, wsdlLocation)
260: .getAbsolutePath();
261: }
262: wsdlLocation = ProcessorUtil.absolutize(ProcessorUtil
263: .getFileOrURLName(wsdlLocation));
264:
265: if (!StringUtils.getURL(wsdlURL).equals(
266: StringUtils.getURL(wsdlLocation))) {
267: Message msg = new Message("NOT_POINTTO_URL", LOG,
268: new Object[] { wsdlLocation, wsdlURL });
269: throw new ToolException(msg);
270: }
271: } else {
272: return false;
273: }
274: } catch (MalformedURLException e) {
275: Message msg = new Message("CAN_NOT_GET_WSDL_LOCATION", LOG);
276: throw new ToolException(msg, e);
277: }
278: return true;
279: }
280:
281: private Element parse(InputSource source) {
282: try {
283: DocumentBuilderFactory builderFactory = DocumentBuilderFactory
284: .newInstance();
285: builderFactory.setNamespaceAware(true);
286: builderFactory.setValidating(false);
287: DocumentBuilder builder = builderFactory
288: .newDocumentBuilder();
289: builder.setErrorHandler(new ErrorHandler() {
290: public void error(SAXParseException e)
291: throws SAXParseException {
292: throw e;
293: }
294:
295: public void fatalError(SAXParseException e)
296: throws SAXParseException {
297: throw e;
298: }
299:
300: public void warning(SAXParseException err)
301: throws SAXParseException {
302: // do nothing
303: }
304: });
305:
306: // builder.setEntityResolver(new NullEntityResolver());
307: return builder.parse(source).getDocumentElement();
308: } catch (ParserConfigurationException e) {
309: throw new ToolException("parsing.parserConfigException", e);
310: } catch (FactoryConfigurationError e) {
311: throw new ToolException("parsing.factoryConfigException", e);
312: } catch (SAXException e) {
313: throw new ToolException("parsing.saxException", e);
314: } catch (IOException e) {
315: throw new ToolException("parsing.saxException", e);
316: }
317: }
318:
319: private void evaluateBindingsNode(Element bindings,
320: String expression) throws WSDLException {
321: BindingsNode bindingsNode = evaluateXPathNode(expression);
322: if (bindingsNode == null) {
323: return;
324: }
325: bindingsNode.setElement(bindings);
326:
327: JAXWSBindingParser bindingsParser = new JAXWSBindingParser();
328: JAXWSBinding jaxwsBinding = bindingsParser.parse(bindingsNode,
329: this .definition);
330:
331: if (bindingsNode.getParentType().equals(Definition.class)) {
332: definitionExtensions.put(bindingsNode, jaxwsBinding);
333: }
334:
335: if (bindingsNode.getParentType().equals(PortType.class)) {
336: portTypeExtensions.put(bindingsNode, jaxwsBinding);
337: }
338:
339: if (bindingsNode.getParentType().equals(Operation.class)) {
340: operationExtensions.put(bindingsNode, jaxwsBinding);
341: }
342:
343: if (bindingsNode.getParentType().equals(BindingOperation.class)) {
344: operationExtensions.put(bindingsNode, jaxwsBinding);
345: }
346:
347: }
348:
349: private BindingsNode evaluateXPathNode(String expression) {
350: String[] parts = expression.split("/");
351: if (parts == null) {
352: return null;
353: }
354:
355: BindingsNode node = new BindingsNode();
356: node.setXPathExpression(expression);
357: for (int i = parts.length - 1; i > 0; i--) {
358: if (parts[i].startsWith("wsdl:definitions")) {
359: node.setParentType(Definition.class);
360: break;
361: }
362: if (parts[i].startsWith("wsdl:binding")) {
363: node.setParentType(Binding.class);
364: node.setNodeName(getNodeName(parts[i]));
365: break;
366: }
367: if (parts[i].startsWith("wsdl:portType")) {
368: node.setParentType(PortType.class);
369: node.setNodeName(getNodeName(parts[i]));
370: break;
371: }
372: if (parts[i].startsWith("wsdl:operation")) {
373: if (i > 1 && parts[i - 1].startsWith("wsdl:binding")) {
374: node.setParentType(BindingOperation.class);
375: } else if (i > 1
376: && parts[i - 1].startsWith("wsdl:portType")) {
377: node.setParentType(Operation.class);
378: }
379: node.setNodeName(getNodeName(parts[i]));
380: break;
381: }
382: }
383: return node;
384: }
385:
386: private String getNodeName(String expression) {
387: return StringUtils.extract(expression, "[@name='", "']");
388: }
389:
390: private String wrapper(String nodeName) {
391: return StringUtils.wrapper(nodeName, "[@name='", "']");
392: }
393: }
|