Modo corretto per decodificare la risposta nel client Java Dojo cometd
Domanda
Voglio spingere avanti e indietro oggetti Java XMLEncoded arbitrari utilizzando i canali Cometd Dojo e ho un problema a decodificare correttamente il payload.
Per fare ciò ho questo metodo di invio in una versione ridotta del programma dimostrativo del client della chat room:
private void send(String string) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("intArray", new int[] {1});
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLEncoder xmlEncoder = new XMLEncoder(baos);
xmlEncoder.writeObject(map);
xmlEncoder.close();
Map<String, Object> encodedMap = new HashMap<String, Object>();
try {
String encoded = baos.toString("UTF-8");
encodedMap.put("xmlpayload", encoded);
} catch (Exception e) {
throw new RuntimeException("could not use UTF-8", e);
}
bayreuxClient.publish("/prototype/a", encodedMap, String.valueOf(System.currentTimeMillis()));
}
Che per ora crea uno snippet XML appiattito in un flusso di byte codificato UTF-8 (sono consapevole che devo occuparmi anche della codifica, ma non è questo il problema ora).
Il listener di messaggi che accetta questo aspetto è simile a:
listener = new MessageListener() {
@Override
public void deliver(Client fromClient, Client toClient, Message msg) {
if (!_connected) {
_connected = true;
synchronized (this) {
this.notify();
}
}
Object data = msg.getData();
if (data instanceof Map) {
Map map = (Map) data;
Object rawPayload = map.get("xmlpayload");
if (rawPayload instanceof String) {
System.out.println("xmlpayload = " + rawPayload);
ByteArrayInputStream bais;
try {
String xmlPayload = ((String) rawPayload).replaceAll(">",">").replaceAll("<", "<").replaceAll("&","&");
bais = new ByteArrayInputStream(xmlPayload.getBytes("UTF-8"));
XMLDecoder xmlDecoder = new XMLDecoder(bais);
Object o = xmlDecoder.readObject();
xmlDecoder.close();
System.out.println(">> decoded payload=" + o + ", class=" + o.getClass());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("no UTF-8", e);
}
}
}
}
};
address = new Address("localhost", 8080);
bayreuxClient = new BayeuxClient(httpClient, address, "/cometd/cometd");
bayreuxClient.addListener(listener);
Come puoi vedere, ho scoperto per tentativi ed errori che la stringa inviata ha i caratteri minore di, maggiore di e e commerciale protetti che quindi sprotetto e chiamo XMLDecode.
L'output è:
xmlpayload = <?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0_16" class="java.beans.XMLDecoder">
<object class="java.util.HashMap">
<void method="put">
<string>intArray</string>
<array class="int" length="1">
<void index="0">
<int>1</int>
</void>
</array>
</void>
</object>
</java>
>> decoded payload={intArray=[I@2f1e75}, class=class java.util.HashMap
quindi è reversibile.I miei esperimenti con l'inserimento di questi caratteri all'interno di oggetti stringa XMLEncoded/XMLDecoded non sono stati buoni - non erano doppiamente protetti - quindi anche la mia decodifica bruta li ha influenzati.
La domanda è:Quale è corretto modo per decodificare queste stringhe?Esiste una libreria JSON che devo utilizzare al posto del mio codice veloce e sporco?Potrei aver riscontrato un errore nella libreria client Java per cometd?
(Nota:Per questo esperimento ho utilizzato le librerie cometd-1.0.0rc0).
MODIFICARE:Si è scoperto che la comunicazione è avvenuta tramite un'altra implementazione nello stesso server web di quella I Pensiero si è occupato delle comunicazioni della cometa, e Quello la distribuzione conteneva filter.json che eseguiva la protezione XML.
http://groups.google.com/group/cometd-users/browse_thread/thread/6fbdaae669e5f9d3
In altre parole un problema di configurazione esterno al mio codice.Si spera che una distribuzione rivista risolva questo problema.
Soluzione
La migliore libreria da utilizzare per evitare l'escape di XML è Apache Commons Lang,
StringEscapeUtils.unescapeXml();
Sembra che questo sia un bug nel client Java Bayeux che usi.La sua codifica/decodifica non è simmetrica.Lo avrei usato.Adesso ci penserò due volte :)