From 687fbb72ed2f716332e4ff08229b8566e31d4f91 Mon Sep 17 00:00:00 2001 From: benni Date: Wed, 12 Dec 2012 14:56:28 +0100 Subject: [PATCH] release of 1.0.5.RC --- README.md | 18 +++++- .../mbassador/1.0.5.RC/mbassador-1.0.5.RC.jar | Bin 0 -> 42152 bytes .../1.0.5.RC/mbassador-1.0.5.RC.jar.md5 | 1 + .../1.0.5.RC/mbassador-1.0.5.RC.jar.sha1 | 1 + .../mbassador/1.0.5.RC/mbassador-1.0.5.RC.pom | 58 ++++++++++++++++++ .../1.0.5.RC/mbassador-1.0.5.RC.pom.md5 | 1 + .../1.0.5.RC/mbassador-1.0.5.RC.pom.sha1 | 1 + maven/org/mbassy/mbassador/maven-metadata.xml | 3 +- .../mbassy/mbassador/maven-metadata.xml.md5 | 2 +- .../mbassy/mbassador/maven-metadata.xml.sha1 | 2 +- pom.xml | 2 +- .../java/org/mbassy/AbstractMessageBus.java | 31 ++++------ .../java/org/mbassy/BusConfiguration.java | 14 ++++- .../dispatch/EnvelopedMessageDispatcher.java | 34 ++++++++++ .../java/org/mbassy/listener/Enveloped.java | 23 +++++++ .../java/org/mbassy/listener/Filters.java | 38 ++++++++++++ .../org/mbassy/listener/IMessageFilter.java | 31 ---------- .../listener/MessageHandlerMetadata.java | 22 ++++++- .../org/mbassy/listener/MetadataReader.java | 53 ++++++++++++---- .../mbassy/subscription/MessageEnvelope.java | 27 ++++++++ .../subscription/SubscriptionFactory.java | 3 + src/test/java/org/mbassy/FilterTest.java | 3 +- src/test/java/org/mbassy/MBassadorTest.java | 11 +++- .../java/org/mbassy/events/TestEvent2.java | 15 +++++ .../mbassy/listeners/EventingTestBean.java | 7 +-- .../mbassy/listeners/MultiEventHandler.java | 44 +++++++++++++ 26 files changed, 362 insertions(+), 83 deletions(-) create mode 100644 maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.jar create mode 100644 maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.jar.md5 create mode 100644 maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.jar.sha1 create mode 100644 maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.pom create mode 100644 maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.pom.md5 create mode 100644 maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.pom.sha1 create mode 100644 src/main/java/org/mbassy/dispatch/EnvelopedMessageDispatcher.java create mode 100644 src/main/java/org/mbassy/listener/Enveloped.java create mode 100644 src/main/java/org/mbassy/listener/Filters.java create mode 100644 src/main/java/org/mbassy/subscription/MessageEnvelope.java create mode 100644 src/test/java/org/mbassy/events/TestEvent2.java create mode 100644 src/test/java/org/mbassy/listeners/MultiEventHandler.java diff --git a/README.md b/README.md index b503ab8..eff3abf 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Read this documentation to get an overview of its features and how cool this mes You can also check out the performance comparison which also contains a partial list of the features of the compared implementations. -The current version is 1.0.4.RC +The current version is 1.0.5.RC Table of contents: + [Features](#features) @@ -39,6 +39,8 @@ in certain environments where objects are created by frameworks, i.e. spring, gu ignore objects without message handlers and automatically clean-up orphaned weak references after the garbage collector has done its job. + Filtering: Mbassador offers static message filtering. Filters are configured using annotations and multiple filters can be attached to a single message handler ++ Message envelopes: Message handlers can declare to receive an enveloped message. The envelope can wrap around different +types of messages. This allows for a single handler to handle multiple message types + Handler priorities: A listener can be associated with a priority to influence the order of the message delivery + Error handling: Errors during message delivery are sent to an error handler of which a custom implementation can easily be plugged-in. + Ease of Use: Using Mbassador in your project is very easy. Create as many instances of Mbassador as you like (usually a singleton will do), @@ -73,6 +75,20 @@ Listener definition (in any bean): //do something special here } + @Listener(dispatch = Mode.Synchronous, filters = @Filter(Filters.RejectSubtypes.class)) + @Enveloped(messages = {TestEvent.class, TestEvent2.class}) + public void handleSuperTypeEvents(MessageEnvelope envelope) { + if(TestEvent.class.isAssignableFrom(envelope.getMessage().getClass())){ + TestEvent event = envelope.getMessage(); + event.counter.incrementAndGet(); + } + if(envelope.getMessage().getClass().equals(TestEvent2.class)){ + TestEvent2 event = envelope.getMessage(); + event.counter.incrementAndGet(); + } + } + + Creation of message bus and registration of listeners: // create as many instances as necessary diff --git a/maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.jar b/maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.jar new file mode 100644 index 0000000000000000000000000000000000000000..d583821ab7f92bcdf954773be94bc00e236f325e GIT binary patch literal 42152 zcmagF19T*+ugBkJL%YF$F^;D%ntv&-#Ons827#Z9;2%E7`0Z_ zTC>)C<};i?ej^o>ZBqXF8HUnr=;! zP2A~`7sL%jN~cbz4$%LO3kXQT)$Koq5B4=Kdnfb%GjbpxxBr?T>_1!B8W}n}d;VKP zZ1J%FcofQiHZ-=kwY9hVxAyf8|0%h@MDo|G|M_4OOJ@f|7h{Wm>+#=1`L7-}md-Aw zcBW4M*5kk5f%Tv7aCS9vHg>XfaIyTikwF3dHIu5Nz<5zmARq`xARvnW?Dfx?h}hd1 zyE-|U+PNs3x{xx_8{2#dBsxh~9#;Y_Wcvovx+4>Wijyw9S4wt276a5WksK*wfsAfs z1{SJpj)5+-Ow;PBV3Q5{djZEgWY$0 zPEGS$NgwS^s|ANf{S8%1A%{Fx__)e2Vn86vuX^7@SpVozc=HU$yo{A5ZLHJ>sQ%$a zlS~_2L5T%1glP3;YCnyLTPsB?4qhLJQ=?Z%`;ol7Q@ zI;O?BGv3@n<4So%c06YO5GJ1IrG=%*oj+er7d+P@JS|YIZZ~=U-0X95!uq%+U6yts zwruC=zt662(t60pb{!qg-Oa`n(HSoDJTX8_knxO!3GfN64==CR9b`i#YogutHq|y# zzOM@Goq2se;GSe)^sG+7NIP+s`?l|reH44Qg(`bET5pRDHkdj8`{K~K@w{!jRaQ9! zSFs{V<~TJvMQ*w64Gi3mLbmx0ob-7*!QlhBhZ#Bw4!$hHF=y`zh5u-ZB8zX1!hcr! z0jb~?CS3ZEY`~fnG2ZJ}H0coM(S1I=$qfm;b4h?g5DnI`bHT9E53lnTAjhztXO%M$ z{L-y&*&FJKBt^K39E>y)SUb}z@)y>e=(cd6c;Ag0bD5&_Paf30UZU%0@%ae406 zb$H;5iKm~e(zra4w>?p*Ym(M~8V~fsryVUfF2<>omocca$PX>5Kcu3G63Sfie`B4B(u8piWL3}N#V zW=Ne=__B_=s@haEOCqB%77hfCh*T_;wSz*E!dPjMIrp4A<9|jWZZt;=$Ynj7SKJqaZJy5SAM-Fx zQ;pfog)F|8xt0>vJzdUDK;en^`GLR3*Q{&CTe_RLK5nL`dw@;`IQ)M1ngGGK78p|l zaa2o=s0vl7NH_p97vn19rgCNb&r2vWNw0d)IHnGO&rao^h!Eb<=os{?y7h-`}$=xUo{Ua-QAU$cz>tH9xtB1XEHM_ zmb)TC57)Yt5X@|t!1fO;riWbQ)8l;0-GuV+-W&C3R`12P%FdhqSb$S5!-=7&n%#J7 zOeWwcMNP87mm8cI2uhC`@1k3%cXsTX*BN7YU$E``{$%z`Tt-u9K43kI2xnN>GYQqq zsrh~H-jych!j7)L$BwMh^U{Po6K;kx8%ia{baDlLNp?`}+h{3>Em2OYi*nckrVLqw z8LyOuRb;Sta%JL1y9|2+$QZk+-d640Du+%6rNtPv>E08qYCVy3_;|Xg@Xo-CwTLDS zT_Pnco;ojOtuMas;)M-0U1FX8I42J71uQEX@^Su5JO-ySZRMNiYM9sjlFu22@{)3R zy3is9dbkJqIocv-3kmtWaMd7-CAF7=12UsA6HOvC!RZMSCn0sX*62!hv&&}wAPe8V zZf3<=hvvO_E!Lg}b!v>}@m@I*2PY4yJ@!iII|M>rFdp>_2KGuc9|SX}=?>jJ&ImDu zLtdpU+(w_R<$DZXYggzigxr3VzoL#w8N5%(G`tT{6MddobvNrZkp3v$CTpsbvj)zG zmVrF9nE%sIbNGX8Pb2+sxD<8O~qP515 zv8x7QNOw0Em<{@HsW#}N#W6$@jiGfWe>1;1)@zbNWcrU|XJ5V~E$T}$ndCnDb6;_HQxtKDYwllVpOXK|8>S^a*Qh3Y{$ zGoX)4<%W{IpMesiR%udncUA|Map_IvEUEVf!zAkXoD-D9xKjmFniSJ94x3O_(w)L& z8{9ExoI~G{xMMy6xt^VJ3U{P(t8G5xngw;^Q~gi4ZzRY^=$hg?*eGghn{(iTg0)pyW zkW1f|2^{HijCsy~=fbpvqpR?SXb4u(#SNq3pp|Po^+b)0O2~;vUzZ2qM%m&<;+fbC zW9teSYtan+NZjo$5r*URgs-Ftg0w5_9+E4H75*Tr#pdqSbQ-4+(Hcq-3r*J}6X=eK z?*>HOb4B@N3Q=1G#Wu(qE1=X~K$nAw7s@NpT_aWLEI_$f!mqKYNTtGOfXE|CsHOJ7 zPa6FgoSy;MJtLC`Jk08LZ5Q`J#+CTNvQK@Q4Kpju>n(3SlS z6q0u0i8sgyjJJDAsh)aGuoWCWj*zCiBK^m&+N~~FqBX%_2#?YDytS=_(B(cb#&2Pk z;hGJ~{!nItMyI1?0n=BwQ%)b|55V~8Q1kWIgMip38sX+k@$xfoUCi_cz~^y&_W+<@ z{>XGX?pE5kp1l`;%|I2**1)rr{$L=R?z(O^6rP<$A&H3uj(PBzlKE4+lzF)4U*_m9 zvV0Seq+I%ChOWL2;{U5Tl2ULoHL)}{bTR#hE#i5wU*?B^fFOY&aD$+CgRm2aSQ-cj z$dVR^P=wE|9H1-@%=2STsT0no}?6qnA(}R?;J>&D^L-KV2_SNs?7@lgrS!> z@yHU1Lsaj)%@rJ|v`paT0l(z{i?wxM`RJCZ<|orl7&8Uf>cg;D1f?FZ%26AjEU> zMSsP=yd0YU>oot9{)*YTIC=il_Nr;y6!|Ho zO^FpJiKaqIz<$Zv+O$0Dg^F_ng7VEV-eXq@7zL5{zA2e8UU07t@r`nTt0B=APohca ztbgiv7MFAPmCy0S+V{`9VSOMB1%Lt6At}5JZ|A`HA*pPq&5jWYlgi313?fZur^!x) zzdCpUkDIYJOjhMqqx)~+em8d5>P|%u^|h9*c#a~P>!bnXo^8+nIz`Ab&p+H!`)hYQWRFnd+f z_R`sfoW*`QFb;ZcSH_68ZMW@}qi!9CFaw>4XBTA!y&gRZF09Qe?q^%|y=^-BSD?(D zU5?62olbt)DEgMV6!9_Y=P^Fk9c@ILY~F=JDe+bnW*kelEmPLEQH)$$=iy{=7yPvy zP2VYHJy90%08!5$pZVMdz?>hR5HHiFJBc@d)2df^_Kb1DWMkIUr$k57hNk|u!{?pr za`R=oE=&8>ZGWfzQ5c(EFM=u~aqk@xA6~ug+NqENFql$54=GwpgVj>`P6l(2ql- zM-Ax;c;sxM@|12tM~!SEt%laspiJhjaUM_t1$fG&VxqX45*>((u@1-Bgr2m)+QCsfQX?LLxX^I z2m4=1R$f70Lr&}?Ozlb}-JsI%9fP{i@VU@rR3APqvAV0_uxLd@q!5pxA)H^2`}fY~ z^v=@bn^SA+GAlMm%wpU?O#hXTTDr&hd}RM z0GhQ}h88F)a|UwdehllOIEi^3)Q(Kl4xMU=k*56djQKCX*idp8N<2adQ2X+g?U4S? zUsf_TvoSUP%hgtOv9xji2UsMlpDW`oqkrmJ7AFrH!HF*neYruG^_AB0Ga$7Ew2-WP3xr5ul@`lJAOp@={EXTxPiSy;ImopD{^+4o zPbFw#aB>>2MxO3<>e1`VA6FX9QWsBS!Ge<UKa4bvt`fcHg)Br;`@(M;2!&SH3% z$ghiUO`OIsaXV}Fl$XMKSu*jd=1o~lB&t}@@)@V#qy>+oGj2D-ZHyZ-1}8NL$X} zG#qEi;lO(G2V`hkHz#P{-m^EDr!F1!#17XkbCSS8(w*X_GU# zQmw`o9w`TpG>r9}IjsS7*ljc*^SLx+7q(Zd)(8oziOb;P{Mtf|jAXJ-?Hhu!ISTtO zfSIc^S=%tV^X4fe_{`PwwuK<_x}xxu7iyOT_oea`uKgk^Z6o`BTW3kFdBz{1t5Q*8+ZgBXZ9p0Vbkj9-zP!q%KYVL^%8-$r9m{#ya?B zYlTTelv1rHyuW_Fma&bx3aEodeIJXq!ID>oaDR-#?TPJ>b2<`Rg8rnqX8IXPodZAn zT7%@4it!vLfBG(&jKOllb`NEeV7)>o=`SSb1-?kU>T%|KzbP(3eCTLo`kou^y>WKf z9{V8~5fXNRB+oywO)}A&Hx3$HuWP6GezKR=>&%-ryytoLqhl^@SGM)fSw&6s!m@ZP zx$$Yhr?N}i>L{GAtQZ4@rnoCiX@%nEfpP{`wS=m%t$u(Mbj>a-oZwWBzUJpostDv9 zPdGl01WLlvWn(+E9QA$=|5>S;$3(sc)mXMvfRa=5*)hU1zmVi$B&aIlwBmqF>Dg|F z>V`4A$CLd|_O~r>JEFV|UCqyyPrJ=w0{4ArC&Pe6KB?G}Gs>riJ>DeMF)Pa9a?0^l zv1+^L-&Imcv27@~qGYw8xV=-e#8)HKtDhp{C`7uU|!{wn~!x12EO^A$adAO!*<`A;q{WaRAP zWN7RHFm-k|G&dD?{ij(j)`0fFJM{GH;bUD}ji(zArCqP5({5HzHH9^fG8s>`K}s<( z9R2alphlg7)f8Y9i?fIVT{XSX>)Hvb*U1|*dA;;ETvk&>4|MKGf@IdnLfOvLJxVRk4 z_LgY%)(|7zS=s#|X8zP;^~`~Pew|?T78>%oaE*$Od!x_IzSFa~zxeF~Qb1K-VE)Eg zM=9jP9;v|t(0?wpU`S7iq=*=;W%0aT)#3e#2;m5ekmQ1^B zW=slWox~xZghOhm;vK>7h=O9rAdh_XkW8E9af`e=#;38vTFlQbbiAS zNI-SvMFd4iro^;rs0%H6^l(C#S;4w2d4GS2L79xJ zyGN8WsPF8q24}LI!@bMpiCza6N(?-QwqIl05aO_e_(Yge?Xqo>wzG3?#q845XTaj0 z5?3xgq*@JL_HAN=iU{h$uy*ju5e~I78Wz-WkG&TM8;1cDtxK&67soL+PhGA{m&cOn zC{Yr_;@vQrBr;x3EI>@Ka(qL|$r=ckX5h;-ITo(<>>LvdJ61G257BPl%bv?g#Ly)( zBx3XciM!)Vv?WUwB~#IK!Ir)%$nmr(swY_H>dco-_p>P)}oQvK99P7yICO5b|7JzO zg)_UhU{1|FvDclG-=dBOhsArY(0oGl`||{pH+B10)L;a#E2`3zEvJ8GlhkVO5Xt93 zo-RFOLqWSxu!8DnjiREzge10#XS;8Fhtr~~mn_`XvmD@C?9@)uPm{^Xx`cVA5_6_G zMs*B>H57z>s83NBrpbv%I2J~EE))DUMSULeDr|OTiV4G}eUzh}_>Jg#ZWW(Q#r_ZQ zkgeV!sbRd!tbBYL5qg1`+_uEIwKF?Yeuq05(@C*nY<~(Z8jW4%x{wGObCX8IoqU?e{wgi~7-4F$#FWIupOMOu zCjRadc4N9qvRM%T(Opm?wvwh#tvQFd5?6+T|sbJ`cD|4g7fsGZtBD&v-b9FOS z5=zjHMNO!LgQyzI+p|e)GSJfdL~%#*cT?siPLr~nhnFaC9Vft z&$zaz-{zpvZ9Q$pW|@wSYAn0RBaG&P#R&g~wIol@tVs_M)?D~8T$@nL%~4$%tHI8uv@Yi5V$pgW0hgU5LymENuId-r-JtaLV9|WL z$*>;uNj{TRa~0uDVV*8U1EF9&Whv5^!+8ecw-^C9u{1dA*|A)c@tTg%F*Dj5+OhpI zNx$HWk0~xFG&57MY+H<5cd$n&dqpiNlcckcUtdh(NgILZA}eKs#&v?2=So|TQnG+z zX9(a55xq7A{T^iw=M#;HtrAZL8ye*K^QHc6BtIz|G_4_$0@!T4Z!YCn*UmC25Jw89 zXPy3K+$pA$cN$|v;q1||Vr<8n!TDWLbspWx`7tzF)f3Y9$Zu5^+x~Y*TU0^&ogevX z294=1p|sV)-u0go3$MoEHhOfP5bldP6Tb+SrQPm#`}RF9kvHm12~H_oWu`iD5Gj^L zPlFP)zid zD3jSQpY`U}iv=?h({=8&LqD;fP>fr3jlMEewAvUFVT+f==^G|Q`>}}dWvx|?+U^#e z9LUiPQ&?AwiScjx5E8?EceLd&=!A+1G7C-CCPfBHZr^KHDjogN4R1+gDJF=_hotDg zk;_zV3|fnse3WkH>FV&HyMB{CKn=gg5-Qh~D2TNY1D6XY=KlbkJ369l*0#j zWexUlmFy{<2C=3Zc%|_6T!dz4SK2emarH78E6~;XA-aPI29MeSDlz?)jip)jFo$!K_ojOUs*_^6tZb zY$;o+>bz;AGz8Zyb`W<;#q$O`>^Ils^DQB8Ai zu$xL3sm+YhvZKCo+}t`?_l*Ar+sgtQt3!+zpg+jdrolDyDQ)A;#}*U$c4z$Oxm{zs??p7G z;xuek&6qnfd_ZWOm@gX)1zXcg1);cSaxQF(0Nf-8aBhpQ(IwAftm(|UD2ZT5YTSIX zi96eBmw)A!gxXWWvad;_Q+_tfqal|c{FUKEb3XFbV2ySiPrA@GsUPUm?3?sdcdqw{ zh*ZZ-<};lzbI$IF)Uc)Z((6j;wQgiWf@bC1b+0v4SO}zfoofFp;>dKHhKi&0{@$ki zgXzFmG+`E?0V0~WDl+Vgi6$9+2lc?p7kRaW*!a?|G{ZNTqZ+NeGJ95Yt3MzIt{qHL z9?V*C>-*3LSB;|(*a0@*+AiUHNj^oUN`^31@>1{6U81_bht9IXqM%<4*k7Y+Y)(;2 zp6hEaDOZvxVGr)A@-P2ECs8wp&t<)kN@lKaUE58qp~?*par%ntjHnrs`10D70zido z#_>_dmghK>@NMEbQyW+(Kl0=BufN2`!?Va5$}eSL40&5<*OXv)NG@&C%!s*nvx}-I`b;e0fv7pqBjW`f*maEGAih2+;apXtRrQL*Rv-wGg=}Ner1B_vrg?gw z1n)sv2AaRzg4XZFbbf^a_nJxiF;BennRE2K_z|f1yHdOwvt@uj`zU(8J2LWmiTo_N z_Gf9^*wO=b%-YFqSW5>E;ksP&(xVWDa!~l zeC}~dZI3^fnN`&ZFXPV~87P9;Yo64+$#P4?54dwgOAl7TdCx1i+be*J+=Y}#aSa5| zu-P=&CeACA?(0vQVchh0yPYR2CHEm#JWO8?Jj^UK&(K1VQUoFfL`;ikFrwEYnZTUc zynR?+l7VDC7l}Z=$H9p<9;s~Qjj|LuO`$)2j}&GzOxNIe=|hUi)Nk-=7|-0)xD9ki zL6NO7F&w=9=T)|g^9MHNx`6cTQ)So%f`+9UI~O(<5b~q$*=G+uGvA;SfB_r-aMT}4 zyKj#zNbib!?BY>M2;p|UX1qc#f6^GV>7>1qAF%OIFfKIlnRvEiBk!3bCHsU12)yS; zOVO_<3l#e&XhEVr?3nw6&Jh1Rk?|ff8YE<>VAxLqi;|6wVY}4Jw&oAxIMyp9CK5Fa zU*Vi5c?ERb5hwGHKEgFC{cF^X?&$E9?d4 z%JplTp(87^SOKH7PExHVbQDu{%6$na{a@C3yZ(AEWf@Roi;^SvvpA0koy!~=<`uF>v>x_JDlFM}saU@9}ZRwYdV8($3p z8IKN+K#be&2}F>a_R4guq9a=KgYdAj#cm?@g5&hF1uN7ZwXjDJRj+q(!fUKOdO>Nj zt-SIUsgw;vZmfF~9OH^UMh+da$Nw0w-`;J8O1;ephJybHjc(OzkiJ6C&0kqBuY99; z3~@RERQlvjbWzP|MsZI)=NQwbrj_&+mh{zj^pKkO`%##+TX^Dd6ssx}i=O}aI#m|3B#I+=O2}y)y+v0)%0fm26=KWXs zi?XMkv5@oENx|OPMdYiz&d|=}A5ryaWkdTp1vI``Vtfs%entFDyVf?Q6}5c{2}!(g zXy_A^k#2!Je|p>PIVE_3ag+H0#1EkFNjKe)kv4hS8C&k#yBp5azP@iS@B0)#T09c{ zW0Y{HIui^j0(Co64CRNrW9nmI0xx+K2SO1IIr*jn)z7haCq5A4RIO9hw#A* z6`g6<4Sz1pqJ|(gsnsIJTl0(k5x&{|D?F*Z&7Y^5MP+=PDzXb<3OfOwDNo#N96l?y zZriz!{>pPK^ThcoE3|rJy7$22Kpd|44??!o%y&XXPSn{}BA;ByKvYwgZa*i_!a8?- z$LNsi#J(c|i2U4QXF4Q($`sR_LnULh2*H7P4nxKa=Kv>MFu9d$$v&db3$3TkJ;w#i zd{5BH$NPrtp;^1T$IA4Wu>S75U&(h>44J1I(zuL@tk+84Tre5-bB@JHLWDj4fHRrFnTGP8-`Y{mx-S2!4FKa~#XpQa z6^Q>K#1JjpCY~0KccE^HIbS|&rPdv&TD~l)f>4w1t2)3t$eV!HfCfOBP;8DU4YH9R zuMGjoW2Tx`A;+aKP_&!nHs#B#n;RQjSa9B}DU?*yvP336j~+vBYYljWAMN31mM#-a zPC2ueZEN^gq7!{IT6xaBE$kQ*Q`+)~t7muqMA5d|9D*$-j(rEpEW0QCS7>PBYjvsP z18op}rFoCO3anWEGc@#n>MzADZCp&hQriEF5sCh@F4NTMpBWsLaV1nCG`?&pW>Rbd zh-=_5Fi+CNUIVyiAQdnwWpo$+K@j!+BKW}3pbWUA%XdhbRJ)DZIBNesaP5jWh@OG^ zh4n-!Q7Ey>vW?4buBWZ}Qv0VCef=1qqB<;b8YLo1tjIk0eM5^hsC|gJK6e&bGu{9= z@=}X=l@pyyT^O>BA;9RvLts)+*CfkKzK%=K|P5 zAgbv|xSRc*PR-Q?eB&+zy=y!>L5HD6*<%8c`qR7tn85GdS;ue}T=RSK&C=EzekC>N zqo|X~@LjD1>m?fAay<=pYFLdS=;a%p-N+pd-Q7kC>{M~;7<^Lg`)%;P+RG8`sxvv& zwhsO2a+S=CiGG?8Z7Kjt&TJ6oMtYw18z-sld(P$sX(m~=5udDfMf&8i6n6dQD7y8d zl!gg>^<;$$1B-?_XA%o<@XNUA-5NaZMvsDgepOxBiX9?w_lR+=^`b`O6gr59sF~l! zn`4-5@0c_Z^rXh&06a`3ZSN#9=wQOOhQ%V3odp z6Ds}~hJF?@qYc|3o!7yfFUa(uSnc+#Ggy=`PEmm586EgDhIO6dNP-Xv)mWdq>{6tp zKGY)qngH1HI6Bt%?R~RH#4%w!4^pVUD~`$@YB_8iNQt$iOdmWExKE5RqT!IROfw73a(QaFK`xC7zGV9C(}*`bGI)%XZ;(E6SH$OwXt{jdzDLEx0@G43i$*GZ?wv3 zue)j9o`>mMvc_pVidZ>KFQHQlb-ofY zzgzl6F3T?(TsYtY6xMk1T__X>ir0>*sWzbIXxrzU!9pS!j0VYKe{LKJ_^WJ((bQ9Y zC@QXNUu@u);G#Muc`E57?|C^%cPSAk!DYh=d)MHf{^8|*Sd@C|mpZuB&G+tbbNp<+ zhoDoLZDK@>G~Abs@L-PGl#F6ysfhc^%1o35qc6}^?llMVw2s$4e4jVgc{) z>=LK#rA5PKY=<~gG_C;57O)ktg`=B3_BY5cT4f3b8!x2S?lPyRSgI4A) zfj41H3=Vd}Acx^LbDcO%GY1OPL=J$Y$-xidH94tvj^(f!#fDK8u+Y$EOZctj%Hd-! zQ);Q2vsQ3`J?Bim86P| zKGV9_P|+iiT~2jnw$bmfo|ou~)HrEI~wwa1g~h_IF7CG^L+W-7>8kLoWG= z@Qg|uB36i}pe{^4Vn?cVtZZF~??9V4ejQ9kBQ#hg4#|;5AlYuBK3VRl;`FT)%$?FN2X zjtswY9!d+%tz(5o<^D?n{^B=5snAWSz(7FOUmS<+ZxrBv>r&iI|7Q6oE3HfS3nKBY z50xxgHEmtJ5I3s^cB_FQi{?}Ry!TD4zF2Z08P&RP@KL<}g?L>!AXTtOhHh%;PH#Rn zf%o|5@CLdU1H+k-Fp4?1!A|uUs#72hf0YSvF>F5uj!ual6YZDH0>)x8BrUWsR zhjRH*PHAK7?4nZkua!HTfP95SX*_**o84UJ^Le6F5zE2(6z;>Tgn_tl1WFIMnV(y00-SsrigDJ+wW@a|iMM z>BGDjSe4()hih|G>Z~Exj$`C{Ye;tyQGW#14M1M4`6#xR=5&G6F4oCz&jE=L`Yxh% zHF9if-nxy*&t_7o6ZBpd_y}yaQF4o-gV+0qV+8{r_>bTe(H1KAUgIuvJuse3rYtX0 zKS}zU;}%yNBWrUF`PP~;1rXN-Em0aO#k0w&WfY(yPan|y>r4Lyb$>9)5>dXOuJy~V za{bMh{(nN<|L))^R{kI3%9q*dc#ehA$7V@o%S7hLAQ$05EnGfErvwD8uq)z=3sykCc&064Wf!Q)o6uD)1im!~$X({DLqN?BX-MgzR5Np>u`bva*HouoG01iwgno_EQuS8?JR$&v;r|adjWpS@t9`%ehlQrGm9J^{Lo#~>%%;SBV_tbJ~9+%9C zam;iR{|7A_WmEBl()mgJu_Se??3TL4L)fFUiS^|W*u-Ymw_`g%oO{I(Sja23GvRz% zMG-6-DD57OC6Dg1L$;{=1#t@VKq=!~NBJxCZ&(-;CsI$8eHvNN;U8+!X4o7K=U^6W zpp*M%XKk`A-)7J&=dxprlI&jILH@PSY z7~;uk)8{}cL$0uOlzO2`hr|PVZhNU(Y|_nU-ohOwyxit&7ay{+w#!YAF&F2IQu95Q zkaH``d1?8i-{M$(*pt$x(K3HbmKNBi8>^&->+m7OszQEl5@KtZK*_F91sYB_T4Fc+ zNiN!@wHT$f24XhJ6D5xEmsVBhEQN=+Rchv#hQr$HeQpDEVtDwx@ZNDF=hlM}sufii9zqgQmUX zu^zoTo9WKObwnyyY?0Z9pu!n{^mwd6m$vwVa2dc@YZR3a`99RK@AGN!(2O!u#uH~a ztS3w6mtO8Vhm1$xbsVjj6#P+dm5%v|Lp9joTW^xz)*lhYa9tc#bIq38oew9E;e@6_ zGWgUz=+4|d3>tF6vLGN*;FwcP%!2lvo=R_sNe#U)U{SR+5o-viXSdw+nO@bvlsC42 zVQHGx%+hK(^ZUZMwmBCdMO-UFsAOcaN{e`rHR;LzaxjRHU~NCJ?E@j3IF3d<0}*jp zQk4VV_7UZPJ(1rc9=4zGMXYP!iq%Ki3+V2kJWE$YNpg-e362LjB-C9RDQGJXLPlZ1Nb;l{bTlDY#AE z$sh?cLkOUo!z(P+m)aISKb1tT3@dSEWto7hCh29w)s}$mM?4|PPu@k8?Dy{$biw~c z&ii&%BLQ;3`5pp3#NU`$Q~*ga6RCXC4~v)nr~-ES{YPboBNVdeEUg;^GH4KM5GRvW zDJsP^u_L#XR$C>PSjK$OYIMo>8M<9EX!8$of!(esb?Ka1)AqmyjYxP1zy9jtqZ1$G zd}~C<@0>`UAf9CmGphu+QT#)f#E-n9?UjB3F~!3tzkgE~@MsNm6Zd8Fkq$?k*z!xs zi$w???kIp?2`0Cf7VvAR2@pqQxk0WClpED(u>Hog2A)==^neOIh31s(F&}9s)J6Mg zOj?mt4kg7QwM6N_4NfQT*ny-aH@rD4IhT{bO>ju9W2npbpIF^T7Vg#)G+ zlG$9xuw}7C2dkD577A8jRZi-#5Sb-Y5F*9Yd)?t4DxZl~4+t${f!&!{(^j>7UIv4M z1b@W->yTQnyYK%(_P@xYso1g$`xjBv|0-ktuRRa{Cm8lOL9l4m)qe!Rg8fa9ghYjO zG~j`;TUzt>K&WSbz+$MrERotWXG~}${+g4&f%RFW{xt_F&|7oOQ|ZLTrwKEXSElmd zvfW*J)z&h7;q&?afcvAtBSDbEtizyhuKyG)lm*%@OJ;|c8Cs`zkd%J6p5W;IGMTh` zFT>vxbQyjFiSf32zk;K?*JSD;Ld{fHt-`)4K-ZV--DgxwZLyqoP0lg@$X)E4Ay3U_ z=e_MRvSe^Uz04d{QgW)T7s|5ZqMOZky&Xl)pJXZ>67p5h0~i|tC?}(`0bb2|%h60dChFjFAAzA-l{Lu{m)X&}{;*{muz$3)Oi$6OAkP_8{3zx- zwaZ##21##mb4u~PtNsBVoT}G-NG{|BlpjL*hw;(R=&!F{U(_c*BvbgR4|7nnDS_xl zE026X=y43ET|6UWY^3{Hnv;s1-1b7&BG_`Ns(++UKdvqm47b7R5UH-K@*ynpt!zQ1 z1Lc&Qz5_sZ%9oeVEmhf$tEabF_W*!z+!(5y>Kg#2O*{GJhuU?*65p5PFNWIUINYm? zDl>x9YQD$sG%+y1tR~CbD}rh%i|b*s$D{^MzJ~In_ha*E&<`3w3FhrlQ?CqJl}d*M zuxyHIQMStIm0pe<5iu2dQ8I8dZ^MnSByAqgC6jNt(nTFq5>e@gdqC90|BMw}MR#Ml z@gLHpJ7X9kTGj1dl6c`TF;Vb4FvzLEi5%uyyjlZ8DFCYZ%1sdiD`O%LDIU7tw z;0YFL!KE1JXpRJB#vS!_CCPMg)-K#9<3&?K_fU`(>uMw@ zEG5siOqf7&XZ@B=BuOKZi`Qas44>S=%?&F|)CR<1T*Pc4b{;7PJkHu0c z38NeY+C+v3U)IbdK1j?ZgnVd#IY^E2_y5Xt0H)Yby1$q^!I!^A`!@_;>Tej8ZOkMB zunZRj_aOh!W+G_E>tBu=ZK;?e9(8c{JN z!uGc&&=T;MHr8myllYuc?R-m{bg1dJM+dg)Cd(uTH4X`iSh5|m4-3+~>XUd(U3%Wc zPd+MM0jO)+F2Mc@LR`r>`4Kof?)d)dP=;lNH~&U3|MFybAyqflzvi#?|B}Ps;E-$V zq!q|ta#(CNLnY$a{#MDw87D&Ttr7qmf)}(gT!*dhX5KeJd9>(s4eUcXiUlA4cApR1 zeopgq^TQW*hhP&-9l9Di+w)Z4Q~|b6gk5v22`!mbi+4JuQkcI^F4Bv<>pSY$QWKkz zMYI;zFu5$(!8@jKIoE*o4&a-K<|p1u1g8A&u7%=R3Uj#=@oGlv3KPmIqK)@J3}ee9 z^bULbp!qUguEAK-!5}@ysN>miLk> z0mNPAONhCDt7-j9NT^mZ{Lxc3em|B#WTo%z>RH5XG4mw)Cflyqf4zVa3O zFY(Q$ni-mkLP1)MGuE>rLf97kXu`3DJe4HtcE4kM-zow~Px1+8Vk0iA=Rzsb`!~Fg zr}&OH+9uXt$7z1(Ru&=k3!^9=fHtHF68V#b6nURZ4s-v0f%{W_t~sQd`1;Z1sD;`+ zO((?R4R^}!F01Xqmft#xZocxNXCtEzE#WZ)r1D1-0CwYhD(TwmpoCX?OW3CrNaS^p z5ujBeEs^C~lhN0)1IT1fFJIqt3-o5@L`+azOt~MLyrM3-uW7Stf}~~*C0SP7lT++( zCsTR1W)C*9d~;z|`TzL(#wbgZCED(?ZQFKr*|ybXoU)BB+jf_2+v>7ycGqxhXTn~u*v zvB^Cop~+(kPpBJZ83ysIMlGiwy&jg^O1CDys0A2A9)D1v0s%^nYtob#roX2xIyE2R z^`!(Je0&*U&IUaO0@IkjH;6hmShA>JoxaNXU&@uBauEXdas3b8pNER_d8j!5d#DnB zUikkglq2OwB!LA`%GnqVksiEwLh#7Y!P`?q`~(!_aade07nlKqu@X(UM9&s@uV45i zJu%Ud(8u_1T&s>%=G&7Oi%h?)s^3(f>JRi$^&LqRM_85029G*7B`O}73`Qab_2c1H%t579I5sM4>W7a%8^9NOBG#^^(~ z+Zr>msRs*ekwzY=m^EVFY0`|;q|Uzrv1x*DP<>7@OPzx0+$_RqrI0eTRwDIqb9>wu zUV@IzAB3WPHafaMe_Qd;G@Yd}E2YV6&KE3v@!@X+=Ddg%Ow54C7d|b|9X|1LuZgRf z)fC6}R5UYu4oa6FcBYDtCRP~q+w8DzUM>CLwp6czcU+e}U5n_BfvtbDT_uM|u>(ly7 z0H#j%e<>&@s%j~%ilV%u!So7ZeDwtot|3WAKq|}@F3QIlNFVou`SsAA#Uq3(RFjG( zOJC0wy+^hmkiwJD_DQFXz#m0Z@laD&S{X^dZmsip&}}~5XXw1$Tx?!^_4LJsq-Mfk zViJuBowaPZdAPZ8VDuo_CdX7%$w<89h$0`B7#@``?PbMeS{Set>Q%x7R=Fw+@Qbh* z7GE+T@QrJrInN($J+V*LHxoHTU0wNR+uYeyik)@VZj>^@Gn;*qc9Cj4UQOHQf@AHb z>A&C=q%c}_YH#YrH>smWe}y{BGsCm{gKIC<7}Na`+WIknoB{ic37HC|`DTrUgEO=E zh<+?gR|DG1#@1r8UQ!?8>++q8P9I}5_iUqi47z=z(hOBw!lG2gcOhzRU-#d~$V*WMyzt*}G}AOUGS?D*Qms=(c1n8Pd8lpa;b*>5AjH{(jVx z%Eb!yF_J2iMYxH2jx07%p0mc;oOECP0Bw;uCjSN3H8qNN#HPS9?dv@5hS5&bX^P-P zI&{lT#>Z013AbjAhbV${{Zk|tsJIj*hM*HDGP_Lucj6eTlwOv;3aQEl*i||o4jsr< zsIbRWD2f?Btml{u+GMNU7}?(?lU|iuN)b>IT@)BYAbpYdI{8~*){67Gad%@nV65Hp z3l(vVoi7pCjt>!He%%nWF-Td`Oy~w+wc@{yzJ9{$l6%W%hl`W&93bam0 zDuI%4r_?5nifJlBsHC_-6+!qmtAUP<_<{!baoaa}^P{WLFM47-IktAuer&tg$lC0? zFTR#Znp?;N1Q}j3+~18PtxU{0<4SBGEkTryK}pJtZi_*Y6rzZ(A6N^IV;#Eyg4ZNS zBX3ybq9MXEksW?4_gFgfNZggv+JW^^AZ#ZDC9LA+Q@HeGSkHngtkP-*SpdMVX)EY>%%4F1p&f*4t*2tMK`No1^${Qu-y~hU}7qso=}F%dc$d z!?SOO4Mh6BO=5Gu=5BWe$$aOXx-1LYWO<#?g|90%t|9%&7LjEEB|V>oITlBGb2_+OZlx66oRbSymv&h_5NNj6vw#oSMI|a6?*4W*uO`_FK zS4?*G&a|ExYoe*fvPzBIc-0bbn8~H0a=!wqUaBTQq1Y(GY_Qn)yyQo%K6}a5RoXl& z{+;tl;Z1-8W8FH#H#yj$oeN)utCb{b2Bo@8RpTb>=JW7haLLmQ+@t3kE;y?>Gc%-c z6%EoheHV`-Guncatn3K118O`j;^+MY$ADdTM;cW->3=_l^+r4wk(?iu?;VGNlLqqGk`hMVWO{?a_ z-OC2g1w%O!%I& zMB$v*G(kakbP6s=G04{q;yX5onApK(^+TisunCL&17VFWb{nCm!x4Z$5XbhYUtFDk z9O$q7u(6ftPdK?GX zOhzfLBHk|)0n~36#fr?ujvA%so`13AKX9O2LAzM}Cyu!PT$KNdC;oy1NhJOs-J4Yu z4^%HdLg1#^SlXk1BKnjdHZWe#4?RLCzc(_v>6lYNG6j29X!xz1{>a1-rS>804bQO~ zC!a6s1{7P6w~$s=)~cpA#QGF13s)@+E6N%3ARl_AM5-rJg%Ek;s*Iz;6;$8zuc<)6 z0zxU{2%u1ASlsCDLZ?0=HOq*`P7@8Jtjz?-oRCg)l?O=mU-3_nAZS@; z?N3*2zno+ao^8Ap^G~)$7p?|gxZC_Ml#-T6E}Z*>z$~ARjQD>){qIof--MNy;;J<= zBLa^s+paEXZ0#lo3d3Ju=1mnPUNUlU z>fK>v#o$4NI;ay}GoxO5ajv|jV@1`(xX>>%ugiJa|-*5@?sG^yAeRvk>6v38P)nOtxA;(H>}@~GYCQl zVT2s8(x_?zwGFYRJ&Kf&LxEHGJ3Ltn#4!DTZKx@fBbNjP_eR}z4pPjm!a)1nxX$t+#u_h;36&(;VE|AI1|f{YY2aOr8aNHrQ*%bE*;EWZ zl!Ym$OP;13dnx|V z3{k0;g2#Vyo4fz72K3)d(|^;We_xA8Wi6#y{!fez6^oHiX{+V0P8%^V?8 zVC=eS?XofzGiTJ-jelA7I2J*)>%UvqHK_YDOJuuuE5=2NX?YzdCGN9< zzP7&On|DT*GG)y0qet_G8LI0cb&qh`9lw5=~mbcs)v! z1&wNojLNDXN-9gB&huY0ZHJDf@dC#~3vB$>juL(Lm+xAP!zCokpMyhU4h+ezR^U1L ziw)!|iKD+6w6I1*JUr6+7q{<2wm8YpWf97C5s2=v*K`;d1$2Wu-b0K69)9oIfZQ3@ zcnk!-uD{j$w!@p#IzC+-^{2c0yO;kvVEeP|_ouo!y5kQoA7HvW2{7nh5Jae-8vI#d zERO;L+VhSSjlp@bg#@ZQ-V1)2)6bj;GF zf(Rz3MqV;S{+b3EvuD+zA>P0|qS2tJYmN*uDprNQ=NV;$<-n~}B}WcS%dc&k964Nr z3N)wV(d0lR0~7Bt6}i<0&?PT;0}38jMxrhPj(8X_jX$_CWU2zx(^FO~UF^3!Do~N) zq7bXu%zgAN`lCu`f6avBa|QDo z;TwFW-AYy)ctn6tMCxSHS|mVej!h)9U@+2#BMBn zuZ>{(nB%^0Y>$RY-ANFLx=^kp1hhmE((s)-7gq0&X?&gAQCvXIA~4%pyic;-4?x~} z5VU~SPx*uJeu6$4(tf#t#(aONAt|hv95qLwfkjX!#;OSfS!DY!Te^bZ$3aRHr6!^y zNoK|j#(N1fjRxkP8|pACBI5=a_q~->Gg2ei2Sh>~hopMV*RtN|!%~VBILJEp#_GR} z(2_@FN;#I}OiX_x zXPm?$NeWd3*Go|tLVhbf&5~v3Yi6^&2>5MzWrx@Y&>G>Oo57u(`KYe z*PoD6q4!MdcVVs;xtGY(R=wrkmTe}=GN&MrI<9m}dQ@IiVb&m`PjqZ?(FCzLxdTx$ zj;zXzAhP8czjURnn}V!44OAb|Y%JM3MMI*moz1O6CsI?8#*Ru=!Z&X>e@Rbt53iGK z4tT(@&L$;&n2&S*nKmzWtR&W8`IQsWtr+QEev3l{66>B)3MuQSa7mne5M2*{p#Ccj z4AM?>k8Mv;#!;smLZj>1;TrXGHw$e1ET1uk1Nn5jp}9MuCIC|;vcqh*P=Y~UqIz4L zqnjBrxR^#Tjx|fSbm$ouV-U})zjd|E1^D>H{ zw(Hb1q4ezV^*q+OJQLEP*S0iy<#O1&n2^@JCAtR0^-P$|n38!<<0xv)V>>KNllGZ> ztM4Y{RURJtNYe0MNl=G~9=K|4inw9*V-OmT*T0YB7r7nOPwWD-Xy@lrmYi{&b@k$A zX$Lo-euN)q|JMIF9&mbw!1(%c0=C-`oRth{6xqc5>K;tCOWzY^HW#Si9(Gop6VIdJz>-yREg!+Kc^#9oO#Oa zRSx4mOe9kaL3SzNU*5pJuoe%X7v23r20-B}G+l)3N?%})PF*Z|7rrz*Mg<9qOs|^i zyQHR@`I)>89|GMYB~W|n@xHk^$=E6@5bW|j*XL3j7FdZjqo|_?iw>uSFo02v{Gw=* z{T;3qJT*V>N7R(mb|B@W_Y8%oJ~_pb2G)2i+YQPF80ZLmt90qWkq;C*B%z>1({N+> zt6|C@%+;9Ef{ER#@tP%6?QcYqmHMvPdMpb~JHUbVa_i<#-R@WH01(edcu_UbHQcLV zQQF4X2A!}#;?OF_`o0sQ>)h1RnDi5XTw1@0vVqv=Kg~`k3oTqZ!sbvUmUM%8b*y{N3XGmU>U=i)`GljBI^KC|;<$zfP(6qoOajgWpH<848|07s3C!!v73* z{#Pr)zoI~3tim64{J_bS#*)OO4rSqKe-r^|9up8GFu%%NEd-u^iezJ>jL3Bj{SQs} zw;$fhj_ic~XzmyXYn-N?qnS^So*v+~fjr<`aL%|aAd=7}$Vg@xnGYuRggUe`TN?n( zAzI&Sbx_e2lAZp$&Hix_`UoHwUj58g&4DBs5$h&7I~w3twH3v=R%3Z%9I|N^E`3EO zfVK&X@0)@_dD?7V*u1dPYRZ&knIJNB#_KVK4~&cO8ikUy^*b_Vkfw|h+_yaN$%}g~ zAh9PkPfSoFPPeoR7nbqV-$hmZIhw0CVBV`2aP8buf9N4tnaJ}C=|K<^WW4!IojDeRWMOE;5Ag1X_44!0?(v*g%He(|4Ov|0VgYs zTwh>5;pD?-j`26{7mSMvfDSV8v;dX)?rIn_z2GBKCTwkLN1(I0lBiyaKgcc3iV`|WD zkIx~;+q7?*{9Htoy;cl{uX+eLOw>!<#9onIfGgdtNq9ke7a`vnP8*LeC}qa;vZi39 zX6<0=tj6D>Jv?I$niwWpH#v!_^+!Fw%TcAd8dB67%h~Zn46mkxL?rJAzj+t0t+U4- zNoHHrF!D6e=F&Cx>F)}k*>?RvZ6*cuQV>k$cmmEq>(M-HQ7Ftf9Nd> zbkfvKzqbl%$O;%dO_|O=VQhpE_ahtSF$6pngk$^p z6&Vowde^Nyl)!>1C)SXjC~0(B^moDhp?6pCx8WH@d6-dzaxmC8UAi7x4%;49t0r~7 zjO}PZQAQLp1YM!6^`4>S$3hMSgpM#I!44!quJ+?1GXsr)4msTB@^fb{qc9{G`E4z^33-+_JEbK{Fm4>`}z;u<4x1Pc3?O7*&>tA2E-92qLXPQ>ruGTj1!ebuO`*_?zuV*p_OF%_;zvwF&Wr!tUp zjoEIq7ns{9GEgj~DW(s|#ra$l4bO187nz&2hJ@kjgA3t^!$-w8R`jl{;Ux2xPz)Wj z-N@eX`%+H%t>pS3L=kl+XI(nCM@)C4JG{&GEAFzEnypFdK@!ZuJQr?0olN14FpFDo(59^3Du0qQ^V2hQi$lM3H0(T#$;wX}MI&&DYU_C&V+3`71#=UJ@D#D%IASJ? z*2ByB{RMLOvhU*JN(gNrPe6x(BADTaz7eA!ci!|ACmY^YOj+|_1j^ua@Jac0HCD{! zoLmUew{;_D7=OgIN4b1y7}$@W0mY8Ml&w zQssml&%%gXHyZ`u8^1=_JzL*)R|RUot63 zZV{Xz-xh#jHvXG*{9&s^7bLv~pHVjD(_a6{|NraL97qH#Ep1#r|Ni986=bA<6i|2; zs~GE8URbn*#m$6;tRlq#)sn#~??@Y$|2LQ{*TeavU6%%RCqe)Z)%wtF_BBA<$DI|$6Hzx6+6 zFBf14uo?v)k1-j?3JYaOv;{wKvZ1hAPZ^zw6(9h+R&4&%MMcf!($|~KT|fXhV=LiA zK7JZB-@aF3vPg4-E@f*GtcaBM2tF4=_eCxa52>3X$NM zB!EV=cUg&y)mQG9oRj+*pwb9gF0%a1=IbQlPW@gx=6sS~_~}tEJ}HfV z@~VGUe*Vmm{~fpg%#>9&m9SM%-mPnmZVdY_C~{EB3rK1Bazo6%*8C7D&Zz(eK&xuR zk!mcR&aBIrUaEWm<2!j?7SMai4^0V}Vq`yWb#3!)$KS23lfvrjr;M$6Jghl%dQ7-< z#lJlG_~3lS@JAJcf@XBwQR1ZuQx6lmq-lD(#KgDvRF~a?J0G-#&mICa(;JXRsd&cn zBUwOxO0C|XLf}uY zEn53JDy{aU%Tj1uMn=UG=3VCR3)(Uvt|M5y>KgDN(=o;OU{n2QQK zP@)dv)}imw8s+Df373{+T4>_>G@F*g$qbX8TBp&9zg0u+pI8)M1 zszEi8Hk0Ozley~1BCO!bW;2Dt7~h{8pnrrbMh17c-X#s7W@Nk}{|a4Uf& z*NWq_nIc9+jzPIzQ648yK8`vnZc|6~el0`W*o%~icE>(REiGPn4LP%G7LMUw+ZMGw0kf-sOyi<#alH7;mBbyWjpsE2^g@=;eOShl=Fc7-s=*7aAQEclMtC6 zp;p;k{LZPQ-5?P+R<55CwPRM;!;r-}FLEcSVqUqtsNg7DuRW_po_z9K){>W!-9VTU z!OE�Y!?kj6{E9Hz1~-vdA+Ff%So&f4IDD@9YUSkouM&{|Gdcpua$<3_&fLEB?n? zYQW({K937orth|uix;Yb=EE*la^XdI%6OKc?YnC2IG@HlX@cW4Q`2d-XvJAb)gGyN2lncit(C0C-ju>3S{ zQ8`Uq#$8O?PJ8fg8E|8Q_FQ>|eh;ESk#>3m z!G7=vqIVJ9;y^(U3V~#IKT|qoy$QYi;b$jy|H~^R|Xo!1FgDA@zR)a&&n0)emJwf#2?l^Kt zndSiR9iq+WzqF+P5uKomA?|P9M*x&NLM%Bb_2{gg=}mu_P4NkF`k~VAV^?(j2PWf^dvZ zrMOI*eM`$ zwUv1jOZ(xlCald2nAj0$d9V+E=|uh`;XbsX?l=0}-0 zy09Ek|BALVyT_Hm)(*KUOS)Se$lUg>7od)XQ9Bm1t`Yaf3h(^`-}sc3C|LzQ{`Yxl z<#~zQhpQK`Z6GpuFkBQ44m5`ssyY<0uYJJ^AkB6ws*NcOiCsRHR3^vcWuO_2V%^ND zy#Ch_)}1kqy03wp2r}R;r(2>RZF!T4XXiYxt2?ns_@!^k4Ecs?K;pB^YDpARri{(G zfdw=wM+WD$<0P(E@l;{U8K*>PyA;)+V(6|Adkn_1nXo^RMmYqVkJo$+ZoAqK1n9rH zQNrw}@wkG&n+EwM*W3f(+w_Q3eN(#&!b9Tob(iKHFLY(Xi7|fV#;yWqIjH&0Btc76 zf4s3S6zMf_ZD$hPeV~1k!$p+MSCT==_i!Xw-2v^XSmY266h7>rDqaWI4GKPRA(&Mi zU`$t`=QIe=i(Fmg)b0jjd!nmT4&A2hWpl0`E$Co5<43r+yZlRi_zz=H5PKsw{yd}f z&ola)B>g|B`oE#tztXC|V6{=nK6wP5S+x~StBOfYbfPf${-3L1>L4{!RK?AuE!5{VhR2%7P_UDR zAIfC}dcKWmz+Dy(t8u(5E3h!o=GiSP)%cd4SLPs6oN#;?+jC9nJgkb1s^1qoErV$r z@QpQbKuSjsf1Q}!YgsCbVXCaQ5a+w~XF(3VlZg!9@2d80_yj;co%Bq(s2?PsL0@6L zY@>tb$JWS`TD}7e1p)RFT&7k6fze!WR&*~!1_9FV$7kl$dwgM>V^W^T(W?< zVxIbj`}%v{iVho(5|!T%lX%Og)^HL`H~1GmhYuScK|{K{%usrfBu}=8aMZ5R@T45t zVbE6_Ok>@MpzO)pUd;tC7enBlj|99VqWG$|Wqx_Q#T<#s}{!lJFRN(<++8DbASOWyWPSTLTUxLKmG*=kF~d6~<4k>Tk1(@fxwY zoZ9H|007dwT0CNNC0yDyF;!-zeu>o(HfQsPk8__c`&UZxt4na_RNc z+p-d~d2w4BrYS+|R6VHW%Y*{o@uNB1F$+6MF;5mM&NN*Ts1tFos?pYSG=fr!(2d(B ze?BCkql)G=gqT>YI?@X2-|AOc7m-LUA<(!N67!gqEHmQ*lZemdej5_Qh6}p$UJXg_ zt`D|&3zD8m%kNHQeL33XbA`$Xuu&3KPDT=cZMVd12-pH&Vqm>K04)YIiBmtL={8UQxsZCSYN=48ra+6rD0_{czu`6%2aMM$l#ot_h%{g+MU34dl=q-CZ1Jbe z0G+2lnM~&Km=Wq`e-nzQ)_}{U4yat|BVLx`mDlT!+;C;#!mXv_#(V%aBTpOU?K9!% zh7qX5K=h>{WW#K9XPDHLX3sM@)xx$4ly~Wl=_99ab~uGYHXb4qgfMDXH+`rmYFF

r6$X*f2ZMd@vFy_ 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 gFzE}?Wmr^3)08o38Q9 + + 4.0.0 + org.mbassy + mbassador + 1.0.5.RC + jar + mbassador + Mbassador is a fast and flexible message bus system that follows the publish subscribe pattern + + + + UTF-8 + 1.6 + file://${project.basedir}/maven + + + + + + junit + junit + 4.10 + test + + + + + + + mbassador-github-repo + ${github.url} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${project.build.java.version} + ${project.build.java.version} + + + + + org.apache.maven.plugins + maven-surefire-plugin + + false + + + + + + diff --git a/maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.pom.md5 b/maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.pom.md5 new file mode 100644 index 0000000..aabc0b6 --- /dev/null +++ b/maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.pom.md5 @@ -0,0 +1 @@ +0a781a5e9f22e5dafeb7f48fff65e46d \ No newline at end of file diff --git a/maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.pom.sha1 b/maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.pom.sha1 new file mode 100644 index 0000000..121ebfa --- /dev/null +++ b/maven/org/mbassy/mbassador/1.0.5.RC/mbassador-1.0.5.RC.pom.sha1 @@ -0,0 +1 @@ +4378b82fa04f4c31f21321424d0c4c328905d3ad \ No newline at end of file diff --git a/maven/org/mbassy/mbassador/maven-metadata.xml b/maven/org/mbassy/mbassador/maven-metadata.xml index b46a275..712c56f 100644 --- a/maven/org/mbassy/mbassador/maven-metadata.xml +++ b/maven/org/mbassy/mbassador/maven-metadata.xml @@ -10,7 +10,8 @@ 1.0.2.RC 1.0.3.RC 1.0.4.RC + 1.0.5.RC - 20121211111454 + 20121212135342 diff --git a/maven/org/mbassy/mbassador/maven-metadata.xml.md5 b/maven/org/mbassy/mbassador/maven-metadata.xml.md5 index f503eea..4ad73c9 100644 --- a/maven/org/mbassy/mbassador/maven-metadata.xml.md5 +++ b/maven/org/mbassy/mbassador/maven-metadata.xml.md5 @@ -1 +1 @@ -ea8a55fc0698b7a0ab7811c938529e9c \ No newline at end of file +e37de32d920e2182f2549b0500dc20d8 \ No newline at end of file diff --git a/maven/org/mbassy/mbassador/maven-metadata.xml.sha1 b/maven/org/mbassy/mbassador/maven-metadata.xml.sha1 index 2f9e0ad..620a47f 100644 --- a/maven/org/mbassy/mbassador/maven-metadata.xml.sha1 +++ b/maven/org/mbassy/mbassador/maven-metadata.xml.sha1 @@ -1 +1 @@ -e9eedffd82184cc31168a051bbd9453e426d7e71 \ No newline at end of file +6b5568c98223ec0a53f7b7ede78e965ba7f0080f \ No newline at end of file diff --git a/pom.xml b/pom.xml index f53981a..12d88d5 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.mbassy mbassador - 1.0.4.RC + 1.0.5.RC jar mbassador Mbassador is a fast and flexible message bus system that follows the publish subscribe pattern diff --git a/src/main/java/org/mbassy/AbstractMessageBus.java b/src/main/java/org/mbassy/AbstractMessageBus.java index 5594d8e..15c31bb 100644 --- a/src/main/java/org/mbassy/AbstractMessageBus.java +++ b/src/main/java/org/mbassy/AbstractMessageBus.java @@ -2,12 +2,12 @@ package org.mbassy; import org.mbassy.common.ReflectionUtils; import org.mbassy.dispatch.MessagingContext; +import org.mbassy.listener.MessageHandlerMetadata; import org.mbassy.listener.MetadataReader; import org.mbassy.subscription.Subscription; import org.mbassy.subscription.SubscriptionDeliveryRequest; import org.mbassy.subscription.SubscriptionFactory; -import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; @@ -118,21 +118,24 @@ public abstract class AbstractMessageBus synchronized (this) { // new subscriptions must be processed sequentially subscriptionsByListener = subscriptionsPerListener.get(listeningClass); if (subscriptionsByListener == null) { // double check (a bit ugly but works here) - List messageHandlers = metadataReader.getMessageHandlers(listeningClass); // get all methods with subscriptions + List messageHandlers = metadataReader.getMessageHandlers(listeningClass); if (messageHandlers.isEmpty()) { // remember the class as non listening class if no handlers are found nonListeners.add(listeningClass); return; } subscriptionsByListener = new ArrayList(messageHandlers.size()); // it's safe to use non-concurrent collection here (read only) // create subscriptions for all detected listeners - for (Method messageHandler : messageHandlers) { - if (!isValidMessageHandler(messageHandler)) continue; // ignore invalid listeners - Class eventType = getMessageType(messageHandler); + for (MessageHandlerMetadata messageHandler : messageHandlers) { + // create the subscription Subscription subscription = subscriptionFactory - .createSubscription(new MessagingContext(this, metadataReader.getHandlerMetadata(messageHandler))); + .createSubscription(new MessagingContext(this, messageHandler)); subscription.subscribe(listener); - addMessageTypeSubscription(eventType, subscription); - subscriptionsByListener.add(subscription); + subscriptionsByListener.add(subscription);// add it for the listener type (for future subscriptions) + + List> messageTypes = messageHandler.getHandledMessages(); + for(Class messageType : messageTypes){ + addMessageTypeSubscription(messageType, subscription); + } //updateMessageTypeHierarchy(eventType); } subscriptionsPerListener.put(listeningClass, subscriptionsByListener); @@ -187,19 +190,7 @@ public abstract class AbstractMessageBus } - private boolean isValidMessageHandler(Method handler) { - if (handler.getParameterTypes().length != 1) { - // a messageHandler only defines one parameter (the message) - System.out.println("Found no or more than one parameter in messageHandler [" + handler.getName() - + "]. A messageHandler must define exactly one parameter"); - return false; - } - return true; - } - private static Class getMessageType(Method listener) { - return listener.getParameterTypes()[0]; - } public void handlePublicationError(PublicationError error) { for (IPublicationErrorHandler errorHandler : errorHandlers){ diff --git a/src/main/java/org/mbassy/BusConfiguration.java b/src/main/java/org/mbassy/BusConfiguration.java index f1fc438..ebe2311 100644 --- a/src/main/java/org/mbassy/BusConfiguration.java +++ b/src/main/java/org/mbassy/BusConfiguration.java @@ -6,14 +6,22 @@ import org.mbassy.subscription.SubscriptionFactory; import java.util.concurrent.*; /** - * - * + * The bus configuration holds various parameters that can be used to customize the bus' runtime behaviour. * * * @author bennidi * Date: 12/8/12 */ public class BusConfiguration { + private static final ThreadFactory DaemonThreadFactory = new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread thread = Executors.defaultThreadFactory().newThread(r); + thread.setDaemon(true); + return thread; + } + }; + public static final BusConfiguration Default(){ return new BusConfiguration(); } @@ -32,7 +40,7 @@ public class BusConfiguration { this.numberOfMessageDispatchers = 2; this.maximumNumberOfPendingMessages = Integer.MAX_VALUE; this.subscriptionFactory = new SubscriptionFactory(); - this.executor = new ThreadPoolExecutor(5, 20, 1, TimeUnit.MINUTES, new LinkedBlockingQueue()); + this.executor = new ThreadPoolExecutor(10, 10, 1, TimeUnit.MINUTES, new LinkedBlockingQueue(), DaemonThreadFactory); this.metadataReader = new MetadataReader(); } diff --git a/src/main/java/org/mbassy/dispatch/EnvelopedMessageDispatcher.java b/src/main/java/org/mbassy/dispatch/EnvelopedMessageDispatcher.java new file mode 100644 index 0000000..c2ef49b --- /dev/null +++ b/src/main/java/org/mbassy/dispatch/EnvelopedMessageDispatcher.java @@ -0,0 +1,34 @@ +package org.mbassy.dispatch; + +import org.mbassy.common.ConcurrentSet; +import org.mbassy.subscription.MessageEnvelope; + +/** + * Todo: Add javadoc + * + * @author bennidi + * Date: 12/12/12 + */ +public class EnvelopedMessageDispatcher implements IMessageDispatcher { + + private IMessageDispatcher del; + + public EnvelopedMessageDispatcher(IMessageDispatcher dispatcher) { + this.del = dispatcher; + } + + @Override + public void dispatch(Object message, ConcurrentSet listeners) { + del.dispatch(new MessageEnvelope(message), listeners); + } + + @Override + public MessagingContext getContext() { + return del.getContext(); + } + + @Override + public IHandlerInvocation getInvocation() { + return del.getInvocation(); + } +} diff --git a/src/main/java/org/mbassy/listener/Enveloped.java b/src/main/java/org/mbassy/listener/Enveloped.java new file mode 100644 index 0000000..695cc2b --- /dev/null +++ b/src/main/java/org/mbassy/listener/Enveloped.java @@ -0,0 +1,23 @@ +package org.mbassy.listener; + +import java.lang.annotation.*; + +/** + * Configure a handler to receive an enveloped message as a wrapper around the source + * message. An enveloped message can be + * + * @author bennidi + * Date: 2/8/12 + */ +@Retention(value = RetentionPolicy.RUNTIME) +@Inherited +@Target(value = {ElementType.METHOD}) +public @interface Enveloped { + + /** + * The set of messages that should be dispatched to the message handler + */ + Class[] messages(); + + +} diff --git a/src/main/java/org/mbassy/listener/Filters.java b/src/main/java/org/mbassy/listener/Filters.java new file mode 100644 index 0000000..7e15011 --- /dev/null +++ b/src/main/java/org/mbassy/listener/Filters.java @@ -0,0 +1,38 @@ +package org.mbassy.listener; + +/** + * Todo: Add javadoc + * + * @author bennidi + * Date: 12/12/12 + */ +public class Filters { + + public static final class AllowAll implements IMessageFilter { + + @Override + public boolean accepts(Object event, MessageHandlerMetadata metadata) { + return true; + } + } + + public static final class RejectAll implements IMessageFilter { + + @Override + public boolean accepts(Object event, MessageHandlerMetadata metadata) { + return false; + } + } + + + public static final class RejectSubtypes implements IMessageFilter { + + @Override + public boolean accepts(Object event, MessageHandlerMetadata metadata) { + for(Class handledMessage : metadata.getHandledMessages()){ + if(handledMessage.equals(event.getClass()))return true; + } + return false; + } + } +} diff --git a/src/main/java/org/mbassy/listener/IMessageFilter.java b/src/main/java/org/mbassy/listener/IMessageFilter.java index 2536dda..e40ba6c 100644 --- a/src/main/java/org/mbassy/listener/IMessageFilter.java +++ b/src/main/java/org/mbassy/listener/IMessageFilter.java @@ -1,8 +1,5 @@ package org.mbassy.listener; -import java.util.HashMap; -import java.util.Map; - /** * Message filters can be used to prevent certain messages to be delivered to a specific listener. * If a filter is used the message will only be delivered if it passes the filter(s) @@ -23,32 +20,4 @@ public interface IMessageFilter { */ public boolean accepts(Object message, MessageHandlerMetadata metadata); - - - public static final class All implements IMessageFilter { - - @Override - public boolean accepts(Object event, MessageHandlerMetadata metadata) { - return true; - } - } - - public static final class None implements IMessageFilter { - - @Override - public boolean accepts(Object event, MessageHandlerMetadata metadata) { - return false; - } - } - - - public static final class DontAllowSubtypes implements IMessageFilter { - - @Override - public boolean accepts(Object event, MessageHandlerMetadata metadata) { - return event.getClass().equals(metadata.getDeclaredMessageType()); - } - } - - } diff --git a/src/main/java/org/mbassy/listener/MessageHandlerMetadata.java b/src/main/java/org/mbassy/listener/MessageHandlerMetadata.java index e7d320a..22d9b13 100644 --- a/src/main/java/org/mbassy/listener/MessageHandlerMetadata.java +++ b/src/main/java/org/mbassy/listener/MessageHandlerMetadata.java @@ -1,6 +1,8 @@ package org.mbassy.listener; import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; /** * @@ -18,12 +20,24 @@ public class MessageHandlerMetadata { private boolean isAsynchronous = false; + private Enveloped envelope = null; + + private List> handledMessages = new LinkedList>(); + public MessageHandlerMetadata(Method handler, IMessageFilter[] filter, Listener listenerConfig) { this.handler = handler; this.filter = filter; this.listenerConfig = listenerConfig; this.isAsynchronous = listenerConfig.dispatch().equals(Mode.Asynchronous); + this.envelope = handler.getAnnotation(Enveloped.class); + if(this.envelope != null){ + for(Class messageType : envelope.messages()) + handledMessages.add(messageType); + } + else{ + handledMessages.add(handler.getParameterTypes()[0]); + } this.handler.setAccessible(true); } @@ -48,7 +62,11 @@ public class MessageHandlerMetadata { return filter; } - public Class getDeclaredMessageType(){ - return handler.getParameterTypes()[0]; + public List> getHandledMessages(){ + return handledMessages; + } + + public boolean isEnveloped() { + return envelope != null; } } diff --git a/src/main/java/org/mbassy/listener/MetadataReader.java b/src/main/java/org/mbassy/listener/MetadataReader.java index 364757b..6ac1b8f 100644 --- a/src/main/java/org/mbassy/listener/MetadataReader.java +++ b/src/main/java/org/mbassy/listener/MetadataReader.java @@ -1,21 +1,20 @@ package org.mbassy.listener; +import com.sun.xml.internal.messaging.saaj.soap.Envelope; import org.mbassy.common.IPredicate; import org.mbassy.common.ReflectionUtils; +import org.mbassy.subscription.MessageEnvelope; import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; /** - * Created with IntelliJ IDEA. + * + * The meta data reader is responsible for parsing and validating message handler configurations. + * * @author bennidi * Date: 11/16/12 - * Time: 10:22 AM - * To change this template use File | Settings | File Templates. */ public class MetadataReader { @@ -31,15 +30,20 @@ public class MetadataReader { private final Map, IMessageFilter> filterCache = new HashMap, IMessageFilter>(); // retrieve all instances of filters associated with the given subscription - private IMessageFilter[] getFilter(Listener subscription) throws Exception{ + private IMessageFilter[] getFilter(Listener subscription){ if (subscription.filters().length == 0) return null; IMessageFilter[] filters = new IMessageFilter[subscription.filters().length]; int i = 0; for (Filter filterDef : subscription.filters()) { IMessageFilter filter = filterCache.get(filterDef.value()); if (filter == null) { + try{ filter = filterDef.value().newInstance(); filterCache.put(filterDef.value(), filter); + } + catch (Exception e){ + throw new RuntimeException(e);// propagate as runtime exception + } } filters[i] = filter; @@ -49,15 +53,14 @@ public class MetadataReader { } - public MessageHandlerMetadata getHandlerMetadata(Method messageHandler) throws Exception{ + public MessageHandlerMetadata getHandlerMetadata(Method messageHandler){ Listener config = messageHandler.getAnnotation(Listener.class); - IMessageFilter[] filter = getFilter(config); - return new MessageHandlerMetadata(messageHandler, filter, config); + return new MessageHandlerMetadata(messageHandler, getFilter(config), config); } // get all listeners defined by the given class (includes // listeners defined in super classes) - public List getMessageHandlers(Class target) { + public List getMessageHandlers(Class target) { List allMethods = ReflectionUtils.getMethods(AllMessageHandlers, target); List handlers = new LinkedList(); for(Method listener : allMethods){ @@ -70,7 +73,13 @@ public class MetadataReader { handlers.add(listener); } } - return ReflectionUtils.withoutOverridenSuperclassMethods(handlers); + handlers = ReflectionUtils.withoutOverridenSuperclassMethods(handlers); + List messageHandlers = new ArrayList(handlers.size()); + for(Method handler : handlers){ + if(isValidMessageHandler(handler)) + messageHandlers.add(getHandlerMetadata(handler)); + } + return messageHandlers; } private static boolean isHandler(Method m){ @@ -79,7 +88,25 @@ public class MetadataReader { if(annotation.equals(Listener.class))return true; } return false; + } + private boolean isValidMessageHandler(Method handler) { + if (handler.getParameterTypes().length != 1) { + // a messageHandler only defines one parameter (the message) + System.out.println("Found no or more than one parameter in messageHandler [" + handler.getName() + + "]. A messageHandler must define exactly one parameter"); + return false; + } + Enveloped envelope = handler.getAnnotation(Enveloped.class); + if(envelope != null && !MessageEnvelope.class.isAssignableFrom(handler.getParameterTypes()[0])){ + System.out.println("Message envelope configured but no subclass of MessageEnvelope found as parameter"); + return false; + } + if(envelope != null && envelope.messages().length == 0){ + System.out.println("Message envelope configured but message types defined for handler"); + return false; + } + return true; } } diff --git a/src/main/java/org/mbassy/subscription/MessageEnvelope.java b/src/main/java/org/mbassy/subscription/MessageEnvelope.java new file mode 100644 index 0000000..1406b20 --- /dev/null +++ b/src/main/java/org/mbassy/subscription/MessageEnvelope.java @@ -0,0 +1,27 @@ +package org.mbassy.subscription; + +import java.sql.Timestamp; + +/** + * A message envelope is used to wrap messages of arbitrary type such that a handler + * my receive messages of different types. + * + * @author bennidi + * Date: 12/12/12 + */ +public class MessageEnvelope { + + private Timestamp tsCreated = new Timestamp(System.currentTimeMillis()); + + private Object message; + + + public MessageEnvelope(Object message) { + this.message = message; + } + + + public T getMessage(){ + return (T)message; + } +} diff --git a/src/main/java/org/mbassy/subscription/SubscriptionFactory.java b/src/main/java/org/mbassy/subscription/SubscriptionFactory.java index 1ca67f0..cfdf00d 100644 --- a/src/main/java/org/mbassy/subscription/SubscriptionFactory.java +++ b/src/main/java/org/mbassy/subscription/SubscriptionFactory.java @@ -32,6 +32,9 @@ public class SubscriptionFactory { protected IMessageDispatcher buildDispatcher(MessagingContext context, IHandlerInvocation invocation){ IMessageDispatcher dispatcher = new MessageDispatcher(context, invocation); + if(context.getHandlerMetadata().isEnveloped()){ + dispatcher = new EnvelopedMessageDispatcher(dispatcher); + } if(context.getHandlerMetadata().isFiltered()){ dispatcher = new FilteredMessageDispatcher(dispatcher); } diff --git a/src/test/java/org/mbassy/FilterTest.java b/src/test/java/org/mbassy/FilterTest.java index 120368a..cafa354 100644 --- a/src/test/java/org/mbassy/FilterTest.java +++ b/src/test/java/org/mbassy/FilterTest.java @@ -4,6 +4,7 @@ import org.junit.Test; import org.mbassy.events.SubTestEvent; import org.mbassy.events.TestEvent; import org.mbassy.listener.Filter; +import org.mbassy.listener.Filters; import org.mbassy.listener.IMessageFilter; import org.mbassy.listener.Listener; import org.mbassy.listeners.*; @@ -46,7 +47,7 @@ public class FilterTest extends UnitTest{ public static class FilteredMessageListener{ - @Listener(filters = {@Filter(IMessageFilter.DontAllowSubtypes.class)}) + @Listener(filters = {@Filter(Filters.RejectSubtypes.class)}) public void handleTestEvent(TestEvent event){ event.counter.incrementAndGet(); } diff --git a/src/test/java/org/mbassy/MBassadorTest.java b/src/test/java/org/mbassy/MBassadorTest.java index eed3d58..5e74760 100644 --- a/src/test/java/org/mbassy/MBassadorTest.java +++ b/src/test/java/org/mbassy/MBassadorTest.java @@ -4,6 +4,7 @@ import org.junit.Before; import org.junit.Test; import org.mbassy.events.SubTestEvent; import org.mbassy.events.TestEvent; +import org.mbassy.events.TestEvent2; import org.mbassy.listeners.*; import org.mbassy.subscription.Subscription; @@ -113,7 +114,8 @@ public class MBassadorTest extends UnitTest { .create(100, EventingTestBean2.class) .create(100, EventingTestBean3.class) .create(100, Object.class) - .create(100, NonListeningBean.class); + .create(100, NonListeningBean.class) + .create(100, MultiEventHandler.class); List listeners = listenerFactory.build(); @@ -122,14 +124,17 @@ public class MBassadorTest extends UnitTest { TestEvent event = new TestEvent(); TestEvent subEvent = new SubTestEvent(); + TestEvent2 event2 = new TestEvent2(); bus.publishAsync(event); bus.publishAsync(subEvent); + bus.publishAsync(event2); pause(2000); - assertEquals(300, event.counter.get()); - assertEquals(700, subEvent.counter.get()); + assertEquals(500, event.counter.get()); + assertEquals(800, subEvent.counter.get()); + assertEquals(200, event2.counter.get()); } diff --git a/src/test/java/org/mbassy/events/TestEvent2.java b/src/test/java/org/mbassy/events/TestEvent2.java new file mode 100644 index 0000000..aa9ce0f --- /dev/null +++ b/src/test/java/org/mbassy/events/TestEvent2.java @@ -0,0 +1,15 @@ +package org.mbassy.events; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * + * +* @author bennidi +* Date: 11/22/12 +*/ +public class TestEvent2 { + + public AtomicInteger counter = new AtomicInteger(); + +} diff --git a/src/test/java/org/mbassy/listeners/EventingTestBean.java b/src/test/java/org/mbassy/listeners/EventingTestBean.java index 1ed6bc4..cb331c8 100644 --- a/src/test/java/org/mbassy/listeners/EventingTestBean.java +++ b/src/test/java/org/mbassy/listeners/EventingTestBean.java @@ -2,10 +2,7 @@ package org.mbassy.listeners; import org.mbassy.events.SubTestEvent; import org.mbassy.events.TestEvent; -import org.mbassy.listener.Filter; -import org.mbassy.listener.IMessageFilter; -import org.mbassy.listener.Listener; -import org.mbassy.listener.Mode; +import org.mbassy.listener.*; /** * Basic bean that defines some event handlers to be used for different unit testting scenarios @@ -33,7 +30,7 @@ public class EventingTestBean { @Listener( priority = 10, dispatch = Mode.Synchronous, - filters = {@Filter(IMessageFilter.None.class), @Filter(IMessageFilter.All.class)}) + filters = {@Filter(Filters.RejectAll.class), @Filter(Filters.AllowAll.class)}) public void handleFiltered(SubTestEvent event) { event.counter.incrementAndGet(); } diff --git a/src/test/java/org/mbassy/listeners/MultiEventHandler.java b/src/test/java/org/mbassy/listeners/MultiEventHandler.java new file mode 100644 index 0000000..fd032af --- /dev/null +++ b/src/test/java/org/mbassy/listeners/MultiEventHandler.java @@ -0,0 +1,44 @@ +package org.mbassy.listeners; + +import org.mbassy.events.SubTestEvent; +import org.mbassy.events.TestEvent; +import org.mbassy.events.TestEvent2; +import org.mbassy.listener.*; +import org.mbassy.subscription.MessageEnvelope; + +/** + * Todo: Add javadoc + * + * @author bennidi + * Date: 12/12/12 + */ +public class MultiEventHandler { + + + @Listener(dispatch = Mode.Synchronous) + @Enveloped(messages = {TestEvent.class, TestEvent2.class}) + public void handleEvents(MessageEnvelope envelope) { + if(TestEvent.class.isAssignableFrom(envelope.getMessage().getClass())){ + TestEvent event = envelope.getMessage(); + event.counter.incrementAndGet(); + } + if(envelope.getMessage().getClass().equals(TestEvent2.class)){ + TestEvent2 event = envelope.getMessage(); + event.counter.incrementAndGet(); + } + } + + @Listener(dispatch = Mode.Synchronous, filters = @Filter(Filters.RejectSubtypes.class)) + @Enveloped(messages = {TestEvent.class, TestEvent2.class}) + public void handleSuperTypeEvents(MessageEnvelope envelope) { + if(TestEvent.class.isAssignableFrom(envelope.getMessage().getClass())){ + TestEvent event = envelope.getMessage(); + event.counter.incrementAndGet(); + } + if(envelope.getMessage().getClass().equals(TestEvent2.class)){ + TestEvent2 event = envelope.getMessage(); + event.counter.incrementAndGet(); + } + } + +}