X-CGP-ClamAV-Result: CLEAN X-VirusScanner: Niversoft's CGPClamav Helper v1.22.2a (ClamAV engine v0.102.2) X-Junk-Score: 0 [] X-KAS-Score: 0 [] From: "Dennis Bliefernicht" Received: from outgoing.xyrality.com ([80.239.144.202] verified) by post.selbstdenker.com (CommuniGate Pro SMTP 6.3.3) with ESMTPS id 26091115 for webobjects-dev@wocommunity.org; Wed, 30 Jun 2021 11:56:56 +0200 Received-SPF: pass receiver=post.selbstdenker.com; client-ip=80.239.144.202; envelope-from=dennis.bliefernicht@xyrality.com Received: from [192.168.178.27] ( [46.94.24.107]) by outgoing.xyrality.com (Reddoxx engine) with SMTP-TLS id EA3F9AADE1; Wed, 30 Jun 2021 12:00:32 +0200 User-Agent: Microsoft-MacOutlook/16.50.21061301 Date: Wed, 30 Jun 2021 11:56:32 +0200 Subject: Re: [WO-DEV] change toString for some classes? To: WebObjects & WOnder Development Message-ID: <8D1F4F21-2B86-45D2-856F-B2A97E774501@xyrality.com> Thread-Topic: [WO-DEV] change toString for some classes? References: In-Reply-To: Mime-version: 1.0 Content-type: multipart/mixed; boundary="B_3707898994_2060976063" > This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. --B_3707898994_2060976063 Content-type: multipart/related; boundary="B_3707898994_1525746681" --B_3707898994_1525746681 Content-type: multipart/alternative; boundary="B_3707898994_588297185" --B_3707898994_588297185 Content-type: text/plain; charset="UTF-8" Content-transfer-encoding: quoted-printable Hi, =20 is there some Wonder (or NS- or Java-level) trick to =E2=80=9Coverride=E2=80=9D (for th= e original class; in ObjC I would simply swizzle the method) toString for so= me classes? Namely, in my current application, I would need that =20 there are some ways in Java to do this kind of thing, Javassist is somethin= g we still use in an older codebase, there is also ByteBuddy which tries to = wrap everything in a=C2=A0 neat API. One important thing is that you need to do = this _very_ early in your application, before the relevant classes are loade= d (because this hooks into the class loading mechanism, once the class is lo= aded, you can=E2=80=99t modify it that easily anymore). In fact we do this basical= ly first thing in the main method. I don=E2=80=99t have any snippets at hand for B= yteBuddy, but below is an outline, how we replaced some methods with Javassi= st. Basically we prepend the method with =E2=80=9Creturn ApplicationUtility.myRepl= acementMethod(this)=E2=80=9D which makes it easy enough to just code up the replac= ement method as usual. =20 Performancewise this seems to be fine, in our case we had to replace a .has= hCode() deep in WO, because performance monitoring revealed that our data mo= delling resulted in wildly bad behaviour of EO objects in HashMaps and after= the fix we got good improvements. So I assume generally the JIT compiler wi= ll smooth out any extra redirections. =20 Hope that helps && Greetings Dennis =20 import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtMethod; import javassist.LoaderClassPath; =20 public class ApplicationUtility { =C2=A0=C2=A0=C2=A0=C2=A0 public static int myReplacementMethod(final NSTimestamp object) { =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // do your magic =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return "TODO"; =C2=A0=C2=A0=C2=A0=C2=A0 } =20 =C2=A0=C2=A0=C2=A0=C2=A0 public static void patchClasses() { =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try { =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 final ClassPool classPool =3D ClassPool.getDef= ault(); =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 classPool.appendClassPath(new LoaderClassPat= h(Thread.currentThread().getContextClassLoader())); =20 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 final CtClass classToPatch =3D classPool.get("= com.webobjects.foundation.NSTimestamp"); =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 final CtMethod toStringMethod =3D classToPatch= .getDeclaredMethod("toString"); =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 toStringMethod.insertBefore("{ return " + Ap= plicationUtility.class.getName() + ".myReplacementMethod(this); }"); =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 classToPatch.toClass(); =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 } catch (Exception e) { =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // TODO: error handling, probably logging an= d exit =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 } =C2=A0=C2=A0=C2=A0=C2=A0 } } =20 =20 =20 --=20 ----------------------------------------------------- Dennis Bliefernicht =E2=80=A2 Head of Backend Development T +49 40 357 3001 62 dennis.bliefernicht@xyrality.com =20 XYRALITY GmbH =E2=80=A2 Friedensallee 290 =E2=80=A2 22763 Hamburg www.xyrality.com Registergericht: Hamburg HRB 115332 Gesch=C3=A4ftsf=C3=BChrer: Sven Ossenbr=C3=BCggen ----------------------------------------------------- =20 =20 --B_3707898994_588297185 Content-type: text/html; charset="UTF-8" Content-transfer-encoding: quoted-printable

Hi,

 

is there some Wonder (or NS- or Java-l= evel) trick to =E2=80=9Coverride=E2=80=9D (for the original class; in ObjC I would simpl= y swizzle the method) toString for some classes? Namely, in my c= urrent application, I would need that

 

there are some w= ays in Java to do this kind of thing, Javassist is something we still use in= an older codebase, there is also ByteBuddy which tries to wrap everything i= n a=C2=A0 neat API. One important thing is that you need to do this _very= _ early in your application, before the relevant classes are loaded (because= this hooks into the class loading mechanism, once the class is loaded, you = can=E2=80=99t modify it that easily anymore). In fact we do this basically first t= hing in the main method. I don=E2=80=99t have any snippets at hand for Byte= Buddy, but below is an outline, how we replaced some methods with Javassist.= Basically we prepend the method with =E2=80=9Creturn ApplicationUtility.myReplace= mentMethod(this)=E2=80=9D which makes it easy enough to just code up the replaceme= nt method as usual.

 

Performancewise this seems to be fine, in our case we had t= o replace a .hashCode() deep in WO, because performance monitoring revealed = that our data modelling resulted in wildly bad behaviour of EO objects in Ha= shMaps and after the fix we got good improvements. So I assume generally the= JIT compiler will smooth out any extra redirections.

 

Hope that helps &&= ; Greetings

Dennis

 

import javassist.ClassPool;

import javassist.CtCl= ass;

import javassist.CtConstructor;

import javassist.= CtMethod;

import javassist.LoaderClassPath;=

 = ;

public class ApplicationUtility {

=C2=A0=C2=A0=C2=A0=C2=A0 public static = int myReplacementMethod(final NSTimestamp object) {

=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0 // do your magic

=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return "TODO&q= uot;;

=C2=A0=C2=A0=C2=A0=C2=A0 }

<= span style=3D'font-family:"Courier New"'> 

=C2=A0=C2=A0=C2=A0=C2=A0 public sta= tic void patchClasses() {

=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try {

=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 final ClassPool classPool =3D ClassPool.getDefau= lt();

=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 classPool.appendClassPath(ne= w LoaderClassPath(Thread.currentThread().getContextClassLoader()));

=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 final CtClass classToPat= ch =3D classPool.get("com.webobjects.foundation.NSTimestamp");<= /o:p>

=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 final CtMethod toStringMethod =3D classTo= Patch.getDeclaredMethod("toString");

=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 toStringMethod.insertBefore("{ return " + Application= Utility.class.getName() + ".myReplacementMethod(this); }");

=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 classToPatch.toClass();

=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 } catch (Exception e) {

=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 // TODO: error handling, probably logging and exit

=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }

=C2=A0=C2=A0=C2=A0=C2=A0 }

}

<= p class=3DMsoNormal> 

 <= /p>

 

-- 

3D"signature_2094861619"
-----------------------------------= ------------------
Dennis Bliefernicht =E2=80=A2 Head of Backend Development

T +49 40 357 3001 62<= /span>

dennis.bliefernicht@xyrality.com

 

XYRALITY Gmb= H =E2=80=A2 Friedensallee 290 =E2=80=A2 22763 Hamburg

=

www.xyrality.com

Registergericht: Hamburg HRB 115332
Gesch=C3=A4ftsf=C3=BChrer: Sven Ossen= br=C3=BCggen

------------------------------------= -----------------

=  

 =

--B_3707898994_588297185-- --B_3707898994_1525746681 Content-type: image/png; name="image001.png"; x-mac-creator="4F50494D"; x-mac-type="504E4766" Content-ID: Content-disposition: inline; filename="image001.png" Content-transfer-encoding: base64 iVBORw0KGgoAAAANSUhEUgAAAKAAAAAnCAYAAACIekNNAAAAGXRFWHRTb2Z0d2FyZQBBZG9i ZSBJbWFnZVJlYWR5ccllPAAAA+VpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1l dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUu Ni1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpS REYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgt bnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6 Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRv YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxl bWVudHMvMS4xLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ1dWlkOjhFRjJFRTE5Qzk5 NTExREZBQjAzQzAzNUM4NDg2QkM1IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjE4REQ5 Q0EyMkEwQjExRTU5MUNERjc0QTdGQjBBNEE4IiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlk OjE4REQ5Q0ExMkEwQjExRTU5MUNERjc0QTdGQjBBNEE4IiB4bXA6Q3JlYXRvclRvb2w9IkFk b2JlIElsbHVzdHJhdG9yIENTNS4xIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3Rh bmNlSUQ9InhtcC5paWQ6M0UwMjgyMTMyN0JGMTFFNUI4MTVGQTAxNkZFQTQyQ0IiIHN0UmVm OmRvY3VtZW50SUQ9InhtcC5kaWQ6M0UwMjgyMTQyN0JGMTFFNUI4MTVGQTAxNkZFQTQyQ0Ii Lz4gPGRjOnRpdGxlPiA8cmRmOkFsdD4gPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij54 eXJhbGl0eTU8L3JkZjpsaT4gPC9yZGY6QWx0PiA8L2RjOnRpdGxlPiA8L3JkZjpEZXNjcmlw dGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnbW5A0A AArpSURBVHja7FwJtFZTFD7/e39FyYtQhFKZp7KSQoaEl4S0zFMsFBUyZIjCy6JoWmUqmVaG 0NMzJWM8ZSjzShNNRCUp1evl9b/f/tb97uq6nXOH/97nedy91veG+597/nP22WefvffZ56QW fq82KKWuFjyl/OlzwRTB7QHKtha8L2gvmONTdhfBbMGlgtcC1H2ZYLxPmemCgYL3VDy0vWCu 4DrBCxHrekOwRHCVio+OE7woOEiwIkD55wXnhKgf/Dzap8xtgovYhoxP2W6CCWn58a3gRvzj 81JHwWGCAQEbvIT13USB8aJeggYUwiC0mwATp59gs+uzlGBXQXfBO4K+ggdjGOA2rLcwBgFs JNio4iXwbydBvYDlhwumup41ERQJHhB85+LpogB1fiy4R3CqoMSn7M2oMyUasB1fPEvwkk/l +YK2IZhyvWCYoLlHB8C4nwSPC64JWC80W28OpInAtCGcAJ0E70YcYAzKDZxY+wnKI9Q1U7CY PI+LThdM9uG1H+0hWMoxnpljHR8IGgoOFmQNZU4UvCXonCc/PuGyejcHTUfHCCCod4RszFjB GsGtHmWw/NcVDA1Rb5ZtreVTpj8Zea9H34IQ+HQKV4smXAn+i7Qdf9eLUAdk5EDyy0SDOS5v 5vHBXYL9qTp1BOH8RqOy/Wg9tdDlnF1uqk8hGUctWBX0sOBwH23pR/uRP2Duz4KuKiETfUil VmT4/Fhq2IH2zAZ9Kig1vHQEXxoYQQA2UNDcdIWggBqqqmgpfxdEqKOQS+4bXGJOT+TMVwu2 punjpiKuJFOdAmjbVYcKTtJov3mCV3NszFraT3A0Gjue16XX9CTtoaqilGNJzpXOFHwkqCAf oA2bJXJmpHcYMXErNEREOlBAs24BnCb4zPXSYRTIQYLKCA0azcG7wfHsUhqrg//lzGzIVaDY YWRnaEgn5K0F29F/cCqzuU5llqfxLttyyQXdSY9qUsTGrBaMYEhkB3rTiCU+K/ihihnRgrPt 9xzfBwPT9NpAKwWzqBUTMtMULrVFDmXWiTJWaRLAqXQ2BtDw7koHZXMMDRrJ5RB2X3cux0VV zIQUhR6G8a851oGA6QLXRHmZglk/kTNPup18aiW4hTwsdhZIG1RnCbUeXngupsZAAEZRuOGU TKQ6zlWwslzWTYRQwhiGBNrl+D216IA87XoOZ+Q+1vt2ImdGwq7WVxzrvQUXKtdmR9rw0gzB kYJLBH/G2KDhdEZ2jaj9Kqh9Bmu0c4Z2G4K82OK7gF5+LgSnbGfBK67n2CVYRm84EUAzVdLu K+ZyvNUOUtrw0kIK4PyYG7RcWfvDiAnOjlAPhGwbQQ+NcwShq6OsIPiICFoW1EXwB20+9/dD CyJuek1EB+3/YAuupxBuZcrlaV6Aqjybf99cBQ3apKJtYykK2G/K2nZq6kJHlnkqovDZ9h+S Gco0n03m9+2byJgn2aaS1lzSCeAA2msw3s9QVkAxbscgFVPHMvztBMwHxC37R6y/CZfgYsPn 0zmZChMZ8x1vZRpztwA2pd03nAb8jwzF/Fspz/D8ES6PUbbfbE1qSudCgP2jJBwT7wDCVV6n tuTaIQRzGj3JmkTPc8ZFyTY5k7bfMo8y8O6OoNOTUEQBRI7dlYL7ObtBz9BxGFjD+rWcTkKv HN+vSw1YSi3a2IA5DNV0SEQpugDeROdgjONZOUMdZ9M5qUn0EDV3qxzeRdQeGdD9qAF/MuB9 lj85EaXcyA7DINbVm9rPvWX1BO3AAQx71BRCAiq2zZAK1ifkuzA7kMfYU3knMeAzBFe7MhxT kYhUbgLYl8wcqSmDEATSpYZREBfXkL4hgP4khai/IZRi8trg/WNbMkjq/SpqwkOUlQGSUMgl uCGXmtHKvF86jnbhLTWsf9DeBSFDJc1pbhQHLA9HBVuLXUKGJrKJ+FkCiJy82tRwJoJnPJRO yp4RvzOOOGDQOhCIRur31SHq7qys+OK0gOXXs2y3EP2C8CGY3sAHBSHq9Iy3/YN1hBovCCAO Dj0q+CWAUY9l7YoYhD4dQ6dqB9QiaPcJ6u/JsH723xe0H4PSJDo7Owcsv5Hf80sAXBmwTns7 MBOBpxnHBImLsowUZE02YPeAs30NB3JtxAbBjqwXsQ5ss2HHI0ia2ETaaUHzAQdRq4Whl/gd awKWx6THDlN+QGcqCJXSGVoWga+LODHitGU3cXWYp1WNC79P7JCEqtcGTCihRAAT+n9SOpVK mJBQNQpgfn7ChISqUQDHPpaksyVUjQI4b16jhAsJVZ8A1q69GZF/BF51d8qdp6zD6s4jicgS 3ktZKeluQno6ArITXY4OklxxsOc3zTv4bHe15cKh15V1kspNyO1ryb8REH9Tmc+VHK+sdCoY GLiaA/mBuhgd7ozBmQ93jAqZMDhO6LyrsDH7rrsfB/fsteDf6AP2hmeEGAe0A5lH3/L/o5R1 ltq+VxH38iE5eInm3WaCc5V13hrxS5xo/MbwPai3A9uIoDPifaY4Iy4XQmxxnUe7cTAMGxPb KismiwwhHFk17bt35Njksy8vQDh6KCsTWkc4E+K+jPJ+Zd4NOUBZxzidahWHm3D1mi5pExFy XGg4l0L3pUFIQeez0bM4GNg61F14hGvBrqOAvsxnpnthcOtDG83zck6MZo5nFzmEzE0Xs012 H1aEVATgTU/H/0j+6O0QaOQ16g4+tSRvl7OvENiRFDQd4RQfNh+wPYmTfcjgMd3wcBmF2ovA /0IqMNS3j7L237fRlEWyxrXKOqQ0mf0qSFNaTds3aCg25nGMEttCOKyOK7w+NpQvp4Agf3A0 n3WjNsg3hIHAvCA3L0AwcQOonfLUjh3+0VUOTNtAzV2hvO+526T0KVR/klHdKejY9kOOYB+P thXze3MhXPeBq0rqUNMuolZJU+jXavqp+A4EcILjGcYJKWjTDf2d6uBJfU5A3dHSMuV/2i+f Qj+F/+PKDRyHaK+25EratCP5M5M8/0wp/z1ZLE9vUcWP4JIMRu9iKF+XQtKKg7YXG1lK5roJ ahuZ2OM46JgV2Jf+WlMW23fYF/2ddTUzLDVgPNLkx7P98/l3WOGAyWAn53bgUm7SzkgceJDf gT7gIPsnIb5rI7V7KwocltH9qc1b24Nl0JxfuJ7NVuZ7E7OcVC35N8yaoSp3ympkaIHS77vj /Exbx7hg1XvCTwDrUSBwWwKyYJpQxffymBHLONM6cUku8VDzKL+KTLAFZLWhbB5V++6cCLBR dOljGZoJdWhanMf2h00lW0WbBkw7wbGc6wi21yjH0rsmh8HE4afO1HzDqPVOoeYYZXgno7be V99WeW8w1KGNC23eN+RECULbKf2x280cZ3tcoNSK8pR36k0th931NFXtH8q8iZ6iFnyWncMM nqa23LypK4+G4SD8z4TpzDAEdCw7UUItp6PGtEE3UfuVeGhsv7SuibSBCzy0kOJStdjRh7Ic Bq6Ukxb3PK+kmVNI7brU452eLo13lWEFsSfxJCqVQcr7LIs9NsqnjDPLpQWX31kBxgXLdaM0 1b/JBiyj1plMo/R1akITgysc2mM1DfIsv7TSUL4BDVe7sxOU/ihkOWf7OtoZQ2gelGkM82up HTNs75CQNqDTBrav5qj00SoPsS155FdJSAHcwOXrKwfv5xsiAs4JcjC9/BXUltC+/TxsdFtY odG70I7W3YCR5mpnmxVjNdpyHT348ex3A/JBZ6/uTafHHhesZMP+EmAAdouWkMBjIjAAAAAA SUVORK5CYIIA --B_3707898994_1525746681-- --B_3707898994_2060976063--