/** * 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.cxf.wsdl11; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.wsdl.Binding; import javax.wsdl.BindingFault; import javax.wsdl.BindingOperation; import javax.wsdl.Definition; import javax.wsdl.Fault; import javax.wsdl.Import; import javax.wsdl.Input; import javax.wsdl.Message; import javax.wsdl.Operation; import javax.wsdl.Output; import javax.wsdl.Part; import javax.wsdl.Port; import javax.wsdl.PortType; import javax.wsdl.Service; import javax.wsdl.WSDLElement; import javax.wsdl.extensions.ExtensibilityElement; import javax.wsdl.extensions.soap.SOAPBinding; import javax.wsdl.extensions.soap12.SOAP12Binding; import javax.xml.namespace.QName; import org.w3c.dom.Element; import org.apache.cxf.Bus; import org.apache.cxf.BusException; import org.apache.cxf.binding.AbstractBindingFactory; import org.apache.cxf.binding.BindingFactory; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.common.xmlschema.SchemaCollection; import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.service.model.AbstractMessageContainer; import org.apache.cxf.service.model.AbstractPropertiesHolder; import org.apache.cxf.service.model.BindingFaultInfo; import org.apache.cxf.service.model.BindingInfo; import org.apache.cxf.service.model.BindingMessageInfo; import org.apache.cxf.service.model.BindingOperationInfo; import org.apache.cxf.service.model.DescriptionInfo; import org.apache.cxf.service.model.EndpointInfo; import org.apache.cxf.service.model.FaultInfo; import org.apache.cxf.service.model.InterfaceInfo; import org.apache.cxf.service.model.MessageInfo; import org.apache.cxf.service.model.MessagePartInfo; import org.apache.cxf.service.model.OperationInfo; import org.apache.cxf.service.model.ServiceInfo; import org.apache.cxf.service.model.ServiceSchemaInfo; import org.apache.cxf.service.model.UnwrappedOperationInfo; import org.apache.cxf.transport.DestinationFactory; import org.apache.cxf.transport.DestinationFactoryManager; import org.apache.cxf.wsdl.JAXBExtensibilityElement; import org.apache.cxf.wsdl.WSDLManager; import org.apache.cxf.wsdl.binding.WSDLBindingFactory; import org.apache.ws.commons.schema.XmlSchemaComplexContentExtension; import org.apache.ws.commons.schema.XmlSchemaComplexType; import org.apache.ws.commons.schema.XmlSchemaElement; import org.apache.ws.commons.schema.XmlSchemaSequence; import org.apache.ws.commons.schema.XmlSchemaSequenceMember; import org.apache.ws.commons.schema.XmlSchemaType; import static org.apache.cxf.helpers.CastUtils.cast; public class WSDLServiceBuilder { public static final String WSDL_SCHEMA_LIST = WSDLServiceBuilder.class.getName() + ".SCHEMA"; public static final String WSDL_DEFINITION = WSDLServiceBuilder.class.getName() + ".DEFINITION"; public static final String WSDL_SERVICE = WSDLServiceBuilder.class.getName() + ".SERVICE"; public static final String WSDL_PORTTYPE = WSDLServiceBuilder.class.getName() + ".WSDL_PORTTYPE"; public static final String WSDL_PORT = WSDLServiceBuilder.class.getName() + ".PORT"; public static final String WSDL_BINDING = WSDLServiceBuilder.class.getName() + ".BINDING"; public static final String WSDL_SCHEMA_ELEMENT_LIST = WSDLServiceBuilder.class.getName() + ".SCHEMA_ELEMENTS"; public static final String WSDL_OPERATION = WSDLServiceBuilder.class.getName() + ".OPERATION"; public static final String WSDL_BINDING_OPERATION = WSDLServiceBuilder.class.getName() + ".BINDING_OPERATION"; private static final Logger LOG = LogUtils.getL7dLogger(WSDLServiceBuilder.class); private Bus bus; private Map<String, Element> schemaList = new HashMap<>(); private boolean recordOriginal = true; private boolean allowRefs; private boolean ignoreUnknownBindings; private Level unwrapLogLevel = Level.FINE; public WSDLServiceBuilder(Bus bus) { this.bus = bus; } public WSDLServiceBuilder(Bus bus, boolean record) { this.bus = bus; recordOriginal = record; } public void setUnwrapLogLevel(Level l) { unwrapLogLevel = l; } public void setIgnoreUnknownBindings(boolean b) { ignoreUnknownBindings = b; } public void setAllowElementRefs(boolean b) { allowRefs = b; } private void copyExtensors(AbstractPropertiesHolder info, List<?> extList) { if (info != null) { for (ExtensibilityElement ext : cast(extList, ExtensibilityElement.class)) { Object o = ext; if (ext instanceof JAXBExtensibilityElement) { o = ((JAXBExtensibilityElement)ext).getValue(); } if (!info.containsExtensor(o)) { info.addExtensor(o); } } } } private void copyExtensionAttributes(AbstractPropertiesHolder info, javax.wsdl.extensions.AttributeExtensible ae) { Map<QName, Object> attrs = CastUtils.cast(ae.getExtensionAttributes()); if (!attrs.isEmpty()) { info.setExtensionAttributes(attrs); } } private void copyDocumentation(AbstractPropertiesHolder info, WSDLElement el) { if (el.getDocumentationElement() != null) { String doc = DOMUtils.getRawContent(el.getDocumentationElement()); info.setDocumentation(doc); } } public List<ServiceInfo> buildServices(Definition d) { DescriptionInfo description = new DescriptionInfo(); if (recordOriginal) { description.setProperty(WSDL_DEFINITION, d); } description.setName(d.getQName()); description.setBaseURI(d.getDocumentBaseURI()); copyExtensors(description, d.getExtensibilityElements()); copyExtensionAttributes(description, d); List<ServiceInfo> serviceList = new ArrayList<>(); for (java.util.Iterator<QName> ite = CastUtils.cast(d.getServices().keySet().iterator()); ite .hasNext();) { QName qn = ite.next(); serviceList.addAll(buildServices(d, qn, null, description)); } return serviceList; } public List<ServiceInfo> buildServices(Definition d, QName name) { return buildServices(d, name, null, null); } public List<ServiceInfo> buildServices(Definition d, QName name, QName endpointName) { return buildServices(d, name, endpointName, null); } private List<ServiceInfo> buildServices(Definition d, QName name, QName endpointName, DescriptionInfo description) { Service service = d.getService(name); if (service == null) { org.apache.cxf.common.i18n.Message msg = new org.apache.cxf.common.i18n.Message("MISSING_SERVICE", LOG, name); throw new WSDLRuntimeException(msg); } return buildServices(d, service, endpointName, description); } public List<ServiceInfo> buildServices(Definition def, Service serv) { return buildServices(def, serv, null, null); } public List<ServiceInfo> buildServices(Definition def, Service serv, QName endpointName) { return buildServices(def, serv, endpointName, null); } public List<ServiceInfo> buildMockServices(Definition d) { List<ServiceInfo> serviceList = new ArrayList<>(); List<Definition> defList = new ArrayList<>(); defList.add(d); parseImports(d, defList); for (Definition def : defList) { for (Iterator<?> ite = def.getPortTypes().entrySet().iterator(); ite.hasNext();) { Entry<?, ?> entry = (Entry<?, ?>)ite.next(); PortType portType = def.getPortType((QName)entry.getKey()); ServiceInfo serviceInfo = this.buildMockService(def, portType); serviceList.add(serviceInfo); for (Iterator<?> it2 = d.getAllBindings().values().iterator(); it2.hasNext();) { Binding b = (Binding)it2.next(); if (b.getPortType() == portType) { this.buildBinding(serviceInfo, b); break; } } } if (def.getPortTypes().size() == 0) { DescriptionInfo description = new DescriptionInfo(); if (recordOriginal) { description.setProperty(WSDL_DEFINITION, def); } description.setName(def.getQName()); description.setBaseURI(def.getDocumentBaseURI()); copyExtensors(description, def.getExtensibilityElements()); copyExtensionAttributes(description, def); ServiceInfo service = new ServiceInfo(); service.setDescription(description); if (recordOriginal) { service.setProperty(WSDL_DEFINITION, def); } getSchemas(def, service); service.setProperty(WSDL_SCHEMA_ELEMENT_LIST, this.schemaList); serviceList.add(service); } } return serviceList; } public ServiceInfo buildMockService(Definition def, PortType p) { DescriptionInfo description = new DescriptionInfo(); if (recordOriginal) { description.setProperty(WSDL_DEFINITION, def); } description.setName(def.getQName()); description.setBaseURI(def.getDocumentBaseURI()); copyExtensors(description, def.getExtensibilityElements()); copyExtensionAttributes(description, def); ServiceInfo service = new ServiceInfo(); service.setDescription(description); if (recordOriginal) { service.setProperty(WSDL_DEFINITION, def); } getSchemas(def, service); service.setProperty(WSDL_SCHEMA_ELEMENT_LIST, this.schemaList); buildInterface(service, p); return service; } private List<ServiceInfo> buildServices(Definition def, Service serv, QName endpointName, DescriptionInfo d) { Map<QName, ServiceInfo> services = new LinkedHashMap<QName, ServiceInfo>(); DescriptionInfo description = d; if (null == description) { description = new DescriptionInfo(); if (recordOriginal) { description.setProperty(WSDL_DEFINITION, def); } description.setName(def.getQName()); description.setBaseURI(def.getDocumentBaseURI()); copyExtensors(description, def.getExtensibilityElements()); copyExtensionAttributes(description, def); Set<Definition> done = new HashSet<>(); done.add(def); Collection<List<Import>> values = CastUtils.cast(def.getImports().values()); for (List<Import> imports : values) { for (Import imp : imports) { if (!done.contains(imp.getDefinition())) { done.add(imp.getDefinition()); copyExtensors(description, imp.getExtensibilityElements()); copyExtensionAttributes(description, imp); copyExtensors(description, imp.getDefinition().getExtensibilityElements()); copyExtensionAttributes(description, imp.getDefinition()); } } } } for (Port port : cast(serv.getPorts().values(), Port.class)) { if (endpointName != null && !endpointName.getLocalPart().equals(port.getName())) { continue; } Binding binding = port.getBinding(); PortType bindingPt = binding.getPortType(); if (bindingPt == null) { org.apache.cxf.common.i18n.Message msg = new org.apache.cxf.common.i18n.Message("BINDING_MISSING_TYPE", LOG, binding.getQName()); throw new WSDLRuntimeException(msg); } //TODO: wsdl4j's bug. if there is recursive import, //wsdl4j can not get operation input message PortType pt = def.getPortType(bindingPt.getQName()); if (pt == null) { pt = bindingPt; } ServiceInfo service = services.get(pt.getQName()); if (service == null) { service = new ServiceInfo(); service.setDescription(description); description.getDescribed().add(service); if (recordOriginal) { service.setProperty(WSDL_DEFINITION, def); service.setProperty(WSDL_SERVICE, serv); } getSchemas(def, service); copyDocumentation(service, serv); service.setProperty(WSDL_SCHEMA_ELEMENT_LIST, this.schemaList); service.setTargetNamespace(def.getTargetNamespace()); service.setName(serv.getQName()); copyExtensors(service, serv.getExtensibilityElements()); copyExtensionAttributes(service, serv); buildInterface(service, pt); services.put(pt.getQName(), service); } BindingInfo bi = service.getBinding(binding.getQName()); if (bi == null) { bi = buildBinding(service, binding); } buildEndpoint(service, bi, port); } return new ArrayList<>(services.values()); } private void getSchemas(Definition def, ServiceInfo serviceInfo) { ServiceSchemaInfo serviceSchemaInfo = null; WSDLManager wsdlManager = bus.getExtension(WSDLManager.class); if (wsdlManager != null) { serviceSchemaInfo = wsdlManager.getSchemasForDefinition(def); } if (serviceSchemaInfo == null) { SchemaUtil schemaUtil = new SchemaUtil(bus, this.schemaList); schemaUtil.getSchemas(def, serviceInfo); serviceSchemaInfo = new ServiceSchemaInfo(); serviceSchemaInfo.setSchemaElementList(this.schemaList); serviceSchemaInfo.setSchemaCollection(serviceInfo.getXmlSchemaCollection()); serviceSchemaInfo.setSchemaInfoList(serviceInfo.getSchemas()); if (wsdlManager != null) { wsdlManager.putSchemasForDefinition(def, serviceSchemaInfo); } } else { serviceInfo.setServiceSchemaInfo(serviceSchemaInfo); schemaList.putAll(serviceSchemaInfo.getSchemaElementList()); } } private void parseImports(Definition def, List<Definition> defList) { List<Import> importList = new ArrayList<>(); Collection<List<Import>> ilist = cast(def.getImports().values()); for (List<Import> list : ilist) { importList.addAll(list); } for (Import impt : importList) { if (!defList.contains(impt.getDefinition())) { defList.add(impt.getDefinition()); parseImports(impt.getDefinition(), defList); } } } public EndpointInfo buildEndpoint(ServiceInfo service, BindingInfo bi, Port port) { List<?> elements = port.getExtensibilityElements(); String ns = null; DestinationFactory factory = null; EndpointInfo ei = null; if (null != elements && !elements.isEmpty()) { for (ExtensibilityElement el : CastUtils.cast(elements, ExtensibilityElement.class)) { ns = el.getElementType().getNamespaceURI(); try { factory = bus.getExtension(DestinationFactoryManager.class).getDestinationFactory(ns); } catch (BusException e) { // do nothing } if (factory != null) { break; } } if (factory == null) { ns = ((ExtensibilityElement)elements.get(0)).getElementType().getNamespaceURI(); } } if (factory == null) { // get the transport id from bindingInfo elements = port.getBinding().getExtensibilityElements(); if (null != elements && !elements.isEmpty()) { for (ExtensibilityElement el : CastUtils.cast(elements, ExtensibilityElement.class)) { if (el instanceof SOAPBinding) { ns = ((SOAPBinding)el).getTransportURI(); break; } else if (el instanceof SOAP12Binding) { ns = ((SOAP12Binding)el).getTransportURI(); break; // TODO: this is really ugly, but how to link between // this binding and this transport ? } } } if (ns == null) { if (ignoreUnknownBindings) { return null; } org.apache.cxf.common.i18n.Message msg = new org.apache.cxf.common.i18n.Message("MISSING_DESTINATION_FACTORY", LOG, port.getName()); throw new WSDLRuntimeException(msg); } try { factory = bus.getExtension(DestinationFactoryManager.class).getDestinationFactory(ns); } catch (BusException e) { // do nothing } } if (factory instanceof WSDLEndpointFactory) { WSDLEndpointFactory wFactory = (WSDLEndpointFactory)factory; ei = wFactory.createEndpointInfo(bus, service, bi, port.getExtensibilityElements()); } if (ei == null) { ei = new EndpointInfo(service, ns); } copyDocumentation(ei, port); ei.setName(new QName(service.getName().getNamespaceURI(), port.getName())); ei.setBinding(bi); copyExtensors(ei, port.getExtensibilityElements()); copyExtensionAttributes(ei, port); service.addEndpoint(ei); DescriptionInfo d = service.getDescription(); if (null != d) { d.getDescribed().add(ei); } return ei; } public BindingInfo buildBinding(ServiceInfo service, Binding binding) { BindingInfo bi = null; StringBuilder ns = new StringBuilder(100); BindingFactory factory = WSDLServiceUtils.getBindingFactory(binding, bus, ns); if (factory instanceof WSDLBindingFactory) { WSDLBindingFactory wFactory = (WSDLBindingFactory)factory; bi = wFactory.createBindingInfo(service, binding, ns.toString()); copyExtensors(bi, binding.getExtensibilityElements()); copyExtensionAttributes(bi, binding); } if (bi == null) { boolean onlyExtensors = false; if (factory instanceof AbstractBindingFactory) { bi = ((AbstractBindingFactory)factory).createBindingInfo(service, ns.toString(), null); onlyExtensors = true; } else { bi = new BindingInfo(service, ns.toString()); } bi.setName(binding.getQName()); copyExtensors(bi, binding.getExtensibilityElements()); copyExtensionAttributes(bi, binding); for (BindingOperation bop : cast(binding.getBindingOperations(), BindingOperation.class)) { if (LOG.isLoggable(Level.FINER)) { LOG.finer("binding operation name is " + bop.getName()); } String inName = null; String outName = null; if (bop.getBindingInput() != null) { inName = bop.getBindingInput().getName(); } if (bop.getBindingOutput() != null) { outName = bop.getBindingOutput().getName(); } BindingOperationInfo bop2 = null; if (onlyExtensors) { bop2 = bi.getOperation(new QName(binding.getQName().getNamespaceURI(), bop.getName())); } else { bop2 = bi.buildOperation(new QName(binding.getQName().getNamespaceURI(), bop.getName()), inName, outName); if (bop2 != null) { bi.addOperation(bop2); } } if (bop2 != null) { copyExtensors(bop2, bop.getExtensibilityElements()); copyExtensionAttributes(bop2, bop); if (bop.getBindingInput() != null) { copyExtensors(bop2.getInput(), bop.getBindingInput().getExtensibilityElements()); copyExtensionAttributes(bop2.getInput(), bop.getBindingInput()); handleHeader(bop2.getInput()); } if (bop.getBindingOutput() != null) { copyExtensors(bop2.getOutput(), bop.getBindingOutput().getExtensibilityElements()); copyExtensionAttributes(bop2.getOutput(), bop.getBindingOutput()); handleHeader(bop2.getOutput()); } for (BindingFault f : cast(bop.getBindingFaults().values(), BindingFault.class)) { BindingFaultInfo bif = bop2.getFault(new QName(service.getTargetNamespace(), f .getName())); copyExtensors(bif, bop.getBindingFault(f.getName()).getExtensibilityElements()); copyExtensionAttributes(bif, bop.getBindingFault(f.getName())); } } } } service.addBinding(bi); DescriptionInfo d = service.getDescription(); if (null != d) { d.getDescribed().add(bi); } return bi; } private void handleHeader(BindingMessageInfo bindingMessageInfo) { // mark all message part which should be in header List<ExtensibilityElement> extensiblilityElement = bindingMessageInfo .getExtensors(ExtensibilityElement.class); // for non-soap binding, the extensiblilityElement could be null if (extensiblilityElement == null) { return; } // for (ExtensibilityElement element : extensiblilityElement) { // LOG.info("the extensibility is " + element.getClass().getName()); // if (element instanceof SOAPHeader) { // LOG.info("the header is " + ((SOAPHeader)element).getPart()); // } // } } public void buildInterface(ServiceInfo si, PortType p) { InterfaceInfo inf = si.createInterface(p.getQName()); DescriptionInfo d = si.getDescription(); if (null != d) { d.getDescribed().add(inf); } copyDocumentation(inf, p); this.copyExtensors(inf, p.getExtensibilityElements()); this.copyExtensionAttributes(inf, p); if (recordOriginal) { inf.setProperty(WSDL_PORTTYPE, p); } for (Operation op : cast(p.getOperations(), Operation.class)) { buildInterfaceOperation(inf, op); } } private void buildInterfaceOperation(InterfaceInfo inf, Operation op) { OperationInfo opInfo = inf.addOperation(new QName(inf.getName().getNamespaceURI(), op.getName())); if (recordOriginal) { opInfo.setProperty(WSDL_OPERATION, op); } copyDocumentation(opInfo, op); List<String> porderList = CastUtils.cast((List<?>)op.getParameterOrdering()); opInfo.setParameterOrdering(porderList); this.copyExtensors(opInfo, op.getExtensibilityElements()); this.copyExtensionAttributes(opInfo, op); Input input = op.getInput(); if (input != null) { if (input.getMessage() == null) { throw new WSDLRuntimeException(LOG, "NO_MESSAGE", "input", op.getName(), input.getName()); } MessageInfo minfo = opInfo.createMessage(input.getMessage().getQName(), MessageInfo.Type.INPUT); opInfo.setInput(input.getName(), minfo); buildMessage(minfo, input.getMessage()); copyExtensors(minfo, input.getExtensibilityElements()); copyExtensionAttributes(minfo, input); } Output output = op.getOutput(); if (output != null) { if (output.getMessage() == null) { throw new WSDLRuntimeException(LOG, "NO_MESSAGE", "output", op.getName(), output.getName()); } MessageInfo minfo = opInfo.createMessage(output.getMessage().getQName(), MessageInfo.Type.OUTPUT); opInfo.setOutput(output.getName(), minfo); buildMessage(minfo, output.getMessage()); copyExtensors(minfo, output.getExtensibilityElements()); copyExtensionAttributes(minfo, output); } Map<?, ?> m = op.getFaults(); for (Map.Entry<?, ?> rawentry : m.entrySet()) { Map.Entry<String, Fault> entry = cast(rawentry, String.class, Fault.class); FaultInfo finfo = opInfo.addFault(new QName(inf.getName().getNamespaceURI(), entry.getKey()), entry.getValue().getMessage().getQName()); copyDocumentation(finfo, entry.getValue()); buildMessage(finfo, entry.getValue().getMessage()); copyExtensors(finfo, entry.getValue().getExtensibilityElements()); copyExtensionAttributes(finfo, entry.getValue()); } checkForWrapped(opInfo, allowRefs, false, unwrapLogLevel); } public static void checkForWrapped(OperationInfo opInfo, boolean relaxed) { checkForWrapped(opInfo, relaxed, relaxed); } public static void checkForWrapped(OperationInfo opInfo, boolean allowRefs, boolean relaxed) { checkForWrapped(opInfo, allowRefs, relaxed, Level.FINE); } public static void checkForWrapped(OperationInfo opInfo, boolean allowRefs, boolean relaxed, Level logLevel) { MessageInfo inputMessage = opInfo.getInput(); MessageInfo outputMessage = opInfo.getOutput(); boolean passedRule = true; // RULE No.1: // The operation's input and output message (if present) each contain // only a single part // input message must exist if (inputMessage == null || inputMessage.size() == 0 || (inputMessage.size() > 1 && !relaxed)) { passedRule = false; } if (outputMessage != null && outputMessage.size() > 1) { passedRule = false; } if (!passedRule) { org.apache.cxf.common.i18n.Message message = new org.apache.cxf.common.i18n.Message("WRAPPED_RULE_1", LOG, opInfo.getName()); LOG.log(logLevel, message.toString()); return; } SchemaCollection schemas = opInfo.getInterface().getService().getXmlSchemaCollection(); XmlSchemaElement inputEl = null; XmlSchemaElement outputEl = null; // RULE No.2: // The input message part refers to a global element declaration whose // local name is equal to the operation name. MessagePartInfo inputPart = inputMessage.getMessagePartByIndex(0); if (!inputPart.isElement()) { passedRule = false; } else { QName inputElementName = inputPart.getElementQName(); inputEl = schemas.getElementByQName(inputElementName); if (inputEl == null) { passedRule = false; } else if (!opInfo.getName().getLocalPart().equals(inputElementName.getLocalPart())) { passedRule = relaxed; } } if (!passedRule) { org.apache.cxf.common.i18n.Message message = new org.apache.cxf.common.i18n.Message("WRAPPED_RULE_2", LOG, opInfo.getName()); LOG.log(logLevel, message.toString()); return; } // RULE No.3: // The output message part refers to a global element declaration MessagePartInfo outputPart = null; if (outputMessage != null && outputMessage.size() == 1) { outputPart = outputMessage.getMessagePartByIndex(0); if (outputPart != null) { if (!outputPart.isElement() || schemas.getElementByQName(outputPart.getElementQName()) == null) { passedRule = false; } else { outputEl = schemas.getElementByQName(outputPart.getElementQName()); } } } if (!passedRule) { org.apache.cxf.common.i18n.Message message = new org.apache.cxf.common.i18n.Message("WRAPPED_RULE_3", LOG, opInfo.getName()); LOG.log(logLevel, message.toString()); return; } // RULE No.4 and No5: // wrapper element should be pure complex type // Now lets see if we have any attributes... // This should probably look at the restricted and substitute types too. OperationInfo unwrapped = new UnwrappedOperationInfo(opInfo); MessageInfo unwrappedInput = new MessageInfo(unwrapped, MessageInfo.Type.INPUT, inputMessage.getName()); MessageInfo unwrappedOutput = null; XmlSchemaComplexType xsct = null; if (inputEl.getSchemaType() instanceof XmlSchemaComplexType) { xsct = (XmlSchemaComplexType)inputEl.getSchemaType(); if (hasAttributes(xsct) || (inputEl.isNillable() && !relaxed) || !isWrappableSequence(xsct, inputEl.getQName().getNamespaceURI(), unwrappedInput, allowRefs)) { passedRule = false; } } else { passedRule = false; } if (!passedRule) { org.apache.cxf.common.i18n.Message message = new org.apache.cxf.common.i18n.Message("WRAPPED_RULE_4", LOG, opInfo.getName()); LOG.log(logLevel, message.toString()); return; } if (outputMessage != null) { unwrappedOutput = new MessageInfo(unwrapped, MessageInfo.Type.OUTPUT, outputMessage.getName()); if (outputEl != null && outputEl.getSchemaType() instanceof XmlSchemaComplexType) { xsct = (XmlSchemaComplexType)outputEl.getSchemaType(); if (xsct.isAbstract()) { passedRule = false; } if (hasAttributes(xsct) || (outputEl.isNillable() && !relaxed) || !isWrappableSequence(xsct, outputEl.getQName().getNamespaceURI(), unwrappedOutput, allowRefs)) { passedRule = false; } } else { passedRule = false; } } if (!passedRule) { org.apache.cxf.common.i18n.Message message = new org.apache.cxf.common.i18n.Message("WRAPPED_RULE_5", LOG, opInfo.getName()); LOG.log(logLevel, message.toString()); return; } // we are wrappable!! opInfo.setUnwrappedOperation(unwrapped); unwrapped.setInput(opInfo.getInputName(), unwrappedInput); if (outputMessage != null) { unwrapped.setOutput(opInfo.getOutputName(), unwrappedOutput); } } private static boolean hasAttributes(XmlSchemaComplexType complexType) { // Now lets see if we have any attributes... // This should probably look at the restricted and substitute types too. return complexType.getAnyAttribute() != null || !complexType.getAttributes().isEmpty(); } private static boolean isWrappableSequence(XmlSchemaComplexType type, String namespaceURI, MessageInfo wrapper, boolean allowRefs) { if (!hasAttributes(type)) { if (type.getParticle() instanceof XmlSchemaSequence) { XmlSchemaSequence seq = (XmlSchemaSequence)type.getParticle(); return buildMessageParts(seq, namespaceURI, wrapper, allowRefs); } else if (type.getParticle() == null) { if (type.getContentModel() == null) { return true; } if (type.getContentModel().getContent() instanceof XmlSchemaComplexContentExtension) { XmlSchemaComplexContentExtension extension = (XmlSchemaComplexContentExtension)type .getContentModel().getContent(); QName baseTypeName = extension.getBaseTypeName(); ServiceInfo serviceInfo = wrapper.getOperation().getInterface().getService(); XmlSchemaType schemaType = serviceInfo.getXmlSchemaCollection().getTypeByQName(baseTypeName); if (!(schemaType instanceof XmlSchemaComplexType) || !isWrappableSequence((XmlSchemaComplexType)schemaType, namespaceURI, wrapper, allowRefs)) { return false; } if (extension.getParticle() instanceof XmlSchemaSequence) { XmlSchemaSequence seq = (XmlSchemaSequence)extension.getParticle(); return buildMessageParts(seq, namespaceURI, wrapper, allowRefs); } } return true; } } return false; } private static boolean buildMessageParts(XmlSchemaSequence seq, String namespaceURI, MessageInfo wrapper, boolean allowRefs) { List<XmlSchemaSequenceMember> items = seq.getItems(); boolean ret = true; for (XmlSchemaSequenceMember seqItem : items) { if (!(seqItem instanceof XmlSchemaElement)) { return false; } XmlSchemaElement el = (XmlSchemaElement)seqItem; if (el.getSchemaTypeName() != null) { MessagePartInfo mpi = wrapper.addMessagePart(new QName(namespaceURI, el.getName())); mpi.setTypeQName(el.getSchemaTypeName()); mpi.setElement(true); mpi.setElementQName(el.getWireName()); mpi.setConcreteName(el.getWireName()); mpi.setXmlSchema(el); } else if (el.getRef().getTargetQName() != null) { MessagePartInfo mpi = wrapper.addMessagePart(el.getRef().getTargetQName()); mpi.setTypeQName(el.getRef().getTargetQName()); mpi.setElementQName(el.getRef().getTargetQName()); mpi.setElement(true); mpi.setXmlSchema(el); mpi.setProperty("isRefElement", true); // element reference is not permitted for wrapper element if (!allowRefs) { ret = false; } } else { // anonymous type MessagePartInfo mpi = wrapper.addMessagePart(new QName(namespaceURI, el.getName())); mpi.setElementQName(mpi.getName()); mpi.setConcreteName(el.getWireName()); mpi.setElement(true); mpi.setXmlSchema(el); } } return ret; } private void buildMessage(AbstractMessageContainer minfo, Message msg) { SchemaCollection schemas = minfo.getOperation().getInterface().getService() .getXmlSchemaCollection(); List<?> orderedParam = msg.getOrderedParts(null); for (Part part : cast(orderedParam, Part.class)) { MessagePartInfo pi = minfo.addMessagePart(new QName(minfo.getName().getNamespaceURI(), part .getName())); if (part.getTypeName() != null) { pi.setTypeQName(part.getTypeName()); pi.setElement(false); pi.setXmlSchema(schemas.getTypeByQName(part.getTypeName())); } else if (part.getElementName() != null) { pi.setElementQName(part.getElementName()); XmlSchemaElement schemaElement = schemas.getElementByQName(part.getElementName()); if (null == schemaElement) { org.apache.cxf.common.i18n.Message errorMessage = new org.apache.cxf.common.i18n.Message("WSDL4J_BAD_ELEMENT_PART", LOG, part.getName(), part.getElementName()); throw new WSDLRuntimeException(errorMessage); } pi.setElement(true); pi.setXmlSchema(schemaElement); } else { org.apache.cxf.common.i18n.Message errorMessage = new org.apache.cxf.common.i18n.Message("PART_NO_NAME_NO_TYPE", LOG, part.getName()); throw new WSDLRuntimeException(errorMessage); } } } }