java - Serializing RPC-GWT -
i'm wondering if there's method serialized string "string table".
what need, post data in web page form. sends when manually:
7|0|48|https://aps2.senasa.gov.ar/embalaje-madera-web/embalajeapp/|03152a2debabdce5d33bf4c88511dd1e|net.customware.gwt.dispatch.client.standard.standarddispatchservice|execute|net.customware.gwt.dispatch.shared.action|gov.senasa.embalajemadera.shared.rpc.actions.ingresardeclaracionjuradaaction/2514804035|gov.senasa.embalajemadera.shared.domain.declaracionjurada/1628723960|java.util.arraylist/4159755760|gov.senasa.embalajemadera.shared.domain.tipoembalajecantidad/4152068152|java.lang.integer/3438268394|pallet|gov.senasa.embalajemadera.shared.domain.tipoembalaje/309031988|java.util.hashset/3273092938|gov.senasa.embalajemadera.shared.domain.contenedor/1178264080|nro contenedor 1|java.lang.boolean/476441737|gov.senasa.embalajemadera.shared.domain.despachante/3149599025|desp||java.lang.long/4227064769|treyes 8978 - capital federal|gonzalo@rsystem.com.ar|spina gonzalo|45510141|direccion destino|direccion exportador|java.util.date/3385151746|chasis/|gov.senasa.embalajemadera.shared.domain.importadorexportador/918958990|gonzalo@gmail.com|46326066|gov.senasa.embalajemadera.shared.domain.datoaduana/2671264783|nrodespacho|ic01|gov.senasa.embalajemadera.shared.domain.lugardearribo/3008903128|nromaniimpo|gov.senasa.embalajemadera.shared.domain.puntoingreso/1183502123|717.3|aduana origen|terrestre camion|merca|gov.senasa.embalajemadera.shared.domain.pais/3238585366|australia|afghanistan|nombre exportador|gov.senasa.embalajemadera.shared.domain.transportepatente/1923027028|acoplado|chasis|1|2|3|4|1|5|6|7|0|0|8|1|9|0|10|1|10|0|11|0|12|0|0|11|10|126951|0|0|0|0|0|13|1|14|0|0|15|16|1|17|0|18|0|19|20|zrcraa|21|22|19|0|0|23|24|0|0|0|0|0|25|26|0|0|27|vntkm$a|0|0|0|0|0|0|0|28|-11|29|0|0|19|-13|21|30|0|0|0|23|31|0|0|0|0|0|0|8|1|32|0|16|0|-18|0|0|-2|0|0|33|0|0|0|27|vntkm$a|0|34|35|0|0|0|10|24754701|0|-18|36|19|37|0|38|0|0|0|0|0|0|0|-20|39|40|41|0|0|0|42|0|43|10|10|42|0|44|10|1|0|-22|-5|45|0|0|0|-18|8|1|46|0|0|0|19|47|48|0|0|0|0|0|0|0|0|0|
i've read this see, little more complex example in documentation. not being able build payload. need method compatible vb6 or php, or explanation can make own routine. thanks
edit: answered deserialization (which may still need if going results from server), asked serialization. first part still deserialization of request, below break, i'll show how serialize request, again limited of information have in question
request deserialization
it may bigger example in document, same rules apply. request one, break down follows, splitting on | character.
7
version 7.
0
no flags set.
48
the next 48 tokens string table, build array out of them. strings represent types of data being passed, actual java strings.
so read strings string[48], , remaining numbers either references or primitives. data zrcraa , vntkm$a base64 encoded long. treat list of strings, , we'll use when start requesting object data.
as document says, read second list, references (starts 1|2|3|4|1|5|6|7|0|0|8...). continue deserialize, need 4 more things: url of app, strong name of policy, service class invoke, , method name in service class.
since these string objects, we'll read strings. in com.google.gwt.user.server.rpc.impl.serverserializationstreamreader, actual java class read this, see readstring() looks this:
@override public string readstring() throws serializationexception { return getstring(readint()); } so first read int, use find string. here's getstring:
@override protected string getstring(int index) { if (index == 0) { return null; } // index 1-based assert (index > 0); assert (index <= stringtable.length); return stringtable[index - 1]; } now, our first piece of data base url, read string. see 1 int read, (1 - 1)th string in string[48] created above:
the strong policy name next, 2, read as
03152a2debabdce5d33bf4c88511dd1e
the server use , find file named 03152a2debabdce5d33bf4c88511dd1e.gwt.rpc, outlining security policy of can created on server (so prohibit hacker creating kind of objects on server).
next service class, 3:
net.customware.gwt.dispatch.client.standard.standarddispatchservice
and method invoke, 4:
execute
from here, need know standarddispatchservice.execute - know takes 1 argument, action instance, since see 1 indicating 1 argument, 5, if decoded object means read 5th string (take @ how readobject works see why). without knowing fields action or other classes have (listed below), can't guess happens next certainty:
- net.customware.gwt.dispatch.shared.action
- gov.senasa.embalajemadera.shared.rpc.actions.ingresardeclaracionjuradaaction
- gov.senasa.embalajemadera.shared.domain.declaracionjurada
- gov.senasa.embalajemadera.shared.domain.tipoembalajecantidad
- gov.senasa.embalajemadera.shared.domain.tipoembalaje
- gov.senasa.embalajemadera.shared.domain.contenedor
- gov.senasa.embalajemadera.shared.domain.despachante
(please note i'm guessing these serializable classes package , name - plain strings decided send on wire part of request!)
request serialization
we've covered lot of basics in trying take apart message, lets try put together. class in gwt client code manages com.google.gwt.user.client.rpc.impl.clientserializationstreamwriter. methods preparetowrite() , tostring() set stage bit, showing first , last things we'll around our work:
/** * call method before attempting append tokens. method * implementation <b>must</b> called overridden version. */ @override public void preparetowrite() { super.preparetowrite(); encodebuffer = new stringbuilder(); // write serialization policy info writestring(modulebaseurl); writestring(serializationpolicystrongname); } @override public string tostring() { stringbuilder buffer = new stringbuilder(); writeheader(buffer); writestringtable(buffer); writepayload(buffer); return buffer.tostring(); } the preparetowrite() method starts off stream adding 2 strings - module base url, , policy strong name, strings recognize deserialization process. tostring() method shows 3 stages write out: header, string table, , "payload", or object references , primitive values.
why have strings tracked differently other leaf values? way have strings in 1 places, can refer them more once , send them each single time. contrast xml or json every time want use value, have write value again, if same.
the header consists of version (latest 7), , flags set (in sample, 0 do).
in superclass abstractserializationstreamwriter, there 4 fields:
private int objectcount; private map<object, integer> objectmap = new identityhashmap<object, integer>(); private map<string, integer> stringmap = new hashmap<string, integer>(); private list<string> stringtable = new arraylist<string>(); the first current index of each object - we'll use keep track of objects we've seen before. next objectmap, can examine each object , check if we've seen before, , if so, where, can write reference position. stringmap field same thing strings - js treats string keys specially. finally, stringtable itself, list of strings we've seen, each added once.
if take apart compiled application's generated java service method list<string> filterstrings(list<string> strings, string startswith), you'll see this:
clientserializationstreamwriter streamwriter = ...;//create serializer streamwriter.preparetowrite(); streamwriter.writestring("com.acme.project.shared.myservice");//service interface streamwriter.writestring("filterstrings");//method name streamwriter.writeint(2);//number of arguments found in stream streamwriter.writeobject(strings); streamwriter.writestring(startswith); knowing written each method depends on knowing method signature in java - compiled gwt js , payload sample, difficult reverse engineer. lets carry on , see happen next.
the implementation of writeobject takes object , first notes type. if object null, write null string (a.k.a. 0) , done. otherwise check if have written object before (and write negative number see go in payload), or need how write rest of object, , serialize each field.
each object can serialized must have fieldserializer, describes how encode , decode object. there many customfieldserializers in gwt, custom implementations specific purpose, tell rpc not automatically generate serializer. 1 example might arraylist, if had passed in - arraylist_customfieldserializer delegates collection_customfieldserializerbase, this:
public static void serialize(serializationstreamwriter streamwriter, collection instance) throws serializationexception { int size = instance.size(); streamwriter.writeint(size); (object obj : instance) { streamwriter.writeobject(obj); } } first write size of list, deserializer knows how many elements read, , write each item in list. in our case, we'll write these strings. then, we'll write 1 more string, second argument method.
so, have data in our string table:
- baseurl
- policy string name
- "com.acme.project.shared.myservice"
- "filterstrings"
- "java.util.arraylist"
- "java.lang.string"
- each string in argument
strings, , stringstartswith, though since don't know if there duplicates, can't know if there going same number of strings.
in our payload lets called filterstrings(["a", "ab", "abc", "a"], "ab"), we'll have references 1 (baseurl string index), 2 (policy strong name string index), 3 (service name string index), 4 (method name string index), 2 (int number of fields expect), 5 (class name of strings list argument), 4 (number of items in list), 6 (type of first item in list, string), 7 (contents of "a"), 6 (string type), 8 (contents of "ab"), 6 (string type), 9 (contents of "abc"), 6 (string type), 7 (contents of "a"), 6 (string type of second argument), , 8 (contents of "ab" again).
how classes action, declaracionjurada, etc? without knowing fields there , order happen in, can't sure. there no way payload reconstruct contents, though if debug running app before payload sent, observe structure of object serialized, , use decide you've found in stream. observe there several negative numbers in sample stream, suggesting either negative values important use case, or there references , isn't simple object tree, full graph, make things more complicated.
the rpc serialization format not complicated - highly encourage reading code in various com.google.gwt.user.client.rpc.impl.abstractserializationstreamreader subclasses understand does. there, should able parse out these 2 lists of values (strings , references/primitives) actual objects, plus structure of of classes might sent on wire, , reimplement in language or framework.
Comments
Post a Comment