/**************************************************************************** ** ** This file is part of the KD Soap project. ** ** SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company ** ** SPDX-License-Identifier: MIT ** ****************************************************************************/ #include "KDSoapMessageAddressingProperties.h" #include "KDSoapNamespaceManager.h" #include "KDSoapNamespacePrefixes_p.h" #include #include #include #include class KDSoapMessageAddressingPropertiesData : public QSharedData { public: QString destination; // Provides the address of the intended receiver of this message QString action; // Identifies the semantics implied by this message KDSoapEndpointReference sourceEndpoint; // Message origin, could be included to facilitate longer running message exchanges. KDSoapEndpointReference replyEndpoint; // Intended receiver for replies to this message, could be included to facilitate longer running message // exchanges. KDSoapEndpointReference faultEndpoint; // Intended receiver for faults related to this message, could be included to facilitate longer running // message exchanges. QString messageID; // Unique identifier for this message, may be included to facilitate longer running message exchanges. QVector relationships; // Indicates relationships to prior messages, could be included to facilitate // longer running message exchanges. KDSoapValueList referenceParameters; // Equivalent of the reference parameters object from the endpoint reference within WSDL file KDSoapValueList metadata; // Holding metadata information KDSoapMessageAddressingProperties::KDSoapAddressingNamespace addressingNamespace = KDSoapMessageAddressingProperties::Addressing200508; }; KDSoapMessageAddressingProperties::KDSoapMessageAddressingProperties() : d(new KDSoapMessageAddressingPropertiesData) { } KDSoapMessageAddressingProperties::KDSoapMessageAddressingProperties(const KDSoapMessageAddressingProperties &other) : d(other.d) { } KDSoapMessageAddressingProperties &KDSoapMessageAddressingProperties::operator=(const KDSoapMessageAddressingProperties &other) { d = other.d; return *this; } QString KDSoapMessageAddressingProperties::destination() const { return d->destination; } void KDSoapMessageAddressingProperties::setDestination(const QString &destination) { d->destination = destination; } QString KDSoapMessageAddressingProperties::action() const { return d->action; } void KDSoapMessageAddressingProperties::setAction(const QString &action) { d->action = action; } KDSoapEndpointReference KDSoapMessageAddressingProperties::sourceEndpoint() const { return d->sourceEndpoint; } QString KDSoapMessageAddressingProperties::sourceEndpointAddress() const { return d->sourceEndpoint.address(); } void KDSoapMessageAddressingProperties::setSourceEndpoint(const KDSoapEndpointReference &sourceEndpoint) { d->sourceEndpoint = sourceEndpoint; } void KDSoapMessageAddressingProperties::setSourceEndpointAddress(const QString &sourceEndpoint) { d->sourceEndpoint.setAddress(sourceEndpoint); } KDSoapEndpointReference KDSoapMessageAddressingProperties::replyEndpoint() const { return d->replyEndpoint; } QString KDSoapMessageAddressingProperties::replyEndpointAddress() const { return d->replyEndpoint.address(); } void KDSoapMessageAddressingProperties::setReplyEndpoint(const KDSoapEndpointReference &replyEndpoint) { d->replyEndpoint = replyEndpoint; } void KDSoapMessageAddressingProperties::setReplyEndpointAddress(const QString &replyEndpoint) { d->replyEndpoint.setAddress(replyEndpoint); } KDSoapEndpointReference KDSoapMessageAddressingProperties::faultEndpoint() const { return d->faultEndpoint; } QString KDSoapMessageAddressingProperties::faultEndpointAddress() const { return d->faultEndpoint.address(); } void KDSoapMessageAddressingProperties::setFaultEndpoint(const KDSoapEndpointReference &faultEndpoint) { d->faultEndpoint = faultEndpoint; } void KDSoapMessageAddressingProperties::setFaultEndpointAddress(const QString &faultEndpoint) { d->faultEndpoint.setAddress(faultEndpoint); } QString KDSoapMessageAddressingProperties::messageID() const { return d->messageID; } void KDSoapMessageAddressingProperties::setMessageID(const QString &id) { d->messageID = id; } QVector KDSoapMessageAddressingProperties::relationships() const { return d->relationships; } void KDSoapMessageAddressingProperties::setRelationships(const QVector &relationships) { d->relationships = relationships; } void KDSoapMessageAddressingProperties::addRelationship(const KDSoapMessageRelationship::Relationship &relationship) { d->relationships.append(relationship); } KDSoapValueList KDSoapMessageAddressingProperties::referenceParameters() const { return d->referenceParameters; } void KDSoapMessageAddressingProperties::setReferenceParameters(const KDSoapValueList &values) { d->referenceParameters = values; } void KDSoapMessageAddressingProperties::addReferenceParameter(const KDSoapValue &oneReferenceParameter) { if (!oneReferenceParameter.isNull()) { d->referenceParameters.append(oneReferenceParameter); } } KDSoapValueList KDSoapMessageAddressingProperties::metadata() const { return d->metadata; } void KDSoapMessageAddressingProperties::setMetadata(const KDSoapValueList &metadataList) { d->metadata = metadataList; } void KDSoapMessageAddressingProperties::addMetadata(const KDSoapValue &metadata) { if (!metadata.isNull()) { d->metadata.append(metadata); } } KDSoapMessageAddressingProperties::KDSoapAddressingNamespace KDSoapMessageAddressingProperties::addressingNamespace() const { return d->addressingNamespace; } void KDSoapMessageAddressingProperties::setAddressingNamespace(KDSoapMessageAddressingProperties::KDSoapAddressingNamespace addressingNamespace) { d->addressingNamespace = addressingNamespace; } KDSoapMessageAddressingProperties::~KDSoapMessageAddressingProperties() { } QString KDSoapMessageAddressingProperties::predefinedAddressToString(KDSoapMessageAddressingProperties::KDSoapAddressingPredefinedAddress address, KDSoapAddressingNamespace addressingNamespace) { QString prefix = addressingNamespaceToString(addressingNamespace); switch (addressingNamespace) { case Addressing200303: case Addressing200403: case Addressing200408: { switch (address) { case Anonymous: prefix += QLatin1String("/role"); break; case Unspecified: prefix += QLatin1String("/id"); break; default: qWarning("Anything but Anonymous or Unspecified has no meaning in ws-addressing 2004/08 and earlier"); return QString(); } break; } default: break; } switch (address) { case Anonymous: return prefix + QLatin1String("/anonymous"); case None: return prefix + QLatin1String("/none"); case Reply: return prefix + QLatin1String("/reply"); case Unspecified: return prefix + QLatin1String("/unspecified"); } Q_ASSERT(false); // should never happen return QString(); } bool KDSoapMessageAddressingProperties::isWSAddressingNamespace(const QString &namespaceUri) { return namespaceUri == KDSoapNamespaceManager::soapMessageAddressing() || namespaceUri == KDSoapNamespaceManager::soapMessageAddressing200303() || namespaceUri == KDSoapNamespaceManager::soapMessageAddressing200403() || namespaceUri == KDSoapNamespaceManager::soapMessageAddressing200408(); } QString KDSoapMessageAddressingProperties::addressingNamespaceToString(KDSoapAddressingNamespace addressingNamespace) { switch (addressingNamespace) { case Addressing200303: return KDSoapNamespaceManager::soapMessageAddressing200303(); case Addressing200403: return KDSoapNamespaceManager::soapMessageAddressing200403(); case Addressing200408: return KDSoapNamespaceManager::soapMessageAddressing200408(); case Addressing200508: return KDSoapNamespaceManager::soapMessageAddressing(); default: Q_ASSERT(false); // should never happen return QString(); } } static void writeAddressField(QXmlStreamWriter &writer, const QString &addressingNS, const QString &address) { writer.writeStartElement(addressingNS, QLatin1String("Address")); writer.writeCharacters(address); writer.writeEndElement(); } static void writeKDSoapValueVariant(QXmlStreamWriter &writer, const KDSoapValue &value) { const QVariant valueToWrite = value.value(); if (valueToWrite.canConvert(QVariant::String)) { writer.writeCharacters(valueToWrite.toString()); } else { qWarning("Warning: KDSoapMessageAddressingProperties call to writeKDSoapValueVariant could not write the given KDSoapValue " "value because it could not be converted into a QString"); } } static void writeKDSoapValueListHierarchy(KDSoapNamespacePrefixes &namespacePrefixes, QXmlStreamWriter &writer, const QString &addressingNS, const KDSoapValueList &values) { for (const KDSoapValue &value : std::as_const(values)) { const QString topLevelName = value.name(); writer.writeStartElement(addressingNS, topLevelName); if (value.childValues().isEmpty()) { writeKDSoapValueVariant(writer, value); } else { writeKDSoapValueListHierarchy(namespacePrefixes, writer, addressingNS, value.childValues()); } writer.writeEndElement(); } } void KDSoapMessageAddressingProperties::writeMessageAddressingProperties(KDSoapNamespacePrefixes &namespacePrefixes, QXmlStreamWriter &writer, const QString &messageNamespace, bool forceQualified) const { Q_UNUSED(messageNamespace); Q_UNUSED(forceQualified); bool supportsNoneAddressing = false; switch (d->addressingNamespace) { case Addressing200303: case Addressing200403: case Addressing200408: supportsNoneAddressing = false; break; case Addressing200508: supportsNoneAddressing = true; break; } if (supportsNoneAddressing && d->destination == predefinedAddressToString(None, d->addressingNamespace)) { return; } const QString addressingNS = addressingNamespaceToString(d->addressingNamespace); if (!d->destination.isEmpty()) { writer.writeStartElement(addressingNS, QLatin1String("To")); writer.writeCharacters(d->destination); writer.writeEndElement(); } if (!d->sourceEndpoint.isEmpty()) { writer.writeStartElement(addressingNS, QLatin1String("From")); writeAddressField(writer, addressingNS, d->sourceEndpoint.address()); writer.writeEndElement(); } if (!d->replyEndpoint.isEmpty()) { writer.writeStartElement(addressingNS, QLatin1String("ReplyTo")); writeAddressField(writer, addressingNS, d->replyEndpoint.address()); writer.writeEndElement(); } if (!d->faultEndpoint.isEmpty()) { writer.writeStartElement(addressingNS, QLatin1String("FaultTo")); writeAddressField(writer, addressingNS, d->faultEndpoint.address()); writer.writeEndElement(); } if (!d->action.isEmpty()) { writer.writeStartElement(addressingNS, QLatin1String("Action")); writer.writeCharacters(d->action); writer.writeEndElement(); } if (!d->messageID.isEmpty()) { writer.writeStartElement(addressingNS, QLatin1String("MessageID")); writer.writeCharacters(d->messageID); writer.writeEndElement(); } for (const KDSoapMessageRelationship::Relationship &relationship : std::as_const(d->relationships)) { if (relationship.uri.isEmpty()) { continue; } writer.writeStartElement(addressingNS, QLatin1String("RelatesTo")); if (!relationship.relationshipType.isEmpty()) { writer.writeAttribute(QLatin1String("RelationshipType"), relationship.relationshipType); } writer.writeCharacters(relationship.uri); writer.writeEndElement(); } if (!d->referenceParameters.isEmpty()) { writer.writeStartElement(addressingNS, QLatin1String("ReferenceParameters")); writeKDSoapValueListHierarchy(namespacePrefixes, writer, addressingNS, d->referenceParameters); writer.writeEndElement(); } if (!d->metadata.isEmpty()) { writer.writeStartElement(addressingNS, QLatin1String("Metadata")); writeKDSoapValueListHierarchy(namespacePrefixes, writer, addressingNS, d->metadata); writer.writeEndElement(); } } void KDSoapMessageAddressingProperties::readMessageAddressingProperty(const KDSoapValue &value) { const QString addressingNS = addressingNamespaceToString(d->addressingNamespace); if (value.name() == QLatin1String("Action")) { d->action = value.value().toString(); } else if (value.name() == QLatin1String("MessageID")) { d->messageID = value.value().toString(); } else if (value.name() == QLatin1String("To")) { d->destination = value.value().toString(); } else if (value.name() == QLatin1String("From")) { d->sourceEndpoint.setAddress(value.childValues().child(QLatin1String("Address")).value().toString()); } else if (value.name() == QLatin1String("ReplyTo")) { d->replyEndpoint.setAddress(value.childValues().child(QLatin1String("Address")).value().toString()); } else if (value.name() == QLatin1String("RelatesTo")) { KDSoapMessageRelationship::Relationship relationship; relationship.uri = (value.value().toString()); relationship.relationshipType = addressingNS + QLatin1String("/reply"); const auto &childAttributes = value.childValues().attributes(); for (const KDSoapValue &attr : childAttributes) { if (attr.name() == QLatin1String("RelationshipType")) { relationship.relationshipType = attr.value().toString(); } } d->relationships.append(relationship); } else if (value.name() == QLatin1String("FaultTo")) { d->faultEndpoint.setAddress(value.childValues().child(QLatin1String("Address")).value().toString()); } else if (value.name() == QLatin1String("ReferenceParameters")) { d->referenceParameters = value.childValues(); } else if (value.name() == QLatin1String("Metadata")) { d->metadata = value.childValues(); } } QDebug operator<<(QDebug dbg, const KDSoapMessageAddressingProperties &msg) { dbg << msg.action() << msg.destination() << msg.sourceEndpoint().address() << msg.replyEndpoint().address() << msg.faultEndpoint().address() << msg.messageID(); return dbg; }