/** * 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.tools.corba.processors.idl; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import javax.wsdl.Binding; import javax.wsdl.BindingOperation; import javax.wsdl.Definition; import javax.wsdl.Fault; import javax.wsdl.Operation; import javax.wsdl.PortType; import javax.wsdl.WSDLException; import javax.wsdl.extensions.ExtensibilityElement; import javax.wsdl.extensions.ExtensionRegistry; import javax.xml.namespace.QName; import antlr.collections.AST; import org.apache.cxf.binding.corba.wsdl.BindingType; import org.apache.cxf.binding.corba.wsdl.CorbaConstants; import org.apache.cxf.binding.corba.wsdl.CorbaTypeImpl; import org.apache.cxf.helpers.CastUtils; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaType; public class PortTypeVisitor extends VisitorBase { ExtensionRegistry extReg; PortType portType; Definition rootDefinition; public PortTypeVisitor(Scope scope, Definition defn, XmlSchema schemaRef, WSDLASTVisitor wsdlASTVisitor) { super(scope, defn, schemaRef, wsdlASTVisitor); extReg = definition.getExtensionRegistry(); rootDefinition = wsdlASTVisitor.getDefinition(); } public static boolean accept(AST node) { return node.getType() == IDLTokenTypes.LITERAL_interface; } public void visit(AST node) { // <interface> ::= <interface_dcl> // | <forward_dcl> // <interface_dcl> ::= <interface_header> "{" <interface_body> "}" // <forward_dcl> ::= ["abstract" | "local"] "interface" <identifier> // <interface_header> ::= ["abstract" | "local"] "interface" <identifier> // [<interface_inheritance_spec>] // <interface_body> ::= <export>* // <export> ::= <type_dcl> ";" // | <const_dcl> ";" // | <except_dcl> ";" // | <attr_dcl> ";" // | <op_dcl> ";" // <interface_inheritance_spec> ::= ":" <interface_name> { "," <interface_name> }* // <interface_name> ::= <scoped_name> AST identifierNode = node.getFirstChild(); if (identifierNode.getText().equals("local")) { identifierNode = identifierNode.getNextSibling(); } // Check if its a forward declaration if (identifierNode.getFirstChild() == null && identifierNode.getNextSibling() == null) { visitForwardDeclaredInterface(identifierNode); } else { visitInterface(identifierNode); } } // Visits a fully declared interface private void visitInterface(AST identifierNode) { try { String interfaceName = identifierNode.toString(); Scope interfaceScope = new Scope(getScope(), interfaceName); portType = definition.createPortType(); String portTypeName = interfaceScope.toString(); XmlSchema newSchema = schema; if (!mapper.isDefaultMapping()) { portTypeName = interfaceScope.tail(); //add a schema based on the interface String tns = mapper.map(interfaceScope); newSchema = manager.createXmlSchemaForDefinition(definition, tns, schemas); definition.addNamespace(interfaceScope.toString("_"), tns); } String tns = definition.getTargetNamespace(); portType.setQName(new QName(tns, portTypeName)); definition.addPortType(portType); portType.setUndefined(false); Binding binding = createBinding(interfaceScope.toString()); AST specNode = identifierNode.getNextSibling(); if (specNode.getType() == IDLTokenTypes.LCURLY) { specNode = specNode.getNextSibling(); } AST exportNode = null; if (specNode.getType() == IDLTokenTypes.RCURLY) { exportNode = specNode.getNextSibling(); } else if (specNode.getType() == IDLTokenTypes.COLON) { exportNode = visitInterfaceInheritanceSpec(specNode, binding, interfaceScope); exportNode = exportNode.getNextSibling(); } else { exportNode = specNode; } while (exportNode != null && exportNode.getType() != IDLTokenTypes.RCURLY) { if (TypeDclVisitor.accept(exportNode)) { TypeDclVisitor visitor = new TypeDclVisitor(interfaceScope, definition, newSchema, wsdlVisitor); visitor.visit(exportNode); } else if (ConstVisitor.accept(exportNode)) { ConstVisitor visitor = new ConstVisitor(interfaceScope, definition, newSchema, wsdlVisitor); visitor.visit(exportNode); } else if (ExceptionVisitor.accept(exportNode)) { ExceptionVisitor visitor = new ExceptionVisitor(interfaceScope, definition, newSchema, wsdlVisitor); visitor.visit(exportNode); } else if (AttributeVisitor.accept(exportNode)) { AttributeVisitor attributeVisitor = new AttributeVisitor(interfaceScope, definition, newSchema, wsdlVisitor, portType, binding); attributeVisitor.visit(exportNode); } else if (OperationVisitor.accept(interfaceScope, definition, newSchema, exportNode, wsdlVisitor)) { OperationVisitor visitor = new OperationVisitor(interfaceScope, definition, newSchema, wsdlVisitor, portType, binding); visitor.visit(exportNode); } else { throw new RuntimeException("[InterfaceVisitor] Invalid IDL: unknown element " + exportNode.toString()); } exportNode = exportNode.getNextSibling(); } // Once we've finished declaring the interface, we should make sure it has been removed // from the list of scopedNames so that we indicate that is no longer simply forward // declared. Scope scopedName = new Scope(getScope(), identifierNode); scopedNames.remove(scopedName); if (wsdlVisitor.getDeferredActions() != null) { handleDeferredActions(wsdlVisitor.getDeferredActions(), scopedName, identifierNode); } if (!mapper.isDefaultMapping()) { manager.deferAttachSchemaToWSDL(definition, newSchema, false); //manager.attachSchemaToWSDL(definition, newSchema, false); } } catch (Exception ex) { throw new RuntimeException(ex); } } private void handleDeferredActions(DeferredActionCollection deferredActions, Scope scopedName, AST identifierNode) { List<DeferredAction> list = deferredActions.getActions(scopedName); if ((list != null) && !list.isEmpty()) { XmlSchemaType stype = null; CorbaTypeImpl ctype = null; if (ObjectReferenceVisitor.accept(getScope(), schema, definition, identifierNode, wsdlVisitor)) { ObjectReferenceVisitor visitor = new ObjectReferenceVisitor(getScope(), definition, schema, wsdlVisitor); visitor.visit(identifierNode); stype = visitor.getSchemaType(); ctype = visitor.getCorbaType(); } for (DeferredAction action : list) { if (action instanceof SchemaDeferredAction && (stype != null) && (ctype != null)) { SchemaDeferredAction schemaAction = (SchemaDeferredAction) action; schemaAction.execute(stype, ctype); } } deferredActions.removeScope(scopedName); } } public Binding createBinding(String scopedPortTypeName) { StringBuilder bname = new StringBuilder(scopedPortTypeName + "CORBABinding"); QName bqname = new QName(rootDefinition.getTargetNamespace(), bname.toString()); int count = 0; while (queryBinding(bqname)) { bname.append(count); bqname = new QName(rootDefinition.getTargetNamespace(), bname.toString()); } Binding binding = rootDefinition.createBinding(); binding.setPortType(portType); binding.setQName(bqname); try { BindingType bindingType = (BindingType) extReg.createExtension(Binding.class, CorbaConstants.NE_CORBA_BINDING); String pragmaPrefix = (this.getWsdlVisitor().getPragmaPrefix() != null && this.getWsdlVisitor().getPragmaPrefix().length() > 0) ? this.getWsdlVisitor().getPragmaPrefix() + "/" : ""; bindingType.setRepositoryID(CorbaConstants.REPO_STRING + pragmaPrefix + scopedPortTypeName.replace('.', '/') + CorbaConstants.IDL_VERSION); binding.addExtensibilityElement((ExtensibilityElement)bindingType); } catch (WSDLException ex) { throw new RuntimeException(ex); } binding.setUndefined(false); rootDefinition.addBinding(binding); return binding; } private boolean queryBinding(QName bqname) { Collection<Binding> bindings = CastUtils.cast(definition.getBindings().values()); for (Binding binding : bindings) { if (binding.getQName().getLocalPart().equals(bqname.getLocalPart())) { return true; } } return false; } private AST visitInterfaceInheritanceSpec(AST interfaceInheritanceSpecNode, Binding binding, Scope childScope) { // <interface_inheritance_spec> ::= ":" <interface_name> { "," <interface_name> }* AST interfaceNameNode = interfaceInheritanceSpecNode.getFirstChild(); BindingType corbaBinding = findCorbaBinding(binding); List<Scope> inheritedScopes = new ArrayList<>(); while (interfaceNameNode != null) { //check for porttypes in current & parent scopes Scope interfaceScope = null; PortType intf = null; if (ScopedNameVisitor.isFullyScopedName(interfaceNameNode)) { interfaceScope = ScopedNameVisitor.getFullyScopedName(new Scope(), interfaceNameNode); intf = findPortType(interfaceScope); } Scope currentScope = getScope(); while (intf == null && currentScope != currentScope.getParent()) { if (ScopedNameVisitor.isFullyScopedName(interfaceNameNode)) { interfaceScope = ScopedNameVisitor.getFullyScopedName(currentScope, interfaceNameNode); } else { interfaceScope = new Scope(currentScope, interfaceNameNode.toString()); } intf = findPortType(interfaceScope); currentScope = currentScope.getParent(); } if (intf == null) { if (ScopedNameVisitor.isFullyScopedName(interfaceNameNode)) { interfaceScope = ScopedNameVisitor.getFullyScopedName(new Scope(), interfaceNameNode); } else { interfaceScope = new Scope(new Scope(), interfaceNameNode); } intf = findPortType(interfaceScope); } if (intf == null) { throw new RuntimeException("[InterfaceVisitor] Unknown Interface: " + interfaceNameNode.toString()); } Scope defnScope = interfaceScope.getParent(); Definition defn = manager.getWSDLDefinition(mapper.map(defnScope)); inheritedScopes.add(interfaceScope); if (defn != null && !defn.getTargetNamespace().equals(definition.getTargetNamespace())) { String key = defnScope.toString("_"); String fileName = getWsdlVisitor().getOutputDir() + System.getProperty("file.separator") + key; manager.addWSDLDefinitionImport(definition, defn, key, fileName); } Binding inheritedBinding = findBinding(intf); BindingType inheritedCorbaBinding = findCorbaBinding(inheritedBinding); corbaBinding.getBases().add(inheritedCorbaBinding.getRepositoryID()); //add all the operations of the inherited port type. for (Operation op : CastUtils.cast(intf.getOperations(), Operation.class)) { //check to see all the inherited namespaces are added. String inputNS = op.getInput().getMessage().getQName().getNamespaceURI(); manager.addWSDLDefinitionNamespace(definition, mapper.mapNSToPrefix(inputNS), inputNS); // Make sure we import the wsdl for the input namespace if (definition.getImports().get(inputNS) == null && !mapper.isDefaultMapping() && !definition.getTargetNamespace().equals(inputNS)) { manager.addWSDLDefinitionImport(definition, manager.getWSDLDefinition(inputNS), mapper.mapNSToPrefix(inputNS), manager.getImportedWSDLDefinitionFile(inputNS)); } if (op.getOutput() != null) { String outputNS = op.getOutput().getMessage().getQName().getNamespaceURI(); manager.addWSDLDefinitionNamespace(definition, mapper.mapNSToPrefix(outputNS), outputNS); // Make sure we import the wsdl for the output namespace if (definition.getImports().get(outputNS) == null && !mapper.isDefaultMapping() && !definition.getTargetNamespace().equals(outputNS)) { manager.addWSDLDefinitionImport(definition, manager.getWSDLDefinition(outputNS), mapper.mapNSToPrefix(outputNS), manager.getImportedWSDLDefinitionFile(outputNS)); } } for (Iterator<Fault> faults = CastUtils.cast(op.getFaults().values().iterator()); faults.hasNext();) { String faultNS = faults.next().getMessage().getQName().getNamespaceURI(); manager.addWSDLDefinitionNamespace(definition, mapper.mapNSToPrefix(faultNS), faultNS); // Make sure we import the wsdl for the fault namespace if (definition.getImports().get(faultNS) == null && !mapper.isDefaultMapping() && !definition.getTargetNamespace().equals(faultNS)) { manager.addWSDLDefinitionImport(definition, manager.getWSDLDefinition(faultNS), mapper.mapNSToPrefix(faultNS), manager.getImportedWSDLDefinitionFile(faultNS)); } } portType.addOperation(op); } //add all the binding extensions of the inherited corba binding for (Iterator<BindingOperation> it = CastUtils.cast(inheritedBinding.getBindingOperations().iterator()); it.hasNext();) { binding.addBindingOperation(it.next()); } interfaceNameNode = interfaceNameNode.getNextSibling(); } if ((!inheritedScopes.isEmpty()) && (wsdlVisitor.getInheritedScopeMap() != null)) { wsdlVisitor.getInheritedScopeMap().put(childScope, inheritedScopes); } return interfaceInheritanceSpecNode.getNextSibling(); } private void visitForwardDeclaredInterface(AST identifierNode) { String interfaceName = identifierNode.toString(); Scope interfaceScope = new Scope(getScope(), interfaceName); ScopeNameCollection scopedNames = wsdlVisitor.getScopedNames(); if (scopedNames.getScope(interfaceScope) == null) { scopedNames.add(interfaceScope); } } private PortType findPortType(Scope intfScope) { String tns = mapper.map(intfScope.getParent()); String intfName = intfScope.toString(); Definition defn = definition; if (tns != null) { defn = manager.getWSDLDefinition(tns); intfName = intfScope.tail(); } if (defn != null) { tns = defn.getTargetNamespace(); QName name = new QName(tns, intfName); return defn.getPortType(name); } return null; } private Binding findBinding(PortType intf) { Object[] bindings = rootDefinition.getBindings().values().toArray(); for (int i = 0; i < bindings.length; i++) { Binding binding = (Binding) bindings[i]; if (binding.getPortType().getQName().equals(intf.getQName())) { return binding; } } throw new RuntimeException("[InterfaceVisitor] Couldn't find binding for porttype " + intf.getQName()); } private BindingType findCorbaBinding(Binding binding) { List<?> list = binding.getExtensibilityElements(); for (int i = 0; i < list.size(); i++) { if (list.get(i) instanceof BindingType) { return (BindingType) list.get(i); } } throw new RuntimeException("[InterfaceVisitor] Couldn't find Corba binding in Binding " + binding.getQName()); } }