/** * 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.binding.corba.types; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.wsdl.Binding; import javax.wsdl.Definition; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventFactory; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.events.Attribute; import javax.xml.stream.events.Namespace; import org.apache.cxf.binding.corba.utils.CorbaObjectReferenceHelper; import org.apache.cxf.binding.corba.utils.CorbaUtils; import org.apache.cxf.binding.corba.utils.EprMetaData; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.service.model.ServiceInfo; import org.apache.cxf.wsdl11.WSDLServiceBuilder; import org.omg.CORBA.ORB; public final class CorbaObjectReferenceEventProducer extends AbstractStartEndEventProducer { static final String WSDLI_NAMESPACE_URI = "http://www.w3.org/2006/01/wsdl-instance"; static final String XSI_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance"; static final QName WSA_ADDRESS = new QName(CorbaObjectReferenceHelper.ADDRESSING_NAMESPACE_URI, "Address"); static final List<Attribute> IS_NIL_OBJ_REF_ATTRS; static { XMLEventFactory factory = XMLEventFactory.newInstance(); IS_NIL_OBJ_REF_ATTRS = new ArrayList<>(); IS_NIL_OBJ_REF_ATTRS.add(factory.createAttribute(new QName(XSI_NAMESPACE_URI, "nil", "xsi"), "true")); } private static final String INFER_FROM_TYPE_ID = "InferFromTypeId"; private static final Logger LOG = LogUtils.getL7dLogger(CorbaObjectReferenceEventProducer.class); List<Attribute> refAttrs; public CorbaObjectReferenceEventProducer(CorbaObjectHandler h, ServiceInfo service, ORB orbRef) { CorbaObjectReferenceHandler handler = (CorbaObjectReferenceHandler) h; name = CorbaUtils.processQName(handler.getName(), service); orb = orbRef; serviceInfo = service; refAttrs = null; if (handler.getReference() == null) { refAttrs = IS_NIL_OBJ_REF_ATTRS; return; } List<CorbaTypeEventProducer> objRefProducers = new ArrayList<>(); String address = orb.object_to_string(handler.getReference()); objRefProducers.add(new CorbaAddressEventProducer(address)); Definition wsdlDef = (Definition)serviceInfo.getProperty(WSDLServiceBuilder.WSDL_DEFINITION); // Get the TypeImpl of the object reference so that we can determine the binding // needed for this object reference org.apache.cxf.binding.corba.wsdl.Object objType = (org.apache.cxf.binding.corba.wsdl.Object)handler.getType(); QName bindingName = objType.getBinding(); if (bindingName != null) { EprMetaData eprInfo = null; if (INFER_FROM_TYPE_ID.equalsIgnoreCase(bindingName.getLocalPart())) { String typeId = CorbaObjectReferenceHelper.extractTypeIdFromIOR(address); if (!StringUtils.isEmpty(typeId)) { eprInfo = getEprMetadataForTypeId(wsdlDef, typeId); } else { LOG.log(Level.SEVERE, "For binding with value \"" + INFER_FROM_TYPE_ID + "\" the type_id of the object reference IOR must be set to its most" + " derived type. It is currently null indicating CORBA:Object." + " Address Url=" + address); } } else { eprInfo = getEprMetadataForBindingName(wsdlDef, bindingName); } if (eprInfo.isValid()) { LOG.log(Level.FINE, "Epr metadata " + eprInfo); // Create the meta data producer and add its child producers. String wsdlLoc = CorbaObjectReferenceHelper.getWSDLLocation(eprInfo.getCandidateWsdlDef()); CorbaServiceNameEventProducer nameProducer = new CorbaServiceNameEventProducer(eprInfo.getServiceQName(), eprInfo.getPortName()); QName interfaceName = eprInfo.getBinding().getPortType().getQName(); CorbaInterfaceNameEventProducer interfaceProducer = new CorbaInterfaceNameEventProducer(interfaceName); CorbaMetaDataEventProducer metaProducer = new CorbaMetaDataEventProducer(wsdlLoc, nameProducer, interfaceProducer); objRefProducers.add(metaProducer); } } producers = objRefProducers.iterator(); } private EprMetaData getEprMetadataForBindingName(Definition wsdlDef, QName bindingName) { EprMetaData info = getObjectReferenceBinding(wsdlDef, bindingName); CorbaObjectReferenceHelper.populateEprInfo(info); return info; } private EprMetaData getEprMetadataForTypeId(Definition wsdlDef, String typeId) { EprMetaData info = CorbaObjectReferenceHelper.getBindingForTypeId(typeId, wsdlDef); CorbaObjectReferenceHelper.populateEprInfo(info); return info; } public List<Attribute> getAttributes() { if (currentEventProducer != null) { return currentEventProducer.getAttributes(); } return refAttrs; } protected EprMetaData getObjectReferenceBinding(Definition wsdlDef, QName bindingName) { EprMetaData info = new EprMetaData(); Binding wsdlBinding = wsdlDef.getBinding(bindingName); // If the binding name does not have a namespace associated with it, then we'll need to // get the list of all bindings and compare their local parts against our name. if (wsdlBinding == null && bindingName.getNamespaceURI().equals("") && !bindingName.getLocalPart().equals("")) { Collection<Binding> bindingsCollection = CastUtils.cast(wsdlDef.getBindings().values()); for (Binding b : bindingsCollection) { if (b.getQName().getLocalPart().equals(bindingName.getLocalPart())) { wsdlBinding = b; break; } } } if (wsdlBinding != null) { info.setBinding(wsdlBinding); info.setCandidateWsdlDef(wsdlDef); } return info; } // An event producer to handle the production of the Address XML data. class CorbaAddressEventProducer implements CorbaTypeEventProducer { int state; int[] states = {XMLStreamReader.START_ELEMENT, XMLStreamReader.CHARACTERS, XMLStreamReader.END_ELEMENT}; final String address; CorbaAddressEventProducer(String value) { address = value; } public String getLocalName() { return WSA_ADDRESS.getLocalPart(); } public String getText() { return address; } public int next() { return states[state++]; } public QName getName() { return WSA_ADDRESS; } public boolean hasNext() { return state < states.length; } public List<Attribute> getAttributes() { return null; } public List<Namespace> getNamespaces() { return null; } } // An event producer to handle the production of the Metadata XML data. This producer will rely // on two additional producers to handle the production of sub-events. class CorbaMetaDataEventProducer extends AbstractStartEndEventProducer { CorbaServiceNameEventProducer svcProducer; CorbaInterfaceNameEventProducer intfProducer; List<Attribute> metaAttrs; CorbaMetaDataEventProducer(CorbaServiceNameEventProducer svc) { this(null, svc, null); } CorbaMetaDataEventProducer(String location, CorbaServiceNameEventProducer svc, CorbaInterfaceNameEventProducer intf) { name = new QName(CorbaObjectReferenceHelper.ADDRESSING_NAMESPACE_URI, "Metadata"); List<CorbaTypeEventProducer> metaDataProducers = new ArrayList<>(); metaDataProducers.add(svc); if (intf != null) { metaDataProducers.add(intf); } producers = metaDataProducers.iterator(); if (location != null) { XMLEventFactory factory = XMLEventFactory.newInstance(); metaAttrs = new ArrayList<>(); metaAttrs.add(factory.createAttribute( new QName(WSDLI_NAMESPACE_URI, "wsdlLocation", "objrefns1"), location)); } } public List<Attribute> getAttributes() { if (currentEventProducer != null) { return currentEventProducer.getAttributes(); } else { return metaAttrs; } } } // An event producer to handle the production of the ServiceName XML data. class CorbaServiceNameEventProducer implements CorbaTypeEventProducer { int state; int[] states = {XMLStreamReader.START_ELEMENT, XMLStreamReader.CHARACTERS, XMLStreamReader.END_ELEMENT}; QName serviceName; QName name; List<Attribute> attributes; List<Namespace> namespaces; CorbaServiceNameEventProducer(QName svc, String ep) { serviceName = svc; name = new QName(CorbaObjectReferenceHelper.ADDRESSING_WSDL_NAMESPACE_URI, "ServiceName"); XMLEventFactory factory = XMLEventFactory.newInstance(); attributes = new ArrayList<>(); attributes.add(factory.createAttribute("EndpointName", ep)); namespaces = new ArrayList<>(); namespaces.add(factory.createNamespace("objrefns2", svc.getNamespaceURI())); } public String getLocalName() { return name.getLocalPart(); } public String getText() { return namespaces.get(0).getPrefix() + ":" + serviceName.getLocalPart(); } public int next() { return states[state++]; } public boolean hasNext() { return state < states.length; } public QName getName() { return name; } public List<Attribute> getAttributes() { return attributes; } public List<Namespace> getNamespaces() { return namespaces; } } // An event producer to handle the production of the InterfaceName XML data. class CorbaInterfaceNameEventProducer implements CorbaTypeEventProducer { int state; int[] states = {XMLStreamReader.START_ELEMENT, XMLStreamReader.CHARACTERS, XMLStreamReader.END_ELEMENT}; QName interfaceName; QName name; List<Namespace> namespaces; CorbaInterfaceNameEventProducer(QName intf) { interfaceName = intf; name = new QName(CorbaObjectReferenceHelper.ADDRESSING_WSDL_NAMESPACE_URI, "InterfaceName"); XMLEventFactory factory = XMLEventFactory.newInstance(); namespaces = new ArrayList<>(); namespaces.add(factory.createNamespace("objrefns2", intf.getNamespaceURI())); } public String getLocalName() { return name.getLocalPart(); } public String getText() { return namespaces.get(0).getPrefix() + ":" + interfaceName.getLocalPart(); } public int next() { return states[state++]; } public boolean hasNext() { return state < states.length; } public QName getName() { return name; } public List<Attribute> getAttributes() { return null; } public List<Namespace> getNamespaces() { return namespaces; } } }