I agree, this is a bug. I've raised a JIRA and will get that fixed: https://issues.apache.org/jira/browse/QPID-3492
Hi all,
For everyone who's been following this thread and have been bitten by this issue, in lieu of a patch to the AddressParser itself the following code just might help you out. It's a basic "client side" code block that, in essence, "repairs" an Address created by the broken AddressParser by working its way through the various Address blocks until it gets to the x-bindings arguments block it then iterates through each argument explicitly setting the encoding of VAR_STRING valued arguments to utf8.

My C++ is somewhat rusty so there might well be more elegant/succinct ways to find the arguments block, feel free to post back something nicer, but the code below seems a fair starter for ten. I've tried it with a basic Java producer and the "repaired" bindings match nicely.

Hope this is some use,
Frase.


/*
// Example Usage:
string address = "testqueue; {create: receiver, node: {x-declare: {arguments: {'qpid.policy_type': ring, 'qpid.max_size': 500000000}}, x-bindings: [{exchange: 'amq.match', queue: 'testqueue', key: 'data1', arguments: {x-match: all, data-service: amqp-delivery, item-owner: fadams}}]}}";

   Address addr(address);
   addr = utf8EncodeAddress(addr);

   Connection connection(broker, connectionOptions);
   try {
       connection.open();
       Session session = connection.createSession();
       Receiver receiver = session.createReceiver(addr);
       receiver.setCapacity(100); // Enable receiver prefetch

......etc.....

*/


/*
There is a bug in the Qpid C++ AddressParser code up to at least version 0.12 whereby strings values get encoded as raw binary values as opposed to UTF8. In many circumstances this doesn't cause significant problems, however for the case of bindings to the headers exchange it has the potential to create a serious interoperability problem as Java producers in particular will certainly set header strings as UTF8 Java Strings.

These methods "repair" an Address by re-encoding x-bindings argument values as UTF8 strings so that they work in an interoperable way with the Headers exchange. Note well the use of references as we're changing the
   underlying Address passed to the method.
*/


/*
This method looks for the "x-bindings" Map within a "node" or "link" block and if one is found it then iterates through the bindings. For each binding that is found the "arguments" Map is looked up and if an "arguments" Map is found the method iterates though each argument explicitly setting the encoding
   of VAR_STRING valued arguments to utf8.
*/
void utf8EncodeBlock(Variant::Map& block) {
   Variant::Map::iterator i = block.find("x-bindings");
   if (i != block.end()) {
       Variant::List& bindings = i->second.asList();
for (Variant::List::iterator li = bindings.begin(); li != bindings.end(); li++) {
           Variant::Map& binding = li->asMap();
           i = binding.find("arguments");
           if (i != binding.end()) {
               Variant::Map& arguments = i->second.asMap();
               for (i = arguments.begin(); i != arguments.end(); i++) {
                   if (i->second.getType() == VAR_STRING) {
                       i->second.setEncoding("utf8");
                   }
               }
           }
       }
   }
}

/*
This method extracts the "node" and "link" Maps from the options part of the Address and passes references to them to the utf8EncodeBlock method in order to repair the contents of the block.
*/
Address& utf8EncodeAddress(Address& addr) {
   Variant::Map& options = addr.getOptions();
   Variant::Map::iterator i = options.find("node");
   if (i != options.end()) {
       utf8EncodeBlock(i->second.asMap());
   }

   i = options.find("link");
   if (i != options.end()) {
       utf8EncodeBlock(i->second.asMap());
   }
   return addr;
}




---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:users-subscr...@qpid.apache.org

Reply via email to