/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.axis2.jaxws.util; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import javax.wsdl.Binding; import javax.wsdl.BindingFault; import javax.wsdl.BindingInput; import javax.wsdl.BindingOperation; import javax.wsdl.BindingOutput; import javax.wsdl.WSDLElement; import javax.wsdl.extensions.ExtensibilityElement; import javax.wsdl.extensions.UnknownExtensibilityElement; import javax.wsdl.extensions.soap.SOAPBinding; import javax.wsdl.extensions.soap12.SOAP12Binding; import javax.xml.namespace.QName; import org.apache.axis2.jaxws.ExceptionFactory; import org.apache.axis2.jaxws.common.config.WSDLValidatorElement; import org.apache.axis2.jaxws.common.config.WSDLValidatorElement.State; import org.apache.axis2.jaxws.description.EndpointDescription; import org.apache.axis2.jaxws.description.EndpointDescriptionWSDL; import org.apache.axis2.jaxws.i18n.Messages; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * This utility class stores methods that can be used to fetch extension elements * from wsdl and will be used from RespectBindingConfigurator on Client and Server. */ public class WSDLExtensionUtils { private static final Log log = LogFactory.getLog(WSDLExtensionUtils.class); /** * This method will search for all wsdl extensibility elements marked as required=true in wsdl:bindings * As per the wsdl 2.2 specification section 2.5 here is how a wsdl:binding is defined: * <wsdl:definitions .... > * <wsdl:binding name="nmtoken" type="qname"> * * <-- extensibility element (1) --> * * <wsdl:operation name="nmtoken"> * * <-- extensibility element (2) --> * * <wsdl:input name="nmtoken"? > ? * <-- extensibility element (3) --> * </wsdl:input> * <wsdl:output name="nmtoken"? > ? * <-- extensibility element (4) --> * * </wsdl:output> * <wsdl:fault name="nmtoken"> * * <-- extensibility element (5) --> * * </wsdl:fault> * </wsdl:operation> * </wsdl:binding> * </wsdl:definitions> * we will look for wsdl extensions in binding root, wsdl:operation, wsdl:input, wsdl:output and wsdl:fault. * If the extensibility element is defines outside of these sections it will not be picked up by this method. * * @param wsdlBinding - WSDLBinding Object read from WSDL Definition. * @param set - Set that will be filled with list of required=true extension elements. * @return */ public static void search(WSDLElement element, Set<WSDLValidatorElement> set, List<QName> unusedExtensions) { if(log.isDebugEnabled()){ log.debug("Start Searching for WSDLExtensions"); } if(element == null){ return; } //This search method uses a simple BFS technique to search for Extension elements in WSDLBindings. //I will Queue all available WSDLElements starting in wsdl:binding and traverse them looking for //extensions. Queue will be empty when I have processed everything. //NOTE:Binding, Operation, OperationInput, OperationOutput and OperationFault are all WSDLElements. LinkedList<WSDLElement> queue = new LinkedList<WSDLElement>(); queue.offer(element); while(!queue.isEmpty()){ WSDLElement wsdlElement = queue.remove(); //WSDLElement in Queue could be wsdl Binding, BindingOperations, Input, Output or Fault //Find Extensibility Elements in wsdlElement. processWSDLElement(wsdlElement, set, unusedExtensions); //check if we are dealing with wsdlBinding; //store all BindingOpeations from wsdlBindings if(wsdlElement instanceof Binding){ //lets get all operations and add to queue //TODO: WSDLDef API's don't use generics, hence we use Iterator below and type cast. List operations = ((Binding)wsdlElement).getBindingOperations(); Iterator iter = operations.iterator(); while(iter.hasNext()){ BindingOperation op =(BindingOperation) iter.next(); queue.offer(op); } } //check if we are dealing with Bindingoperations //Store all input, output and faults. if(wsdlElement instanceof BindingOperation){ BindingInput bi = ((BindingOperation)wsdlElement).getBindingInput(); queue.offer(bi); BindingOutput bo = ((BindingOperation)wsdlElement).getBindingOutput(); queue.offer(bo); Map map = ((BindingOperation)wsdlElement).getBindingFaults(); Collection c = map.values(); Iterator iter = c.iterator(); while(iter.hasNext()){ Object o = iter.next(); if(o instanceof BindingFault){ BindingFault bf = (BindingFault)o; queue.offer(bf); } } } } if(log.isDebugEnabled()){ log.debug("End Searching for WSDLExtensions"); } } private static void processWSDLElement(WSDLElement wsdlElement, Set<WSDLValidatorElement> set, List<QName> unusedExtensions){ if(log.isDebugEnabled()){ log.debug("Start processWSDLElement"); } List list = wsdlElement.getExtensibilityElements(); if (list == null || list.size() == 0) { return; } Iterator iter = list.iterator(); while (iter.hasNext()) { ExtensibilityElement e = (ExtensibilityElement) iter.next(); //TODO in JAX-WS 2.1 Respect Binding implementation we are ignoring //SOAPBinding, review the reason behind this. if (e instanceof SOAPBinding || e instanceof SOAP12Binding) continue; if (e instanceof UnknownExtensibilityElement) { UnknownExtensibilityElement ue = (UnknownExtensibilityElement) e; String reqd = ue.getElement().getAttribute("required"); //check if extension element is required. //one can set extension as required two different ways in wsdl //lets check both ways here boolean wsdl_required = e.getRequired() != null && e.getRequired(); boolean wsdl_attribute = reqd!=null && reqd.equalsIgnoreCase("true"); if (wsdl_attribute || wsdl_required) { if (log.isDebugEnabled()) { log.debug("Found a required element: " + e.getElementType()); } WSDLValidatorElement element = new WSDLValidatorElement(); element.setExtensionElement(e); element.setState(State.NOT_RECOGNIZED); set.add(element); } else { if (log.isDebugEnabled()) { log.debug("Found a NOT required element: " + e.getElementType()); } unusedExtensions.add(e.getElementType()); } } } if(log.isDebugEnabled()){ log.debug("Exit processWSDLElement"); } } public static void processExtensions(EndpointDescription endpointDescription){ if(endpointDescription == null){ throw ExceptionFactory.makeWebServiceException(Messages.getMessage("RespectBindingConfiguratorErr1")); } EndpointDescriptionWSDL edw = (EndpointDescriptionWSDL) endpointDescription; if(endpointDescription == null){ throw ExceptionFactory.makeWebServiceException(Messages.getMessage("RespectBindingConfiguratorErr2")); } javax.wsdl.Binding wsdlBinding = edw.getWSDLBinding(); Set<WSDLValidatorElement> set = endpointDescription.getRequiredBindings(); if(set.size()>0){ //we have already looked for wsdl extension once, no need to //find them again. WSDL is shared for all serviceDesc artifacts. return; } List<QName> unusedExtensions = new ArrayList<QName>(); WSDLExtensionUtils.search(wsdlBinding, set, unusedExtensions); if (log.isDebugEnabled()) { log.debug("The following extensibility elements were found, but were not required."); for (int n = 0; n < unusedExtensions.size(); ++n) log.debug("[" + (n + 1) + "] - " + unusedExtensions.get(n)); } } }