beepcore-java-commits Mailing List for Java BEEP Core (Page 9)
Status: Beta
Brought to you by:
huston
You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(22) |
Aug
(1) |
Sep
|
Oct
(16) |
Nov
(60) |
Dec
(2) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(3) |
Feb
|
Mar
(4) |
Apr
(2) |
May
(13) |
Jun
|
Jul
|
Aug
(10) |
Sep
(34) |
Oct
(27) |
Nov
(2) |
Dec
(2) |
2003 |
Jan
|
Feb
|
Mar
(3) |
Apr
(15) |
May
(11) |
Jun
(14) |
Jul
(5) |
Aug
(1) |
Sep
(24) |
Oct
(4) |
Nov
(26) |
Dec
(1) |
2004 |
Jan
(3) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2006 |
Jan
|
Feb
(3) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Huston F. <hu...@us...> - 2002-03-30 16:19:45
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core In directory usw-pr-cvs1:/tmp/cvs-serv16992/src/org/beepcore/beep/core Modified Files: Channel.java Log Message: start of new listener threading Index: Channel.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/Channel.java,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -r1.20 -r1.21 *** Channel.java 15 Dec 2001 00:07:19 -0000 1.20 --- Channel.java 30 Mar 2002 16:19:42 -0000 1.21 *************** *** 23,26 **** --- 23,28 ---- import java.util.*; + import edu.oswego.cs.dl.util.concurrent.PooledExecutor; + import org.beepcore.beep.util.BufferSegment; import org.beepcore.beep.util.Log; *************** *** 118,121 **** --- 120,125 ---- private Object applicationData = null; + private static final PooledExecutor callbackQueue = new PooledExecutor(); + // in shutting down the session // something for waiting synchronous messages (semaphores or something) *************** *** 412,415 **** --- 416,420 ---- if (frame.getMessageType() == Message.MESSAGE_TYPE_MSG) { MessageMSG m = null; + boolean notify = false; synchronized (recvMSGQueue) { *************** *** 427,448 **** recvMSGQueue.addLast(m); } - } ! Iterator i = frame.getPayload(); ! while (i.hasNext()) { ! m.getDataStream().add((BufferSegment)i.next()); ! } ! if (frame.isLast()) { ! m.getDataStream().setComplete(); ! } ! // The MessageListener interface only allows one message ! // up to be processed at a time so if this is not the ! // first message on the queue just return. ! // Question, so how do we EVER catch up? If something ! // gets stuck here. I suspect it isn't getting taken off. ! synchronized (recvMSGQueue) { if (m != recvMSGQueue.getFirst()) { return; --- 432,452 ---- recvMSGQueue.addLast(m); + notify = true; } ! Iterator i = frame.getPayload(); ! synchronized (m) { ! while (i.hasNext()) { ! m.getDataStream().add((BufferSegment)i.next()); ! } ! if (frame.isLast()) { ! m.getDataStream().setComplete(); ! } ! } ! // The MessageListener interface only allows one message ! // up to be processed at a time so if this is not the ! // first message on the queue just return. if (m != recvMSGQueue.getFirst()) { return; *************** *** 450,473 **** if (frame.isLast()) { ! recvMSGQueue.remove(m); } } ! // notify message listener if this message has not been ! // notified before and notifyOnFirstFrame is set, the ! // window is full, this is the last frame. ! synchronized (m) { ! if (m.isNotified() ! || ((this.notifyOnFirstFrame == false) ! && (recvSequence - prevAckno) != ! (recvWindowSize - prevWindowUsed) ! && (frame.isLast() == false))) { ! return; } - - m.setNotified(); } - - ((MessageListener) this.listener).receiveMSG(m); return; --- 454,501 ---- if (frame.isLast()) { ! synchronized (m) { ! if (m.isNotified()) { ! recvMSGQueue.remove(m); ! } ! } } } ! if (notify) { ! try { ! callbackQueue.execute(new Runnable() { ! public void run() { ! MessageMSG m; ! synchronized (recvMSGQueue) { ! m = (MessageMSG)recvMSGQueue.getFirst(); ! synchronized (m) { ! if (m.getDataStream().isComplete()) { ! recvMSGQueue.remove(m); ! } ! m.setNotified(); ! } ! } ! ! try { ! listener.receiveMSG(m); ! } catch (BEEPError e) { ! try { ! m.sendERR(e); ! } catch (BEEPException e2) { ! Log.logEntry(Log.SEV_ERROR, e2); ! } ! } catch (AbortChannelException e) { ! try { ! Channel.this.close(); ! } catch (BEEPException e2) { ! Log.logEntry(Log.SEV_ERROR, e2); ! } ! } ! } ! }); ! } catch (InterruptedException e) { ! throw new BEEPException(e); } } return; |
From: Huston F. <hu...@us...> - 2002-03-30 16:19:45
|
Update of /cvsroot/beepcore-java/beepcore-java In directory usw-pr-cvs1:/tmp/cvs-serv16992 Modified Files: build.xml Log Message: start of new listener threading Index: build.xml =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/build.xml,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -r1.14 -r1.15 *** build.xml 31 Oct 2001 00:04:22 -0000 1.14 --- build.xml 30 Mar 2002 16:19:42 -0000 1.15 *************** *** 28,32 **** <property name="sasl.doc.dir" value="${release.dir}/doc/sasl"/> <property name="sasl.jar.name" value="beepsasl.jar"/> - <property name="sasl.packages" value="org.beepcore.beep.profile.sasl.*"/> <property name="sasl.src.dir" value="src"/> --- 28,31 ---- *************** *** 62,65 **** --- 61,69 ---- <include name="**/transport/**/*.java"/> <include name="**/util/*.java"/> + <classpath> + <pathelement path="${java.class.path}"/> + <pathelement location="${beepcore.home}/lib/concurrent.jar"/> + <pathelement location="${release.dir}/lib/${core.jar.name}"/> + </classpath> </javac> </target> *************** *** 68,74 **** <mkdir dir="${release.dir}/lib"/> <jar jarfile="${release.dir}/lib/${core.jar.name}" ! basedir="${core.build.dir}"> ! <include name="**/*.class"/> ! </jar> </target> --- 72,76 ---- <mkdir dir="${release.dir}/lib"/> <jar jarfile="${release.dir}/lib/${core.jar.name}" ! basedir="${core.build.dir}"/> </target> *************** *** 86,89 **** --- 88,92 ---- <classpath> <pathelement path="${java.class.path}"/> + <pathelement location="${beepcore.home}/lib/concurrent.jar"/> <pathelement location="${release.dir}/lib/${core.jar.name}"/> </classpath> *************** *** 124,128 **** <mkdir dir="${example.build.dir}"/> <javac srcdir="${example.src.dir}/" destdir="${example.build.dir}" > - <include name="**/*.java"/> <exclude name="**/util/Log4JLog.java"/> <classpath> --- 127,130 ---- *************** *** 179,190 **** <mkdir dir="${release.dir}/lib"/> <jar jarfile="${release.dir}/lib/${sasl.jar.name}" ! basedir="${sasl.build.dir}"> ! <include name="**"/> ! </jar> </target> <target name="sasl-doc" depends="sasl"> <mkdir dir="${sasl.doc.dir}"/> ! <javadoc packagenames="${sasl.packages}" sourcepath="${sasl.src.dir}/" destdir="${sasl.doc.dir}" --- 181,190 ---- <mkdir dir="${release.dir}/lib"/> <jar jarfile="${release.dir}/lib/${sasl.jar.name}" ! basedir="${sasl.build.dir}"/> </target> <target name="sasl-doc" depends="sasl"> <mkdir dir="${sasl.doc.dir}"/> ! <javadoc packagenames="org.beepcore.beep.profile.sasl.*" sourcepath="${sasl.src.dir}/" destdir="${sasl.doc.dir}" *************** *** 262,268 **** <mkdir dir="${release.dir}/lib"/> <jar jarfile="${release.dir}/lib/${tls-ptls.jar.name}" ! basedir="${tls-ptls.build.dir}"> ! <include name="**"/> ! </jar> </target> --- 262,266 ---- <mkdir dir="${release.dir}/lib"/> <jar jarfile="${release.dir}/lib/${tls-ptls.jar.name}" ! basedir="${tls-ptls.build.dir}"/> </target> |
From: Huston F. <hu...@us...> - 2002-03-30 16:19:45
|
Update of /cvsroot/beepcore-java/beepcore-java/lib In directory usw-pr-cvs1:/tmp/cvs-serv16992/lib Added Files: concurrent.jar Log Message: start of new listener threading --- NEW FILE: concurrent.jar --- PK órñr 4+óÚùFÁ ¸v£m!þgÄ©~ØoH>>»xÃyRaÝG»õ7ÚK·×^X³Üu'é2F#«utL¬æË¼6QØKã @0X1ÈÑ æU,!ø:NãqmùO=Æh8³²¹yqäÑOXæèD^ON§pl.Ön õ|Ø´ò¬û'Ò1.¡4pÀ7zÌXÌt&¶[ywý ZÇ'(Á7Ê|õ²`ÖÖ5Y]Õu¶.¼RÐ,¡ x<wÕ5ß Â]Ñ^õ gáÑ«f¡ÎÐWÂfÊÍðP60_5W5XżkxZCZuòÛ ZHèÓ6&¾Ràx$ê"ýoC[«ÚøZh¿Ô3ãQM-< õoäÌÝöá.Ê@δ&kꦩçÞrÛÝÓr qQo¤;¸¯Ý*³Tqp%ù)õææfLa÷«m4NÀdü¨*èD)ö}ìý~VÙKdÞ+2È"¬3übá«lØ×=$$ëÜ¥ÑuàyøsúÅK>.xÉ® RC±dàC÷1ìaßOÍÇ ? [T`sÂ4V¨ÀNT°4QA`zY'é(3#CØã¼mÎee.aµYýfÂIæÒNOK½ùÆéV90ïçMF%§ÿj[×rjå<I«S(f->ð6ÂÛ-l 3÷3ÙG¿/Nö¬úTì¼Ü|÷4ÜB¥Ã|éJz³CÐ(nÕÉGê[(kàH¨r@G×Ìâ&Î_ÿ@×þ.&ê"]9ÍÐ(OS ³´Ñc ¶'ÉQqÓ!4e0s¹ãåï9lÍòS,b]ù÷BZe|¿ÎsõÏÜwPÞRX×¢Lak "N5×6O_ë¹!¬+[X;oëÂÐûÔ¹:úTFâþÀ.>S(n-¦öÛÅó-Êõ>böN\"ºý°õ%\¶µÓ v¬¦ þìÂ%Z¿ÊμÆÚ^gÞ ×eFyÿoÆ·qç¯àöâ]\áê½¼®lãH9]ù"KoG~'¤n3ZªÛtª½úò䣿¹©-ã²³ìâ´Uqr½à-LþZm½Ì÷ùH?`AÒê*=>¢ÇÇ,éºÊöÁ}¸ÆÎdìëÀþ+Kæùe°{u¿Ú|þjÁ,R«àÏçÖ³äi$Ïa®v)s,ôQhïcÌU6NRáí!¬ 2 ¥ÏShq[/eî+ü5WßÐú[ð?n×9÷ßÓëF¹nüȹÿÿ:äÏ|¿ÁèÙ¼<ÏuZÿPK$ÏJ Â0Dç·µ©u#xºé¿àÊ 'I¨-!6Q¼à¡Äܸr1Ù¼a^ïÇ@ @!0( ©Úp'¤ÕzO(>öÊìZk«N½=Kç;y6:²n¦ñ¬Öch-+ïTì{ãÿjå$²®áé3*ª¿#_;'1éx2BÙÔL >PKï¨ wiæ¶N'$Ã4QÍ àCwPF¥òóݸy{y0ÁqÃG11Fí2xQr¹RJeòj¾"íOÓ;ÞôYSésg×1Æ·XP%0þ¥÷W ô7ÀÕÒSÛfÿ Þ¸Pi:Ï ¿Ô?{PÖÔ¼@BYnýDK'õZfF©Õ¡ªÈzùÅtãíëà½×âͦ[U|¢'?¦ë©ªBé)ûn]W@ Å£¿ qÑå,æSÄë'Ûè5ôÉ.öÉ>3àýç> {*áâïÂÐBSN|¨»Q5³Iÿ$v¿ñbpPKª¶»Æ ÕMÍ÷I6ÍI Ê»_HÓ¶Içä(J)lo꿯¥7Je.8v+3³¶(ß«*1¸f:3>nfjî£Õß|p\÷Ô´ [7»4°ûì¥×4úR)s"êÈNä§HÕ° <D=øÐH0´hÀØ£;ã8(ÛAy@ó¢` ¢hÑ1i ã »Ö!KÛf6¶Íä:Tñ)1áKÓòrÑÀQ¹ôQþÐû½7{ ÿÕªó|<6ɶ÷µè2Çãù]´X£¢kÂ$¼ém_îfii²¬x>0ÂÑJϲ©Éjk--4¼·ì zÃs¶9¥°bÄ2cV*e:¥_z¿ùöp`@a7thR.Î2M*FY-|qä~GjÂG6e³#+hϲr ñíÜ/¡ìÜ ÜBÉ(å\kZÀµ °c°?ÇXvÔw ¸¬bò0ÊÁðm4çQ&U°@bÐø¨Eµ _ºÅÓYª(EqÌh-(åz§ßßÁ6¼íX"a¾KÂ|p©³Â|V·iÕº /C)ðExEp±Ðm!®¯©M@\¼ªÎé¬ë>sM, ¯üÞ$Jh?c)?~Aí_rü¡üð~C«ßÒË[èÂïiý|Àüñï3Yâ-+ùñÞ ¤ÄîÖ¨æ×w·¹w{??Ý;ÏMÔµéÅÀÃwà«qËzýÚßëÕ¸Q¿ª5ºi¶¹gï¾uãe!¢>ÑôIÄüàY#b ุäÈBÄDZëññ_ñ_ñߨýw»·I×°,ï0Ú¢ÿ¢õ¿ùì]+2JCVyÖE_-"b2üªÀdmWBì0¡íV^+UãȨJº2 «2«rìPÜáGèÚ¦caÇag*iI$AÎKé¡2éyÐ*\ÊÖ÷¸ÜZÇ-~B$AhõÖ]DUÚ*åGªC£ªç'')bÇ PÚ·ì@6xgmäl*sq W«ÇïfV¶{æÚté¯äªF'ÓlÁ3á¼×ktÚÝý«µ´hW:'©ÔTêKÜEiÔC£L*ÉV4GNm±Wðc:N¼Ì8úðaG^Ágù2¾àȽlö«ÎùÇy_uäUNÿ««ùgAu2ß]Ìwöª'P}8¨úѦD»@:5êFÔ0Ϊæù4ÿ]yi5¼:+êY¼¤Æð)Çg/©óø²ðªÄk*µ¡läBoQ²{аqlß®ÍBsµWvÎÉè.|4ü¨§n=¹_¿ñS®¦Ù}Q¯²Üíän ºþPK;o DпÀâJüf"ÄÄ4½ßcî9ß=çûöóóW /ÆW*)Éõ"Deaå#?8´.ê¥d¹ªád9UZ&ö:´ÒºÝè!¶¤ýXßFSÞáP=fÌÐýYB\£]8س©J ½õÿPæ©ò¦ïTv!ÌÓ;ÔcoE#Ló; §Ö}IùãBª\/,5Io þ®Ò¡5T¥Å"J<´i;D¢KÒR]§Cñ¡7¾7?ôJÞ3R©WNr^Ò~C-¤Øó¤Û=óã8L?Z¸åǾ¾'wIç=ªï#AûjÄCB?B'ú 9ýØáÐçÄÇKb\×Âb}G~¿'æ¹Ì°ò 1[EEÀ\ÞìÛ}3oÞÓþøùí;Öë¨bµm¸dÃ+>® xÇQj@kxG2ô¡|2:Rqy_ÀÕêMIØÉÆ, kòÍ4* Uܪ±YñZf2.ä8¦LRg:6y®t)_DI¹+õÔ(£6¬ E½83ªb[ ú ÑIùP Ýý·ï9[o´nvÌd¤ò½hòfáeèRå^(¥{ݹìl÷è"Î&²9Eæo]ßÍL«ÄÎÔú£j` N ¿BbJX ûS¸yÏá[ä é.Þ*Ò`DçéWËùv cÁPÔ+.¢¸#8û4eγ+8%47Ñ%ñ3j8.ÊqlÇPk¦±Åç< ÆJ¬)já Îè$sÌ#(:ß%xz/Â;%DÝû|»+Zb¸?/ª u*ÕíJQ5,¿{Íùî#>'ìW&ày×P§Q6T¿gߣÐgNç#Öúgfÿ üÃò3#3R¤UhBMG±ÕÁØÄ8è`N6^´ÀI.ði.ñ þ3G/ð>~Ûð3O󤾼>¼$^§Pgñ&Îâ-¼sXI §r]^¸(y}ü21^JT1©B5:r¨µ#h¸r²zϬ¬Q׬®nÃãzw*$?zí^áw&d¸ÞGáKÊ,Ãåw^¿{V¤cw%Q-dxWäî5¼b%6ʵTÑë¸u4 ÄìC/±O8Sq/Í ¼bPÏóÌú| >Æ&|¬1Þzã¼Ý&`b¸D»}FÝ/ãYLá®PÅi¼/y_ÎQTÐyEù{,rì_IE(í]¥³G½X42sýVC~¸8~ž&Á7ÜÚoQï H×à<é)ι[$cWxÞïÙstÕè$7)y®\Wøj~Ú¯X5gßÚæj«özç¬üÀ~Ä"üDA~f?¿P_y¯³ßXûwpøÂþYÐW`öÜ)·ØòдtNS>M`Éís\Ê5±æMV)`ªçä qÉLÊùB*Q]£L(T!î@îºÁ9M6ëé½þ_7;nÖèæWŨc\éÎ na½q°ÿÑnb7s0·®mXÌGÅ¢>±¢Õ¢uÂõ¢ Íb)¶jtex\ÔÀ+1(ê«qB¬ÁSBʸLE< w52Ëú.Tÿ PK_V3Âm ݪ9ï/DöÚ\op/<L6îyAT«ù"äN¥Æ %:©á2Ã,w"ÓóUß´Ó©þÔ¶}ÎJ°y\ãÅÊb)ò4[åJÇE±j§w4·¡·Qk^ÿ¯d0J÷RåºeGé⪲©4êô«äí¢Ù5"Û=0cj)c`Ê;Z¢;K¶p(O¡*ÏUã²Cnô$ 0Éï¡Ð:ئ¾$þu]## åÙÞzÜ2®MÆ=ùKÈ+²}8ÌÐ'¢±_nc,Qܲú½ú¶¼ôÒ2±d'=j¢£Ëå :©$º|G´Ô&-ÕY>Öi} ~K´RÒ²æÈÔÑá¤[ïØ";¡Ià}hQËaý ì0Q :õú+ÙÑÓßÈ{f)áR\;ý9Ða_DîPK9°k 8åÇô 8@?ÎØÙ 1ÀôÈ8/#)ã"Óv¥hÓZÜuô|<¥ÛNÒáæV?Cnäø,¥%|ΤnwtɸÄH¤oeÜ Í $ [¼fÛÜfNñ7í~ßgíx._ÎFÖµ,n8ñYK·,ÝáC¥Í UI*ìÏÌÎ$wô,>£º3À0Ùºt2zAJ9ÎÐÒ >îNMpëº6§<©Ùã|6åDïP¢Q"ÑÒå5ã~<=ñgEu}ÅâÓºéÒ¾k¡_Ð¥£#!:¼úßå¨ÏâSæ4/.SC^S¦ÈßU«Z.Gg1]+ËÇtÑhËFûìlûÑ¥ a»Ñª Ë ÆÑ*#à ®*Ø GpTÁ5pDe¯aÜ̸ÙÉÑ<¢SÍò£Bö$*1Á8¼Úð ÃvÓrx.]¢ü !³Õ¿nÍð·C·?Eæ-Î0¸Õ¶èräz7çL2ϼw¯øïwoJ®_þ µFÑêZ²õGíôrh£w!azï[èÖ¡µv_ ¥pÜX.,zI»nW$ªÀiäóE¡QÔ¿ÑÑ^®kÙ³x\ͼÈ×2 pzy{òä^ÐKS &|Hø0hÜÈ1豤^ÐRåçË9Y^ãJgö©}6cqã¹Óóz6SÒf<ç6IGKø,¬fë*þD=a£;4¯Hÿ<Üp×çgR3¹É4ÄdH§©=7^n¾/I§¯g¥aO*"ªk¤ëÙl9ÖêJgWq¯:|:G:¸ç²Õft-O£gTVqC.<Q±®øàWqgUËa~þjø¾r³5¿ñ2«Û®æ"QÈi/ÓåR:3Ê \±Æ«³ê5W2õÂJ¬Ïk¼¸Ë:PEN¼+8Çêky¬HÎOUÇýIöqIÅ(ÆT\Á¸«S0w¨²ª6ÑP}?ÉÀ:ÅØl\û¿Q$äÈ^2¬³×%3-Ùê*GÆnÏ>ãµöÈÉúºV`}É9е"Ek˳ÑnKɰWd}ÖûE%±áØ23|0jre»ãÍ~>಺9ë5mW,¶3 È<¿hG{^£ÎØ{qmQÛláhϵçDîs¾ O¶Ñ^ÁUpI¹ÊªDø{.Ú¨¤ }íD`ò[Ft,·p2"{01qv=Æù]¤<*bܲvà> -ÎÃ%.0øE§Q1ËôbWdHÄAëqfl¡3Ü mDDp×#ì°ä¡Aj<¸¶SÃFva'1(¦¸;ËûÊ+ò ùPäÙõþÙ Ùðí,$YL]µáÛåA#|mbp;|*Ð?VnÞK)¡÷õûEÚu½?áOkòX¤£XbÙ vßÀ!yÝ·¡iÜ$ôMܶ¬Mè,ZI(AB·Hè6ºDýb!¸H#&î %îÒûê~º¿'I2bÿnOªl-ÀFÄAã°5¨¬"|fY× ÿ%AÌ×}êð:, O<_,²!*Ó3Â6§{L¬Ô¤¯Ft/·Ñ3;²Ü¨ ÓT^ËÖ óñÛr;¬àÿÀ})ÌÜÞ Ó¸±¼ueQê!¥ºb¼ $á¸cÙÚ÷"OR+$õâè«HgôbÂlrßÑO 2ýQÕx?ªô.V5òZã6úì"Ù°ÓfáÅÁßuËÖ²ùlÉ÷¨KüÆRyIñ;Ï\£GýOYÉlâ£:ÍSyªbPKÛy mgif¦í$Ó6LÒériÚöÌt:sÂ|÷¾'Ùbz&3ÇÇïÝwïýÿÿû÷{õ½_0o wxa`¯ }¥¸w©ÇÝ¥øîQ{½ÜpÅ~5º_=îRÑjô=láZøØ«¦>ïÅ<æÅA²°Hí<lá ǽ½<¡ÞOªÇS<ÞG½àõØ«PóâY|A=úÔã^| _V¯¨G¿âx·_õâkøºÇ=ø o¢Þøññ¼Räy¥,xÑ^ôbNZxÉÂ)ïÒÖÕm½:{2¾Æd2^ÚïéIôr1HÇ3©´;NÇwo¨ZÛtK|G¼¾+ÜRߺéD{fK/øk§]7¦:åMÉDKï¶Môªø¦.θçw&;3Úé7 jmêÞLgWýÒTWÉ;SÉyjmTmÖjÁÝêÞÝSlGc£ÚcötîIh)VgϲmÝÝúû&O{*w&{EdܤH]/±L§/GíUd¯^(¥õ3YQ®ö®T¨«k§3ªI-¶Í^[Ô4E=alIdEY=juZmcvE÷Ç;::Åö+ϤÛR;¨A©=XÉu~¹jm§ºqóâM=$¥f½°¸«ë:£Äæ¦÷q¬ôØG~d^E£6m"®ãZÍêPL 7/Ýh¿8w¦;3 [KñΣxko¦»7ÓI'âÛ´¼Ëvµ'º¯ßRÌñ,ù¸BòÆäpj/3<3)Nt&·F=K7¸Û{ã]_ÏÖxÏV;×<¹ä¥Òºet¾.fþPÍÛ×4l{¹)¶jõdËHµrnÁFnð¶¥zÓíå*ëK±ÉÕÊ:Õ¦Æa˰\ ¢0¦,úp-|Ø=Nûp«}x->4b W}x ¯û°K|¸m>ìÄu>Ü F7bµÀìDGo}ªggbKª¾½§¾£ËÆÈÈkïM§5õÅ L²TådK*ÓÖÛÝJg9÷ ÚÖ¤qñ®eét*í÷qÖÂ9¾£Þßõá{ø+¶aÀ¤á4*ñ{3¤z=Ã8*ôúÞÍô¥æNðá¯ñ7êñ·t}lBËìÅeÍïûÐë,¼áÃßa¹ð!Xø¡?R3ÿ¨ÌV6k-¼éÃ[ø'ÀFä;ÔÛp» û°M?Y'ë0 äO}dFNS|~Ê.Uà/»ÙTgS-îwuî±§«²ÓÃ,>a8öDº|¹òʰ-ÕÅ @åŹÆLìb YLÐ=Ým»{2m¬eºªn&)Ö".ÕÝ<,ê$É«zÙW^0Eñ$µÆIfVíîNäEo:±Y©SïôÒdbgc²'O¶sßÔÚ$ï&îxww"É«½¸j]\ÈìÎ+5ÅVýÅÑc/]éÄæxoWfõðÚíѼQõ ³V²hsWçKiëÃʺ¥j¼f\Q;â]½ Õà§W¬À*^xé³¢Gy~mÓGJ&R¨áQÒà_=æbö©ºÌ³sUuåÌR~ ù|»"ÏCç@à/øtëÉu|²;[ë õlYädÄxÆßÈ ,`L´ÃMzµCz×L¾4iô$Lc@³±° Bx!b'áhãË8tá½!ááóVòêÂHß1¬c¢Ýñ=ÛµÜkrMÎBÑÁx !ïâ¦Ý¼&crH¯KC®¤! Ï¿B÷Ö½¨Â}ess8sLëÀ;Ø_`ÛGølF³w³·{KÁ2û` $óÉà\éØt´bß\ïðEÄ6Æ/P>âü"g¯ÇJI½Ã¤<I!ñ$¦åpº);Ä=ñs*g+ÜO'CO_ø}B¶g¹0²ÃÖ~+Dàåó52{%l´å8K÷¾m ¾(mdzÙúUû ÀÍ÷ ¾¥n°ÁÃP«u~±¸ý®þ}.áwùMìC^¬ªU (oÃ{Ã0Í¢ªÀÛTü<1½2¼Kÿáö/·wù_2µ~ __ò?cÙ ý7 øwZöи×!¾ Ì|Û^¹ð>í ãªÅß]dÛÉîJE#;Çaa`²01C¸0ã+ ¥ñgm{!¸ø^¢mK»5Ú®¦¶«Ù¿Ï¼à7\ø ãõ²ªµjnù7ðÌ@)£ñcP"(c1Jàx²#"Æa¶9/5¤âÏÁ'e°: §ù\~ͱè FLegté;Þt kN ê´ÎÉüé@«FÄ¡ebÅ×c¢IñsÇÇsuq®#n§¥4SFV@N¥Jå'1üмQ->¦ù¬qø´;|.×a EUt A«¢ ZÓ^fæÚ£>Î5uè >Q`Ô> þjd}WÁ%çÂ#ç¡BΧô(b2Ç3ä"csNâsçÉ&¸ÖQPC _MQ7׬$qe*àhËEÛyÝSÔv£Å<XPV¾yt¬Éfl!ÈV+Q-Û0Z®BXÞ@7èjÌá÷b¹åNnÀZ¹q§[þO üÿQ l£I*ÐM¶S4è¡è¥i*° ÜFn§ ¤[Ñé(ð>(QÇ6ûà ¥>» ¥ Vê ¹§N¥ã!ð\~·©Õ xÚÔN#ß÷»5_?.Ë:#à1tb\ªªçUdtmáÁò³°ä~Æò¨b|!ùÆËG1M~ùy\.`¡|q}«8·^>| )ù4vË£¸S>ûä1ê~Kîò4Ź<\|qòª+ OIùUÜó÷£ÙÚr¹èúP~ÇQÝÖ1L"u ¸ì»ÔEu4ÿL&OPé©ôKL¡SÊoQÙQ/1[ÆR¾ä¬¯j]Âß;}ò#ôÌVªÁôvûíê²5riØ4Ü~÷¨²©åq£v^Ì £Á£tu÷ áÄJÛ>ð{ôq>på+»wbȰZýåòGôä'ßÂùc\+Õò§X'ßfäÇvùÏôæ;ø|ûù> ÇåÏYR·åÊ¿ÔakF0tôϨR½àú(ù>ùoÉ-É[¬Ô¼opî ÍT¡ëV¬çÜãzrÚû=b=UQ5ïmÌ˹mÑñÁuç(¤í9{ãüìo/ïûó#ËXi¬ãÖá5Öc¤±8qîÚ=¹rgÚ¿gBÃ¼Æ \Yðó¡ÊÈm¸ýC²G|"w'4k²sàùËøbièd_}0ý(Æ~û~ÆÉTìA*õ0ËÝ'ñ)GܵÎýcZî°gó¡cCç¼S³gò¸ªàhünã?|b^ü'}ñ\ø4èsèïùð¡ï ðý7PKS ¥ÅNGä?|ÑÄg^æ DÔh" ¼ù~?à¸ÚºWÏÞ{í½ÎÞçûï/ß íçE{$Ôî7[Åvü?¹æZ¨S¾0sRö¾ÐhT|Õ´ÙkySB]¹Þ½,ÆlDZóg¤4d® ÒõûÅÚuÇA î1 ÅWçELÒ_zÚ:ékôOtýäì&b7èH-¥WhfjHZ"ÊÄÌgÄß"õOHné£íu(úG~ ¿ßýÙYGÅXf§gkz´£´tEXjÐ v*qmîà8±ÃÐ1£v/[Â1FJ~RXÑ;$a¼w;êT| Þ»Ó/¶T¾áIHð(¶dQX¬§Q¹2®[MWM¦$îþR¤µÞãÚeÔSò[·¡'B£N@D¸ v¤±·Kß9¹ÌËE»°[:¥0UÜ¡b@²Þí3 íZÓô§íi߬6Ìk6CÇ5«¾Wmí æäWÝÏçc Ü5æäO (ã~ÍØ\v<ûX³^±VÅ¥%a¶P aúgªölèø^C@º]ë¸ÜD~7iÏr髾U«Z úôI¿TíÃÄ3Æ}¯vÒ g¬§-[Ño`®Sq§»°W`@:L×ò¦Í#^hAs6´kW÷Uq·µO{¤¢ý _ŽÆp8hàúrÿKÄjU½ÝíWfìj¸ÎtâÀ¶ji§[ZÄ Ï¾óØPÛµ¹P:Ü%=?t£Çª>Õtz6¦¬íw}._ÞXïZ»Zƺ*'ç¡]زÂ{:긮Ójè\¯Sëì|Èu1Èíes/y%8ßÊÀ6® q {Ivê"Ôô£Ô©]íâJ©cÅÝíyô´°·¤Ì#QÚ¥D|$ÙB¼¦ ´.© mÿ¼-yÚ2ôE¤Ï'ÄMÈòY)<HoR¾Ë=îaïR²E¤>8ÕLDQ-ÎæòqÞ$ÒÛÂ;Èã]6é3/à0.2{ b0 ð(.£6fp"I\ùÝH¤armÐóâz:âc Qºdµ³¯a`ƾD!»Mõ%ììÙW¡*-(ñ±RBI´3ÊJÄuF]c-%YKµKZ|DßÈZZ¡¬é]Ö´ío¶,b%öá8~GºG;E} v¤gñÇmSü´}ÌÈO¸úHñ÷9ûæø¸_ùkRö Êø9ßé{ÔñÑ~Ä~"â/x¿â9üçñ;^Àÿ¢q7³«:Ý8H-dJº¨Ë1lÿÏðáI«´ÐCöPKét w E_î{gιçÞ;¿.¿ÿ M×m?Uò¤®¾ÈÂ:H²4{qß)q¥¼Ò¹yÌßq³¸Å°ÉUäøRK7²ºû!§:NiÌØhà»h2<þßóZsÏÿû»^ôµÊccð±B[µhÛÜÃlZÊdM¡«ÆEQ§doS´HÛ}¡Ã²µ"Ù$²æÊ§Ï&Ï6Z0qJoêϯ0Zç{s ý´©ö:ÅDA3*)À$Ø9joÔ{:ɾ¶VáÌÞ¬êß`ÜÔ¸D¶U´8ÿPK)4Ø ó1¢ ¥à CgÓ¹²zBäÃN-¯éäP²oÓP!«JX=¬åÕTyfR-IOæhi%O¥Ï¦ã¹t~*~pòÑwûªsõÍ^kA%¨3 ÏP2Ù7A{é\ú-¡a5[JçÔ©B<Sgsñ²®åâB>S.Õ¼Íg¦ ¼öMæ)D>·ÏÕÂ\gUkmOg³\¥ò¤^LghpÍsºv&7Ë=dµ³x!g^Jë\x¸«39+4ÏP[¡Èåbt4]T$øB ^X¼úB9+ÝÃïéN¦kyté Q½¨å§$´úêÜkÖÜÏh¡\̨{5äÖ%ï½Qxѧ¼èB·XöbG¼xõbÛ½x!/¶!$aS³©qQǼÇq§©ø±tQ«µGëâ« )¬×Õs ¼Z³²YÆî>Ú¹Bæ4ÛsírXBK] gKº:C×5}v¿ö¥ ]ðy¡lP ôò¬`C`¯|óè¶sÝCLÂ}| ·qöoB ®ÃvOîç¸ vÝìÛèÁf\Q]Þ½a`ôÁC5¢¶fà±À¾y82ÏÉ6©+©H56GV á-thÁ:c®Q:9qìjÞNÎ=äpD ªAc+ýr´ê+ G´êwÔXÛ৯¹ð[¬mÜ"°è6x±MÝA´Û®©LÑÀ&Ò;S±ùy|²½_öÉá )êû±ªÏQI8cU¿³¦ºLà?fÌõªCDws½YÝKtÑ¢¦êSèæüt$|ü7 TÂ#Tô\1þ? §¢×àNÈ~y>v ÃïÆ¢ô½üaýN¿£ê«>g%¡¥2pñÙïcâ?@8d̰Q<smÃà(k9ÆÕ1hi:Îæ`:aÔ³dz;q'fd̪ù0_FÔ<ÈÔyEÍ3 òÉëËJïc{]oÌõݤ=EëiZ76d^i1gb.Õi-Ó·+EL©Ì«Ds æ±çÁhµ³`ù廹˸_&zÖWhÝÔ{µÅmû5¢¯ÓúæÃ ¹[,îé&¹ß$úoÓº¹!÷;×$÷;Dߥõ=Z±*yQ²É½VTR3Ì .vó(ëòZ#ú#¢xm\&ò1G-þQ³SºÉ·nßv¡±@Ûüws½À¢WyO|BäS"[¬ä5ÓK¾VÁ8o ,ËÏD×2Ï~A/Ü&ÒßPÂgI¼Ú¼Ä¢ßPâ["ßÙÚP¢Í¸Ð¼ÄD¤ÄOD~&²ÍØb~:üâz>b»Á Â0ÿè´:¼yó¬û Ùæ_s©ss»`L~Ô¼iV+¾øÒJ`yoS¼*uÔFÙguÆ&̹ÒV7>Y©*Yh|©¥²FçØxùãÿÁíñÌʦÿÑÚxv.\<¿ºBMPBh#ÜÔÔnLûzoPKéwØÏ± £{%4W -ìÃþ0A«J]¸öR&CèA á0Cäá¸ÞdÆb¨Ñf3W3ª±¦Õ¾ee²¦èc(÷f·6wi"ç«¶» ¦mUwÕ©úaªºmé¾ãËSÏÛ¶)r#B÷=Û!çpúåÍÏШ߰oa,¾e¦ÍBk¿È²s!ªHùù¬p&¥!àøa\n¤mßÑŨ! Õ;%±ZÔ+¨F)ØúºÁQǤæ8ºÐ#·D¯>ô24G6nyÂqüyOÒëbÞ3lKA?N1toñ[/ÙÎp(ikeܲ3df\W¸UëÇËÎ Ýcý#u3¦E±#jãí·Dh$5<9>Ka䩦y?/IÒÆuAmÄÆ¥:³øZ1Ö²3htʵX'ònb£#o¡aÛ¢Eß;g5Ô,h¡Ë ¬3ݦ,:évB~F-vÑz7ÍÚh M|K$Á˼'Ca9IðÔ/«N¿:HòVâ#ZòÆdH°Ëä«ÐC¾2-ùåoÑ(rÈZƶ9\@397VÒFJ¢âͯK¨. ^[R@ÍÄÊ:¾§T+Øþb1LA@! I(`¥ù¢,ýÃ(%ü6Êøù]Dù=ÔñháçÐÃã43ü)Fù3hü9Rü>¦øþ& ü5¥ª¡ÀFz ±WÒ[sÁ¿PK>i$¸ hâPâOB.Ýìm¥ùÎFÁ8b϶ü}|¾½cVc§ÆaÖyµOâÎlî5ïÖæÙ°7aÅ%Óy9=Y håª÷B8xPõâ._Ŭq>fj´kq 5½ÈJÙ&vKî=[ ¶Ä(!óïäÑùæÿfnLp^â@ò§ÓÞ ñÂ$öﻵØLàRTÂcѰ é0M°ý¡7ojìVíPK¨Ð\Ñ Bß²a7kd¢ö?õ¡RüýQ¥wVQT|H ÷Ìý<3ó÷ßÕ5U,x(!¨`Ãx.&]L»a(nÕß2¼kÉ(ç:»ÍEÆ£ç&N¸ÐJäi*áûZ'2Ú¼"7:]c¨~Q¦+M,hÐXÅfá}£ð¤¥cÁ¦$Cµ+¹µez¶´-NeôQX+ÉF«< UäJÙ²µ¥ÏÞ¡ÎS!·bÛ6ñcÕöøðPóábÈÅ7¨¹gX/¸oXOºRmÜ,Æ0ú8àï(%ÓffÌÆîÞk÷¤0rÞξñIíPELIg3 +lðT-J¥9IÉ.zB%ÐeÓX +°CÃäûä-ïzË¿ÁW~ÁùNÝ%YÛçÙQToëë¶~håè-|½«ölÜù²óNc}¦q¼&ú¯0E¶L8[öÿPKÉÎ #×¥%Ê}ÇV^?Sq²ÌPX#UG¨Ð'¢¡ÕMëÎÐLµ'F3ÃX+âaö¢- ¯ÑM±ÅþsÜöUK²ÓÚñ^znäÉm÷q&¥-×2Xëqøân¨Ã&~ϱ clļQØ&®ØpP3Q·ÑÀUCÒU©Dd]¥Ã}ÑÕyM\³i¶®EÌ3ܲÅꦪÍwúÍP£ÝØ«R¤yi*RÒaAkíá+{Ãfp÷}êâ¾'H$4Ä~É9zîF:ݶµõ¡~¼ .çí_PK sÅ î¦`£c3ÿäÆ .ÜàGw´ .È=97ç>rÉÛûÓ39ûpÑW@e=0ämS%Só5¦Ü$×òÌpð0â©UF4¥¶üÀH7R¤ÖÄK ú¶Mi DËJ+»Â°Xm;Óô1»nBÉÐSSZî¥ <¥FdÄ W UF3WkçÁUÀ£@ñÃTëL¶4}Êà×M¹¥²°þ5æ²" ¨çaaÍ>§6T"8<iJ½öÕCù/gqWk¯GAÈ¡÷»áýƹa»ÝÚÜ_±è01Íãß\5,o³&è¸`è ]ÎEØl9ä/À'ÞEl¸CèÏ<ÍÌ>À¹'F''óB¶î¾Bé÷îîü=ù{1DX¦Sý¤z£ùâPKô6%q ¢¬vw²WâÈê!øbºí,[¬SÒN½üÿ/¾àü>xÅx ¢Û¦çôÌù¾sf¾ùôëÃG ÃÕ6Rñ>Cz&ô8CwÕüNò¸Î£E§ÐH¾î#î]u¥ A«ºâ<qìÀËö½D6]|À`,Iäò¾Z¶'ÇZc¢eyté8iâ&tØ&&Q1qgtL82ÃÈ6Ã<U©°\¾ªÐqÎÄy\0qQe϶Ùïøu?vÈ«åRk-2í=eÎ Á£Àc3ôlX«¯pW2Üj·öfL}Í:ÂxD{¼çLÊRe·ÉÄÐÙ$Z£ñ¡ôo}ÌP¶àIÌúß\RÐjë·æÕ¿7:ÂFCu0`íWòéÝ-+ê7JÄÍ^lFÜ¡ãÈ·ø·â>ëOÖÍQuEü-ý`êÒAÒ׫DH¾êÑ&eîÛ]P^À(½+ß@{M)l<´ÏdûÐßÊç´:E¾RZ¶TvéZQÂ4^ [^Gá%ÛïÑùÙô+,è-øa"ö]ÚWjßPоÃÒ~ÀÖ~RI¥âù^ú3(ÿ8äKó7PKÆÊuZ ')Óhfu{é\ WÆCS64|Gàä¢u¿éÇáÐFoÈ4#¹ÝáH¿ü¸`}ë÷¶ö®k:Ü;<Û:¶lÞܾճ«U@x Z¡hÌm÷ãæTjOçTj!çO·µ¶nq·{¶·vy:¤¨MZkçú.÷Ö6ö=Þ½^WÐêutÈ»;h®=àÝl [××È@(c«°ß4ÝÁÀ^³+0 7òúhÓæ~:ÚMÜî3{Ã._ÔåºhuÐå|ñHÄÅ\-¤AªË¤ÐvºÅSmÞ½ÇôÅ&Zób}ÓëòsVÖÜá$aÙîì^&±çì¤m¼áHÕ"F5¹MtF¬Y@®Ù.`k ûM '2;ã»ÍHt$ª=ò¼®úܽ!éëg@o)(î5cé!³°1m£Y,úôx&)37í¤\å{ýþ.ËýÌ¿êl¹#ÑøH3ÑÄbf$¹Ag´/ó÷ Ü=ÜÞ ûÌh4êmI<pEÜþ.o´2rüo DÕ5SÞÊôMmSsÑ2>;:íÀV½IbÔ÷Yn}8ĽUçàïÜHÜYË\Ú%JÒ p÷IoÝï3eÑIÆbÐFï\FÒ St_f*ög)ieþ3VDÍ´ÔÐkyM¾`òè[ÃñÏÜI^:¼zéKÎjÕÖ!__$ Ç£Éä6p-¼rè1Ð vÛä°W0²UÂÀNì2p¤èÆ7Z&se£7ÚÇ"aàj¼K`Á$¿'4{½Aw¤7>@©P ,{{Y!×À÷ð¤§<g4<kà9|ßÀ¤AAôèà ;Ô`<&°¼zú{gúNM¶GQ_ÈÝ+l,ei½±%̺æÞ'mI¶}ð T®;§¬7s½W¤Öy° ¿×ËîjÍÛ¬Ù&{,çÙI5{«u~u^"{¨µÏ¦À¹2Ù©9îæÊAͬd(tØyJ±z¶aù³>:uC\qÅçOòÕ'(à«ÈÂvq«Åf&ÙªlygVE·A·[=IÈ!%u@£XA®Ã6ÍQ¼èTo§zcHxVè¨ÎÌrÇlñ´xçMjªçgC°nèbf](>ÌýX,Ã)îÂÅâÅQ¬wÝ?fgé®Ç#Ƚ?%2Wnû8Rj AÒÔ⣰D qÊQAxP ¥iâºiEâ8w÷dU¥eª:ű?ª#骴LUÏPÕ³TõwYUfªzÃOôj®l/vì$íZºü$Jw:'pA]^V;rt^mÝ(.TÑ]w@.¤\èúQ"^Á<ñ*]þ\âuR1Ôt'MÊy¬®V°VÚÊm§©¥sîEáÍpÐms_nB¹5ÚWæp.Ï9u³*æTÜ3þTåý4~6s¶òjá²æ\fÍ T& Ä[PÄÆlñT¿b®øâ¨ÿÂJÿ&Ç{R÷çzÎò¿fVKxíÎÓÒîQÚQ\Ä»;":d¾ÀXÐI?,äªJàðø[NÕWÚcå¶SÃ4U#K)èR¬°æ¬¹ÜMÑèÖ<,Tò±ß+v4)¤¤ ÜÆÀÈÒ4 ¥ð0ïCÝŤc28Ç¥Ö¼çXí)ÎzF±Xt<j¦!ºr*r¾y¢KȰ$ñÖY% ¹(Sæ¡BEJÅX¥T2XÝM&Î µé$j¡:G(òGáTÑY÷$r¥»è¥Ú¡ñ7;mMCã¯WB~Yí1 *`YÐÀe5¥º²0Ö¡RiÁ<¥UÊ:k#uJ.SÚYùrN¥½J{ýô´WºIºû¤U(×1E'£j)^ä(»iÝ\¤¿&iíÚÓÛâ â%t×Ê`tÖÕ%`.UUÖPP*³Ké¡{Q¤ôѶ 6RX³°a¡l¡Â;ñ2¤kõ;L+ô$C¡ã+yizRwE/ $¯ä°û¨¥ðjµÎ@<Õç×F©Ò¬ÿ'Ì&}íʶÌ(Oà¶pãP¿ÜFR7³í ¾eaá\zÑPöCîFܸý»¡rÖRÅüßä3ù LOJóaçB)©["MrÕH7fh,¶Ce¾H¤ññâ¿A: ®¢£,OÙyF>{8{£D'»dáüR«HS3ÿ@êþhôë}Ê+ãV±IÞ&4uàü Ê Ö âÚݨwÓîVäÚç ía(B\ô³}ÅÐê ;æ~x/>·Bn»<[¾gÅA ¼O)î2È{çDû©Zý!ÝömÁï:8oû"è}*z(fÝôkó«ÏïOü»]ûzæÇ%:NrÒT÷<AshÞ¡1Î'à½,T²;¿];ñÃ]ÓðÓþPXªô?dú7ôF.R´&Ãh×ïÝo.GH½ ý4frst(_Ar¢>¡ô®f<#}llØx!äÓäËX¹üFäqqdW)K(`²JUdh_PKº²XUl Â@ ßø¨(ÀBÜ6 UܰìB6«àÑ,<±q÷á=¾¹?®7 V.>Áæ»÷ëØZjÍÙ\EÖ²%t¿#ÿàzBåPPEØ*¨¿ÔCXx2ã#ð'PK£ûc¾ ºÒN>0R Ò:<dÑ1£ÛæL ÛN&?ýaéíÍÄÝIylgö8¥yõHñFÜÌ 'yVÅ£:NH'¥}ëù¬õêZÓåËÉÍstV¢¿£|æ!¬¹±Î&9HjÊñ¬ýÃm¶}M׺¸ÂLJ-a'¯Qu §ynx~rd?¶X¶m³Ë±ñÿ_¿<Ù¹12£n&g,©?ûæ%ÔF ÜÒþõ9Ä'Pñ[Z¹TGò§0òªÖoÝ÷/[iF~ûÂüÞÕr*ø ÉòiKç¹bZ-OºOùdûr ¦*ã¹õ¼¶2×Ìò"¦Fý$¨gEã(~?óªùÊù9þÄÝG Þk#d¢D.¥: ¥þ,Ê'QƾÔ)£~Ñ2rczOý©qT¢Ò¨ÿáQTÍ28ðg3¾J¼øËðnÆçWó×Xo¸ qÜK¤ èÆ(ßbD9RËùi¯¾î;Nö2ûÿ¥wãr SbZÂHíÝiH©/ü;Y{\oú^ïC[Ît8Ï,ÎèEFp Æ0/ËE^z?z)²-ÑK-S½z! sse¬e>mÂ-> B5ñO$àG¶»Â?ñÆ~F þEø#~ÁrüÊk±ÃË4x˲seF´XÃó×&M±Þÿ.⨠,iÇ<d(@ ã>²3YÌ?»Ø¯É £0¯vGBÞ÷Byö1h9+Í^ `$Ô½º+B%md?<¤ó¬n-ÇÑXÖÞé¸ÿyÂvj°U®ãSÓsa ³,!/''½|,¿PK².òG ¶=êØ °ËPÏI¬ÔjRI{ÅPF§®u&:c©Ä½[Ì&³*ýh4~L'jÎ'ÖH5¿ðp¢IÅô¬ÞT.vöæ%Kï2ôêØk¡À£Ã¹È׫g1×<]ñ,çÎʧZ¥Î¡,ÿ?aÿ×ýNYa[Zý!#¿N/Ú´&éU:C×ïA¨D¸Å~1Êô0^Åo(½ì&ÅvÑ9¢ ÇÄ?)tÝõ*ñ`òFáDæTÝ*ÛßPKüw{f |ÉÔÿÅb^(h1m1V^Τ1kñ$dä>*wêàÇ9±èE»$]W,,ºL§fxàK%Q= bÀcóðI§NËNN\2%ft\ÛuÛ)æ®õÈT5ÄpHC/h8z5ôá´ÖZ!C¶+§¼èün*Î «¡_Å¡Îi@»<I°Zð ãRY(Vdn+Ôçô|9S,-B1+eòV¦ìV&W´seÇa¾=Y+h®_9jÑù¿ËvnOhµ; êÍZuhÔ´a;jçÎÁdj¿¾úäA»è.ïAX.±M ì bÔ´,iIþlÂuL»ÐB;°Aü²!R¿ì mçì×ùt>î&} ®<@y ÂÈc î(àZWs%í)Éà =¯·$È¡dïÉÕ$4Nêy-UZMk Y5#§-\Q×ÕxNÍ/ŧÓ+ZÆ%Íäê%£(öJ@gÕUgg(ì] ¿¸¡®IMjÙRÜ(nhKF<Sgsñ©çâ#) ZÞÏlæ3Ë#¯¬e9C¥+¯f³ÜÅRÚ,¨"»WK9S_ËmÒ[V_×Eèº]SÚ¬aG2þ¿=ÒÒª4ù.í£+¾@¹ºÕâ²]KnÓ1z~IBk¨÷Íà1J Ôr§Oøpã>E@ìÞöa>t¢KÁ)ôùp} *áêé1Ó>¼¨w}x3® iN-èöд¦9buÅf·aç¼fsY§¹|gÎÈ<äÐ9)Ðt¤ES[%Ã7uss¬ÚÆC-+Y ÎãysX7ÏUº¥X×ezQ¬Ñ8¼¶mhGN4·ºûsèàú2OaÊëH½á§ÂÁßP÷+O^áÚ Í¬8[,jCºH8WQjÚ.Ò.b8§¢TÒ ¥gPÛå3Z8mÔ6+û á]©ØAP¸ùö(òdG¿ìÁî¦W¿ÜïýÎí+V¸l·¿(sEº¡ô6[3ÊÞ¡´*n÷YCéýHøgâïAÙ OERÑgpÇø= §¢»ð$ä|Û 7á8¢±(u÷PÏß]a6è 8˹ÜîÚI(b«ì'Ü<ÜûlDî'èf÷JÐKÃu·¨ðUVc3ïr7ÏÝc8E÷)Véÿ >¤¥JË4-/W;b2"åó¬OtêkL/°hÉh¹g'Ávd»`~ü:,zt R#wÜPMìªØ§Ä.QºNîÑ[»¡½rJìO(ýÜÏÈ ×Än¬bçOý9¥_û%¹|[+ØÛÙ!`´;øÝc(u[hèÁuppåí*×z È ÊÓà G¬j:4±oã7zßIõ?Ѽ3ÇÕ¿çÇ«õáúÅÈßèü æG8+¢µêÛvlKù1êñ#ßȽÂÑ´ñÄû"¼XWåZ{Âõ5¼^[»õcÚ[\¯Ö¡ÿ?PKd\E kk±¬ì2/0|ô¼½W£Z8ܤ媳¶#?ÇòËëÛ/m.z«rÞ«V½æT͢Ϭ'ä«cÏùSªÜ;Ô Pwêáÿ,ÎñÞÍÓ$íÜÏX;ÖÐ6VrIë3ROvÞFæ=µä³âZa´cäÔ\AaKp?g}@ò-qK|VGõÔ¯ÞCk§5pyßb>cèkd,p¬æýF=ÀÂ|l³§ý ´ÔRÉÉî7µ¡{ë«Ä ¦ö j°[!xSv©Ã°êøaæNÎm"=ôe¾)7ÿJ¼§FÔ,³¤8û5ÓÔÞ£tû¢õ©wÓ"üz¤®fƧ۹:¶ÇÑèLÝ¥¤?ØCûBþç;hú2Ñ~W¥I^¿E:¹µ«2z¨ër4mu¦ë8qCÛDû)mk¬m®¶/cúÿåéϳãVÞiìÍD:æ:ÏÊË´*S»¸¯ÂxNåÛÄ9©üHÿPKÕ¹¸W :&uLmá4¬].Á\!×|'DDÐ7öÎÅa¡*Fâ0´ÝÈnøv{¾íH)Ø®¬W¶jâÔ9; ¥X"´Êw0æ~¨NÖeÿz¯ÒVq Aè¨zØLNëBî8u+¹éÅ¢º'¢Ulߢîõ"3ja"]Qñ¯_PÃØ{ãsÇDº åßùWªimh',7%ýôçéGQ¤è$,þDèT.lß íú±pãfÌ|ahÖz?VskðI½TÜE.8¯c¯ oi¯òÄ9Íu1Ç>òç|éTz@j߸Cúgö¹½ ~Í Ä C09\Ͱ©Và?PKM6¨ Â@çiÌ_%Â4ÙØ[SX¯GH»°Ù5x5à¡Ä,baå4óñÍóu =8ìHÞPK._¸ ~5*6*RQìlwve»+û¡þG¾Vh|ðµà%Yj0ORÉ˹wv~÷Ìaþúþ@·ëÐq¹ ®¨°XCW \7pS ²/]ÿ@íd/sKsE2énÊÔÀ²@UnÅ>×GÒÏ8ý$÷bÇK?tò,/¼<Id9Æßîý81ºõó37ÙXïQ=(·;¯´~Ñ¥1 "¹ìÊ仲¢Q*L`³=ª!?gëºÑîLé\õí8O<9èæ`8x1ÞÐ}ï~tMGÃÓÄ +0 Üèý³ÿ¬¥²¿.mf"7ÐXûÿ ô§`¯3¢ÅݳMàÎY»cO[ç{/ASær¦)99£çev_ ë%QR¡ü%9Æ&?î1ÞG ¸U͸p xάÄqÅ:Bù³eï@Ð&¬ÙÇÐ,{¹@qÀC [Ã<z¸Çü¤y\<å¾%Uq;dNPj2²ì#hJeQbmÍ>ã1ö)yl¹Á§µU](¹ÄU`踪fBýÎÑ¥ %-Áü PKA;î Ö lpìp^ßqYÞ(¡5HS÷^¢`höd*ËsݽôÆDý,¦®ÎP¦âJM'"¿å*æ(Sy$BY%Ne:SþüåÂâ/¡'bdÅ«xȨâ$P¥L(K#ç"-UwácZج`Á_ÎáäOAýF<'Ñ\ol`¡=7w¸¬S÷W~VÏïôÿ8N«£ÛBФ̣ºFl~ÝÏÐØA{«ÛV M4`á"âlÄE´R4©ºEÖÛºõPKÞ= EBÀD£±èº4 MU[UÍcFãc¥&º2FIt1aÃd'.ƽ{ÿÿ WâwæâbWúTî¹çüê;çª?þùí!>ÜH¡×0С̳jÙB2)t#«=:zSx}ÊÊÓ¯ãy/è:nA@¼/ ¹r3Ô1 |þ·Ê²,)×þDÑ T«9ÏæÎä´Ë¦lÈgæÓ.åÐ)yÏÍ}_º¡1ìy¹fV<_vr;N0cã:á¸@<ÓýeLDôºÇsåµ%é/XKEzSpbG¹5¶·à¬I[2V360©Éͼ, 粺íã¯SâSó^ÙÏËÜt!¢oÕZ·¤ÑlàÔ¨Çc^D³ACÖ1bà%CN MÅEË-Sn(}¿\ ¥}ªWÇËÆñWqÍÿÃÔ=ø¥UgCF¯f[]/t·ú/Káú2¿"ó ¼~ù3ù¯S~®Àù k ©Y§XthЦ9ÑHhiuÂçRV|iÙµ'©uS¦{æbç<é"®ñ]åã BA Ñ]ìUpäÑÙ~ à£{ å½}ÌìÞ}|¾½`§mõ[çW$\hMf¨,£ÌÇ@ÍfÇiÄÉêq¬ãüDÀíõo¼ambMãb1%s¦uF&8ï(*d=Ñ,a&£DyÈ0Õaaé\ÂÑêá>5Ôý¦û-|dÅ|zÎ ô¬×_ «@c&¤ÓØÝùÕ2«G ºmÃÿK ´,LÉËéìÃ%¬ pðWoÿ½=.<»øø¶Ë(+û¯/쬰Á;ÏCUq M8hvÆ6{68pÁPK¹{- ÌËXP CFF4Yáx««Qp·Es§mã®p^±ANÁîÁû2ÈX±ÂýÖ°¼Ç>÷9ºjÛÜÉU×å.CøÅ³ï²ynúzÍ}ÁË5½äêfE÷=«¢jvÉwn{znyÕ¨oÕ8Ffz³my·î&?´6³Á åj&ÉÈ[6/øÕ§ÜY7VhD6JÏ|Ë¡^8)û/K¼îY5ÛÇ«uâk3ß1Dê/mñÒ; ÈÇvDd,YV>Foâ_NFðÕ2÷VÙ6*NäåäÌ© án¸¼µ4±ðbÍwJü%ª2ÒÅHÿ`<7TÄ1«â\±ªb 3Ä^1ì²¾j{ÜqüºÇÍã¤pÍpWñ *¾Æ#ñDEiWE³.]<¡ÊV6*NÙ¯Rc]Cð¬ç|ÊhO ߨÐ`}_Úÿp^øðZ0vÖ·¾åpÃdYâÓÁ1kÂaîý7bFì Y[·ªÜlQn| é/Q1r4Jç¼M§· î Li¤i¼{³×%f@+YEÝ3ÛÆÜ£yQå}ÑwÍáÑC½.Õ5qvZ1¦ãÛ?½{Û½³aOèûIÈçdð&!ú'cBRég|¾úPKÕ¾ ,wÎä¹ôÔÿ¸wFm öCÚg+ÕtKÉ8nÖNr-Ó'¥N¨é(õ(:=Å7¥ÃÆ64:ö°îaÃæ-²U'-:¦È TªWvG6uÅkóËÞs©®I¢^®n±«ÝspØ.£ éå1¯wyÏàÞ/PK0tMQö >æ\S8b9VpTË\ (¸%¡`kÑrÄD¸8+¼)cÖæ>zÃÀr_AWz¬¸`\3r¶ásÛðý|æ~/jxOôK ÚW)¥3¦úÖMúJX/¼@ú¸97» Ì /QhâFà&-:ÓVº# âîÜðlßÀÍx 2¿ë"?ÙØ)¼ä>½Bl[ rÿëð:¥þ¦ w24çÏ`Þm&§ ·i1)è%ÑîrãXÔüIãºMSø~Äd iâ9¹ÐÛ5׬¹2¼²"ÖìÙm¬H)¦¦ÏòF[z¥Íc' ifï^h.kþPz¦µ"è®ï 69âz½p`Mþܨ ´ðÀ¯%6¾æ^§æ=aèÚjÖ]Íý©æÕÐòJó-_Î ÎÎ%u7_ÂðC§ì ¾Ã²=(UÙb:õ¬}>É{¹áÚFË.Aéý£mz ±ålï#¨ÙÇO÷Þ^Bâ´Ú"Y·?äû8ö ÁqÝ¿mØ. ó4ÿwdX dÈý?òF9·aHõw$§c?ó¡ªbÓ°ÜIMÇsè]ÂæÉáx¶[íW±åOÄ «©ÕÔ ©N¬¨#H³L8FDÇtHOñÄëÅ)~.òGàL ùâl£6ÍL² Aq9ôQ*ñì/Pï¯HÔ6®î®¥$iÚ^ÅÖÏ×O©ª|LH*ö×u¶>¡Qæþj2õ+¶Ý«®Y¦cg³UtÖtýÍgëÛ]ËkôÑåöFàýü³Èׯ&µ{s´)ÓÊ"½zü½Ã H·(N9òdH»ªxîâ±ûQ`êýaµ¬[]¦Ût{x0À*v bg<o± ^`_OfKê- Ò"?2¹LqDXì§ÓÒªãS(-©ù¹äR+Å©Õäz2Mæ£3K«jª8(<¬Ëjc lÖ*AÒÖÖ2ü¶õ¹p7yG À.EµÂ]uY¦ Ñt6Z*f²ÑKòy5WÎnäR+y-y_MjZVMæ w²ê÷P-KK°hyNߣS ɼ:§A\ùbôõêëvõÝR2[xÊFéXIVD2/ôpµÙb>[Ðè;äd¬ò`³Z)RÇ3"×mu"êNnø1áíbvÅ×0éF7zL¹1¨Ïâ97ÂHø/¾ý nÌળGâOæ3F·´qL¯±Ü|h9«åTc9J2¹nËj©ÛìVϰÆC©Ü(Õ5.eÒ+Sܨ¡±6áý̼#tëT=¼D°àÚÀn9ç mäÜü ·Ðº ý?Âò¿$tq<+Ç.z%~'M¿½Ú?µ®ã°! ¿4SÈÌÕé.f e»«axt¢öô*ÛDúªýp9í!ß3¢¯Ó W:Ëqö O6$ÚôëÐNêöÑ"¡DdH°®Ä±ªÄ½£Klý÷|H$TWâxU⣣KÜ'ú1%>!ò)¾¨¦ÄyyÛDwøÙÍÖm¸;¶XÊU&þ8|Æ>×úMóÙpCz»5¸7õ}{ôÉí¿ iÚí_q<ÍíÍí=¡ßÐúM[8!B5._Ùz@c<9ЯùF=äê¼dÒcº&Á1äç}õ4oÃæi©=ç·<çw\ÀYÓU<z">ý>÷û¸Ëc´ûPKyÚ¬ Ù4Á¡t¯¬XZì:ÿá ^s³¢$ìÎÿà/ðx%BL¼èù~ÞsÎsúý÷o BT¤F"Hü~í/)=³¶ Ñ*ÊܹwÎ=sÏõþøÀf¨Ã6ÛCãe9ìÐÑa@Ã+r±S©»dàn9Û£c¯Û¼}:öh0È¡S4Ð n9ëÑqHÇaÚÈäN+Hô\9/£ùd¶Ì9ɲg;ÉlÞÍEázÉ>Û¹t>'v)¨/½¾|vGWõÍË$;<:|Vd=ú5'Sòèl<±=ÛíÎ2ã; ³wÛ®ííUhk?©@í$(cA¤ËñÃw¶[EOÁÚ¶åIäI]\ð,#Ö´µ?G<]²¢àÙy·DjùQT~foû¤ã)MAq¦°K]ï¢OVzyÇzÐÌYÑmKþM+²Ø,M´ Êý¥M¬C³gñë(!ñ6xëåÐ+#èC³ ;Í8û£å Ô*¢£ßD<÷H°ëb±\ðD®hâyël2qQ&á¸\*ÿGÖ~-´=1¼s,ãºV]Ì^pó=B´sGB<RÄ¡±"ÛXA½Àeï-¼XòÄÕ$Cöè·Ç.ùêöòe=V¾:(x*ÿX]¾Ê5R"ZUÚ·T6Ä8ʱ«ÜWhÛc· Äî îí±ÀT®µSÊ-g ÇbÓÐgPÁÔã:9î"ŧ» wvÚ°{¬}5Åu Ó%B ?~WZMs]R#ê]9IÌ ãPQç'ÑÒh#Ú]ê5òè,8]F*çn2Ií:-¾Õq=´=l©ÑèíD#"üª´¢³x Ãôö²©4û¥JüÖT^q¼zuWéiÒ{XFCµj´õxJµæ#êTJ³$oÕkä^òm Ì& ÀZÐ;ÀÙ1¬Äq¬Å «9DYNÀk~Ñ/r^ç9H[Gµî£áLjôÔÜm¬¸*W\5ÍŬY¬\Ðf¼ÅïëÛD>Mä3Ô¾ØüogQ*Ø]´2¶õ Øê%àYç.>²Üâ%+àQzv| à,?ÂÖ=hÖTµ'b§¨³z=7ÉÞ«ºWWvsܵÒñùÄT¥VO>ü;½àª¶Fb.¥²/Ô9¦²¶¤eårLß1ßVè` k³XÛÂãa]mòá¶LtÖ/eÈ3¬ã u5Ú.kw¸\»]®ò_sö eÿU¸Fß÷|ó?ðKð#?\?a?~¦ä¿ðiþJÉ'òä:§ð!n²ò¿uzQlá¼[ÿPKÖ¡ ; ÏZ¬lÁrÏd:+ì`§ee×.XθÈXç_".3(òå¬WzEñ²v)/dËSÈÚk}_¸AvX[Å1ÏôÐ Ýï»`9ëTAéÍåÅð\1T¨é»× z¨Çh}^^(X:è¸âhyüðG$_ÁÛ*Z¶\ ý$:nIøæ+®q1ð-© 8G0)æwð¢-ã¹%ùÉ+¤ëEzÞ I+;FG¨Å2ÇòÞP(½Ó§ /áb:G|Ø+û¶8äÈR¾äÚc¾çzåRß庢°YÒL´aUH)È=t',6Üò#×µáH7GL¬Æk±FAúÿÖDd,[X V¤LîoÖÄQä1yáYsØ~ùåb òµfx31ÏKÞl4±l{xjôJAö¡¬ý^ÙÍ|¡qÐre|QV30,û|ÙñC-àâ4:¯ø1_Xyɪß{÷ùY¹qç^°O1Î1hr¤|ýI(×VeKU¶ßëçð\ÏC¦B¹#}JZE]ú:Ôñ«Ðf»OשR_28õÄIfQ?C²vüÍ ¦Ð(µu,®uǦ`æôÓ¨7Ç&Ð7UíÖ%ù.íÖõÉ#¯Ð§°n 9#¥Ý2rZ³>q÷ëvzJ»¡L§+hÌI>ñIi¦ §ôi&d3Lz/^ÀËaͲ(7\º×ü,ðM¢ÞB#Þ¦õ2§û9ï5Á½Äv¼>Àn|H/W8â#úûg¹CÃg(âʸø¯â^ÃmF¸CÏ_Íëùõ|SuQÛÒ]¬Y°ßrq¿ïçM`Km ߣr/ÔÉ|)4GÍOª½lnÔ"Á÷NÝýµeâ^27¥5¹Ýa´UÛNÿî¡Ïì eÏVfüÀ¯?Rû Ëñ3Ñ/dýÆõù?ÕlÞ_Ø¿±ÿ¹zTn#h+d¹ÑBÄÔ+aÑÚÜCkEE½¢!©èhRyí{R>LlÿPKЬ´° R¸,Ìá^&-Cq¡¹ÊmÛ_fh-óO+XyÈÔãp¯`¾Ï}©§enºë¿ä«®^õuÓÖÃÀ²õªëTCÏãN B ¯Ï×\§þàM0Ä×cò JÆJ9g9Vg¦3Hפ´meËásáú ÷"Íãs/ @&#Ãî\mÓýôñÅÕ6å5`©:gB!óÀ3ªî^zøT¨JÅ ½*/Zâ8=<Ëõ¬àUcSæñÂPÑ.:CîtV¡¢ME;:d©GVÅuÜPÑ*HʸÉ0}l#E¦êßZ¤ãHLÆ-;ÿ®Cá$gÈLCvqºm8«úâÇ ÄÁÒºßMýð÷*ºÜUÔu¨õ2µvöäú2ôäxð çÜ-®f¸y£4£~UMA^ÆqmLkW¾"òQÍm¢Kûhâ"K;hª¼f,!»o÷¾§MgÉöA&;I ,Z1Að<z1Eÿ<ÆpâÔ`éf(YÆÁOhÞ,Ìl#¤©ô1-IÉñ cªÁ 1õPK . Ý:NËY4DtìÊ ¢:ÎÈÙYyú C}ù1Z'5aË)/¾YÑû,KØ= #dét~]Òµ±1¯ÿ_³,$ÖPÙ#6-+ðĺ)gêºòRA å¶#{íädTLg)ÙÀ±"&Ëe%¤ jDiÿÄ:á]ãÛ6üÓn Òëy2?ÓäùJê6uæ_ #ÓrÉ44æe® d»°yaæx"ÁyÏ-¬Ï¤øL¯[1'Å H)7ùýÙç{µl;¡`òQRÞùñ°Wò¥R¯¢ö øüÁÐ (ÁÐ'(X ªàEÀ¢Ç$àgJåù(ÿ6Ô§nÀ³¬DM+ÁE,¡è ögP\]Ø1¢¦Õ ̽¿¢ÙosV3ðu¨M«êrh ¥ro¾%øC˲}ûå.´²'Ú WÂ+³Aö¢ãUàÊð:O¿=xè·P·Æ;D¾KKïáÞÇQ|n|(®³|g±ç°DèKq5¼nVJÉOy6p=Â@µÐ7X*A!Ç[ØÛàS6«½9¸CÉ(ÙNì2ÇZìË«sµ«×· v¨êJ÷µ«¨ÈFQÚæ©TWw{æ×ù®¶É¥¢ùví&ÊÚ½2m åTtø×i¯ôG3hÍ% (¿Dùçk x h×Ý»³ ÈÀß¡SVêË9j^§y¹pa÷±-¸ HBêUjx#*nhC½W0¢á¦%ä0¤I Mr1 i ·äîW5Ì`VBæÂmñ¬rÊ_h ËöhZÏf³t³Àsf]ÒÓ½·þ¯[n$î¡<sK6{&Ì<±nɹtà EI¨Í:ºí¸1;³2%Ö<À¦ !ûe{pþ$F6i-þ:ÃÙ¦NüVÆ1ïnp"2ö;\£a¢ÀÓw6Tx¯¬DX lk/4Ì£à(y:O°>»å{J¨|ærÎ\f:mfÝê{÷wÍü>VPÿ*y+YÖB~|üXòUåõ9^]DP4¶Æ¢h\Oý,¯x¬C=o/YúXP¼ÐgP^ßïÑÉÇÑ(Úÿ>bÛ(îAõ%ðwîn?ýaÊSØìLò¦ÃmÃr{riдØÁ.GÚ^ô±¬A&øØ^~¤À´+½@Ç9GàkáTà[Þýð=£D+~B?3òöô+®â7~~Ç(þàÇãO~EþÂ<Þ¢",Â8ðyäþ9m§§J/Ò$«ÆöPg«Å<UQB%¨ ÄÈDv1 U>ìéá1{ãMÛ j,#ÚA¾^Oàë<(Þáð\&06lq*1¹r9W®ã¾+·ð+=2ÝôËPFåÌ_ÂT:ªBªÑG5¦0®S-Æè,ÁÇT;TÏ k &d¨ëtïQÞ§V|@p.ãCêÀÇÔ O(Ô}¬ÈE|Àc®°<Ç5¬rãUøúÄ0¬(üÇ!ƦüPKjéS] - ¡à64ÔM©Z¨Ðf=¸[µ´¶kàÊ/qç¸ráJ5 ¸"ñG!¾Ùµ×ÔqZ¤äòÞÎÌû¾÷ͼ7cÿýÏï(bÝÀ.f1Kʼ¡Ì¢2K:Þ4Ʋ¼¥ã²l4xÛ yÇ@ WÔ×UeVt¼«ãUãvà5eP®» «¾/RÍi4dkH§éxO »áU}§VÀ¨ã6½2h|" 0MF{®|ßyàØ5ǯÚ7ï]k;^Óó«}ho&©\gæèzYVZv½ÑÕºí6ìJÍn5½íÖ}·ÒoÚôý@~*9vC]á¢8ÙßóçÚñ»~äN/y¾×\Hæo h¥zEreÏkMÜt6kɶ{xùÂü³5l|á»äϨs`S®C-,FåöÏsÈB¤géêí^~H!¦4ÕË~ÑdVúÖqGúQÝÿôUù'aÒtéW"åÿsO¯HÜ¥êÀHÜݱQo®\ñTfJQTmkbs&ÇQÓÈ8¦¾fpT`õÀúQ%¹n⼸Ö~'8&Î`AGÙÄ ¬8OÈÀòþò÷oõúæ}é6Ïäà¸vPE(öÙ1ê®>U|κèÞø0{s×|Q'ÀÇï¯¦Ú Oµ¦:&ôǺãÐV=D?J»ö$Gqþ¼õ+í aêKS&eýô.êdøUßF¹G ¢EvD§øp ^Â!(ëS,à\ì4g£3ô*eÊzÜNL'´ ¡¡ÁP!óñFæ gsÖÇÐIý Hj°¦vvö»3ëì,HôGÒëöÓÄ'_ì "©I7)&þ!ýôQúÝÙ»4ÍÍÜsϹç;?¾{æÙË?þÐOtà=¯á÷ñ>*Jm28¶[Í6«ý°¤íxÃÖØ4ÐpRA˲íåk 1*îç# Ô¾±£(>óóBÁÁq×bN3v®@f;7*nÀS¼O:go:¢º¾Wa(¥°æ (»LocÚ¯8çÊ =ZSð1-viÁDÿ¢½d§p])tâu ¦ðN"/¬íÍ[ç=bJ)ùWÉ%¤; Lá´T>F·¡Î`XZº|ÅòËËbÞ·²/XÐ-Xï9 Ö¦Àü_psk£Ü @ØyI·QwÄùÙWA±ö M¹EáHåñm<?tçVv¹L¯É´¶zî·(&ÜBÁ-G¡ÇpOÝÁibI$O É+÷7¨eçfú1SØzäþ&÷ÑÕiBÎÀ TðºÓªR[ßCò ÔÙÇHTÍñÌ_æZøÅV×ÐjÎn@3Ä#híu©Ä9 nnb½t}umçEín1y2äÉ `¢É¾ä±êdf;[eÞS¸Ê¥¢&Q_Eò*J¬Õ?Vî#ìãSz~EÎÑû<#|ÉÆ1 Z'qkSpó¸ë¸ÌHWó(ÑÆÛµîkhA7Oöt?ݧêÝwÈò÷Ëò÷«jv»C}ÖWC2^×láÀ`"=¨Ib:µMdVRônjÚä©MÐצ ëL1¨uj¼ó´á¯»é»9ìÒ«CFv»Ë¨² )Üç4f±Ávó¡7"ʾäwXä}lE²Fkó|MZ¿!Ò&E9Òê-øçͽ/°Hb¯3iø¤¶D¯( Àʼ[XÆ]ÜÄ=¬0Ã÷ø?`?2ÓOM´÷ru×§Õ¦d=µKâÚeO{'ö§õgoGàG}àeJ|H}ÀÉg^ÃíM¯þºó|o¬;uüBë;Ôcx÷PKbÅ©z H`Õ5é#Á-ùSÂȨxPÇCxXÇ#ÈèØYé¬ýö¦Y`ÖDtÛs{Í<»ºv®°ë[Ø`ÛS,õ=æYN_µ5Qö÷ê¡ã(y%'ÝSLì:0Ì)âP}Ê2lµlÛ Ço9û³£¹(ûlHMîPËÙNTBÁR¾ Ð(äðQQäx+',X[ÊúeÁ í§\ÁÓDPÅU5ÄÄÛÜ \Oã pª$4Â5m¡ÊDÄ'¡È]´iÕgë:n4D\ÑÆû £+è°K?wÔ²óõ(2 n\´bâã»FÙi[Ù©n²ÕXImoU,ÖwO3ÿg áY2W2qIDÉÙsÞ@g!t#ÍHíÂ0«þ*ÌÊ 5.ó 6F#Ý/R¾Ä÷eÌÅ+lÁ«¼MãÆÇ§;r¡Uå(V5"QTO¿}}éÔÜÕ¨,øi@RÇ*˯¯FHSÍU¹&BI®Qd¡¢æôþ¤2ñS¨=CEa Î 5Tau¥6Õ"DvélجÓÍ ?Þ øãMÑÔxmÉIëûÇÐ0N|tMÄ)$BItÄ;âGj¢ñ(;¥éh2zuú|Îż«OʺGß@,©Ðïå÷i¶1fñÆ8C¸üæÕ!°2;ãoã±ja5pÏQ/ø}Éïë+ÖòkjÏq¾aUϣߢߡßÓÊ|X dqÕcìµ@áPïâ>41 ùr¶79%ð8[%p-Ó6¿ùH~ójÿ,T¿íǰß#pÐúfá¼íÜkº±(À7Heo¤ò¯óépÔYò¸gùæP)[a½ Ç]>õÕD|,[Èæû>Ü!_ ×¢ò]ëàdûmêùjðð]êyN¦#ÞâïQg[Açj´Sv-©ÓÖ¦N¡1äUå¨Wmí ä?fà¹uzR^Õweîý2l6ÃÃö²ylîÍ}>~Ê£ù¶ã=¸û¬?Ç!üø%µÝ"3é·1Ûåû&4²T§}Zqiòªê6û¼v5fMÙ[{'íÂk÷]ûS\%óÔdÁør(ÎÚ°í¯é×÷Qß¡¿ÐÆÁÑ?£ãQü #ø;²øwo¥9[fÒh°ÈË"âïPÔwr!Xí¿ ãËnÁXYÐ}4Üc®YTD¬¹Ð*O4¨w§àé°S6Øo3¨fhÖòÅ{êÔ±!<táD p£VxðÐy³U`¨ÂQ¢=¢§DD=w¶ý¨~hD3Ð Ññ8h¥[hÄ6ÑN#$ýö[,s¬ÊOb5Ð=8¥Æåç]#çÅa8Dnq¢#¼¹b7 £ú"ÓÝÒÆ7Akï¡&oxmÞöÅÚÚì6¥UAFgàð*°B4xëÊÜ_,BÜZ7 ÞÇM¬ècÇåo%ÌÂסÉÕWáôF29Ú¶6×ê^WkfaNÁÞát ¯Ëë¼6÷aãö4íp²J?<Æ<r'NÃ@=^Åe\E}ÞýrãPÄ3p>,'éågá§°]Ø)bØ+LtRèC8-â0D /,¾.ÆñªÀeqWŸÆþâ%LW¨Qeaéz»r^Å~þ»&Ïe}ð*éO±áy ^¿ô@0DÓé £ª`DB¼*q ëĵèÝyèCpYÐ}«.cýÞM¬êóÍbµ«(Ë£ß]ÜÁ£âÝô=E_#Ñ¥$zcyôßý·Dÿ =l8×FyòÝ2"%rÊ@.Âå\ü¸ÿbø~bk,ÂçS.7//'ýÈ·.Á£¶©¡»^õzàܹ¼ö0`9d¿^ÑÝAkÜÁqÇõÜÝ¡ î6h·bk¯[wY5XWñKn¢aRî¡z)мâ~¸¥ªR ]©BRMâ5ؤÔbâE»R=Ê t*+yËícÄä\ #¥¶×:Û®)UÌ#9ñ¬¿e ¿aR>ËÐ+s¿ é»SÙHMp)ͨRüð)ld¿UÙL-7 ö<ü9Ø$Bá50GòþàØY¥Ï6öukî¯%¯eÊVÚÛJe;ê)×*±?I=^âBÿ PKîn¹W åÀbfvùzçëûã@iy»ä¬1MNO s[3a¼h_û§ÝCYµBbç !»·Þi¾lÚ»õì¹¾xeí{ëUù\æØDBqíí^xiîTÝ*ß7ÒÖhï^÷Í äWư·e×qGª-ÍRÝT+Ö=aúî¼1AÉQ¢].ÄDüRyH¤@NßAo+Fââ·~K÷,þ+ ·1 [ÑPKÚnGä÷ § ëà6g³èÂÑç¸ÀÐÚn86ÅP¶D+2ýp]¬ø¦-Ïë/(TæB$"Ñ}.HùA !]!U[(×!¢ë®tÕ4Ãü ÷RU¿%z-WZô¤)Ýô("I6¯Aº¸éêÜï,«ö3£Ñc ÏQ@Ñ@cjéÙrÅ\¤ÔìÎäB£Ãûy©DDkJpÄr}ÉqI£®pÀ1ªgùþñëRUÏC2ôí¾Ó\b0X 4xªËÅKPmÛÔG*æÿK")û1½|¾`ýÙ/³µú-X¿µÞ°©¿.©Eö!ëxÂí@Ø-Ðêr0ZRJ+H¾ú@d=çQä3Åw`ÅÒ6Ñ:í&ÔÈ?ñãûÀRåâ[Hî Åð ]Vé º_¡G§SÛ0:,}Á@i¨Akm¼üñm¹¬ ðr·7Ð5ñ±¦Oß"ó:¹ÓW04ùiÌÁlìç`Å~¯½«4°$)®ÓwØ qîb÷iUÀÄÊt^Á#bX¦6eàXüÇq^NlYº;Ô.PKQùM ×]Ì1gmAhn>ð3îCåê÷Ri 7·$æ\ÃÊÛü¬mX®c'ß7©Å&KGÜíqdÌè a¾ë,¤&ÅÌ ?/zɪv3BAm:ëÉàÝYáMËLÄ,[^]H^f2Y'ëRp$±ól$PõDÎ7=¿D(Z[UPzk£7,±èg]ÒY,èÐ;¾ðÎ{®%r¹¬37cßÌg?mæèÝñßÞÒ©&Ý%ÖzÀ²iiSnàYb,+౬ÝR¬6´ë8.pPÁñÿù8ãCxVAï¶gÜÀÉßhAdBBïÖñ:t\Æ«*^Ó1+*^×ñTg KÅ:ÞÂUOc¿örµÇÇ})¬Pjo#¡ÃàYX:úÐ¥ g·ùõ(c0ǶEä[qÌ´èóRNÜTзÝ(*쟿>,çñèö4rƺwàÜ:b©8yÇd«Y®ÛlSPU»ÄNÇ£¾Ð´>ì¹ÙkÂòÃzì)øD³Å^â·dѵm =ü'½Úʯ¼'QÅ<çßÿ°5¹ÈNæÞ(§*Ü9Ü5Ú#AT§6îl/T¥¾r²ÑR\«Cc?è*¸v Z«SÊ2û%_và4%ÒÂ*ø÷S¼iN"ê\FEê!*gxªZFu_O?Àç ëhÂRÈS@EW'\YEÍ*¢£¿>`bF 5Q@=F7íìKqñ¯z zÌC^¯`Ïf9"XÉY³[¼9Äw²6µ8Ñk¨ LgdàSÒ|Æß·q§JÞ=A}½%} 4¤±?¯o¯$üu!åhéoP¿ûÅùÊm$Y¯ò.ÓúêéûJô!é{SËÐò1wøä®¡±ÿúãßé¬zg)X;ÿa °6ØÇµ9×ü PKæ5ÝX> V¾·ô)ÙN~§ ¡RÁÎJhI¶÷2'ÍtÎ̦+ÚÄÏä¼Um9eeJ4Íâ~Çõÿ~ÊÑLÖgÅjykÔ,Ù4o&ÀJPíü¤U(2<0sF^æÒ³nIöÝEÌÃå=nqÕ²ö¤µ²=ÏrqÆ'Ì5ìH&6²ý +dV.uÚ5sÅ~'*~\cfq¬2,ì<CC[ÈXlq ·u Vâî"£$ÑÁ*´FC«½úà{Ü'-"°G°k8Äi KëÈ¢--Ø*D¦êâ$¬¸êSWüyZ¯óÕ¶² ¶³Ï·¦sVØ\8Ôç¼R.ϰU| +ü¾W -BGWv÷Hh,×X.z ÷ñ×ýô`!§®Bú*@ñt-êZWí£dë|×KÑÀ5E}\zj`úmrbÞ%*_w 5ªðG?®¡éª®]GÀ§¢rTùa*Âã3 Á忤®yº¯ç¬F@ t {GQß Ê±S#³®·ã=a8ÕµïÓXÙå4EZ9*{øhØË«ß,»Í×¥Y6Pé6¥·É©RúHUUºYÎuýÙ`Êcüú:-¾Ä2´DhÛ¤I¡'öÿð""_`L-£nQ.Í©ÄO.cû"¬õoóGÙ(å7¹ÚXhA#7ñ¬]üêÅN%^ ÒN xeìXf*»Izwè¬z´QK!DÞ½^µ¨Ý}Çq¾ÒöG¸'á.¡ñL®¬%4QmS¾{ÿ§Ôüéc ©ôûê ,1E3ýþ¢²_Bó<¬WhGøøJ®´åЦ30Såp]é ¨$Ë ëÙt.0m4&r×bÎYÔSÊê&iqý=ÅdÕÏÌgÜíB7HnçéÀÅ ´NátÖï¤eP?¯ZíÉ÷8"^ÂÎë6ÐY}=úëè.}èÏ#²7¼ÔFTþ$¨¦x¤ôúö]¦Uyfxéz¹ßG뫸@Ã$Ç!¾|ÃôÊmàyõ¨ðü£Êó [Çô%Hj$_ÂÒÒÄ:¸W_XífÙð »6¡yb )&6T*÷p)Ü&5N[§Ì¤/E>qDdÉ#sùE¼ôKIfáGuصÄQ2¥^Y{¾o÷ÛÎÇÿyÀÂï:.ã«®é8ït¤ð½c¸®an_âF7uzÞÒ¡á6{~ÐpGÇîj(gqOG°ùÍOlæ5,høYCU`(öCõ§ÀLU6:v?ÍÐvc»áÛåù¶n'd ì:!ç.»¾Ç&ÁÍÜtc³á7wáfe¾²X-§½FR`¬úÈyìØ¾4í2G PÃõgZÊs27¼ÀS·R³ÅérØ V®ê²ÖiÈhÉYñÉjwÀøì@¸ÅGÒUsLÓï?ue[yakx@å ««28 ½O.LB×É] KÉõ(cÆpCp´vÍë=Y® :Õ8cré4å¹»Ö¥Þ¸?Ç)w3ÿjî»UCèªcÁ7]ôc®þ@+rðÚh [z=)¨ü¿PKøåï. /q|ã äøÇ)üÇG9>FáÇ9>ÁñI âøÇ§)|ã3¥ðG9>Gáç9¾@ã9¾Dgôe¯ÐñW9¾Æñu ¿ÁñMoQømïp|Âïq|ãþãG?¦ð'?åø ?çøÇ/)üǯ9~Các¿åø ¿çøÇ)üÇ9þBá_9þF«ú÷ E½@Ì1í¿ös fôìNu¦óÛÊiûA±Ð=F\,tÝ@"æRãº9B!,7µµ]©¬1)ÖwóµgU"3Y×ÖïòúÌhÎeK»¸p[éDv;C[ÛÌ-0ãÊQÙ.wèiùÖXÒ®6rfLïKÐ*,,·ÐrÐÃþ½8cm4ÜkÈÀÔpÌ ®6 mU6a ëßÜÛìJâ °2|\Nد&JkSî8`¸õ¼Xª&¬³ó¨>[R@7£mÇr¶av¥,p»]`D¨c»+ÊTè¶+ô ½XÉv-ñBgÝý¡®¼ÿÑKÐ5Ö0XêÚs¨«o}@$|2[o¡á!Ô56޹Ρá4*EÆ'¦R;|È/y¯&4ùR! Y¨f4ÛH¥DYh!d±BZ$Òb#´ZXBÈe Y"%6Â%²ÔÂ2B.WÈ2,³zUéIBÄ,WLH2!Q¥la1mY!£jµ[³R1aɦJ2VQÌ*ɬr d:-¬&æ ŬÌj©ÌkY§µYë0dÖ[Ø@ÌFÅlÌ©Ì&]ÄlVLdº¦V2[,l%fb¶Jf«ÃÔIf» Ä\©Ùá0õ¹ÊB71=éL·ßo¡Ò;UºW¦{/¢O¤p׬ÂÝîWéÝ2½[ ¥pϬ½Pé½2½W çJáÕ³ )½O¥ezP çIáþY (=¤Òdú6Iáð¬ÂJ_£Ò#2=¢ó¥ðà¬ÂQJ?E¥GezT Há¡òB 1J_«Òc2=¦ÍRx ÃD<U%qعÖ%s½ #ÄDsD2GfdÆ-Ä+&&ôHF·0A̤b&$3á0%sÔBcIH&¡s8^ú¢Ø :¶ÇÿçàE";/ÆI1Aÿ5pNÿPKÜãÒv, $.Ô T©E¢Jtç8ëÊA~àSø¶ @âØóþq')%@VX¹wfÎs}æ¾ûñú-5\¶`¡VDuKXÖÙig,äqV/VtvÎÄyM!½¾ Ìmíy<7òdà¶Ó8ÁuBAfý® Ô"BzÝHôÇÆ°·'5øF(Ãô&36ZÍmëªÇij[¡·<}`"ÝøÅ5ßhNd³1ÐBcFk̤*"qÌ5ô®ÕVYìÍP«-¶I7V2|쥡°/â5Mg£5áØXÅEG`Êÿiè%³(Ùì°KؽÌUÉC(×OÜ^äfi¹¾~ÇB¦n?L|wöJg7^¯%ï).u|a·¤ñzä%H¥ßeÜéî ?%\ûYÖº¥£Fo«}o5'=¹ÑØÑÚÝÑo{Q&¾î`{ÇâË¡¤}⬤ÍþØ eÌ[³M^Oq¬;û §:ÀS} Ü ÏA8Îó·%è=ú"}D>¡FYwÏF5Ä1ï¼ùìðjAoÒÀÉhŵ|ÁYýCfýÊØET°W¹TM[V¦¹_bú Lã)ÜßuZ¾¡Bß9«òÎN¡1<!öh 0ýPKc» é¤ý ¬ýäA{å/ð,¬FP'ÙÄ?AO)ÈÃ4Ú§N1Gª²û7.¢"$HY·gÏÞÁÚ,0Ï×2ýÿ PK>ÁðÀÐ Ä@âÀB\oiO«¥\ßû{ìãoß¿|°n c¤¶|ªrÁ +&&Óê]lU¦j*Í.ñì)ì3çÑ<Dýî1ÃÂ~HÆ@iù²¤Æ£Ôý ÛúZ·Êa=ijǧËã~Qn9pù®#²Ây¨A뢦;!Ä2Ú!B, ¨!ð±â>ØF.çòGê<a eÛTWhnô>õÃë£òΫ«4ÃkSlâÚ/PD G~ÀBï#*?áÊ_DàÖ¼MÔ½-ÊVË×q¯âßÏÑÂ&:XüPKï°¯Ì 1P¢§²ÒÎîÌÎÌ÷´ß|ý`}5¬×áá5·¹ãã.îù¸ º2Ô¬,chÇGÉqrÊ©ù NÆ"Ûa¨ß+3F¦U 6 ÇLeÑ}°IÉóâDæ<-ø$ã¥OsZeøL)§FéTçJ~HÌÕHÎ&ê®TÒ<g ÿÓè¢é½w/F,Ø/gc¡GÉ8£HElhüa^êT¼öaý"mÛ?À*:hðq%ÀU\óð(Àcz"l §Ñ}Ê íè3X´5õç¨Ds¸aUkÒ '&»Îy¥k£hFg×ýO¨.«|å¼BÃÙ§ÛöM<X¼½Å4ø PKÏÔÒ FÀ2ÎVøABM¶3³=svæôÏß¿ã~=èDo>\ Ðç ú PÁuû¸áìM·|Ô}4*vYåÃÓMJ(Ë×i)d%iTXF2Ó²0´Z*Ñü¦Ë&ÓêClU¦TÌCÞ·ËddÌi¥}$ðxä$ õ7í3YB]M¥éEÑZ$³/¦n'.ó÷iQ"08Ò\×â(^·9è'eʬóK°`>+¤gÊôVsÜ!8ÑgÐåc,ÄmûBLàN»=þ¥(·ódåÌç`ÎiMf&órG¡;Ä=L ·Jc½ÍiKƫ٠I«6Äã4}NS8»_çåâ I+ÐhC*·Ä\ÚF\[¿4÷ rVàkÐL/GÞ?GÉÓ,K)Ö¬ÝÉããÛ/-{ð%/c-)e]æ66öà`k{º,;ûºÐÚ ¸Ôct²!þ}CDW· ÜãñbAp|½k» ±Ñýonø]aoßqi/_¡ml§ßàý@ÛÚ¿¢êÚÂó~¡òÖÙ]ø;8½ Îçÿ¿ÛRCcèØ+ÑËEàm êm¢æ}DÝû1ï3&½/L«VÒ½Ì$Á=ÎíÃUö;ËàPKÖB¤E ªJ/"Ê©±ç¬¼^% eðÎUA(ËA¢YëU Tàq̹@j^`!×HÐÍK¡O¥@Ò¤¶JQÙ]jëiËg½ £ù¹Òº»é:îrhS^LM5³VÂ$òèQ ô9¦#ØèFÁF'θmc&&mÜÁÀòéë.S¬V( (æT vQJªnSlã.¦MÜÓ36f1ó³qÜÑ+iUW®9E©( Eþò¶GÈÆô]6% ÎC§«ëä)þc»[ bE½@SN÷xæôÐÜ×ó(æq,pª±áù¿ó¡ùðJ®äA<W¿F*íÁ+¬¤m^gÑß~-0~²\øb9ÂI}Rô¢@»F/W"rý}øÅY,êkí©£CÛ{°né<O¤Ô{®Y¤hA~Úy¤:øtéJ©þ>Ý8ÇòyæXÖ+¿ýcz{øßÊÆ{þ÷âÂ}ÈÚ&¦ù]?ÐTGóWLjáZ^jªÏ.Zë0÷¹3Ìí!Sõ mµ®{Ãe1)´õð{ ã²ÆGL0e|Ƽñ ëK¾kL»káÇtùlZþPK½p °+(¾g2åL¤' é´²þú î~%Vz|ñIT*'§NUòüòø` K 0QA?&La:ÆL¹_}×äµuí&µåÔɤÎe; 7©ÔÕ sd½ì\ËãßVw]fÍò&³'¦GnK Âqß%o4snküÀný3¤ßNú÷²6 5¥E¯EîDµÒQ: Èe®Gmåzó\](©.½¤@ý£ì¿$K³Âi:0`î½k¡óUıPÅ"æ¹;¯£¶! m³Ç±É E¥¾Ý¦g6õ6\EÓ6lö°°5vröÒ'ÈÉÉ9_¾ó$¿ÿüü`[ æÐ¬¡å±ãIµOæýX»Öý> »+:Ï¥rrÉÂëLªÜ¨ÂZ2^NµSòäÚ¨±Í¾I½ÎÍ©}-Pã¸×9÷µÑþÀÛöÿvÕ^>"ž6tXLdOÓa"© Èc²s;¥ÀV»?I/S^yIú ¼~Iä Uô^µY5÷C Öë±ãYØäÛ¹¨0l/K#'Ð(µf©9Gà )/°1S~_;O|R ÒM¼º¿~%G¾7&uÁ ªí³Î Å\Û¢VUD%¤¨Cog ¦¯d{ÚU~qàôGU¯¸pK¶Ç3oÞ¼±ý÷ßå¶, UG<ÂãOb¬ÅXXôSív÷4)dîÎé4ÊÉI&¯3©r£ kÉx9ÓNÉáW£¦67ú[êunFzFöµ@ý~J^+æ<ÐFû7oÛ÷!íTûùVÚÐb6&;JÇYð¤* ?=Éí&[íÁY:Oezî%Íõ»rì,æ Uô^µÛjöC 5£c£M<çÛ¹{»/ Ð82l?K#'Ð,µf©9Çg¤¼ÀæòÚyâLJ;4ñêîJøùþÔVPmîc?ÅË[äÙ =ó^GÏt¶vø\zº¿ º{?}Ghk×ýXÆÊ5þÅ5¾Þ½@TùÊ < è7jѶe©U<-#,«,ÿPKIóë¸ cîy6W6vMé øµÜø]\Ëq×sÜÀÍ9n¡'ðxv9½û\dä;ÖR=,÷äYGK¹d òÕdtX?AÅÈø@ëG-g' PZ÷Ì) ÓõèÿàcÏ+IYþ/fÁ1uíª*hKñû³À?\ å¹»Æ{8]ä|>ËÖ&£'|Üýäb?ÎññH~ðºåñ}Þc|>øä+æ>cþÍ1"wÉOt_l´¯b½½Ì¨PKÜ® &ľ@t^G#/ Âáè>ÝzÄôfTÚõ¿·È4CÚ¥¢ n=µÔª¿SFyå_# Ê¡ 5oX¦ïfQ±Ó×}Cû èaÐL!M÷9:Ð]K¬â[°bé ×@fhñÖ8õS¿ý]`©4Aìâk«íaff®<Aâù?¯5ÏH_0k|EÆøF¾¢NãöJÉ(*ü ò¾ðh,ýÞÝàI0±±[&ª68j&¶lÔqÛÄwqáÑé±olÕÀ`·|_ÍE""Ð1¾áå/ºÂUù ·e¤ù1E |åw´0,öÒbG(Ü1µùbiFä¯Ôè,y+×ò=1³´J÷åÞ3Âõ6¼+Âݸ½õ?É%VQ!NO/kDjXM¼¡êkÿZÁýÅV© 5zr5ì,%=;´/@ ZdI^¤Ó:ÉZc?+ø &Ä©@t^WL"/MÒßÑ}uðx4Ñý¨¼ÛnY´[E<<z©]CkçÕØ[¾ö¯íPÐ/6KMäéËYT°4uïÐ~ zÄh¦¦û t׫ü ¬\ùØ Â ? 6Ù¹3wî¹sϳûíûç/ B§IO$K¯Âïó(Ù{ ÷ÞW2àëõãÂyO&ß]O#W²·¡ê %=êʤPgXýÏ<õºqÊw®N·%{"¦UJµÆð¦xD'fSzÁv"_07e(ö{mo¹í<9©D¯¥\%®vÏ0[ln»»;Î× =æ²ZQ?öÄ¦Ôøéãj¬i¼ l#gÃÆ² ªtOzw';2ìðÇNÔkGëÑ®[¨à6êX2±lã6î0Ü?}§ KÝC;$Z¹!¹Èògímá)cø6eBB1QÔ¬§þÖPzÙ¥;èëL±tÔÅß7I 9B8ß}±;<¥Ápïôtéb\ëõ³¬ôoðNøÏÅkbU?)X'¸p¨¸_.e¥ô§>ú,ýÎ! ¼ÍÏC?y³«½äc¸@³EZdÇËÁÊ=¤ÊÕ=ï¡ÅqÆYhÄ¥CC4ÙùÊ>Ò_1ò¤ºÌZùR`1f÷1úò(I^1j<±9ás/«ÂY]yvX~ ®2ÜøwêÅ¥ë`pÜ0¤¡^eä"˶·¯òGðmÊXÂ1X%ÃzæW=aÈv 6fKî°¯ùRyÔÅ7i¶B:DÇ ;bo .RùÏè>^¿G¼¯¥h*µM¼KF]2i5Rÿ[É[véÁ¤èA1C93eZùrfð?¬ýYò1 ÕÙé©Ê°Êâ>ê>¬·0Ó:Ir4¬$§qê;è&A¤óH~ÆØêÆ×ÞÁ®¼U¨`âé(@ε^bÂz Ië5æ¬7óô°\"mªN kÃ7PK5lA ½^Pñ®L<NX¯G¡|á* Û²+âU³&C©Öîÿ'ÐSyÊ®G¾`È5d(¶zÝ·ÝV@+yâÕm*WzÇ ÛÂg+7vݾËÝ=ÅE_GwèÌ==ZÕ±¬fÔ=±)5~ö¸¤5·1ò6lL¨ÚXÀ"ôÞðdOmþ u[ÑF4°q 5ÜÆM¬Ø¸·ÿziùl'I°ÀM-X~H. ²üQkWx¡xßL QÖ¬g~ÕɶPzÚ ;êk±\uñÇMÒ6O£á;¡/Ã,t*F÷ÉÖ}ó§+ɰòû2jά¨¥¿ÅP .;ÞKÞà ¤0¥ ¦ñIèoJkÿ}¢ÖNÑhæù\õ Xua©êâ>Ð&!ãÙiùºC4ùâÂÒ0öpñ ©%ÏìíÌ̳ûîËë7 ½^Pñ®L<NX¯G¡|æ* Û²+â5³.C©6nþ'ÐS~Ì®G¾`È6d(¶zÝ·ÝV@+9©D·©\%ê#b>ÃB©±ëö]î}Ý¡3wôhMDzQ/öÄ¦Ôø¹£Ö4ÞÆÊ6²ÈÙ°1i¢bc U½;äÉ@m~¯u[Ñíhhã2j&¸e¬XµqWnü;õâÊu0ØN`$Z°Ü\@dùÖ®ðCá¾ (A8£¤YÏþª'Sm¡ô´) wÐ×B©|ØÅ7IÛ!ï¾²ÐE*ÿÝG[wIÌïñ¡+©©þþ¢6JgVTËòßb¨ÖDM²C/%C/áRÈk¡i|úËkíÌRôOÑà -ÒÜ ¼«,í!U©îÁx-Ø4Ùqò0ÞÁÉo I/,í#ýc÷«ûßx³òÆBmOäõQã&4>aÞøL9O*Å%òºę̂6|PKþ¦Ù9 =9Î(ʱ%{²À¿Ñ q@ùG¬âMØ,ùm3ßÛçý×7oÔp=$VH`U\g7q69Kà<.$qLL¬(2¤WhK'jôé!¶g3$ZÏ|ÕJºóª'£Ba«):D#Ñ ¸ñÇJzÜ |wÂW¼/#Öí /;Jþ®ìpülI_ªmÛÅÿq´g0ÄAGPúMéA¿-Â]§í%-è·£D£çø]ÑaÈûÎÐáÎHq1ÔÞmºsWKÚW²BWÜ¿rTÐÆ[È d! ´&Ê*¨2,éÓ1FÒïò ßîcWP3Á-Ô±nbÃÂU\c¸ùï¥Öo0Á²}_ Ï"=°ô´8åÚûÂU¹#êmÊH Â1E]õò¯zÂé ¥ÕðÈÝa_sÅÒ¬?ÒlÓ84íwÄx ©ôgå>Þ¹O3Õ{ȰñûíuGS@ýo1`$Ævɦ Ãp1dõtI>ýeõÀh1ú3dc8AÒéñTù5X¹rX¹z 1RXò<vçof¾~ûô@ÜA,aÓ Ø²Qt°m;(Ù¸i£lã6ÃæÄÊýäèHDmïçK}Ò Ò1Cê°Ãé(=Zúz$ãò=½®$<§br?æ'ZÜDPeìsÂú£(Tò§e¨äXD-ʳ'Ôû*ÿè°S}Í`µÃ`Èv¥/q_D^? ÔbÜÓí§bÀP¬t½Ç½©æbb²w(橱Z&ÓÈϤÁo^öhÓà]äpÇÅUd]\kc×EUUs;ãñTª!ÞÇýðq8sQCÝFÃÅ]4þ;åò}j>ÜR4°Àc3¨ÜT@$ù«þ±ð5Cá]kA8tÅ°ÝøS/VB·'JwÞÏB¥zѽß/i¦9BAG Älþ -пÒ}"¼$ÐfJJ?×ð± R¬ %Úä1wBÞ4ìe/oæðËKÑà ùy²vÉOÎÖ>Õê§HÕ§H¿iâ5¤am¼Õ ,Òëõ3X_°ð¢qÅýÚ{¤Í°/Àyf±dmcÙÚÁU"èÚ¼uÜ"íPäÒ¼.|PKE«Þ¦ T¼6Ò2\ô ¡Ó¦bb1ái»;ilgÝ) ÿJ#5ñÁøì2~SÄãmï2sÎwùúíÓg úq,á=°A7ÖJ¾õÔjÄkij.4[¥ÿ!Úo_185 ¦Tb·ßkxÏoGäÉI#z-ãQëúª#B¹RóÀ?ô¹d¸8´ìu:óÔjk+ÛÒý8;Òâg. ºhñ&Qö0ã.*ªX`²»Ç<9ªÃ5Ýkëm}ìá]pKXv±âaÿ{éÅe0xu¥D\ü$±Ë ¨Xþ¢} ÃP¸ Þ¦L Cºd«þUO&;ÂX³%"¢;ík¡T>ïâÏ4Û!N"¬«P£ÔÊVîËÝgîÙUdXýý9oZu(å¿Q xN©QnÐÉÐb¸òvĤ_ýòvê?¬ýäc¸BÚ<Ùi`ê R ¤ßÁê*£$álÐ: kg M8$Õ/y¾0ÀèÆ{¸HÏñÆ^äíQgcÎ;[u¶)æõa&Ó¸OÒfæïPKt7/ _YÝ(V1úfqÖs4[¢ud¦| V^>A¬;Aü3ôºE$Dp¹ó - !-Ë_ûÄwL|8E2k"U|ô ¢ UËñrµà[@¿Ô4 ~Ü^7tñØ3w{Eý3þ5"F?Ê8Û0DMïÃÜÎdæ¹gf¹ï?¾|°{y8u09sºbÌÕ<¸æà:nØ(9°1ïÀÃEK6úBè «28mÍuJBm·ù+?9jÏTã ®1äë¯n -*Ö-Ëë5ÑLý(9{$~3ôS-C?TƱPÚ?IàSmÐ#%ßp-#µ#DL}ëRIý¡^êè,ÂóO¬¨)kRÍô !âÞ)SE¶d"I«eênU)oÐxAÓØí Y±RY?{N=Jã@<ÏäYÅ˦ÎÅ0F\0ébc.1dÃwQÆM+Xe¸ßÅËÆmwp·G° ÃáíºÝjì@3¶S¥º°ôoßÙiÅ7é&y e[ø¿_Ì)GѬ*Mc/ÿo ÉdOèXhQ6zUCÕHnêwEÔÝ%©¥ÜTíè ¨q-bRíÏÙ¸1³ò$Wdé7@ª ;jÄB±s@Ç#Áx&«óäÓinÄ;FÆ[8BÖ[<ó²G°ÞìÁÙ!cmaÈÚĽ.`òBa 7Á=m=Á°µUǬõýÂØÊ¥5DðØ»Ò>$Ý^2¸Ô±q±ÓgfÑ}ìîë'PK(ô^ ry<6ì£ûUâ:äòxRr*ºÐ G% ©¨ÀyÒ+ï=-û$ׯà wTÅSPð:aÚkdÃÀâeÀrÓ¶H¦HrÓ¦ÓØÊЩu^YÝpôTFϹfF7²³ma¹ú´éúð9ËHÛYË|=éYkÄvCänZ¸¦AݦeºÅm:ÁÀ{³)Á°9aZb 7=.ìäx$Ç%xÐÎY´Æ$¯gs¶!úM ^{¯K-SɳI ;Óð0¶k¢^CêhÄq ÏcHÁ°¼ àqRÃ)ix /+8á^ÑĸCnR-÷çF¿4¤)&lÜùÆAKÇePnsZܲÝ+ËD8ÒÇÝ&Ö`bJëÈhÆCIZzÜr mçf\ê5Äo%£E¡¯¥QÃÂ6¨º~S±öþàø0ÈôÊ5ÑPβüêX§7âU:þ?Ï®î«cM»µ¨Ká·Í¬mºç¨üb^¡tnܪÝÕfëMgMCz£Fì/2>"Õëwué;ÅðÈ+¢CÖ?AQ)ó]èóÂòãrr4È!§q_+ âý¿/¯Ý)ª>2«õAïP·O ×ëùøùmÿ»ùCbâͧ;wWßrúÎíÜ´Çâ÷éÉêLéZËá¢øwKzü̳®WRñÔì¶ä<èÈʤKD¿w}Ȱ¹:è9a¥Ö¶Ó·é+JÃ>Ïr~Îv@þé'vѾ¸Ð¨n^kÞs æà5å¯áü}ù(ç¢ä¡ì^ÂïDJú{ ÌÊeBùP>¡GóQ¤wk J 5/wÓìä¡,¿w¢y½0GØD _Ä1FÛH%ÒÒÁ¥| j¥|^+ ì:Ê;C{·òÚP/¢F|F#زÊóæá_BU°ç<cÞ£CT[@U´êQßüÜ_oÌ#2] 2¹yÏa[§2P²ÒY"uxèrÉUr]Áä±ègX!7óøÊ£+¸áQ?H§QCAú NãyláØÁÑÈ¡óëØÏ¿F7ÿGù òo1οÃYþÞä?â-þ.ðñ6¿wù-\á¿ ÏÅçü7¬ðßqÿAj¢WhÆa¢u^¹´á)âk>K´è(JþPK7r×þV ÃÓ¶¹Å îQ<5ÄJq,<dxqñ52ÌOÁÝqÄw?дÀÓV í³íYgWÎ0h7Ðb XõJ¿ÍÂ-êcª·0óOÇéD°~GhñÞ"ÿûXX¡WbÓ/!¢¹Éó0_Ññ ¿Ò¯tô$ñ|ó+Xsíæú `rh8ÒU¢×P%=§$²¢Öüäg¤&H©À2ÂÙS"RP^D)½jzÒ«ÓNjä5 ÐÄesÓñPK×qVÛ OM yö+ÙnÓ¨-Ç4êÙomFӤϴNºCó´ÿÌ_î`Èí ç¯t÷ËùÏde%¦Î[ÂëíLûiþä>Á£)_îµ §»é(|8ï0î¼ÇóÎG¢¹7sǦè¿qäb6~PK·^ù6 U[¬ÚE»W[kwkíN]¨Òÿ¾, J Ï)çpÿåÞû¿ÿþ;Ã3ï>ú8¶QA'.±c.Ëeb¹\Á¸R,WÙ±WÛ±×ȸVìO*Äù`ïØu ®Ç »QÁM¸YƧº÷UKdܪ ÂnË.·+/(ø"îq§©¸KÁÝø3ðe {ܯÈè±[A!î³ã«¸_`_Sð Ê0ÞÙG<A;}ä1ßPP%½l¿ ü¦ Oø¤ O M¾e÷<hÃÓ~GÁ3xVxÎï Î÷lø¾?°áy_°á ~lø± bÃOü ?÷~¡àE¼$ÌñKa_e,¾i1ÄÅ &ñk¡ð+bù8ÿ[¿ñ{aú?Èø£ î²áO2^UÐ?+¾&ÿEÆë2þ&ãïÁpÌßÖÃÀüx¡ÚRxG(VXÆPS¯µ%JõØVm³^¶ KñP¸4¨G ÃÐ"ñÒ®P,XÚ´-ì0ôHèâ@<¤GC]QÍ`'~¼C$³& ÅÏfXâP¿Ö:kÞ¦18ëCmu¢«U3aâHF"B«WRôÔÄçxÒJ¶º*bèQÅE*ºQ¡#"ã*þ©ø7Éø7ñ·UÆ\â^Oilk(²¹tU} U«xïª8 2Æ,*UeeÈLVÙU¦°L©Èb( PWeædXqê+¬ F%ÒòÒhF]8i±±hW·-ÓBÈ,[eKe9ÌŰpzVÌc+3·ÊòX>ÃlaðÒpÌmhía-/õGºõ`êZÀجÅõµhÊTÑ#3Ê&áÊ&³)*J^d§©ìtaúYcSníêcvS³×ëzT¨] ³i*Îf¨¬!³*;S¼Á{bvÈaâ±}U'-Uæe³ÊÆv©±nXYVÄfçM)F¬¼Ì0t i X¼ #ÐhÝZ¤ bæZÞ^.ÓÄý²2ئø¯`sòF5Å JÚD{; Çæ«¬UQá)ÈK³EXa>FµÃâ'¬F`R}¡ÙÙ2[$¾°X]Büæ5į54#u&Z'Ð¥¦ZòÅ2uÄYnn%t @¹¿µÀGÄJæÙ*#Q/ò´-Ùja*;UYkVÙy¬¡êF®5ôN-Ná d8mÄþH\3D4®µÚu Ê3Ê#wóëôH,n$ÌRP0¼±h6_8o½ÊÎgù*kajÇ!nMDÅ cÙ#¯YÓº ²6]:S¬µH$UµGk6ã!+ýÁ!:×;«þØSäÅÌo4Bºo£¶à5»Ãòq¼B(®µ ¤EÉÁ¡òèß86úôß©K¢\3´X"7ß 6n¬?ª5Õé]Q=BBèCYT$ë¶Ùв¨kÈ¢Tzô°.:vfh$6Í>JAÊõe¦³ÚRV&¶shd¨ëÐCAaËF$@XáÜ2¢ãêõ³N|yäÖæ7yâ2xÌz&YÆ|ì(õ+>rõ×jí'>Ý965R&¯PlØeó¼þ1¾dhà¨.H×Þ¯Õ"Ç$&Ú h¹ }ØÝ8ó Õêú÷[¦FóÄzÉÅC"³B4tjK"më!rn¾÷ýâRs7ÅÁÎfzûÑÕ¨i¥j ¼Ö#¤dGÕáz=ØIYt<ÓsJKRÎc¬#ælm«d"âKÕ@Ôå«?ü£Ã¾Cp5ïã*ÕôtkT×i¶)?ñ·é hZ07«-Yh¬8*Ø=ÉPzb)P5%?ØÉ[M@¢Y½Äë2©&,ÕÂÚæ8PìC21Çÿ«cÇp>5¤ÄIaÎ|²êñýæ©IѼ1TËE! ¸VÄI BºÍ;{Tõ%¿;õ®^Úª0]$Ô tiGô³éÉhTÍyÎñ¬òVj¤¦{©%¿ÿîQÂÒEê«A(/DÂQÞVJ¶ÅÕ`þ#]LÌ=9Iõºiò¾döòUÂ*«>èQCoK5#¥¦*j{¢k´¶±±ÌûKµö ÏNb¸|ò7÷ÈIäwéDnK?Ü>Û òZÜܺÉcëG¾Ï>g/&úZ=¾ÌALj)*îÇäLé çzÔ$N#¡§ïA póLódÄJÄôáË*½(¦(lñdyÙá±÷ã_öÌôbg&áÝá`nß}äù^ì÷dfù²H£»PRäsxôÞÙÓâ¡×{)i$7«%>§è¤#¥$²ÝnΣ»5²Wy?*ö#\é*½X;,5Û-Ôá¯N0åbs=ÙÃò'ù.!ß%¥äxú[;Ìít;î>ò@ÊÜó¿îAå ªÈÀÈg%ásUÓâ&׸&<q¶ka{°¼%øKLª6MÕÔÒ$%±ÜµÂ¤V¦÷ü&µ*McRõiª¨¬ès£1½q®IMSMD%ÑÄyõÉ^dúrzrö{ìI¬[^mI¬¯"W¸3:®©ræeíÌÅù¹ØÐçÜ©5aâ\P#'V)m rLe^EïǸp7ô"èãÖݨêE/ÃZCDënÙ¿Ovi£+.@Û ¦2{72<îý¾¼Éùho)rç{¬ýØ<@¦Ã=t_^¸}Ø©8h¹Ár3¥òÍ[D¹åå06 (qLèFåðI%´_z6àJ^eyS@ËaÉ" Ä% ÝÒlHsÍsfö³éXIÙÿdëØ9u.a6·¢ÛQÍ4pëyÜgã*îÂN]Ü;yîåôñìåÓ1Èg`??ùL<ǽxϼ¯ðÙxÏÁ»¼ÙyËãå¬W°|.+ãóX%Ïùv!÷±v^Í¢|!ëæØ¥|1»/a×óZv+_Êâ+ÙcÜϦ½øö2o´ìä,·qÍrßl¹,÷ó-y§å)¶<Ë#xÔò*¿ÈrÇ-y·åß*q¾M²ó%'¿Dróˤ)ür©_!y9YoªùÕÒ9ü:i-¿^ÚÈo¤*ºÍ¬ãETs± Rÿñö4ÜBü¿ÜNð ØþPK%0 û§ ¿4=D&ÌÂg¸ M ],&IÙþªAÖ±¼&,¢,)4)t)²¸p8¾êÅÃ(W A}LðïmþD±Zg¶}oçV|æIïÒÏ(-ÝB©¿IûÑ dP© §Ñ@Fzh Ø ¨Ì3ÌѼ4Ô 1&KcÓ}eP¹ JÏ&ÑX©ÈÝgÐx.ë<â¡ &°¹ëôÎD&°%g²ASL¸uo8SeXÔM¸SæÔR¥¦eNã¢I·¦§[3ÒCÓÃÒéVUºUnÍJ·f§[sÒ¹® èð1ª1áY|ÞCóĦóe¸{hAMxQä*½´êdÍp±ê ZbÂ4VFôÐRLxË2Èo»´,µ|©'ÕÐS ˳ó»ÑO<t´AÇð9GX© pARèRx¤ð J<ÔhPÐï¨ÉC¶A«LDjaV{hA!³øX5(l¢×?bPÔÄ\§§ÅCÇ31LS"%kÛÐ>t¹á7àZgÐzÐ!´Ñ¤ãéN4ñ jÒiô37Iqº !}gtΦs<t®P?ϤóéÙzèçâz¼Õ.2èbcQÄ^bÇVM$bǪÃxÜt ÷Tb±[j¶c]`ÊÔz;ãÔÅBD}"KÈÈhª¬tBÌ´9¾W¯LËk©ªvQõüÍÜ[ÄHbi ÜjkÊ@`-©Y0{ÑKÔ<éCo|c$¸ Ú$¤¼ugW×Ô×,Z(&M¤eA8|yÝÔZ¯·WGËñò¦pyk".F#ÁÖXÌ$ÊCñ`y=S\FBÇ¡hD)=¬C«iLw ·íØâèzæÕª£áÖæî9 È4mg¦¥Úé!+fÇ[Ã%Ò¹¡xùòÚcëÊãëCÕåóª£Í-ÑÅs#ö²aMÓ\ñút¨a³ÜB¤qQTÌë6+`7GYò±?L²: ®uæOÅ£w³z.Ñb{¨F[âuìYì$L¤¯\]ßÈ.Ó¼¨ÝirÏÈVE£a; ÒqñÇx"ÚÂt3-[ÕH8*$ïÂÖæF;¶b,ЩEtêµF"Lq'+/Æ9ãÃÂÃÀ°ÃÄÃ-*/§D+X0µÀL×ËÃ5v"D¨ì áºÖÆp(ØA|JOgÃ÷³~¶Wx+Ü©=µÑÈj :©G³?ºx=bi7+¤=AjhI¡Mè ÚЪ¨ÂêÙ:ÆBÑX(±ñGIº 5aoè9ÚbÙÜ=÷Å iÌC{ÄPEʺ½ª ùÝ9:áÎèwnÆøéD G+[½&éïÕ"kí¦#ZíV{ßFÎm»hûjªhk¤ÉnúQ,]ܪÖU«ìX¨zi mZϸ¥<Þµl±ëÃÑľ[%uRD[ã²z;0½'êÍ Åì`bö;ØÆzìjÙÓì¦Ô®îke¦Ö=ÚmÎ¹ß B$¨³5_o8uè_º¼Ó)Vàtpõ´Ky¼33>ÖÙmçUÙç>Í<À½ÊçsiÍÈ=)ð´ÆP Þ1Íl©è¬Æ IÏDy˺¥ë¤³#·%bNËøàwr¯ºòþ¥#3ÕÏØFÜvdΫ©Ì ')5´Réòò¬ê5vpm\è/®ìCBPb \6¹©\Õ º²å¯1ZÝÀ[bÑ¦Ö «ÏÄ)äU·6ïÑÛ1NMB ;wAɲTÓlty䨼VÛ 2ÄÔN0Ðò^tP$G¶&ÐW%Uâí'ZYßýJ3U¨ 4²å¡89Jß)ÜiÎâ,æ¬IìçL½!h·Ü|׸a;ÒFË"AQÏaÜùÒËó:ÃÙ+#/íÆ»I²Ì@/ ñaãÆCHöârÀälêÊ0^dH´ü/rñÿ ÿsþN6â?Iø×÷÷ù~Åä޳ث?»,¦C{§ó»¡Ä¬¶ÆöD¢î0ÆLÞ[øü¥ +Á£±ÁÂåøÁ6á ®°èJÜPÒe_,&æÈÞC:¦,ªI³ìUΤX,³è*ÚláUt5B~ÕçÄ9hñ;VÃ%¡HIs(Æm6BïÜCzq- tzl²°½3Ç#,íîÞ9Ñ$>ªyW"r[ë ¥ÉpVKJ]Â^¸ÇÁ&6Ï 0zGl*¹ÿ+´æ/OÚì%òÆÉW¯Þzã,z^âóaf0Zg¸êNhgáõx 7H±E¥¸I¥¸E[¥¸Zk¥¸Nx áÅ{DP÷bÂç\a ó°Ú³ñ^=Ò+}ÆôE¯òæ¦×èuÞSç¥Ì®ô+,zSFNµ{âö$í? ɱûF¡ `KDù³EoÑÛr~¿P0¼¤ãêV_pn·½M øwÅïYxP¬r/'sÅiª[V¯xM^ï³+²Í- 5Öîõúd>+ïW"÷ÙN´Ýl/ÉO±èC!? ¤9°!µþô§Zô9±Î5è¥-úÈÔÛ/%J³FÆ{G¿bAÃ<)nùW>%Í ¸Ùno©'ùÄÂ7éoý]ø|ÚK*û?>£Ï-ú¾4è+þA_ôEÿ¼æ[úEÿ¦/-ú¾·4ÀËSé®JsÒ7CCK#MãMÒñQÒÔ*û°Äy¨4Ù*nhYMW³ü ×'¢-¾µ¼¡ªz¡Yúícn/tþ^ÛˤÓË^ÒIît¥äÜÆÅZ[vç;gß.×R>wVEcÕ}Ò\m'ð ;°Òn_ý »{âÛt^ ©©!i®¯ ±<±Îî\¹ØëTÞ1C!öa¦ÕNSÇ¡B@Hæv¾×¤{4æ0ª´3JêãîÈî:Ù»Zrß4ãvbi(RÏÙ;Âv÷^êÜ uô¼uîI¤ßTûtLOrbÈyÝX!ý¦Z±¯[V£ÓTßðÕc)çàY¥Î;ª<:wQ§ÃNß@××µ}'û£lͬõkBröÕfÈs/SbÃItä _ÚuPÌ]9+?s1RûucEGô>ÌdA(jnm®ç¿cjÆmVqòñTùÂÅ>n79åMÙ¹çwBçÉ<¢¼<¿;«÷ïF$õÜ|X¯ÞjR[c¦JQþÓÖÈ¡6Ò rMï~aÑ!¦9îá¼&p¸È|cvßQ%BVcXm\eÚZ×þ ÈÑé|`¼¥Ýía5´¤÷]ÞÄç ÙâÎõRÉDC _sBuѵvm !Z«oöÒ-ÃR{MHçð¬zN gOÖv=Ô¬¾¼Ì5 »¹cKöXäÎãλH#÷Í(êã'õ¹·>ËæX½ÆÙ)Ak8 á[ z5s¦[©1Ì*§ç ÄgE[S^fIÜõâZï°÷ÕS½2ÔgÂÌÞɦ\Ôrn»V~CÃ+«¾øÔÙ±ªTêÚ7õ§/ýÊÃtçyqÊòe¯ ´îWÒj÷X¼ó mñ^j¥yBÏ>È1ÅÇ÷IÜqÞÈyÿÏ GO½Ë`(àd ½>3<Ù+ÕMßÿÉSdðp~yçÞ"oUòkwll¼rqäá,ýn¶Ú,ýÃ0á%~¦àc0 3ðqX¿åÜnÄ'á$|ñ/Ä»w-;ê^7°" ãPq{]¶üàßãÿ/ !2aL¬Õ¦o ò²Aí05T_6¨¢&ûytÞSpð «ÀâÞíPi æï)Óá!ÛaºL̨ÔÛáPþaÏjYíPå÷ú|mP]-@lv £fùóg·ÁJOGl6שç*+ 5Ì`V¡yêXr~.K±¢Ð«7M6Û¡VäWhVÜXÊ 9E9í°È?ªÐlº$QSÅNUÏ]R3& G:ĽE9õe Þ¢$,mØäÅB¯£×uúds+<Th2«aµ sÓQUdµ9å´Á²$,r,VdÕY¢ÄOêh®é1¢¬A®hËdû(ôuñsúÖõqW:U+ \1`Q_µ -^ÆpÃ&-ÿ¢ý*¹ùo¬/Ùe¿ýðì¦_ÃüFþX fâ¿àpü7,Æïa%ûb3!@A:OYp)eÃÕdÀ-ä;É{)î#¦\xúÁ»T ÷ç}î-îm%Ü;? Ü Ê¸=Qûfòá0_G¨Ó9Ϲ²=áÊvÏL %ÎV6ï¥ãr6C¹G9w\Ë·w»ç)ÝòY7Þx;±_·ûN7`º^ `d?» p@+VÅujK«QÄAýpp÷:¼Î:Q:ì¯Ö§¤,ç=ª{=FÃh} LÔõJ8B Ü^©Of}6¬×çÀú\FÙ·¹zLe-$Ð(6.à}r%qDCÇu£ÌÓ©/ýôå@ò\ é<&T÷ì$4};%q¤0£:Ȩ§>=ýX諯 zÅý:ßÎäîHßCÊ#x¢ed1å6§GHwÝF9Ëùç`êv][öKÄ1[aèíXîÚ»cKNâx¶v+ÊÞVöðVð,,{xÌîm _§Ær=*Ö(WuLRµ#Á0Xuo a»¨Ùçж=0ÒkÆ} ><Ö0qxáÂI¦<L{x)PY×Fç¦Ú_ÃÃP%¡ÙWc½Öw6ÒFÚÚЧ¢»G¶ãÖʶ0l\¿6¢Míf·Lt`S£¿¹NMGwÉ®8ù 7zÈ4r¯IiËw8Ãè+øó¸ZáAɪxdÉ~ܽ¾aìXGéYbÏ|!]6rÿ;$Þ´½Ó Ãú@9ïÖF²+@òÖtLàÃò@¡uLb6`êuLcFÇ]ÜÓ±ûÙ^ö^T¸1äûjvΰÝíÉÿFÖÕ(JÈ<zÊùá#Oö+å\î<éîS«ýûé Z`@®Ñ£Ã$1%ÓOoJf´"Â$ýÔä5K³YBF¨,6Á~Ðá*)iT>Ò8G¢×ëDMfZHH~?ç^GºÊoÛµÊÉ&R-¨å&Ò ©¡Ñl¸½}#'ËyæÙ7½sÌ4OV>cBù9å+å dKày$pã1týHÿPKlïTE U«¾ö¿¡7Tµ*é]$ÆÒÎ9s.ßóí¬xt÷8Þ âyÄèD">lb¶° ÛåF¿íðc Hò%©IÉjP÷SØ]rØ--_à ^Á^9þ öcXzËWåËÕ >éHÅÃr:ªâc*Ƹ5ìhCßÈyûÌ't;É%KèyS/Z0Äaëqa;#ù|a!06k:Yá:ÅÙi³akìYug¨ÊgChÄ0ÅhqjBXãéiVXEÆ4 å. ¹ÑJÉõ¬7«iÇÈãÆ°âÓÓ6 Wê×ð:«8¡á TqJÃiÑpç4¼óÛmÜC×íx&hãhãmü¨eä-ÃSÇFhHcB+T\Ð0¬5\BNÃLy Lk°¤Æ£¢(åI %Ä+Ñ0+ñ\ ÐðÞfØñÔêíµò¹7mY°öÏè¢ ÏϰN>KéË*yl áôR;ÑÍ`ÐR¦)¬¡\Ú¶ ÍдêÈÄE¡;áEÕ±¢izÝë®-Uzofû¨°*'cØòt&-@dèеï>Ä®Iá¸K1Ä<jÁ2¦ÒÖ,CoħÓN?%uëɰ*Ö=²X=WII]N¢3êÅêv4ÊÑÅQ3º+{ÖÇì9aN> ÓÅt UùåÄØ£üòÎ)ÃPþ¥<Ä;Ê¿ø@y|Ê/¹»ã[®â{ļ?ñüÌñáÙ?äaÆø*æãÍÌÏ[X¯¦Fµ²¾õ𵬷±-¼ ð¶w²aÞÅNó ÄÆ.K7á5ÉKBÚéý£ùPK)< âÇø1è(o~*3Îè8þÔs7-¥éÉ9÷ãß½÷÷;÷î×Ï_л°[F4a2 6â¡(6àaaö ³O^aö+xDë Gñ0D·OLæÓ2(Hàq21½qÝ5]Y³XM;ÞfÉI^ºXNW}«6Û¨º®iûéåé¡ÜÑ^yµ*º;ÅÀ-ßt=6 FÑv6Öïêo9¶Õ]×2Ýû¦²eªgPr´êù¥µ{!2f¹o'öeÝó¬c& /Y,'fr3)6<áZkùSy³B'ehÍÒ×ÓeÝ.¥ûX,?eûã¦oÄß~˶üç;Ö@àÿzȵ×9Ì õ9Ea]Ö²Í\µ2jº}´L#ßôü¬ãL0lè輡ªm¢#\ça[ÇMyßµìRoçmøSòNÕ5Ì~K¬ÐFdã®c[/êâ ÿ ×øïøÿëüùUàÒ.º°½.+$¢!Ù´s7¶ü/R|}ðÝÞD~}ê]°sÙtÍCZ -j¥j-ôÁC4ÕB" %HªT´µÚþVzú[çô/(½wvv`Ρ99{ß¹ïï½w&7ÿ{å*(¾á0¾ïÇü8BÁBXX°/1õ#/3ø1£~Âà¯2xÁO¼ÂøSÇgðs¿`{¿dêW~àdxÁS|t:0Þ`êLoâ-íûk?Þ¡ï°Àoü8; sq|×GYààíÛ·XÕçÅ·Xó=çÙä Ý´UKJµY¥ZŪM$kY©vL©6¥YJmGû %ã.y + ÕÐîUmM¡ðiºf¯à©«ßL7²Æ¹¨UÓÝÚmïHr6¦j©tCÞºfèê>·ãHÒ{T{].3 ´®~©ru¡!5Íjùñ!ÅË=7ÕMu_íÚz¿Û·aäqÃmáp§i:Ý¿OnàÃÂ÷h:gOËz99ç¹Øîï³Ó65êºúIêX¦$Ýj:©¨ë5®]ùXÏÆ9+n3Êú~\1g%ÔÜa®Ý°×=/ ª1vÃZ«îÌ ¦aʸdôâ:MÆÃØ(ã)ÊøVÉØÄìãL=ÂÔV¦:ÚÆT'SÛzYÍÇ 2ÚÐ.cìÇoeta#õÈX8 a¢FÝ£ê5´xl-Tk5éÜT6L¡#d|q")ßÂ*?>ñ uJc7-»ã1e/yJÅõ[üOqößX]ç>ñWîsöñ${û.³*vJ¨'oѬ·¨bEÉ({y²·( gøFçOusrl¿°`Ê+ÿ £o¥þÿ+³ï$ eÎfÄ:US'©aé/×Î,fÇud3IÛêø-º£«iNwf{a®Mµ¬8|Y]ýWgìiÏMÞfgç4gwQó4:÷[¶¢ç&ËÖ¦%yjºbª):¥u_w÷í«ã0dæ;SÂÉvÐd/S¡"zãVov¯Î¬kDu3?hì·¾ÓÇÒ |å X «éK¢ a¬`= Ë ~ êõ.¦÷P.ΣZ\ÀÑOA^ßn cnÞ}g$Fà×0]|2qê1J®?& ©Àq½ÓÇ1j"øzkÃ0j»©¥îÄkÛÖø Q'a¬EJ9Tñ)|â&Uú3Jêsª èTM¿ö¸i&VÙ®_Þ@`Eeº¡àleø|Þ³³y«3¹ Ädõ?¡Düï/(Ã^ìsím!kÜhV!ròúzï>âݾ³ØÛb:nÔèÑî¼ÒoøÔíÿT_=`¢}ðVË{+äÅ_ÉËß÷zé~RðòûÎÁôÊs¤ÊwI²áóQ6óÇL >ÿ øt~:Ãs¢.Ü!zàÁ¼ÕÙ®Õ NfùÔªô&u¯«/àK\t¾unª«wÔGú+ ÈÝ|/ß¿ýOìdIñ-§»n ¨tá%|£{ 2â5<'^ÇQq'HVÂsÎf?ô?PK×¶u` ¦Ì*c¨¿¡å: gÚ¶2.l¶À]5ݬp »YÃéìe88!2^Òrn%+©;ÉL.é¹F.©[¦îÙ¶0ÝdÞpôäôÈpÜ Ë*ú¨aîC|ëð ÄYê+#b)&½ü¢°ç´ÅYªlÏ$NÑY˳u1fÈZ(z=k[¦qKs Ë3òÂÝÐT$Уbâ*:ñUżsøHÁó¸ à¢K¸¬à *tdW±¤"+-®)Xü²ò*Kn$«3ã*L ë°U8¸ðTÜä&Vþ÷ÈaÛZæ°fÛ°O®è¢ Óeè¹&s¹L®°m¯à̦UôP?·ÚÎ>0¨iÓöHNsá04¼¼ljñÐ]ƦÏ4v½â7µ a¨+_´¡o'&^÷¢ªu;mm¸«4ñ´ìx¢²è©Ø4;Áv¹TÍòË!ª"ÅÑ»UMçpýMWÞ5~à´W NV³©·ÂM³5]öBïÙ!¬9£ìY<1J«í¸FSYÜ(c¬ê9C/¾¢HþyÛF^³©óÝæM=§ÂbE§m[¢"#fËŧ÷.(¥ÜFSäº*È#ð¥ëËm¢ÕBùñ+Ôí¼t§%Nìß×Î+Kë_¾ÈÆ ;é»d7íáÐ(1÷ú}£|Ù6µý'ÐEz7IûH¯"ëú¬«ûB]mPõ }kOVÚý÷âà0'|¯4Æc¨ÏѾ-TÛÚ3ý#gþ$|=V®ãy1¦q?FfÕÚõ®7¸JâÉâJÜõ2ç*÷ªýC§åpñ¿^?âU¿iQ÷¨}G´!-k s~jô6çGxéaÔûì}m®Açrº¶þt±L¥IpZg¸õ~t-²´á60lb>x¥àEfI÷Òc×è¾¢~®cêó57 Á+Ï_f°e$/iúç'PKVæ-¹ ùþÖæÆ:Év3°{nI%³ÛÆinÓÝ] ùTb3O"Ã;Íí Tu2 R1ÐËÞ8xøq FþáXÙzó.C¥¯ó4w¤I^é?SáãT+ù<ȤV´cò<Ì£æá<=\ÁUÇqÂÃ5Ônù(ÈDW'I " à 1T¨\©=IµÚïT1õö]Äv{tóȤ1DV˼E^t:=¸s(£U#¾ÆÑKÖÃ"¡-²ÕÖ[°V{V«½{ÎkbIñÁø'8ü3ÊüùWò,¡¶_£Nk½µÒA&7<ÿFû2NîGoP5ìZûø}Jq®Ózñ%kö½BÉÙ³C-|GÿÀÿUþ<§ÈcáôPKÃzjÜ í¦ <!ë*,Í7¯´8÷Vׯn©¾ôª!* $VRHÀfþiÓ0ºka5 5¬%í¿½/ýz EÈÂù=Cilõ¹a´ 0ñ!ºÒáHâAé:¥IzÙpO:sþI¤ÈNQ´Iq¼]+÷ÜRDrGül¯ú-ÄÂ,ÒOïy@l_ 7²3#²ìPKs¡b *¡ ÐæZôR=ìÌÎ0gÎÌ×·§ æ¾!õãiÂ/)ËDڲ׿^gª¬P²0Ýí?S׳rÄ¥#L¹e¤&]2î3ǪMÔ¥ßvÉÓÔëºc¤ÇÈaÎVÏ.ÂÊ7PKâà«o )¢#dkï!uâ8CñLHÞ½!öÐ¥L2ä[]ÅZ2â´ÝJ²ËPøÍ]GvD ½ïÇÃO ×úÒ¹ |)ìHør <´ïì{Û@ºMl(bÙ@ yöù(¶üðßøZ#×#áZ/8¸,OuìºÓî½ÃÁÿ4çñÐÎ,;«^302£9¾7å¸mú²,ÔJÑ¡A@·:EF1m¾½Ð Á ̨¤VÂò1£6¤M5³ùÄ"·L\r?oµ}EòyZ!êÊ|]HQó¦iN =Af±{p^ ¬ý »*H1Üû°DÑQ±ÆU(F]%cZ,ñ;©â&¦²b7Ä2Í0Ã0+!jk¾ÏÝà¹<·jWÝç%Ï(V Ë1jíEÏmÂ+·¸ç{®ý[yÏ--KPVl×Ö$Èzúкgq íyÛå[µò.÷·Í],räÖs³Ýû®él #1sÚ.l+C-x5¿ÈïÛÞÓLm¶çnÛeîg/M ÝHJùoñæÐ/ؽ:ÑE¢E8Ã1ݱáûO¶¼éNãísKoi¸-h}bÇEÜaXÒ°^ ÍÅ}üZ%àÖÆAWl +XÕ°&U\¶«EãÞºCbmmJHÿãqùAPàÜÐçª oSãDä¨>+zåJM\4¡¡l'¬çré§âMööÏM ®:W$´6_Ø»ôtþ*$j_Ô)Ê 3aEÕé¢ZHktCN@gæRæ-;'úðÑ9í:mÖëGBìèAo#À0ùÈõÊN#òí§ÐlðÔ¾>E/D$d>!\GôãtÐòÞ¼(íâÖJÜZ×!gêPBd¨Ø"Â$CI¥í=BGodi ïÃÙϤÒÿöÅ Z[ ½8ϾSÜi¡eºÓ¬óh¥¬#Ù(6GM éèaiL°t6Iox ,e6u6KìAb·`è7PK#3/¥ ¶ûÀFyÂ|04<ÐbôÉ,»:¦!ÛY¿þ&²Müþ(½P%áExØ3÷ã{ïÜÙ?'?XEàÁÇó|ÞõPÀ½*&°ÀÖ"CÓ#waá¾.VªQ¥©ÔöÀZG&YhFdßñ(LafÕ Âî¿OV_eÒ1ºÿL ü\ie7Vûµ@ñI¤ÀTGi¹ ÷eÚöqFÒRºµÍ¬ ¥Lu4Øâ )·jc{IdIáuMÆrS±|î¢udÑ=5éêècäc Ó¯=¼euÃÇ$j>êxä£Å±mvëh<ùoí¡Åç ¸òîÎ@ûj¢3nEË϶+er¾!ÚÓç͸±dV¢IæÓS4xV²ôÑÅ)r¬5ÈêÁDð ·ÇpP<Déûl°p×QtbO¾Ý¸À2å(/øÒbò]K»/O{óôSqà ós¸ß.±7}ëßx+ä1{2ÕÞå/ oWÀÜ)PK9Ve¿± 8®%^A¼ôQÈ-H<!×^ EÎmnÿ´Hí; \Ú9sf´?}?Ð ïÂŲm`E_oh¸©aÕÆ-6mܶqÁIxÊQÁ_2¬õyRYþ³0ÎÃ$ ËB¤aɸTË"<¶ï34)¦ßyÎ`g géÉåh«Ýh/¥L3çÅFÕ¡ë¡Öm'Ëïú34©zì°GË7ÉXÄü½Îæúå÷Æm,¸QºãÛ³ªÄÝÉJó-¡'ZØù ãW*âcTLîWÝ×ÑÛÈÃ9´<4áy¸Ë®`ÖÃÎÍc¶£IaÉa¸©T¦înã $4CçÔ+°Úô\z4¨¶EC¹¤ÌE .àbU·Du`í¯V³7±ªç¯¸têSÁWkÔ-BÚREmWv¦}û°>ÕØçþoWÂ{ªnã1áüIÚºvV´«lS³À~q飻OìkÿjÀ~Bìë¾ÿÏ.ÒÍÀÒoPK5âôØ V±¦`6L#« <²{ãÅ5ytkvÇsý6%]î Z¹>^y÷ÃÞ&Íöírå~ÊØbè#60M«2¢Tj¬úÈUÑ µTø¹¥¡Tú?zbH7Lh0z (-?F_p n2lâëï jä÷(âŬúHÑC÷¨n+ÅÊ߬(ÙØAr'½£["ÝYËì{PæÂש"úºØEr" ͤBëà+h6Më ñòëçß«àÜD+/ [è¦ýù[hõ`wÐæ<q¤2U(´âU¨¤6W±åÔwV3C÷êÌ;lb[lµÖL a(wÒ¯ûïîN÷ýóñ ÇQ,Ã^-ì'è$8`/¥vÀu{3ö.¡3Æ®óÊwÒvFÐPs<yQâÁh%_+µÊLþX<gT:®gZh.^VÜYYq¡pƲüÖYZf9dÈ7"µlÄw7¾a8ÿ®¼¦ ¥r ö»£h .z3 íùô×zÝöÿ v¿Bk è}½µã5³äÍkê]»¿PK(gV/÷ ò0Hný彤¿vuG8Bà~è99ÜtìØeíÞØC¼DcæÇªmËaèÑ»ÃØ±¶ÿ >%îöê|Ã73ß03?¿ß (gÑmîÈc/Fó0±O/ïÔÞ]q`´£9 ½»uô{s¸÷ksPÇisX#QVdâÀ£ô4<ûÉÇöUT=4½ö¢ZðL»mÖf8 Óö\;ô}åfMYõyß T G ¤;®Ø_¼ÞÃ¥9Ôq¯®6WWUÃæåÏZgÜÉXöS¡ã«@²¨3s'ÎÙª8Û^ÎÁUç(ivAÑOº$7ã ¾N:±0ókõ=×yÖÒ0³NSù£OXO[°ËÀvÜb`ãÇÇÄ 'uä40)Ó0°SïUôÞiìØ¡1Ìå.n |?lª+Q5ð6ð>WÃ!íÍâQóª¢5¶mÖæµdµê)6éÚNT½è¾Ñv3YL ^_¨µÏõe·T,]½É1|M²ÓJ-ZN »ÂB§t T³Å~¦S¥Ç²]Eu@8´ÒW eµyjËz#fÏêª6uòÖÖ}¼ÁÆ,uÖG<Ûk¶B=>WU[ucëûùDÒóB/M S~òs_ðÿÓò+"Ü=G|6 »;E÷m(zp©×¢ ,ðY«a;Çòk¶ø¶ø[lß±ï±SþÀÛÙË/t¤©ÄÒÜt 4ùε7ÇÊlû·2ç[ËëR¦ñ+ùÊüLe~¡2¿²ªß¨ÌïTæì¢áHdøÏ$0Ib"Óé$B þPKôz|ÿ iið¸Ý,ºìÂ&Qô<| ÓÉÿfÉ/1$+?Kç8@n×£¤¥I{äáÑÞÀ®è,á½|ÿZ'õÛ^o4$×ÁÆPKväÂÿ r'¬{F51Äæ\Ï æ"fö%Ctɯ dÙõÄZØØrÃÞ¬ÓH,lÖì}Ý¥#ºj´oýçlKßs?Ûë{nCÈü[ûͰ"j¡å·vÄo9-«V·ÂÀ[ï9¡Â¬ ¶T¥ùB7~8¢"ìÚáXÙwÞ¸¼KEã îcÂ@´¢H1d¼U·½-ëGÓʰÚh*fÌbÎÀ#5Ï<°hà1¦gn¸-çÔy¥Z'µë¥Õr»¢`ϱGÿlŬ:"n;ïCWêiX¡ð¸à5[eèT¶(¿¨Cþb$-)? ³fölAÕ3¤3|."&E]Ø-ê¶ÓÝØV¢]ÇÜv"ÿ³H+î¶;æsüF3T5W³´WÚÝøN{a ËÒõtУ&$¼BEû öjûìRÎpP'6x ¡k'U_©*Jßr¼ÛCÞÎÜ7ÄJÚ8Ãâ_XûÄÝ\ÿºJ »<@Ï GosH+49UªX~ìbÝäb|1>Hò,Ò<>>#Ï'Pà,òI,ó)<çEáúáûþPKÎË Üf â+Ï1ä¼ÉÌt¯ü`»NÁ6_èìdÕÜÎ0G¥áciøiHb@C ÞÇ n¿1}³d¤Ï¤«aOSWp«1ûÓÉk¸ Û>Åg*¶5 þzêä-Ø®t¯HͲÈ&*¤ä5ìbÈ»TqQi×Ñ3;¯ÂÔp#Âg°4|/4ì+ ¨á9F¨êfܱ¤áRp£Ê®îø¥D¨ÁáÈÚê&sÃ%Ö2çújy]ÜlµZå-gï5ÌôlÞ|#.÷¤Á¢óQÈx´±î:Qçîh¸¨ÕFau%/êÆk¯ËWw©S¥´Hµ÷ÄΫJ)ôY+£F¢ª%Aí\dÇa2Ô¼§[ÚÞ£ ðÃÒWBW0Õ ÑM ¾BSÝ6Êøbtiº×ig¯M©_Ðôó9ÕiR¥A¨RJ¬zTC¯Ñ:Ft#UZàhIZhE c xÍ1IÏe hôËÊfDß&cßÐÂâ_Ñ^Æ[/}7-hG[ÖÁ×"ÖÐ"ÖÑ.¡K<Æ Fâ?D/cFä5ú)¸ ®Ð-°ä õjtÉ5 ³çH¡»wFø uGü¨Ê¸öe¼;yl5À#$F"Ý2zÑ»ÑÑWÁ?{ò³Ú¤1ßæï¦IýI "$¶éò $DbÃbwy±Â¦°±%ØÏaÂÅq@(£ÂØPKírmÓU (ÛXqAÙ U¹?³fcÝÆAþPBd;WÖrRG¼\õýA`^Üãg"1ÕÞcÈnů ûbÌUëÖ¿ó=¸(ìñaLetÏG²kP&C+ÅCMÇ"bô"Í]vÏ=lbþ˶ âL>pk©<TQ#ØO7r5S vÓL1âºÍ>òµÙG«ÑI×ðÉ|Þ/>¯68¶Íb®Y¸qÇÈÔSæ'2×Sd'°ÌÀ~AK&V`Î3,ç%ç5çÍdM&Ò/PK°? #&ë³àÙ¬g²{Õr=^ÉEC)_ª£Sýò¿KqR_K\¶G}#µÜr¤RÎH«MjÀneR!Ñ"9@Jªéö¶16>ÀÔGç¥, è/Hé¯Èëo(éïÒ3+= ÌýPK±Ák _ÁÍN{;Ò±ëʬOmïb7Buà¥* ª-ãú7ï»ç !{=µU"ܺ(Ñû¸ùÞÁsÌ9xAóxÁà>ðÏ,,8xET^g3Ñ«A>(§ÙÈf é[È/¥Õ+÷¥«AlÃÔÀà·zÙð»z|)ÛiÍÝXz~Â`}õ±ûäFoPê!²úo¶~+ÒÊà·iT `®CaÒôE9©Ýh¦YyÚ9Xí¹/çÈwP¨¡¯þÓ.:Bã 5ÕŤî*¨îNÐÏDP?B!1Áð£Ä[$*¨`}O×½çÜç·ï_ìàNMôÜl¡~!ny³â«3ha-Àz P)²s^¾F-| 6!à JxbÖãSÔ>ü4¼3|Cæ¿¢î^Q»ú úgVz |Nø¼Kä`ùPK¶i¤ sÄ÷1±`#³©½¶¦HðÎ-TÛ:L·Nì8kô%mÝSn52Õ0á½Ê·Åwud¹,xÞåÁë.ÖÈà2÷t!ù¶%ʼå óG¡^F3ù5,FÊOϦlw¹Ê·î_kÃÚÿbæúl¼r.ûPÔ,b334êËÍ';4 ·ÿWIüB~ Ú)!¡£DtÃòæhg´4ú`Wä0ÔÈVc0='Kb$®£Lü ÒÁ»>Ê;>*+׸Fõ; a/0þÀPúé%)^¡üÑûKýPK£.ü ¨(¢m»!Ê)áÅB4/·³²ÝMöŤ?pfÞ°ÝlÎÌóÎ;{Îü¹<ÿ º &r¨ÂdÂÎxlÂ@¥'ÖÙSÏÌ0äW)^oH7±èÜ lÙ®g'±òlø" CéÇv«JÇî;8+ÊWñ*C¾ZûHZk+JÊI·-ÃÓöh¯ïz¥¹$¡ëJÏOmø¢¾úæÄ*ð[ª+ÃÆ³ïX(aáͽ®º*öVÒöHÅ>l¾·090laÏû>/ðÒB5ål6þW!/Y6OÙ;ÌP$ã·Ò»NL©Q½¿8©±M]ßèeÃokªñWý6b0vAìÑè5J4BVÿÖoDÚüÞAµ~ÌÐ¥°èÚ0Lê>¡,G9µÅ4j"O0Q?«_ ÷ùù õô0ø+EËË( Óf4Ì2dÄàkMáD .EGY<°×BéZ\y<ò}á Ö¡R®pv)= ß`ÈmJO[éå"m+G0ÒQ¯-üÝvéFßäîW¦q¬"=ßO_{¼ë+OÞØ¡T^Kö_?³/l&ÖÿýSOÜ:Ú®ä ìè`ßÄæM(X@ECÕÄ" ÒþI@jÎ`Ê?B ÂáR©õåÿû0HÛË¿yÉËW{Õõ í4»sªUÚ<í£¡þ"FAvN ¤Éʵ>Xí©Ó>ÒÈÔî}Dî6É!èÑû(êO(éÏùU ÝA»GöWúÙÑäõ±OPKjå| ´I}ÑaÎö8v9Kµþ r*bȪX¶2írÖ!^Ø$Íf¨P±E>Ò|&ËÝmr¹½âë\ z5ìF=ØË©.olVièG^Ã~i0¨a4Ä! ÃÒ7Q:¨êrʳ¢¼«Ãï¶((DAòptÛpz¿ÏK´U9rZúÃó!Uü¼ùN;¥jo·§3ïÏ®V)¤µRHjhL,4t`ì0F"0¾¡ú˨þÿöIía©ñKÌËðéô3$KãêùIà ¤ÈMzLºÇ ¡é-¥òRïqj9Ò¾åkÛ^þ-°.â ºø©l <-4Ûx´×½ý ±¯/!>ÄTÓJ¶àWà×PϯB?¤¬åèVzCbôMe/"¹9ù Âç°-ôÙHþðèM²a%Ð)$dQì4Rd³hεÍÇA èmÓ¨Ä.J§C\=uäY4E®hZ7Es±Xk#Wý8ûêA¯PÙN½ßBÏBã·±ßAÿëø/Èñ»Ðù=lå¿¢ÿnþ;öñ?0ÌÿÄQ~ë)>Ay6Ðø¸ÒÈjC6gTvÉZèO¢1GÎ¥3X/÷sóÕsr4N@-7²VMßÛo°ÍÒÛþbüoÔðhâæåcbùX>%ÏÐÇÿù»4ÍcȼPK¨Ñün Kʸ¬£`` 4zt/9'=Þ¡¸ÌÔ¯äü¢ÐÐXJ"Xµ7\ZÚ¤§á|fê½âÛ)KÃÄ Ô1]IéUD@ä`¦tmo³U*tñ2l¯Ve ØÑ`¬øQà©öÆÑå¶lÏî´ºdÂã95G pÃÄU\Ó0|ZL\Ç´_akèoó/Q¥ïØÀ ¦¬)s>ü@ÃPRü0íø^%"'L+×w©câcdZ¤È¦B©j± ¦t1 ¤·öˬSÈòmOO´ò L|/M¼ÀM¾Ë¡x/ACÆÙCǦ-HÛ*sïb¦sás;¸uºÐÞák¤éȹv¥²ì~äé4L®@Ú®üݯâèSQ,¿²+6}Ë©XE×BéZLªðB«$+Õúøf?xiEìòï ïº-·Å¸ ÷Wô{úLA»ËTLí쬲pűÒ&ÅÈᦫÖÞQG#Í£]»Eí5ô4]¯nÃB9S¬±?Ú85+§S6ÞÝ£l5¸Àï×~GüceÆ+çÕñÌ6঺ã'ÜEhççÉ& e_£mý ?BOAÓzG1»Àãc^Gs5Å9mSB[H4kªàVôüQö^Ð>F/¹W ×BkL 5kc:F¶ô7özrXQHf5`ÂøPKüâM yT1à@\B*ÑûÆ^'Înå_r¬T@å >1ô©b8)S%Àigð¸'0(ÔÄçbuVì=%Ô«sbïñ©h+MÇ%pÐ+aDF£BP0&£ã ÒÉ´³¬$ÒmÜj*ÅSþ55ÞkÅ9w«És[b<[©I°ÂZ*7ÂiG7ÂejiÛæ¦>JDuFm®ÆI§"6¦WÃj&Âî&ûí¬Q:ß½43bXÚxTåÙó>ŵ´Ã»=Á¬W3ª:¼£À*©ê°Á; 6ûǸæÆq¯¸2¦¼7=1Ìí!ÌP>Çq¸å:ÍÐìy`ðª~?·u+®kªa!´8ahQOSMUÁÿ7¡$¸ *Ce°i±PhWí9¡â PlrTçO¦¨5iÒÒäSxs½ZÖ«Ì¥ð¹S7ug?|ÊJÛ?¬`H· /v= ¦I]xVAB lìQ°R P*7äÑm<¡]v"=AÐCSO:ºe @§Ò ÎU3¶*Ä´JVðð}QÁ%!ö¢^ÃËxEÁe±zUøs¯)x]ì½+ ÞÄ[ Þ{ïà CmG&%N:<>ï æ*- ï*xïÇ?`Øù0µ#t?dغ]Kgsì°ª9=}:ÅmÒû«2O$¬>ÁÝLìa... [truncated message content] |
From: Huston F. <hu...@us...> - 2002-03-30 16:17:13
|
Update of /cvsroot/beepcore-java/beepcore-java/lib In directory usw-pr-cvs1:/tmp/cvs-serv16781/lib Log Message: Directory /cvsroot/beepcore-java/beepcore-java/lib added to the repository |
From: Huston F. <hu...@us...> - 2002-01-23 18:40:33
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/echo In directory usw-pr-cvs1:/tmp/cvs-serv26942/src/org/beepcore/beep/profile/echo Modified Files: EchoProfile.java Log Message: fix bad check-in Index: EchoProfile.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/echo/EchoProfile.java,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -r1.13 -r1.14 *** EchoProfile.java 2002/01/15 16:14:38 1.13 --- EchoProfile.java 2002/01/23 18:40:29 1.14 *************** *** 69,142 **** public void receiveMSG(Message message) throws BEEPError { ! OutputDataStream data = new OutputDataStream(); ! InputDataStream ds = message.getDataStream(); ! while (true) { ! try { ! BufferSegment b = ds.waitForNextSegment(); ! if (b == null) { ! break; } - data.add(b); - } catch (InterruptedException e) { - throw new BEEPError(BEEPError.CODE_REQUESTED_ACTION_ABORTED, - "Error reading request"); } - } ! data.setComplete(); - try { - message.sendRPY(data); - } catch (BEEPException e) { try { ! throw new BEEPError(BEEPError.CODE_REQUESTED_ACTION_ABORTED, "Error sending RPY"); ! } catch (BEEPException x) { ! message.getChannel().getSession().terminate(x.getMessage()); } - return; } } - - // public void receiveMSG(Message message) throws BEEPError - // { - // new ReplyThread(message).start(); - // } - - // private class ReplyThread extends Thread { - // private Message message; - - // ReplyThread(Message message) { - // this.message = message; - // } - - // public void run() { - // OutputDataStream data = new OutputDataStream(); - // InputDataStream ds = message.getDataStream(); - - // while (ds.isComplete() == false || ds.availableSegment()) { - // try { - // data.add(ds.waitForNextSegment()); - // } catch (InterruptedException e) { - // message.getChannel().getSession().terminate(e.getMessage()); - // return; - // } - // } - - // data.setComplete(); - - // try { - // message.sendRPY(data); - // } catch (BEEPException e) { - // try { - // message.sendERR(BEEPError.CODE_REQUESTED_ACTION_ABORTED, - // "Error sending RPY"); - // } catch (BEEPException x) { - // message.getChannel().getSession().terminate(x.getMessage()); - // } - // return; - // } - // } - // } } --- 69,113 ---- public void receiveMSG(Message message) throws BEEPError { ! new ReplyThread(message).start(); ! } ! private class ReplyThread extends Thread { ! private Message message; ! ! ReplyThread(Message message) { ! this.message = message; ! } ! ! public void run() { ! OutputDataStream data = new OutputDataStream(); ! InputDataStream ds = message.getDataStream(); ! ! while (true) { ! try { ! BufferSegment b = ds.waitForNextSegment(); ! if (b == null) { ! break; ! } ! data.add(b); ! } catch (InterruptedException e) { ! message.getChannel().getSession().terminate(e.getMessage()); ! return; } } ! data.setComplete(); try { ! message.sendRPY(data); ! } catch (BEEPException e) { ! try { ! message.sendERR(BEEPError.CODE_REQUESTED_ACTION_ABORTED, "Error sending RPY"); ! } catch (BEEPException x) { ! message.getChannel().getSession().terminate(x.getMessage()); ! } ! return; } } } } |
From: Huston F. <hu...@us...> - 2002-01-15 16:14:41
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/echo In directory usw-pr-cvs1:/tmp/cvs-serv11346/src/org/beepcore/beep/profile/echo Modified Files: EchoProfile.java Log Message: fixed to match new semantics of waitForNextSegment Index: EchoProfile.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/echo/EchoProfile.java,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -r1.12 -r1.13 *** EchoProfile.java 2001/11/25 08:38:42 1.12 --- EchoProfile.java 2002/01/15 16:14:38 1.13 *************** *** 69,109 **** public void receiveMSG(Message message) throws BEEPError { ! new ReplyThread(message).start(); ! } ! ! private class ReplyThread extends Thread { ! private Message message; ! ! ReplyThread(Message message) { ! this.message = message; ! } ! public void run() { ! OutputDataStream data = new OutputDataStream(); ! InputDataStream ds = message.getDataStream(); ! ! while (ds.isComplete() == false || ds.availableSegment()) { ! try { ! data.add(ds.waitForNextSegment()); ! } catch (InterruptedException e) { ! message.getChannel().getSession().terminate(e.getMessage()); ! return; } } ! data.setComplete(); try { ! message.sendRPY(data); ! } catch (BEEPException e) { ! try { ! message.sendERR(BEEPError.CODE_REQUESTED_ACTION_ABORTED, "Error sending RPY"); ! } catch (BEEPException x) { ! message.getChannel().getSession().terminate(x.getMessage()); ! } ! return; } } } } --- 69,142 ---- public void receiveMSG(Message message) throws BEEPError { ! OutputDataStream data = new OutputDataStream(); ! InputDataStream ds = message.getDataStream(); ! while (true) { ! try { ! BufferSegment b = ds.waitForNextSegment(); ! if (b == null) { ! break; } + data.add(b); + } catch (InterruptedException e) { + throw new BEEPError(BEEPError.CODE_REQUESTED_ACTION_ABORTED, + "Error reading request"); } + } ! data.setComplete(); + try { + message.sendRPY(data); + } catch (BEEPException e) { try { ! throw new BEEPError(BEEPError.CODE_REQUESTED_ACTION_ABORTED, "Error sending RPY"); ! } catch (BEEPException x) { ! message.getChannel().getSession().terminate(x.getMessage()); } + return; } } + + // public void receiveMSG(Message message) throws BEEPError + // { + // new ReplyThread(message).start(); + // } + + // private class ReplyThread extends Thread { + // private Message message; + + // ReplyThread(Message message) { + // this.message = message; + // } + + // public void run() { + // OutputDataStream data = new OutputDataStream(); + // InputDataStream ds = message.getDataStream(); + + // while (ds.isComplete() == false || ds.availableSegment()) { + // try { + // data.add(ds.waitForNextSegment()); + // } catch (InterruptedException e) { + // message.getChannel().getSession().terminate(e.getMessage()); + // return; + // } + // } + + // data.setComplete(); + + // try { + // message.sendRPY(data); + // } catch (BEEPException e) { + // try { + // message.sendERR(BEEPError.CODE_REQUESTED_ACTION_ABORTED, + // "Error sending RPY"); + // } catch (BEEPException x) { + // message.getChannel().getSession().terminate(x.getMessage()); + // } + // return; + // } + // } + // } } |
From: Huston F. <hu...@us...> - 2002-01-15 16:03:02
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core In directory usw-pr-cvs1:/tmp/cvs-serv6703/src/org/beepcore/beep/core Modified Files: InputDataStream.java Log Message: Fixed bug with setComplete being called after waitForNextSegment Index: InputDataStream.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/InputDataStream.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -r1.2 -r1.3 *** InputDataStream.java 2001/11/08 05:51:34 1.2 --- InputDataStream.java 2002/01/15 16:02:59 1.3 *************** *** 161,167 **** } public BufferSegment waitForNextSegment() throws InterruptedException { synchronized (buffers) { ! if (availableSegment() == false) { buffers.wait(); } --- 161,174 ---- } + /** + * + * @returns null if isComplete() is true. + */ public BufferSegment waitForNextSegment() throws InterruptedException { synchronized (buffers) { ! while (availableSegment() == false) { ! if (isComplete() == true) { ! return null; ! } buffers.wait(); } *************** *** 185,189 **** void setComplete() { this.complete = true; ! // @todo notify objects waiting for more buffers. } --- 192,198 ---- void setComplete() { this.complete = true; ! synchronized (this.buffers) { ! this.buffers.notify(); ! } } *************** *** 195,258 **** private InputDataStreamAdapter stream = null; } - /** - * Returns the content type of a <code>InputDataStrea</code>. If - * the <code>BufferSegment</code> containing the content type - * hasn't been received yet, the method blocks until it is - * received. - * - * @return Content type. - * - * @throws BEEPException - * @deprecated - */ - // public String getContentType() throws BEEPException - // { - // return this.getInputStream().getContentType(); - // } - - /** - * Returns the value of the MIME entity header which corresponds - * to the given <code>name</code>. If the <code>BufferSegment</code> - * containing the content type hasn't been received yet, the - * method blocks until it is received. - * - * @param name Name of the entity header. - * @return String Value of the entity header. - * - * @throws BEEPException - * @deprecated - */ - // public String getHeaderValue(String name) throws BEEPException - // { - // return this.getInputStream().getHeaderValue(name); - // } - - /** - * Returns an <code>Enumeration</code> of all the MIME entity - * header names belonging to this <code>InputDataStream</code>. - * If the <code>BufferSegment</code> containing the content type - * hasn't been received yet, the method blocks until it is - * received. - * - * @throws BEEPException - * @deprecated - */ - // public Enumeration getHeaderNames() throws BEEPException - // { - // return this.getInputStream().getHeaderNames(); - // } - - /** - * Returns the transfer encoding of a <code>InputDataStrea</code>. - * If the <code>BufferSegment</code> containing the content type - * hasn't been received yet, the method blocks until it is - * received. - * - * @throws BEEPException - * @deprecated - */ - // public String getTransferEncoding() throws BEEPException - // { - // return this.getInputStream().getTransferEncoding(); - // } - --- 204,205 ---- |
From: Huston F. <hu...@us...> - 2001-12-16 01:02:17
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core In directory usw-pr-cvs1:/tmp/cvs-serv3300/src/org/beepcore/beep/core Modified Files: BEEPException.java Log Message: added basic exception chaining Index: BEEPException.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/BEEPException.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -r1.2 -r1.3 *** BEEPException.java 2001/11/08 05:51:34 1.2 --- BEEPException.java 2001/12/16 01:02:13 1.3 *************** *** 1,7 **** - /* ! * BEEPException.java $Revision$ $Date$ * ! * Copyright (c) 2001 Invisible Worlds, Inc. All rights reserved. * * The contents of this file are subject to the Blocks Public License (the --- 1,6 ---- /* ! * BEEPException.java $Revision$ $Date$ * ! * Copyright (c) 2001 Huston Franklin. All rights reserved. * * The contents of this file are subject to the Blocks Public License (the *************** *** 20,45 **** /** ! * A subclass of java.lang.Exception that we provide so users of the ! * library can differentiate between BEEP exceptions, and JVM exceptions. ! * * - * @author Eric Dixon * @author Huston Franklin ! * @author Jay Kint ! * @author Scott Pead ! * @version $Revision, $Date$ */ public class BEEPException extends Exception { /** ! * Constructor BEEPException * ! * ! * @param s * */ ! public BEEPException(String s) ! { ! super(s); } } --- 19,124 ---- /** ! * An exception for representing BEEP related errors. ! * <code>BEEPException</code> adds support for exception chaining ! * similar to what is available in JDK 1.4. * * @author Huston Franklin ! * @version $Revision$, $Date$ */ public class BEEPException extends Exception { + private final Throwable cause; + /** ! * Constructs a new <code>BEEPException</code> with the specified ! * detail message. * ! * @param message the detailed message which is saved for later ! * retrieval by the <code>getMessage()</code> method. ! */ ! public BEEPException(String message) { ! super(message); ! cause = null; ! } ! ! /** ! * Constructs a new <code>BEEPException</code> with the specified ! * cause and a detailed message of ! * <code>(cause == null ? null : cause.toString())</code>. * + * @param cause the cause which is saved for later retrieval by + * the <code>getCause()</code> method. + */ + public BEEPException(Throwable cause) { + super(cause == null ? null : cause.toString()); + this.cause = cause; + } + + /* + * requests to fill in the stack trace we will have to ignore. + * We can't throw an exception here, because this method is + * called by the constructor of Throwable + */ + public Throwable fillInStackTrace() { + return this; + } + + /** + * Returns the cause of this <code>BEEPException</code>. */ ! public Throwable getCause() { ! return cause; ! } ! ! public String getLocalizedMessage() { ! if (cause == null) { ! return super.getLocalizedMessage(); ! } ! return cause.getLocalizedMessage(); ! } ! ! /** ! * Prints this <code>BEEPException</code> and its backtrace to the ! * standard error stream. If this <code>BEEPException</code> was ! * initialized with a <code>Throwable</code> the backtrace for it ! * will be printed as well. ! */ ! public void printStackTrace() { ! printStackTrace(System.err); ! } ! ! /** ! * Prints this <code>BEEPException</code> and its backtrace to the ! * specified print stream. ! */ ! public void printStackTrace(java.io.PrintStream s) { ! synchronized (s) { ! super.printStackTrace(s); ! if (cause != null) { ! s.print("Caused by: "); ! cause.printStackTrace(s); ! } ! } ! } ! ! /** ! * Prints this <code>BEEPException</code> and its backtrace to the ! * specified print writer. ! */ ! public void printStackTrace(java.io.PrintWriter s) { ! synchronized (s) { ! super.printStackTrace(s); ! if (cause != null) { ! s.print("Caused by: "); ! cause.printStackTrace(s); ! } ! } ! } ! ! public String toString() { ! if (cause == null) { ! return super.toString(); ! } ! return super.toString() + cause.toString(); } } |
From: Huston F. <hu...@us...> - 2001-12-15 00:07:22
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core In directory usw-pr-cvs1:/tmp/cvs-serv1446/src/org/beepcore/beep/core Modified Files: Channel.java Log Message: more cleanup Index: Channel.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/Channel.java,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -r1.19 -r1.20 *** Channel.java 2001/11/12 16:12:41 1.19 --- Channel.java 2001/12/15 00:07:19 1.20 *************** *** 46,64 **** static final int STATE_CLOSED = 4; static final int STATE_ERROR = 5; - private static final String ERR_CHANNEL_MESSAGE_NUMBER_PREFIX = - "Incorrect message number: was "; - private static final String ERR_CHANNEL_MIDDLE = "; expecting "; - private static final String ERR_CHANNEL_SEQUENCE_NUMBER_PREFIX = - "Incorrect sequence number: was "; - private static final String ERR_CHANNEL_ERROR_STATE = - "Channel in currently experiencing technical difficulties."; - private static final String ERR_CHANNEL_UNINITIALISED_STATE = - "Channel is uninitialised."; - private static final String ERR_CHANNEL_UNKNOWN_STATE = - "Channel is in an unknown state."; - private static final String ERR_CHANNEL_INCONSISTENT_FRAME_TYPE_PREFIX = - "Incorrect message type: was "; - private static final String ERR_REPLY_RECEIVED_FOR_NO_MESSAGE = - "Reply received for a message never sent."; private static final BufferSegment zeroLengthSegment = new BufferSegment(new byte[0]); --- 46,49 ---- *************** *** 287,291 **** // in the buffer right now. if (size < recvWindowUsed) { ! throw new BEEPException("Size must be less than what is currently in use."); } --- 272,277 ---- // in the buffer right now. if (size < recvWindowUsed) { ! throw new BEEPException("Size must be less than what is " + ! "currently in use."); } *************** *** 364,372 **** switch (state) { case STATE_ERROR : ! throw new BEEPException(ERR_CHANNEL_ERROR_STATE); case STATE_UNINITIALISED : ! throw new BEEPException(ERR_CHANNEL_UNINITIALISED_STATE); default : ! throw new BEEPException(ERR_CHANNEL_UNKNOWN_STATE); } } --- 350,359 ---- switch (state) { case STATE_ERROR : ! throw new BEEPException("Channel in currently experiencing " + ! "technical difficulties."); case STATE_UNINITIALISED : ! throw new BEEPException("Channel is uninitialised."); default : ! throw new BEEPException("Channel is in an unknown state."); } } *************** *** 686,692 **** if (previousFrame != null) { if (frame.getMsgno() != previousFrame.getMsgno()) { ! throw new BEEPException(ERR_CHANNEL_MESSAGE_NUMBER_PREFIX + frame.getMsgno() ! + ERR_CHANNEL_MIDDLE + previousFrame.getMsgno()); } --- 673,679 ---- if (previousFrame != null) { if (frame.getMsgno() != previousFrame.getMsgno()) { ! throw new BEEPException("Incorrect message number: was " + frame.getMsgno() ! + "; expecting " + previousFrame.getMsgno()); } *************** *** 720,726 **** if (frame.getMsgno() != mstatus.getMsgno()) { ! throw new BEEPException(ERR_CHANNEL_MESSAGE_NUMBER_PREFIX + frame.getMsgno() ! + ERR_CHANNEL_MIDDLE + mstatus.getMsgno()); } --- 707,713 ---- if (frame.getMsgno() != mstatus.getMsgno()) { ! throw new BEEPException("Incorrect message number: was " + frame.getMsgno() ! + "; expecting " + mstatus.getMsgno()); } *************** *** 729,736 **** // is the sequence number correct? if (frame.getSeqno() != recvSequence) { ! throw new BEEPException(ERR_CHANNEL_SEQUENCE_NUMBER_PREFIX ! + frame.getSeqno() ! + ERR_CHANNEL_MIDDLE ! + recvSequence); } --- 716,722 ---- // is the sequence number correct? if (frame.getSeqno() != recvSequence) { ! throw new BEEPException("Incorrect sequence number: was " ! + frame.getSeqno() + "; expecting " ! + recvSequence); } *************** *** 739,746 **** && (previousFrame.getMessageType() != frame.getMessageType())) { ! throw new BEEPException(ERR_CHANNEL_INCONSISTENT_FRAME_TYPE_PREFIX ! + frame.getMessageTypeString() ! + ERR_CHANNEL_MIDDLE ! + previousFrame.getMessageTypeString()); } } --- 725,732 ---- && (previousFrame.getMessageType() != frame.getMessageType())) { ! throw new BEEPException("Incorrect message type: was " ! + frame.getMessageTypeString() ! + "; expecting " ! + previousFrame.getMessageTypeString()); } } *************** *** 797,805 **** switch (state) { case STATE_ERROR : ! throw new BEEPException(ERR_CHANNEL_ERROR_STATE); case STATE_UNINITIALISED : ! throw new BEEPException(ERR_CHANNEL_UNINITIALISED_STATE); default : ! throw new BEEPException(ERR_CHANNEL_UNKNOWN_STATE); } } --- 783,792 ---- switch (state) { case STATE_ERROR : ! throw new BEEPException("Channel in currently experiencing " + ! "technical difficulties."); case STATE_UNINITIALISED : ! throw new BEEPException("Channel is uninitialised."); default : ! throw new BEEPException("Channel is in an unknown state."); } } |
From: Huston F. <hu...@us...> - 2001-11-29 04:00:03
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/sasl/anonymous In directory usw-pr-cvs1:/tmp/cvs-serv29433/src/org/beepcore/beep/profile/sasl/anonymous Modified Files: SASLAnonymousProfile.java Log Message: First pass cleanup Index: SASLAnonymousProfile.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/sasl/anonymous/SASLAnonymousProfile.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -r1.5 -r1.6 *** SASLAnonymousProfile.java 2001/11/08 05:51:34 1.5 --- SASLAnonymousProfile.java 2001/11/29 04:00:00 1.6 *************** *** 215,219 **** if ((ch.getStartData() != null) ! && (ch.getStartData().indexOf(FRAGMENT_ERROR_PREFIX) != -1)) { throw new BEEPException(ch.getStartData()); } --- 215,219 ---- if ((ch.getStartData() != null) ! && (ch.getStartData().indexOf("<error ") != -1)) { throw new BEEPException(ch.getStartData()); } |
From: Huston F. <hu...@us...> - 2001-11-29 04:00:03
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/sasl In directory usw-pr-cvs1:/tmp/cvs-serv29433/src/org/beepcore/beep/profile/sasl Modified Files: Blob.java SASLProfile.java Log Message: First pass cleanup Index: Blob.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/sasl/Blob.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** Blob.java 2001/11/08 05:51:34 1.4 --- Blob.java 2001/11/29 04:00:00 1.5 *************** *** 61,83 **** public final static int DEFAULT_BLOB_SIZE = 1024; // Error Constants ! public final static String ERR_INVALID_STATUS_VALUE = "Invalid SASL Status for Blob"; ! public final static String ERR_MEANINGLESS_BLOB = "No valid data in blob"; ! public final static String ERR_BASE64 = "Base64 encode or decode failure"; ! public final static String ERR_XML_PARSE_FAILURE = "Failed to parse xml"; // XML Fragment Constants - public final static String FRAGMENT_ANGLE_SUFFIX = ">"; - public final static String FRAGMENT_BLOB_PREFIX = "<blob "; - public final static String FRAGMENT_BLOB_SUFFIX = "</blob>"; - public final static String FRAGMENT_CDATA_PREFIX = "<![CDATA["; - public final static String FRAGMENT_CDATA_SUFFIX = "]]>"; - public static final String FRAGMENT_ERROR_PREFIX = "<error "; - public static final String FRAGMENT_ERROR_SUFFIX = "</error>"; - public static final String FRAGMENT_QUOTE_SUFFIX = "'"; - public static final String FRAGMENT_QUOTE_ANGLE_SUFFIX = "'>"; - public static final String FRAGMENT_QUOTE_SLASH_ANGLE_SUFFIX = "'/>"; - public static final String FRAGMENT_SLASH_ANGLE_SUFFIX = "/>"; - public final static String FRAGMENT_STATUS_PREFIX = "status='"; - public static final String TAG_BLOB = "blob"; - public static final String TAG_STATUS = "status"; --- 61,68 ---- public final static int DEFAULT_BLOB_SIZE = 1024; // Error Constants ! private final static String ERR_INVALID_STATUS_VALUE = ! "Invalid SASL Status for Blob"; ! private final static String ERR_XML_PARSE_FAILURE = "Failed to parse xml"; // XML Fragment Constants *************** *** 120,137 **** StringBuffer buff = new StringBuffer(DEFAULT_BLOB_SIZE); ! buff.append(FRAGMENT_BLOB_PREFIX); if (status != STATUS_NONE) { ! buff.append(FRAGMENT_STATUS_PREFIX); buff.append(statusMappings[status]); ! buff.append(FRAGMENT_QUOTE_SUFFIX); } if (blobData == null) { ! buff.append(FRAGMENT_SLASH_ANGLE_SUFFIX); } else { ! buff.append(FRAGMENT_ANGLE_SUFFIX); buff.append(blobData); ! buff.append(FRAGMENT_BLOB_SUFFIX); } --- 105,122 ---- StringBuffer buff = new StringBuffer(DEFAULT_BLOB_SIZE); ! buff.append("<blob "); if (status != STATUS_NONE) { ! buff.append("status='"); buff.append(statusMappings[status]); ! buff.append('\''); } if (blobData == null) { ! buff.append("/>"); } else { ! buff.append(">"); buff.append(blobData); ! buff.append("</blob>"); } *************** *** 175,192 **** StringBuffer buff = new StringBuffer(DEFAULT_BLOB_SIZE); ! buff.append(FRAGMENT_BLOB_PREFIX); if (status != STATUS_NONE) { ! buff.append(FRAGMENT_STATUS_PREFIX); buff.append(statusMappings[status]); ! buff.append(FRAGMENT_QUOTE_SUFFIX); } if (blobData == null) { ! buff.append(FRAGMENT_SLASH_ANGLE_SUFFIX); } else { ! buff.append(FRAGMENT_ANGLE_SUFFIX); buff.append(blobData); ! buff.append(FRAGMENT_BLOB_SUFFIX); } --- 160,177 ---- StringBuffer buff = new StringBuffer(DEFAULT_BLOB_SIZE); ! buff.append("<blob "); if (status != STATUS_NONE) { ! buff.append("status='"); buff.append(statusMappings[status]); ! buff.append('\''); } if (blobData == null) { ! buff.append("/>"); } else { ! buff.append(">"); buff.append(blobData); ! buff.append("</blob>"); } *************** *** 223,240 **** StringBuffer buff = new StringBuffer(DEFAULT_BLOB_SIZE); ! buff.append(FRAGMENT_BLOB_PREFIX); if (status != STATUS_NONE) { ! buff.append(FRAGMENT_STATUS_PREFIX); buff.append(statusMappings[status]); ! buff.append(FRAGMENT_QUOTE_SUFFIX); } if (blobData == null) { ! buff.append(FRAGMENT_SLASH_ANGLE_SUFFIX); } else { ! buff.append(FRAGMENT_ANGLE_SUFFIX); buff.append(blobData); ! buff.append(FRAGMENT_BLOB_SUFFIX); } --- 208,225 ---- StringBuffer buff = new StringBuffer(DEFAULT_BLOB_SIZE); ! buff.append("<blob "); if (status != STATUS_NONE) { ! buff.append("status='"); buff.append(statusMappings[status]); ! buff.append('\''); } if (blobData == null) { ! buff.append("/>"); } else { ! buff.append(">"); buff.append(blobData); ! buff.append("</blob>"); } *************** *** 285,289 **** if (status == STATUS_NONE && blobData == null) { ! throw new SASLException(ERR_MEANINGLESS_BLOB); } --- 270,274 ---- if (status == STATUS_NONE && blobData == null) { ! throw new SASLException("No valid data in blob"); } *************** *** 422,426 **** throws SASLException { ! if ((blob == null) || (blob.indexOf(FRAGMENT_BLOB_PREFIX) == -1)) { return null; } --- 407,411 ---- throws SASLException { ! if ((blob == null) || (blob.indexOf("<blob ") == -1)) { return null; } *************** *** 428,436 **** Element top = processMessage(blob); ! if (!top.getTagName().equals(TAG_BLOB)) { throw new SASLException(ERR_XML_PARSE_FAILURE); } ! return top.getAttribute(TAG_STATUS); } --- 413,421 ---- Element top = processMessage(blob); ! if (!top.getTagName().equals("blob")) { throw new SASLException(ERR_XML_PARSE_FAILURE); } ! return top.getAttribute("status"); } *************** *** 454,458 **** Element top = processMessage(blob); ! if (!top.getTagName().equals(TAG_BLOB)) { throw new SASLException(ERR_XML_PARSE_FAILURE); } --- 439,443 ---- Element top = processMessage(blob); ! if (!top.getTagName().equals("blob")) { throw new SASLException(ERR_XML_PARSE_FAILURE); } *************** *** 484,488 **** return new String(encoder.encodeBuffer(data.getBytes())); } catch (Exception x) { ! throw new SASLException(ERR_BASE64); } } --- 469,473 ---- return new String(encoder.encodeBuffer(data.getBytes())); } catch (Exception x) { ! throw new SASLException("Base64 encode or decode failure"); } } Index: SASLProfile.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/sasl/SASLProfile.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -r1.6 -r1.7 *** SASLProfile.java 2001/11/08 05:51:34 1.6 --- SASLProfile.java 2001/11/29 04:00:00 1.7 *************** *** 50,59 **** // Constants public static final String COMPLETE = "<blob status='complete'>"; - public final static String ERR_INVALID_SASL_STATUS = - "Invalid SASL Status attribute value employed"; public static final String ENCODING_NONE = "none"; public static final String ENCODING_BASE64 = "base64"; public static final String ENCODING_DEFAULT = ENCODING_NONE; - public static final String FRAGMENT_ERROR_PREFIX = "<error "; public static final String LOCALIZE_DEFAULT = "i-default"; public final static String SASL = "sasl"; --- 50,56 ---- |
From: Huston F. <hu...@us...> - 2001-11-29 04:00:03
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core In directory usw-pr-cvs1:/tmp/cvs-serv29433/src/org/beepcore/beep/core Modified Files: BEEPError.java ProfileRegistry.java Session.java Log Message: First pass cleanup Index: BEEPError.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/BEEPError.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -r1.5 -r1.6 *** BEEPError.java 2001/11/08 05:51:34 1.5 --- BEEPError.java 2001/11/29 04:00:00 1.6 *************** *** 42,61 **** private static final String ERR_MALFORMED_XML_MSG = "Malformed XML"; - private static final String ERR_UNKNOWN_OPERATION_ELEMENT_MSG = - "Unknown operation element"; - private static final String ERR_PCDATA_TOO_BIG_MSG = - "Element's PCDATA exceeds the maximum size"; - - private static final String FRAGMENT_ANGLE_SUFFIX = ">"; - private static final String FRAGMENT_CODE_PREFIX = "code='"; - private static final String FRAGMENT_ERROR_PREFIX = "<error "; - private static final String FRAGMENT_ERROR_SUFFIX = "</error>"; - private static final String FRAGMENT_QUOTE_SLASH_ANGLE_SUFFIX = "' />"; - private static final String FRAGMENT_QUOTE_SUFFIX = "' "; - private static final String FRAGMENT_XML_LANG_PREFIX = "xml:lang='"; - - private static final String TAG_CODE = "code"; - private static final String TAG_ERROR = "error"; - private static final String TAG_XML_LANG = "xml:lang"; private int code; --- 42,45 ---- *************** *** 187,207 **** StringBuffer sb = new StringBuffer(128); ! sb.append(FRAGMENT_ERROR_PREFIX); ! sb.append(FRAGMENT_CODE_PREFIX); sb.append(code); if (xmlLang != null) { ! sb.append(FRAGMENT_QUOTE_SUFFIX); ! sb.append(FRAGMENT_XML_LANG_PREFIX); sb.append(xmlLang); } if (diagnostic != null) { ! sb.append(FRAGMENT_QUOTE_SUFFIX); ! sb.append(FRAGMENT_ANGLE_SUFFIX); sb.append(diagnostic); ! sb.append(FRAGMENT_ERROR_SUFFIX); } else { ! sb.append(FRAGMENT_QUOTE_SLASH_ANGLE_SUFFIX); } --- 171,188 ---- StringBuffer sb = new StringBuffer(128); ! sb.append("<error code='"); sb.append(code); if (xmlLang != null) { ! sb.append("' xml:lang='"); sb.append(xmlLang); } if (diagnostic != null) { ! sb.append("' >"); sb.append(diagnostic); ! sb.append("</error>"); } else { ! sb.append("' />"); } *************** *** 258,266 **** if (elementName == null) { throw new BEEPException(ERR_MALFORMED_XML_MSG); ! } else if (!elementName.equals(TAG_ERROR)) { ! throw new BEEPException(ERR_UNKNOWN_OPERATION_ELEMENT_MSG); } ! String code = topElement.getAttribute(TAG_CODE); if (code == null) { --- 239,247 ---- if (elementName == null) { throw new BEEPException(ERR_MALFORMED_XML_MSG); ! } else if (!elementName.equals("error")) { ! throw new BEEPException("Unknown operation element"); } ! String code = topElement.getAttribute("code"); if (code == null) { *************** *** 269,273 **** // this attribute is implied ! String xmlLang = topElement.getAttribute(TAG_XML_LANG); Node dataNode = topElement.getFirstChild(); String data = null; --- 250,254 ---- // this attribute is implied ! String xmlLang = topElement.getAttribute("xml:lang"); Node dataNode = topElement.getFirstChild(); String data = null; Index: ProfileRegistry.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/ProfileRegistry.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -r1.10 -r1.11 *** ProfileRegistry.java 2001/11/27 17:37:22 1.10 --- ProfileRegistry.java 2001/11/29 04:00:00 1.11 *************** *** 39,61 **** public class ProfileRegistry implements Cloneable { - private static final String SPACE = " "; - private static final String FRAGMENT_ANGLE_SUFFIX = ">"; - private static final String FRAGMENT_FEATURES_PREFIX = "features='"; - private static final String FRAGMENT_GREETING_PREFIX = "<greeting"; - private static final String FRAGMENT_GREETING_SUFFIX = "</greeting>"; - private static final String FRAGMENT_LOCALIZE_PREFIX = "localize='"; - private static final String FRAGMENT_PROFILE_PREFIX = "<profile "; - private static final String FRAGMENT_QUOTE_ANGLE_SUFFIX = "'>"; - private static final String FRAGMENT_QUOTE_SLASH_ANGLE_SUFFIX = "' />"; - private static final String FRAGMENT_QUOTE_SUFFIX = "' "; - private static final String FRAGMENT_URI_PREFIX = "uri='"; - private static final int FRAGMENT_GREETING_LENGTH = - FRAGMENT_GREETING_PREFIX.length() - + FRAGMENT_QUOTE_ANGLE_SUFFIX.length() - + FRAGMENT_GREETING_SUFFIX.length(); - private static final int FRAGMENT_PROFILE_LENGTH = - FRAGMENT_PROFILE_PREFIX.length() - + FRAGMENT_QUOTE_ANGLE_SUFFIX.length(); - // Instance Data private class InternalProfile { --- 39,42 ---- *************** *** 65,71 **** private Hashtable profileListeners; - String greeting; String localize; - String features; // Constructors --- 46,50 ---- *************** *** 78,92 **** public ProfileRegistry() { - this.greeting = null; - this.features = null; this.localize = Constants.LOCALIZE_DEFAULT; this.profileListeners = new Hashtable(); } ! private ProfileRegistry(String greeting, String localize, ! String features, Hashtable profiles) { - this.greeting = greeting; - this.features = features; this.localize = localize; this.profileListeners = profiles; --- 57,66 ---- public ProfileRegistry() { this.localize = Constants.LOCALIZE_DEFAULT; this.profileListeners = new Hashtable(); } ! private ProfileRegistry(String localize, Hashtable profiles) { this.localize = localize; this.profileListeners = profiles; *************** *** 95,100 **** public Object clone() { ! return new ProfileRegistry(this.greeting, this.localize, ! this.features, (Hashtable) this.profileListeners.clone()); } --- 69,73 ---- public Object clone() { ! return new ProfileRegistry(this.localize, (Hashtable) this.profileListeners.clone()); } *************** *** 240,247 **** return this.localize; } ! byte[] getGreeting(Session session) { ! int bufferSize = FRAGMENT_GREETING_LENGTH; int profileCount = 0; --- 213,224 ---- return this.localize; } + + byte[] getGreeting(Session session) { + return getGreeting(session, null); + } ! byte[] getGreeting(Session session, String features) { ! int bufferSize = "<greeting></greeting>".length(); int profileCount = 0; *************** *** 252,256 **** while (e.hasMoreElements()) { bufferSize += ((String) e.nextElement()).length() ! + FRAGMENT_PROFILE_LENGTH; } --- 229,233 ---- while (e.hasMoreElements()) { bufferSize += ((String) e.nextElement()).length() ! + "<profile>".length(); } *************** *** 263,283 **** Enumeration f = profileListeners.keys(); ! sb.append(FRAGMENT_GREETING_PREFIX); if ((localize != null) &&!localize.equals(Constants.LOCALIZE_DEFAULT)) { ! sb.append(this.SPACE); ! sb.append(FRAGMENT_LOCALIZE_PREFIX); sb.append(localize); ! sb.append(FRAGMENT_QUOTE_SUFFIX); } if (features != null) { ! sb.append(FRAGMENT_FEATURES_PREFIX); sb.append(features); ! sb.append(FRAGMENT_QUOTE_SUFFIX); } ! sb.append(FRAGMENT_ANGLE_SUFFIX); while (f.hasMoreElements()) { --- 240,259 ---- Enumeration f = profileListeners.keys(); ! sb.append("<greeting"); if ((localize != null) &&!localize.equals(Constants.LOCALIZE_DEFAULT)) { ! sb.append(" localize='"); sb.append(localize); ! sb.append("' "); } if (features != null) { ! sb.append("features='"); sb.append(features); ! sb.append("' "); } ! sb.append('>'); while (f.hasMoreElements()) { *************** *** 309,316 **** profile.listener.advertiseProfile(session))) { ! sb.append(FRAGMENT_PROFILE_PREFIX); ! sb.append(FRAGMENT_URI_PREFIX); ! sb.append((String) profileName); ! sb.append(FRAGMENT_QUOTE_SLASH_ANGLE_SUFFIX); } } catch (BEEPException x) { --- 285,291 ---- profile.listener.advertiseProfile(session))) { ! sb.append("<profile uri='"); ! sb.append(profileName); ! sb.append("' />"); } } catch (BEEPException x) { *************** *** 321,325 **** } ! sb.append(FRAGMENT_GREETING_SUFFIX); return StringUtil.stringBufferToAscii(sb); --- 296,300 ---- } ! sb.append("</greeting>"); return StringUtil.stringBufferToAscii(sb); Index: Session.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/Session.java,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -r1.21 -r1.22 *** Session.java 2001/11/27 17:37:22 1.21 --- Session.java 2001/11/29 04:00:00 1.22 *************** *** 83,87 **** /** @todo check this */ - private static final int MAX_PAYLOAD_SIZE = 4096; private static final int MAX_PCDATA_SIZE = 4096; private static final int MAX_START_CHANNEL_WAIT = 60000; --- 83,86 ---- *************** *** 90,148 **** private static final String CHANNEL_ZERO = "0"; - private static final String ERR_GREETING_FAILED = - "Greeting exchange failed"; - private static final String ERR_ILLEGAL_SHUTDOWN = - "Illegal state for shutdown"; - private static final String ERR_PROFILES_UNAVAILABLE = - "all requested profiles are unsupported"; - private static final String ERR_NONEXISTENT_CHANNEL = - "Session call on nonexistent channel."; - private static final String ERR_STATE_CHANGE = - "Illegal session state transition"; private static final String ERR_MALFORMED_XML_MSG = "Malformed XML"; - private static final String ERR_PCDATA_TOO_BIG_MSG = - "Element's PCDATA exceeds the maximum size"; private static final String ERR_UNKNOWN_OPERATION_ELEMENT_MSG = "Unknown operation element"; - private static final String ERR_MALFORMED_PROFILE_MSG = - "Malformed profile"; ! private static final String FRAGMENT_ANGLE_SUFFIX = ">"; ! private static final String FRAGMENT_CDATA_PREFIX = "<![CDATA["; ! private static final String FRAGMENT_CDATA_SUFFIX = "]]>"; ! private static final String FRAGMENT_CLOSE_PREFIX = "<close "; ! private static final String FRAGMENT_CODE_PREFIX = "code='"; ! private static final String FRAGMENT_ENCODING_PREFIX = "encoding='"; ! private static final String FRAGMENT_NUMBER_PREFIX = "number='"; ! private static final String FRAGMENT_OK = "<ok />"; ! private static final String FRAGMENT_PROFILE_PREFIX = "<profile "; ! private static final String FRAGMENT_PROFILE_SUFFIX = "</profile>"; ! private static final String FRAGMENT_QUOTE_ANGLE_SUFFIX = "'>"; ! private static final String FRAGMENT_QUOTE_SLASH_ANGLE_SUFFIX = "' />"; ! private static final String FRAGMENT_QUOTE_SUFFIX = "' "; ! private static final String FRAGMENT_SERVERNAME_PREFIX = "serverName='"; ! private static final String FRAGMENT_SLASH_ANGLE_SUFFIX = " />"; ! private static final String FRAGMENT_START_PREFIX = "<start "; ! private static final String FRAGMENT_START_SUFFIX = "</start>"; ! private static final String FRAGMENT_URI_PREFIX = "uri='"; ! private static final String FRAGMENT_XML_LANG_PREFIX = "xml:lang='"; ! ! private static final String TAG_CLOSE = "close"; ! private static final String TAG_CODE = "code"; ! private static final String TAG_ENCODING = "encoding"; ! private static final String TAG_FEATURES = "features"; ! private static final String TAG_GREETING = "greeting"; ! private static final String TAG_LOCALIZE = "localize"; ! private static final String TAG_NUMBER = "number"; ! private static final String TAG_OK = "ok"; ! private static final String TAG_PROFILE = "profile"; ! private static final String TAG_START = "start"; ! private static final String TAG_SERVER_NAME = "serverName"; ! private static final String TAG_URI = "uri"; ! private static final String TAG_XML_LANG = "xml:lang"; // Instance Data private int state; - private long messageNumber; private long nextChannelNumber = 0; private Channel zero; --- 89,101 ---- private static final String CHANNEL_ZERO = "0"; private static final String ERR_MALFORMED_XML_MSG = "Malformed XML"; private static final String ERR_UNKNOWN_OPERATION_ELEMENT_MSG = "Unknown operation element"; ! private static final byte[] OK_ELEMENT = ! StringUtil.stringToAscii("<ok />"); // Instance Data private int state; private long nextChannelNumber = 0; private Channel zero; *************** *** 248,252 **** // check the channel state and return the appropriate exception if (zero.getState() == Channel.STATE_ERROR) { ! throw new BEEPException(ERR_GREETING_FAILED); } } --- 201,205 ---- // check the channel state and return the appropriate exception if (zero.getState() == Channel.STATE_ERROR) { ! throw new BEEPException("Greeting exchange failed"); } } *************** *** 557,564 **** StringBuffer startBuffer = new StringBuffer(); ! startBuffer.append(FRAGMENT_START_PREFIX); ! startBuffer.append(FRAGMENT_NUMBER_PREFIX); startBuffer.append(channelNumber); ! startBuffer.append(FRAGMENT_QUOTE_ANGLE_SUFFIX); Iterator i = profiles.iterator(); --- 510,516 ---- StringBuffer startBuffer = new StringBuffer(); ! startBuffer.append("<start number='"); startBuffer.append(channelNumber); ! startBuffer.append("'>"); Iterator i = profiles.iterator(); *************** *** 568,578 **** // @todo maybe we should check these against peerSupportedProfiles ! startBuffer.append(FRAGMENT_PROFILE_PREFIX); ! startBuffer.append(FRAGMENT_URI_PREFIX); startBuffer.append(p.uri); ! startBuffer.append(FRAGMENT_QUOTE_SUFFIX); if (p.data == null) { ! startBuffer.append(FRAGMENT_SLASH_ANGLE_SUFFIX); } else { if (p.base64Encoding) { --- 520,529 ---- // @todo maybe we should check these against peerSupportedProfiles ! startBuffer.append("<profile uri='"); startBuffer.append(p.uri); ! startBuffer.append("' "); if (p.data == null) { ! startBuffer.append(" />"); } else { if (p.base64Encoding) { *************** *** 580,592 **** } ! startBuffer.append(FRAGMENT_ANGLE_SUFFIX); ! startBuffer.append(FRAGMENT_CDATA_PREFIX); startBuffer.append(p.data); ! startBuffer.append(FRAGMENT_CDATA_SUFFIX); ! startBuffer.append(FRAGMENT_PROFILE_SUFFIX); } } ! startBuffer.append(FRAGMENT_START_SUFFIX); // @todo handle the data element --- 531,541 ---- } ! startBuffer.append("><![CDATA["); startBuffer.append(p.data); ! startBuffer.append("]]></profile>"); } } ! startBuffer.append("</start>"); // @todo handle the data element *************** *** 666,670 **** &&!((newState == SESSION_STATE_INITIALIZED) || (newState == SESSION_STATE_CLOSED))) { ! throw new BEEPException(ERR_STATE_CHANGE); } --- 615,619 ---- &&!((newState == SESSION_STATE_INITIALIZED) || (newState == SESSION_STATE_CLOSED))) { ! throw new BEEPException("Illegal session state transition"); } *************** *** 673,677 **** || (newState == SESSION_STATE_GREETING_RECEIVED) || (newState == SESSION_STATE_CLOSED))) { ! throw new BEEPException(ERR_STATE_CHANGE); } --- 622,626 ---- || (newState == SESSION_STATE_GREETING_RECEIVED) || (newState == SESSION_STATE_CLOSED))) { ! throw new BEEPException("Illegal session state transition"); } *************** *** 680,684 **** && (newState != SESSION_STATE_TERMINATING) && (newState != SESSION_STATE_CLOSING)) { ! throw new BEEPException(ERR_STATE_CHANGE); } --- 629,633 ---- && (newState != SESSION_STATE_TERMINATING) && (newState != SESSION_STATE_CLOSING)) { ! throw new BEEPException("Illegal session state transition"); } *************** *** 745,749 **** if (ch == null) { ! throw new BEEPException(ERR_NONEXISTENT_CHANNEL); } --- 694,698 ---- if (ch == null) { ! throw new BEEPException("Session call on nonexistent channel."); } *************** *** 967,984 **** StringBuffer closeBuffer = new StringBuffer(); ! closeBuffer.append(FRAGMENT_CLOSE_PREFIX); ! closeBuffer.append(FRAGMENT_NUMBER_PREFIX); closeBuffer.append(channel.getNumberAsString()); ! closeBuffer.append(FRAGMENT_QUOTE_SUFFIX); ! closeBuffer.append(FRAGMENT_CODE_PREFIX); closeBuffer.append(code); if (xmlLang != null) { ! closeBuffer.append(FRAGMENT_QUOTE_SUFFIX); ! closeBuffer.append(FRAGMENT_XML_LANG_PREFIX); closeBuffer.append(xmlLang); } ! closeBuffer.append(FRAGMENT_QUOTE_SLASH_ANGLE_SUFFIX); // Lock necessary because we have to know the msgNo --- 916,930 ---- StringBuffer closeBuffer = new StringBuffer(); ! closeBuffer.append("<close number='"); closeBuffer.append(channel.getNumberAsString()); ! closeBuffer.append("' code='"); closeBuffer.append(code); if (xmlLang != null) { ! closeBuffer.append("' xml:lang='"); closeBuffer.append(xmlLang); } ! closeBuffer.append("' />"); // Lock necessary because we have to know the msgNo *************** *** 1023,1027 **** if (ch == null) { ! throw new BEEPException(ERR_NONEXISTENT_CHANNEL); } --- 969,973 ---- if (ch == null) { ! throw new BEEPException("Session call on nonexistent channel."); } *************** *** 1036,1051 **** StringBuffer sb = new StringBuffer(); ! sb.append(FRAGMENT_PROFILE_PREFIX); ! sb.append(FRAGMENT_URI_PREFIX); sb.append(uri); if (datum != null) { ! sb.append(FRAGMENT_QUOTE_ANGLE_SUFFIX); ! sb.append(FRAGMENT_CDATA_PREFIX); sb.append(datum); ! sb.append(FRAGMENT_CDATA_SUFFIX); ! sb.append(FRAGMENT_PROFILE_SUFFIX); } else { ! sb.append(FRAGMENT_QUOTE_SLASH_ANGLE_SUFFIX); } --- 982,994 ---- StringBuffer sb = new StringBuffer(); ! sb.append("<profile uri='"); sb.append(uri); if (datum != null) { ! sb.append("'><![CDATA["); sb.append(datum); ! sb.append("]]></profile>"); } else { ! sb.append("' />"); } *************** *** 1166,1170 **** OutputDataStream sds = new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! StringUtil.stringToAscii(FRAGMENT_OK)); try { --- 1109,1113 ---- OutputDataStream sds = new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! OK_ELEMENT); try { *************** *** 1192,1196 **** // @todo got consecutive shutdowns... now what... log it? ! // Utility.assert(ERR_ILLEGAL_SHUTDOWN, -1); } } catch (BEEPException e) { --- 1135,1139 ---- // @todo got consecutive shutdowns... now what... log it? ! // Utility.assert("Illegal state for shutdown", -1); } } catch (BEEPException e) { *************** *** 1244,1248 **** OutputDataStream sds = new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! StringUtil.stringToAscii(FRAGMENT_OK)); try { --- 1187,1191 ---- OutputDataStream sds = new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! OK_ELEMENT); try { *************** *** 1357,1361 **** try { ! ((Message)zero.getAppData()).sendERR(BEEPError.CODE_REQUESTED_ACTION_NOT_TAKEN2, ERR_PROFILES_UNAVAILABLE); } catch (Exception x) { terminate("Error sending error. " + x.getMessage()); --- 1300,1304 ---- try { ! ((Message)zero.getAppData()).sendERR(BEEPError.CODE_REQUESTED_ACTION_NOT_TAKEN2, "all requested profiles are unsupported"); } catch (Exception x) { terminate("Error sending error. " + x.getMessage()); *************** *** 1446,1454 **** // is this MSG a <start> ! if (elementName.equals(TAG_START)) { Log.logEntry(Log.SEV_DEBUG, CORE, "Received a start channel request"); ! String channelNumber = topElement.getAttribute(TAG_NUMBER); if (channelNumber == null) { --- 1389,1397 ---- // is this MSG a <start> ! if (elementName.equals("start")) { Log.logEntry(Log.SEV_DEBUG, CORE, "Received a start channel request"); ! String channelNumber = topElement.getAttribute("number"); if (channelNumber == null) { *************** *** 1458,1464 **** // this attribute is implied ! String serverName = topElement.getAttribute(TAG_SERVER_NAME); NodeList profiles = ! topElement.getElementsByTagName(TAG_PROFILE); if (profiles == null) { --- 1401,1407 ---- // this attribute is implied ! String serverName = topElement.getAttribute("serverName"); NodeList profiles = ! topElement.getElementsByTagName("profile"); if (profiles == null) { *************** *** 1471,1475 **** for (int i = 0; i < profiles.getLength(); i++) { Element profile = (Element) profiles.item(i); ! String uri = profile.getAttribute(TAG_URI); if (uri == null) { --- 1414,1418 ---- for (int i = 0; i < profiles.getLength(); i++) { Element profile = (Element) profiles.item(i); ! String uri = profile.getAttribute("uri"); if (uri == null) { *************** *** 1478,1482 **** } ! String encoding = profile.getAttribute(TAG_ENCODING); boolean b64; --- 1421,1425 ---- } ! String encoding = profile.getAttribute("encoding"); boolean b64; *************** *** 1500,1504 **** if (data.length() > MAX_PCDATA_SIZE) { throw new BEEPError(BEEPError.CODE_PARAMETER_ERROR, ! ERR_PCDATA_TOO_BIG_MSG); } } --- 1443,1448 ---- if (data.length() > MAX_PCDATA_SIZE) { throw new BEEPError(BEEPError.CODE_PARAMETER_ERROR, ! "Element's PCDATA exceeds " + ! "the maximum size"); } } *************** *** 1512,1520 **** // is this MSG a <close> ! else if (elementName.equals(TAG_CLOSE)) { Log.logEntry(Log.SEV_DEBUG, CORE, "Received a channel close request"); ! String channelNumber = topElement.getAttribute(TAG_NUMBER); if (channelNumber == null) { --- 1456,1464 ---- // is this MSG a <close> ! else if (elementName.equals("close")) { Log.logEntry(Log.SEV_DEBUG, CORE, "Received a channel close request"); ! String channelNumber = topElement.getAttribute("number"); if (channelNumber == null) { *************** *** 1523,1527 **** } ! String code = topElement.getAttribute(TAG_CODE); if (code == null) { --- 1467,1471 ---- } ! String code = topElement.getAttribute("code"); if (code == null) { *************** *** 1531,1535 **** // this attribute is implied ! String xmlLang = topElement.getAttribute(TAG_XML_LANG); String data = null; Node dataNode = topElement.getFirstChild(); --- 1475,1479 ---- // this attribute is implied ! String xmlLang = topElement.getAttribute("xml:lang"); String data = null; Node dataNode = topElement.getFirstChild(); *************** *** 1540,1544 **** if (data.length() > MAX_PCDATA_SIZE) { throw new BEEPError(BEEPError.CODE_PARAMETER_ERROR, ! ERR_PCDATA_TOO_BIG_MSG); } } --- 1484,1489 ---- if (data.length() > MAX_PCDATA_SIZE) { throw new BEEPError(BEEPError.CODE_PARAMETER_ERROR, ! "Element's PCDATA exceeds " + ! "the maximum size"); } } *************** *** 1566,1570 **** if (elementName == null) { throw new BEEPException(ERR_MALFORMED_XML_MSG); ! } else if (!elementName.equals(TAG_GREETING)) { throw new BEEPException(ERR_UNKNOWN_OPERATION_ELEMENT_MSG); } --- 1511,1515 ---- if (elementName == null) { throw new BEEPException(ERR_MALFORMED_XML_MSG); ! } else if (!elementName.equals("greeting")) { throw new BEEPException(ERR_UNKNOWN_OPERATION_ELEMENT_MSG); } *************** *** 1573,1580 **** // this attribute is implied ! String features = topElement.getAttribute(TAG_FEATURES); // This attribute has a default value ! String localize = topElement.getAttribute(TAG_LOCALIZE); if (localize == null) { --- 1518,1525 ---- // this attribute is implied ! String features = topElement.getAttribute("features"); // This attribute has a default value ! String localize = topElement.getAttribute("localize"); if (localize == null) { *************** *** 1585,1589 **** // with 0 profiles NodeList profiles = ! topElement.getElementsByTagName(TAG_PROFILE); if (profiles.getLength() > 0) { --- 1530,1534 ---- // with 0 profiles NodeList profiles = ! topElement.getElementsByTagName("profile"); if (profiles.getLength() > 0) { *************** *** 1592,1602 **** for (int i = 0; i < profiles.getLength(); i++) { Element profile = (Element) profiles.item(i); ! String uri = profile.getAttribute(TAG_URI); if (uri == null) { ! throw new BEEPException(ERR_MALFORMED_PROFILE_MSG); } ! String encoding = profile.getAttribute(TAG_ENCODING); // encoding is not allowed in greetings --- 1537,1547 ---- for (int i = 0; i < profiles.getLength(); i++) { Element profile = (Element) profiles.item(i); ! String uri = profile.getAttribute("uri"); if (uri == null) { ! throw new BEEPException("Malformed profile"); } ! String encoding = profile.getAttribute("encoding"); // encoding is not allowed in greetings *************** *** 1668,1681 **** // is this RPY a <profile> ! } else if (elementName.equals(TAG_PROFILE)) { try { ! String uri = topElement.getAttribute(TAG_URI); if (uri == null) { ! throw new BEEPException(ERR_MALFORMED_PROFILE_MSG); } String encoding = ! topElement.getAttribute(TAG_ENCODING); if (encoding == null) { --- 1613,1626 ---- // is this RPY a <profile> ! } else if (elementName.equals("profile")) { try { ! String uri = topElement.getAttribute("uri"); if (uri == null) { ! throw new BEEPException("Malformed profile"); } String encoding = ! topElement.getAttribute("encoding"); if (encoding == null) { *************** *** 1691,1695 **** if (data.length() > MAX_PCDATA_SIZE) { ! throw new BEEPException(ERR_PCDATA_TOO_BIG_MSG); } } --- 1636,1642 ---- if (data.length() > MAX_PCDATA_SIZE) { ! throw new BEEPException("Element's PCDATA " + ! "exceeds the " + ! "maximum size"); } } *************** *** 1792,1796 **** // is this RPY an <ok> (the positive response to a // channel close) ! } else if (elementName.equals(TAG_OK)) { Log.logEntry(Log.SEV_DEBUG, CORE, "Received an OK for channel close"); --- 1739,1743 ---- // is this RPY an <ok> (the positive response to a // channel close) ! } else if (elementName.equals("ok")) { Log.logEntry(Log.SEV_DEBUG, CORE, "Received an OK for channel close"); |
From: Huston F. <hu...@us...> - 2001-11-27 17:37:25
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/util In directory usw-pr-cvs1:/tmp/cvs-serv6472/src/org/beepcore/beep/util Added Files: StringUtil.java Log Message: Added utility methods for String to ASCII --- NEW FILE: StringUtil.java --- /* * StringUtil.java $Revision: 1.1 $ $Date: 2001/11/27 17:37:22 $ * * Copyright (c) 2001 Huston Franklin. All rights reserved. * * The contents of this file are subject to the Blocks Public License (the * "License"); You may not use this file except in compliance with the License. * * You may obtain a copy of the License at http://www.beepcore.org/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * */ package org.beepcore.beep.util; /** * * @author Huston Franklin * @version $Revision: 1.1 $, $Date: 2001/11/27 17:37:22 $ */ public class StringUtil { private StringUtil() {} public static String asciiToString(byte[] b, int off, int len) { char[] c = new char[len]; for (int i=0; i<len; ++i) { c[i] = (char)(b[off + i] & 0xff); } return new String(c); } public static byte[] stringToAscii(String s) { byte[] b = new byte[s.length()]; for (int i=0; i<b.length; ++i) { b[i] = (byte)s.charAt(i); } return b; } public static byte[] stringBufferToAscii(StringBuffer s) { byte[] b = new byte[s.length()]; for (int i=0; i<b.length; ++i) { b[i] = (byte)s.charAt(i); } return b; } } |
From: Huston F. <hu...@us...> - 2001-11-27 17:37:25
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core In directory usw-pr-cvs1:/tmp/cvs-serv6472/src/org/beepcore/beep/core Modified Files: Frame.java ProfileRegistry.java Session.java Log Message: Added utility methods for String to ASCII Index: Frame.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/Frame.java,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -r1.15 -r1.16 *** Frame.java 2001/11/27 16:04:58 1.15 --- Frame.java 2001/11/27 17:37:22 1.16 *************** *** 19,24 **** - import java.io.UnsupportedEncodingException; - import java.util.Iterator; import java.util.LinkedList; --- 19,22 ---- *************** *** 28,31 **** --- 26,30 ---- import org.beepcore.beep.util.HeaderParser; import org.beepcore.beep.util.Log; + import org.beepcore.beep.util.StringUtil; /** *************** *** 281,291 **** header.append(this.CRLF); ! Log.logEntry(Log.SEV_DEBUG, header.toString()); ! try { ! return header.toString().getBytes("UTF-8"); ! } catch (UnsupportedEncodingException e) { ! throw new RuntimeException("UnsupportedEncodingException" + ! e.getMessage()); } } --- 280,287 ---- header.append(this.CRLF); ! if (Log.isLogged(Log.SEV_DEBUG)) { ! Log.logEntry(Log.SEV_DEBUG, header.toString()); } + return StringUtil.stringBufferToAscii(header); } *************** *** 360,365 **** } ! Log.logEntry(Log.SEV_DEBUG_VERBOSE, ! "getMessageType=" + types[ret] + " (" + ret + ")"); return ret; --- 356,363 ---- } ! if (Log.isLogged(Log.SEV_DEBUG_VERBOSE)) { ! Log.logEntry(Log.SEV_DEBUG_VERBOSE, "getMessageType=" + ! types[ret] + " (" + ret + ")"); ! } return ret; Index: ProfileRegistry.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/ProfileRegistry.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -r1.9 -r1.10 *** ProfileRegistry.java 2001/11/09 19:12:25 1.9 --- ProfileRegistry.java 2001/11/27 17:37:22 1.10 *************** *** 3,6 **** --- 3,7 ---- * * Copyright (c) 2001 Invisible Worlds, Inc. All rights reserved. + * Copyright (c) 2001 Huston Franklin. All rights reserved. * * The contents of this file are subject to the Blocks Public License (the *************** *** 20,31 **** import java.util.Enumeration; import java.util.Hashtable; import org.beepcore.beep.util.Log; /** ! * This class is used to save pointers in Sessions - if the peer is using ! * the same set of profile and associated StartChannelListener for all ! * sessions then they should create one of these helpers and use them in ! * the corresponding factory methods. * * @author Eric Dixon --- 21,33 ---- import java.util.Enumeration; import java.util.Hashtable; + import org.beepcore.beep.util.Log; + import org.beepcore.beep.util.StringUtil; /** ! * Maintains a set of associations between URIs and ! * <code>StartChannelListener</code>s. This set is used to generate ! * the <code>greeting</code> and to demux <code>start</code> requests. * * @author Eric Dixon *************** *** 33,37 **** * @author Jay Kint * @author Scott Pead ! * @version $Revision, $Date$ */ public class ProfileRegistry implements Cloneable { --- 35,39 ---- * @author Jay Kint * @author Scott Pead ! * @version $Revision$, $Date$ */ public class ProfileRegistry implements Cloneable { *************** *** 117,122 **** * */ ! public StartChannelListener getStartChannelListener(SessionTuningProperties tuning, ! String uri) { --- 119,125 ---- * */ ! public StartChannelListener ! getStartChannelListener(SessionTuningProperties tuning, ! String uri) { *************** *** 173,178 **** * */ ! public synchronized StartChannelListener addStartChannelListener(String profile, ! StartChannelListener listener, SessionTuningProperties tuning) { --- 176,183 ---- * */ ! public synchronized StartChannelListener ! addStartChannelListener(String profile, ! StartChannelListener listener, ! SessionTuningProperties tuning) { *************** *** 205,209 **** * */ ! public synchronized StartChannelListener removeStartChannelListener(String profile) { InternalProfile temp = --- 210,215 ---- * */ ! public synchronized StartChannelListener ! removeStartChannelListener(String profile) { InternalProfile temp = *************** *** 316,323 **** sb.append(FRAGMENT_GREETING_SUFFIX); - - greeting = sb.toString(); ! return greeting.getBytes(); } } --- 322,327 ---- sb.append(FRAGMENT_GREETING_SUFFIX); ! return StringUtil.stringBufferToAscii(sb); } } Index: Session.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/Session.java,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -r1.20 -r1.21 *** Session.java 2001/11/22 15:25:29 1.20 --- Session.java 2001/11/27 17:37:22 1.21 *************** *** 40,43 **** --- 40,44 ---- import org.beepcore.beep.core.event.SessionListener; import org.beepcore.beep.util.Log; + import org.beepcore.beep.util.StringUtil; *************** *** 141,146 **** private static final String TAG_XML_LANG = "xml:lang"; - private static final String DEFAULT_STRING_ENCODING = "UTF-8"; - // Instance Data private int state; --- 142,145 ---- *************** *** 597,602 **** // Make a message OutputDataStream ds = ! new StringOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! startBuffer.toString()); // Tell Channel Zero to start us up --- 596,601 ---- // Make a message OutputDataStream ds = ! new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! StringUtil.stringBufferToAscii(startBuffer)); // Tell Channel Zero to start us up *************** *** 989,994 **** synchronized (reply) { OutputDataStream ds = ! new StringOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! closeBuffer.toString()); this.zero.sendMSG(ds, --- 988,993 ---- synchronized (reply) { OutputDataStream ds = ! new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! StringUtil.stringBufferToAscii(closeBuffer)); this.zero.sendMSG(ds, *************** *** 1051,1062 **** } ! StringOutputDataStream sds = ! new StringOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! sb.toString()); // Store the Channel ch.setState(Channel.STATE_OK); channels.put(ch.getNumberAsString(), ch); ! ((Message)zero.getAppData()).sendRPY(sds); } --- 1050,1061 ---- } ! OutputDataStream ds = ! new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! StringUtil.stringBufferToAscii(sb)); // Store the Channel ch.setState(Channel.STATE_OK); channels.put(ch.getNumberAsString(), ch); ! ((Message)zero.getAppData()).sendRPY(ds); } *************** *** 1165,1171 **** // Send an ok ! StringOutputDataStream sds = ! new StringOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! FRAGMENT_OK); try { --- 1164,1170 ---- // Send an ok ! OutputDataStream sds = ! new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! StringUtil.stringToAscii(FRAGMENT_OK)); try { *************** *** 1243,1249 **** } ! StringOutputDataStream sds = ! new StringOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! FRAGMENT_OK); try { --- 1242,1248 ---- } ! OutputDataStream sds = ! new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, ! StringUtil.stringToAscii(FRAGMENT_OK)); try { |
From: Huston F. <hu...@us...> - 2001-11-27 17:37:25
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/transport/tcp In directory usw-pr-cvs1:/tmp/cvs-serv6472/src/org/beepcore/beep/transport/tcp Modified Files: TCPSession.java Log Message: Added utility methods for String to ASCII Index: TCPSession.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/transport/tcp/TCPSession.java,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -r1.20 -r1.21 *** TCPSession.java 2001/11/27 16:04:59 1.20 --- TCPSession.java 2001/11/27 17:37:22 1.21 *************** *** 41,44 **** --- 41,45 ---- import org.beepcore.beep.util.HeaderParser; import org.beepcore.beep.util.Log; + import org.beepcore.beep.util.StringUtil; *************** *** 404,408 **** synchronized (writerLock) { ! os.write(sb.toString().getBytes("UTF-8")); os.flush(); } --- 405,409 ---- synchronized (writerLock) { ! os.write(StringUtil.stringBufferToAscii(sb)); os.flush(); } |
From: Huston F. <hu...@us...> - 2001-11-27 16:05:03
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/util In directory usw-pr-cvs1:/tmp/cvs-serv14355/src/org/beepcore/beep/util Added Files: HeaderParser.java Log Message: Improved header parsing --- NEW FILE: HeaderParser.java --- /* * HeaderParser.java $Revision: 1.1 $ $Date: 2001/11/27 16:04:59 $ * * Copyright (c) 2001 Huston Franklin. All rights reserved. * * The contents of this file are subject to the Blocks Public License (the * "License"); You may not use this file except in compliance with the License. * * You may obtain a copy of the License at http://www.beepcore.org/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * */ package org.beepcore.beep.util; import org.beepcore.beep.core.BEEPException; /** * * @author Huston Franklin * @version $Revision: 1.1 $, $Date: 2001/11/27 16:04:59 $ */ public class HeaderParser { static final int MAX_INT_STRING_LENGTH = 10; static final long UNSIGNED_INT_MAX_VALUE = 4294967295L; private byte[] buf; private int off = 0; private int len; public HeaderParser(byte[] buf, int len) { this.buf = buf; this.len = len; } public boolean hasMoreTokens() { return off < len; } public boolean parseLast() throws BEEPException { if (hasMoreTokens() == false) { throw new BEEPException("Malformed BEEP Header"); } int tl = tokenLength(); if (tl != 1) { throw new BEEPException("Malformed BEEP Header"); } char c = (char)(buf[off] & 0x7f); if (c != '*' && c != '.') { throw new BEEPException("Malformed BEEP Header"); } findNextToken(tl); return c == '.'; } public int parseInt() throws BEEPException { if (hasMoreTokens() == false) { throw new BEEPException("Malformed BEEP Header"); } int tl = tokenLength(); int i = atoi(buf, off, tl); findNextToken(tl); return i; } public long parseUnsignedInt() throws BEEPException { if (hasMoreTokens() == false) { throw new BEEPException("Malformed BEEP Header"); } int tl = tokenLength(); long l = atoui(buf, off, tl); findNextToken(tl); return l; } public char[] parseType() throws BEEPException { if (hasMoreTokens() == false) { throw new BEEPException("Malformed BEEP Header"); } int tl = tokenLength(); if (tl != 3) { throw new BEEPException("Malformed BEEP Header"); } char[] c = new char[3]; c[0] = (char) (buf[off] & 0xff); c[1] = (char) (buf[off+1] & 0xff); c[2] = (char) (buf[off+2] & 0xff); findNextToken(tl); return c; } private void findNextToken(int previousLength) throws BEEPException { off += previousLength + 1; if (off > len) return; if (off == len || buf[off - 1] != ' ' || buf[off] == ' ') { throw new BEEPException("Malformed BEEP Header"); } } private int tokenLength() { for (int i=off; i<len; ++i) { if ((buf[i] & 0xff) == ' ') { return i - off; } } return len - off; } private static int atoi(byte[] b, int off, int len) throws NumberFormatException { long res = atoui(b, off, len); if (res > Integer.MAX_VALUE) { throw new NumberFormatException(); } return (int) res; } private static long atoui(byte[] b, int off, int len) throws NumberFormatException { if (len > MAX_INT_STRING_LENGTH) { throw new NumberFormatException(); } long res = 0; for (int i=off; i<len + off; ++i) { if (b[i] < (byte) '0' || b[i] > (byte) '9') { System.out.println("b[" + i + "] = " + b[i]); throw new NumberFormatException(); } res *= 10; res += (b[i] - (byte) '0'); } if (res > UNSIGNED_INT_MAX_VALUE) { throw new NumberFormatException(); } return res; } } |
From: Huston F. <hu...@us...> - 2001-11-27 16:05:02
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/transport/tcp In directory usw-pr-cvs1:/tmp/cvs-serv14355/src/org/beepcore/beep/transport/tcp Modified Files: TCPSession.java Log Message: Improved header parsing Index: TCPSession.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/transport/tcp/TCPSession.java,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -r1.19 -r1.20 *** TCPSession.java 2001/11/27 07:31:21 1.19 --- TCPSession.java 2001/11/27 16:04:59 1.20 *************** *** 39,42 **** --- 39,43 ---- import org.beepcore.beep.core.SessionTuningProperties; import org.beepcore.beep.util.BufferSegment; + import org.beepcore.beep.util.HeaderParser; import org.beepcore.beep.util.Log; *************** *** 54,67 **** // Constants ! private static final String ERR_SEND_FRAME_FAILED = ! "Unable to send a frame"; ! private static final String ERR_TCP_BUFFER_TOO_LARGE = ""; ! private static final String SEQ_PREFIX = "SEQ "; ! private static final char NEWLINE_CHAR = '\n'; ! private static final int DEFAULT_PROPERTIES_SIZE = 4; ! private static final int DEFAULT_RECEIVE_BUFFER_SIZE = 4 * 1024; private static final int MAX_RECEIVE_BUFFER_SIZE = 64 * 1024; - private static final int MIN_RECEIVE_BUFFER_SIZE = 4 * 1024; - private static final int SEQ_LENGTH = SEQ_PREFIX.length(); private static final String TCP_MAPPING = "TCP Mapping"; private static final String CRLF = "\r\n"; --- 55,60 ---- // Constants ! private static final char[] MESSAGE_TYPE_SEQ = new char[] {'S', 'E', 'Q'}; private static final int MAX_RECEIVE_BUFFER_SIZE = 64 * 1024; private static final String TCP_MAPPING = "TCP Mapping"; private static final String CRLF = "\r\n"; *************** *** 80,87 **** // Instance Data - // @todo had these per stack, but have - // since changed my tune, since we'll be thread/session - // for probably a while yet...this'll help on performance. - // reusing fixed size buffers. private byte headerBuffer[] = new byte[Frame.MAX_HEADER_SIZE]; private byte[] outputBuf = new byte[0]; --- 73,76 ---- *************** *** 397,401 **** StringBuffer sb = new StringBuffer(Frame.MAX_HEADER_SIZE); ! sb.append(SEQ_PREFIX); sb.append(this.getChannelNumberAsString(channel)); sb.append(' '); --- 386,391 ---- StringBuffer sb = new StringBuffer(Frame.MAX_HEADER_SIZE); ! sb.append(MESSAGE_TYPE_SEQ); ! sb.append(' '); sb.append(this.getChannelNumberAsString(channel)); sb.append(' '); *************** *** 466,470 **** } ! if (headerBuffer[0] == (byte) SEQ_PREFIX.charAt(0)) { processSEQFrame(headerBuffer, amountRead, is); continue; --- 456,460 ---- } ! if (headerBuffer[0] == (byte) MESSAGE_TYPE_SEQ[0]) { processSEQFrame(headerBuffer, amountRead, is); continue; *************** *** 665,692 **** // Process the header ! StringTokenizer st = new StringTokenizer(new String(headerBuffer, 0, ! headerLength)); ! ! if (st.countTokens() != 4) { ! ! // This should just shut the session down. ! Log.logEntry(Log.SEV_ERROR, TCP_MAPPING, "Malformed BEEP header"); ! throw new BEEPException("Malformed BEEP header"); } ! // Skip the SEQ ! if (st.nextToken().equals("SEQ") == false) { ! throw new BEEPException("Malformed BEEP header"); ! } ! ! // Read the Channel Number ! int channelNum = Integer.parseInt(st.nextToken()); ! // Read the Ack Number ! long ackNum = Long.parseLong(st.nextToken()); ! ! // Read the Window Number ! int window = Integer.parseInt(st.nextToken()); // update the channel with the new receive window size --- 655,673 ---- // Process the header ! HeaderParser header = new HeaderParser(headerBuffer, ! headerLength - CRLF.length()); ! ! char[] type = header.parseType(); ! if (java.util.Arrays.equals(type, MESSAGE_TYPE_SEQ) == false) { throw new BEEPException("Malformed BEEP header"); } ! int channelNum = header.parseInt(); ! long ackNum = header.parseUnsignedInt(); ! int window = header.parseInt(); ! if (header.hasMoreTokens()) { ! throw new BEEPException("Malformed BEEP Header"); ! } // update the channel with the new receive window size |
From: Huston F. <hu...@us...> - 2001-11-27 16:05:02
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core In directory usw-pr-cvs1:/tmp/cvs-serv14355/src/org/beepcore/beep/core Modified Files: Frame.java Log Message: Improved header parsing Index: Frame.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/Frame.java,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -r1.14 -r1.15 *** Frame.java 2001/11/27 07:31:21 1.14 --- Frame.java 2001/11/27 16:04:58 1.15 *************** *** 3,6 **** --- 3,7 ---- * * Copyright (c) 2001 Invisible Worlds, Inc. All rights reserved. + * Copyright (c) 2001 Huston Franklin. All rights reserved. * * The contents of this file are subject to the Blocks Public License (the *************** *** 25,28 **** --- 26,30 ---- import org.beepcore.beep.util.BufferSegment; + import org.beepcore.beep.util.HeaderParser; import org.beepcore.beep.util.Log; *************** *** 293,357 **** Log.logEntry(Log.SEV_DEBUG_VERBOSE, "Processing normal BEEP frame"); ! int limit = length; ! StringTokenizer st; ! try { ! st = new StringTokenizer(new String(headerBuffer, 0, length, ! "UTF-8")); ! } catch (UnsupportedEncodingException e) { ! throw new RuntimeException("UnsupportedEncodingException" + ! e.getMessage()); ! } ! ! int count = st.countTokens(); ! ! if (!(count == 6 || count == 7)) { ! Log.logEntry(Log.SEV_DEBUG, ! "Illegal header tokens=" + count + "\n" ! + new String(headerBuffer)); ! ! throw new BEEPException("Malformed BEEP Header"); ! } ! // Get Message Type ! // Kick out if we've maxed, or if the type gets set. ! int msgType = MessageType.getMessageType(st.nextToken()); ! ! // Read the Channel Number ! int channelNum = Integer.parseInt(st.nextToken()); ! ! // Read the Message Number ! int msgNum = Integer.parseInt(st.nextToken()); ! ! // Read the more flag ! char isLast = st.nextToken().charAt(0); ! ! boolean last; ! if (isLast == '*') { ! last = false; ! } else if (isLast == '.') { ! last = true; ! } else { ! ! Log.logEntry(Log.SEV_DEBUG, "lastFrame=" + isLast); ! ! throw new BEEPException("Malformed BEEP Header"); } - - // Sequence Number - long seqNum = Long.parseLong(st.nextToken()); ! // Size ! int size = Integer.parseInt(st.nextToken()); ! ! if (size < 0) { throw new BEEPException("Malformed BEEP Header"); - } - - int ansNum = -1; - if (count == 7) { - - // AnsNo - ansNum = Integer.parseInt(st.nextToken()); } --- 295,315 ---- Log.logEntry(Log.SEV_DEBUG_VERBOSE, "Processing normal BEEP frame"); ! HeaderParser header = new HeaderParser(headerBuffer, length); ! int msgType = ! MessageType.getMessageType(new String(header.parseType())); ! int channelNum = header.parseInt(); ! int msgNum = header.parseInt(); ! boolean last = header.parseLast(); ! long seqNum = header.parseUnsignedInt(); ! int size = header.parseInt(); ! int ansNum = -1; ! if (header.hasMoreTokens()) { ! ansNum = header.parseInt(); } ! if (header.hasMoreTokens()) { throw new BEEPException("Malformed BEEP Header"); } |
From: Huston F. <hu...@us...> - 2001-11-27 07:31:24
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/transport/tcp In directory usw-pr-cvs1:/tmp/cvs-serv9482/src/org/beepcore/beep/transport/tcp Modified Files: TCPSession.java Log Message: reduced the number of calls to read() Index: TCPSession.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/transport/tcp/TCPSession.java,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -r1.18 -r1.19 *** TCPSession.java 2001/11/27 02:39:03 1.18 --- TCPSession.java 2001/11/27 07:31:21 1.19 *************** *** 66,69 **** --- 66,77 ---- private static final String TCP_MAPPING = "TCP Mapping"; private static final String CRLF = "\r\n"; + private static final int MIN_SEQ_HEADER_SIZE = (3 // msg type + + 1 // space + + 1 // channel number + + 1 // space + + 1 // acknum + + 1 // space + + 1 // window + + CRLF.length()); private static final int CHANNEL_START_ODD = 1; *************** *** 227,231 **** } ! thread = new Thread(new SessionThread(), threadName); thread.setDaemon(true); --- 235,244 ---- } ! thread = new Thread(threadName) ! { ! public void run() { ! processNextFrame(); ! } ! }; thread.setDaemon(true); *************** *** 411,452 **** } - // Lame hack for J++ - private boolean modState(int i) throws BEEPException - { - return super.changeState(i); - } - - /** - * This specialization is designed to process Frames unique - * to the TCP mapping (e.g. SEQ frames). If the Frame is - * not an SEQ frame, it calls the regular TCPSession - * processNextFrame( int ) with an integer that simply - * indicates how far it's read ahead into the stream. - * @exception Throws an exception if it encounters a poorly - * formed header or an IOException in the underlying socket - * stream. - * - * @throws BEEPException - */ private void processNextFrame() - throws BEEPException, IOException, SessionAbortedException { ! if (Log.isLogged(Log.SEV_DEBUG_VERBOSE)) { ! Log.logEntry(Log.SEV_DEBUG_VERBOSE, TCP_MAPPING, ! "Processing next frame"); } ! int length = 0; ! InputStream is = socket.getInputStream(); while (true) { try { ! int b = is.read(); ! if (b == -1) { throw new SessionAbortedException(); } ! headerBuffer[length] = (byte) b; } catch (java.net.SocketException e) { --- 424,517 ---- } private void processNextFrame() { ! running = true; ! ! try { ! InputStream is = socket.getInputStream(); ! ! while (running) { ! if (getState() == SESSION_STATE_CLOSING || ! getState() == SESSION_STATE_TERMINATING || ! getState() == SESSION_STATE_CLOSED) ! { ! break; ! } ! ! if (Log.isLogged(Log.SEV_DEBUG_VERBOSE)) { ! Log.logEntry(Log.SEV_DEBUG_VERBOSE, TCP_MAPPING, ! "Processing next frame"); ! } ! ! int amountRead; ! ! try { ! do { ! amountRead = ! is.read(headerBuffer, 0, MIN_SEQ_HEADER_SIZE); ! ! if (amountRead == -1) { ! throw new SessionAbortedException(); ! } ! } while (amountRead == 0); ! ! } catch (java.net.SocketException e) { ! if (getState() == SESSION_STATE_ACTIVE) { ! throw e; ! } ! ! // socket closed intentionally (session closing) ! // so just return ! return; ! } ! ! if (headerBuffer[0] == (byte) SEQ_PREFIX.charAt(0)) { ! processSEQFrame(headerBuffer, amountRead, is); ! continue; ! } else { ! processCoreFrame(headerBuffer, amountRead, is); ! } ! } ! } catch (IOException e) { ! Log.logEntry(Log.SEV_ERROR, TCP_MAPPING, e); ! ! socket = null; ! ! terminate(e.getMessage()); ! } catch (SessionAbortedException e) { ! terminate("Session aborted by remote peer."); ! } catch (Throwable e) { ! Log.logEntry(Log.SEV_ERROR, TCP_MAPPING, e); ! terminate(e.getMessage()); } ! Log.logEntry(Log.SEV_DEBUG, TCP_MAPPING, ! "Session listener thread exiting. State = " ! + TCPSession.this.getState()); ! } + private void processCoreFrame(byte[] headerBuffer, int amountRead, + InputStream is) + throws SessionAbortedException, BEEPException, IOException + { + int headerLength = 0; + int amountToRead = Frame.MIN_FRAME_SIZE - amountRead; + + headerFound: while (true) { + int tokenCount = 6; + try { ! int n = is.read(headerBuffer, amountRead, amountToRead); ! if (n == -1) { throw new SessionAbortedException(); } + + if (n == 0) { + continue; + } ! amountRead += n; } catch (java.net.SocketException e) { *************** *** 455,526 **** } ! // socket closed intentionally (session closing) so just return return; } ! if (headerBuffer[length] == '\n') { ! if ((length == 0) || (headerBuffer[length - 1] != '\r')) { ! throw new BEEPException("Malformed BEEP header"); } ! --length; ! break; } - - ++length; ! if (length == Frame.MAX_HEADER_SIZE) { throw new BEEPException("Malformed BEEP header, no CRLF"); } } ! if (Log.isLogged(Log.SEV_DEBUG)) { ! Log.logEntry(Log.SEV_DEBUG, TCP_MAPPING, ! "Processing: " ! + new String(headerBuffer, 0, length)); } ! // If this is not a SEQ frame build a <code>Frame</code> and ! // read in the payload and verify the TRAILER. ! if (headerBuffer[0] != (byte) SEQ_PREFIX.charAt(0)) { ! Frame f = super.createFrame(headerBuffer, length); ! byte[] payload = new byte[f.getSize()]; ! for (int count = 0; count < payload.length; ) { ! int n = is.read(payload, count, payload.length - count); ! if (n == -1) { ! throw new SessionAbortedException(); } ! count += n; } ! if (Log.isLogged(Log.SEV_DEBUG_VERBOSE)) { ! Log.logEntry(Log.SEV_DEBUG_VERBOSE, TCP_MAPPING, ! new String(payload)); } ! for (int i = 0; i < Frame.TRAILER.length(); ++i) { ! int b = is.read(); ! if (b == -1) { throw new SessionAbortedException(); } ! if (((byte) b) != ((byte) Frame.TRAILER.charAt(i))) { ! throw new BEEPException("Malformed BEEP frame, " ! + "invalid trailer"); } - } ! f.addPayload(new BufferSegment(payload)); ! super.postFrame(f); ! return; } // Process the header StringTokenizer st = new StringTokenizer(new String(headerBuffer, 0, ! length)); if (st.countTokens() != 4) { --- 520,670 ---- } ! // socket closed intentionally (session closing) ! // so just return ! running = false; return; } ! while (headerLength < amountRead) { ! if (headerBuffer[headerLength] == '\n') { ! if (headerLength == 0 || ! headerBuffer[headerLength - 1] != '\r') ! { ! throw new BEEPException("Malformed BEEP header"); ! } ! ! ++headerLength; ! break headerFound; } ! if (headerBuffer[headerLength] == ' ') { ! if (tokenCount > 1) { // This is for ANS frames ! --tokenCount; ! } ! } ! ++headerLength; } ! if (headerLength > Frame.MAX_HEADER_SIZE) { throw new BEEPException("Malformed BEEP header, no CRLF"); } + + /* 2 = 1 for the min token size and 1 is for the separator ' ' + * or "\r\n" + */ + amountToRead = (tokenCount * 2) + Frame.TRAILER.length(); } ! if (Log.isLogged(Log.SEV_DEBUG_VERBOSE)) { ! Log.logEntry(Log.SEV_DEBUG_VERBOSE, TCP_MAPPING, ! new String(headerBuffer, 0, headerLength)); } ! Frame f = super.createFrame(headerBuffer, ! headerLength - CRLF.length()); ! byte[] payload = new byte[f.getSize()]; ! int count = amountRead - headerLength; ! System.arraycopy(headerBuffer, headerLength, payload, 0, count); ! ! while (count < payload.length) { ! int n = is.read(payload, count, payload.length - count); ! if (n == -1) { ! throw new SessionAbortedException(); ! } ! count += n; ! } ! ! if (Log.isLogged(Log.SEV_DEBUG_VERBOSE)) { ! Log.logEntry(Log.SEV_DEBUG_VERBOSE, TCP_MAPPING, ! new String(payload)); ! } ! ! for (int i = 0; i < Frame.TRAILER.length(); ++i) { ! int b = is.read(); ! ! if (b == -1) { ! throw new SessionAbortedException(); ! } ! ! if (((byte) b) != ((byte) Frame.TRAILER.charAt(i))) { ! throw new BEEPException("Malformed BEEP frame, " ! + "invalid trailer"); ! } ! } ! ! f.addPayload(new BufferSegment(payload)); ! super.postFrame(f); ! } ! ! private void processSEQFrame(byte[] headerBuffer, int amountRead, ! InputStream is) ! throws BEEPException, IOException, SessionAbortedException ! { ! int headerLength = 0; ! int tokenCount = 4; ! ! headerFound: ! while (true) { ! ! while (headerLength < amountRead) { ! if (headerBuffer[headerLength] == '\n') { ! if (headerLength == 0 || ! headerBuffer[headerLength - 1] != '\r') ! { ! throw new BEEPException("Malformed BEEP header"); ! } ! ! ++headerLength; ! break headerFound; } ! ! if (headerBuffer[headerLength] == ' ') { ! if (tokenCount > 1) { ! --tokenCount; ! } ! } ! ! ++headerLength; } ! if (headerLength > Frame.MAX_HEADER_SIZE) { ! throw new BEEPException("Malformed BEEP header, no CRLF"); } ! int amountToRead = headerBuffer[headerLength - 1] == '\r' ? 1 : ! tokenCount * 2; ! try { ! /* 2 = 1 for the min token size and 1 is for the separator ' ' ! * or "\r\n" ! */ ! int n = is.read(headerBuffer, amountRead, amountToRead); ! if (n == -1) { throw new SessionAbortedException(); } ! if (n == 0) { ! continue; } ! amountRead += n; ! ! } catch (java.net.SocketException e) { ! if (getState() == SESSION_STATE_ACTIVE) { ! throw e; ! } ! // socket closed intentionally (session closing) ! // so just return ! running = false; ! return; ! } } // Process the header StringTokenizer st = new StringTokenizer(new String(headerBuffer, 0, ! headerLength)); if (st.countTokens() != 4) { *************** *** 549,588 **** this.updatePeerReceiveBufferSize(channelNum, ackNum, window); } ! ! private class SessionThread implements Runnable { ! ! public void run() ! { ! try { ! running = true; ! ! // Listen for and post the Greeting Frame ! while ((getState() != SESSION_STATE_ACTIVE) && running) { ! processNextFrame(); ! } ! ! // Keep processing frames as long as we're active ! while ((getState() == SESSION_STATE_ACTIVE) && running) { ! processNextFrame(); ! } ! } catch (IOException e) { ! Log.logEntry(Log.SEV_ERROR, TCP_MAPPING, e); ! ! socket = null; ! ! terminate(e.getMessage()); ! } catch (SessionAbortedException e) { ! terminate("Session aborted by remote peer."); ! } catch (Throwable e) { ! Log.logEntry(Log.SEV_ERROR, TCP_MAPPING, e); ! terminate(e.getMessage()); ! } ! ! Log.logEntry(Log.SEV_DEBUG, TCP_MAPPING, ! "Session listener thread exiting. State = " ! + TCPSession.this.getState()); ! } ! } ! private static class SessionAbortedException extends Exception { } --- 693,697 ---- this.updatePeerReceiveBufferSize(channelNum, ackNum, window); } ! private static class SessionAbortedException extends Exception { } |
From: Huston F. <hu...@us...> - 2001-11-27 07:31:24
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core In directory usw-pr-cvs1:/tmp/cvs-serv9482/src/org/beepcore/beep/core Modified Files: Frame.java Log Message: reduced the number of calls to read() Index: Frame.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/Frame.java,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -r1.13 -r1.14 *** Frame.java 2001/11/27 02:41:25 1.13 --- Frame.java 2001/11/27 07:31:21 1.14 *************** *** 45,48 **** --- 45,50 ---- public class Frame { + private static final String CRLF = "\r\n"; + public static final String TRAILER = "END\r\n"; public static final int MAX_HEADER_SIZE = (3 // msg type *************** *** 59,63 **** + 1 // space + 10 // ansno ! + 2); // CRLF public static final int MAX_ANS_NUMBER = Integer.MAX_VALUE; // 2147483647; public static final int MAX_CHANNEL_NUMBER = Integer.MAX_VALUE; --- 61,79 ---- + 1 // space + 10 // ansno ! + CRLF.length()); ! public static final int MIN_HEADER_SIZE = (3 // msg type ! + 1 // space ! + 1 // channel number ! + 1 // space ! + 1 // msgno ! + 1 // space ! + 1 // more ! + 1 // space ! + 1 // seqno ! + 1 // space ! + 1 // size ! + CRLF.length()); ! public static final int MIN_FRAME_SIZE = MIN_HEADER_SIZE + ! Frame.TRAILER.length(); public static final int MAX_ANS_NUMBER = Integer.MAX_VALUE; // 2147483647; public static final int MAX_CHANNEL_NUMBER = Integer.MAX_VALUE; *************** *** 66,70 **** public static final int MAX_SIZE = Integer.MAX_VALUE; - private static final String CRLF = "\r\n"; private static final BufferSegment trailerBufferSegment = new BufferSegment(TRAILER.getBytes()); --- 82,85 ---- |
From: Huston F. <hu...@us...> - 2001-11-27 02:41:27
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core In directory usw-pr-cvs1:/tmp/cvs-serv18022/src/org/beepcore/beep/core Modified Files: Frame.java Log Message: a bit clearer Index: Frame.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/Frame.java,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -r1.12 -r1.13 *** Frame.java 2001/11/27 02:39:03 1.12 --- Frame.java 2001/11/27 02:41:25 1.13 *************** *** 145,149 **** b[0] = new BufferSegment(buildHeader()); ! b[b.length-1] = trailerBufferSegment; return b; --- 145,149 ---- b[0] = new BufferSegment(buildHeader()); ! b[j] = trailerBufferSegment; return b; |
From: Huston F. <hu...@us...> - 2001-11-27 02:39:06
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/transport/tcp In directory usw-pr-cvs1:/tmp/cvs-serv17443/src/org/beepcore/beep/transport/tcp Modified Files: TCPSession.java Log Message: changed to make a single call to write Index: TCPSession.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/transport/tcp/TCPSession.java,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -r1.17 -r1.18 *** TCPSession.java 2001/11/23 04:24:04 1.17 --- TCPSession.java 2001/11/27 02:39:03 1.18 *************** *** 77,80 **** --- 77,81 ---- // reusing fixed size buffers. private byte headerBuffer[] = new byte[Frame.MAX_HEADER_SIZE]; + private byte[] outputBuf = new byte[0]; private Object writerLock; private Socket socket; *************** *** 258,288 **** try { - // @todo consider the costs of colliding these into one - // buffer and one write..test to see if it's faster - // this way or faster copying. OutputStream os = socket.getOutputStream(); - byte[] header = null; synchronized (writerLock) { ! if (Log.isLogged(Log.SEV_DEBUG_VERBOSE)) { ! Log.logEntry(Log.SEV_DEBUG_VERBOSE, TCP_MAPPING, ! "Wrote the following\n"); } ! Iterator i = f.getBytes(); ! while (i.hasNext()) { ! BufferSegment b = (BufferSegment) i.next(); ! os.write(b.getData(), b.getOffset(), b.getLength()); ! if (Log.isLogged(Log.SEV_DEBUG_VERBOSE)) { ! Log.logEntry(Log.SEV_DEBUG_VERBOSE, TCP_MAPPING, ! new String(b.getData(), b.getOffset(), ! b.getLength())); ! } } os.flush(); } } catch (IOException e) { --- 259,297 ---- try { OutputStream os = socket.getOutputStream(); synchronized (writerLock) { ! /* Inspite of the extra data copy if is faster to have ! * a single call to write() (at least with the JVMs we ! * have tested with). ! */ ! BufferSegment[] bs = f.getBytes(); ! ! int n = 0; ! for (int i=0; i<bs.length; ++i) { ! n += bs[i].getLength(); } ! if (n > outputBuf.length) { ! outputBuf = new byte[n]; ! } ! int off = 0; ! for (int i=0; i<bs.length; ++i) { ! System.arraycopy(bs[i].getData(), bs[i].getOffset(), ! outputBuf, off, bs[i].getLength()); ! off += bs[i].getLength(); } + os.write(outputBuf, 0, n); os.flush(); + + if (Log.isLogged(Log.SEV_DEBUG_VERBOSE)) { + Log.logEntry(Log.SEV_DEBUG_VERBOSE, TCP_MAPPING, + "Wrote the following\n" + + new String(outputBuf)); + } } } catch (IOException e) { |
From: Huston F. <hu...@us...> - 2001-11-27 02:39:05
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core In directory usw-pr-cvs1:/tmp/cvs-serv17443/src/org/beepcore/beep/core Modified Files: Frame.java Log Message: changed to make a single call to write Index: Frame.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/core/Frame.java,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -r1.11 -r1.12 *** Frame.java 2001/11/08 05:51:34 1.11 --- Frame.java 2001/11/27 02:39:03 1.12 *************** *** 67,70 **** --- 67,72 ---- private static final String CRLF = "\r\n"; + private static final BufferSegment trailerBufferSegment = + new BufferSegment(TRAILER.getBytes()); /** BEEP message type of <code>Frame</code>. */ *************** *** 103,135 **** private LinkedList payload = new LinkedList(); - /** - * Initializes a new <code>Frame</code> representing a BEEP ANS frame. - * - * @param messageType indicates whether a <code>Frame</code> is a MSG, - * RPY, ERR, ANS or NUL. - * @param channel <code>Channel</code> on which the <code>Frame</code> was - * sent. - * @param msgno Message number of the <code>Frame</code>. - * @param seqno Sequence number of the <code>Frame</code>. - * @param ansno Answer number of the <code>Frame</code>. - * @param payload Payload of the <code>Frame</code>. - * @param last Indicates if this is the last <code>Frame</code> sent in a - * sequence of frames. - * - * @see BufferSegment - */ - // Frame(int messageType, Channel channel, int msgno, boolean last, - // long seqno, int ansno, BufferSegment payload) - // { - // this.messageType = messageType; - // this.channel = channel; - // this.msgno = msgno; - // this.seqno = seqno; - // this.ansno = ansno; - // this.payload.add(payload); - // this.size = payload.getLength() - payload.getOffset(); - // this.last = last; - // } - Frame(int messageType, Channel channel, int msgno, boolean last, long seqno, int size, int ansno) --- 105,108 ---- *************** *** 142,146 **** this.size = size; this.ansno = ansno; - // this.payload = null; } --- 115,118 ---- *************** *** 159,174 **** * */ ! public Iterator getBytes() { this.size = 0; Iterator i = this.payload.iterator(); while (i.hasNext()) { ! this.size += ((BufferSegment) i.next()).getLength(); } ! this.payload.addFirst(new BufferSegment(buildHeader())); ! this.payload.addLast(new BufferSegment(TRAILER.getBytes())); ! return this.payload.iterator(); } --- 131,151 ---- * */ ! public BufferSegment[] getBytes() { + BufferSegment[] b = new BufferSegment[this.payload.size() + 2]; this.size = 0; + int j=1; Iterator i = this.payload.iterator(); while (i.hasNext()) { ! b[j] = (BufferSegment) i.next(); ! this.size += b[j].getLength(); ! ++j; } + + b[0] = new BufferSegment(buildHeader()); + b[b.length-1] = trailerBufferSegment; ! return b; } |
From: Huston F. <hu...@us...> - 2001-11-25 08:38:45
|
Update of /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/echo In directory usw-pr-cvs1:/tmp/cvs-serv31642/src/org/beepcore/beep/profile/echo Modified Files: EchoProfile.java Log Message: removed unnecessary call to setAppData Index: EchoProfile.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/src/org/beepcore/beep/profile/echo/EchoProfile.java,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -r1.11 -r1.12 *** EchoProfile.java 2001/11/08 05:51:34 1.11 --- EchoProfile.java 2001/11/25 08:38:42 1.12 *************** *** 60,64 **** Log.logEntry(Log.SEV_DEBUG, "EchoCCL CloseChannel Callback"); channel.setMessageListener(null); - channel.setAppData(null); } --- 60,63 ---- |
From: Huston F. <hu...@us...> - 2001-11-25 08:00:31
|
Update of /cvsroot/beepcore-java/beepcore-java/example/org/beepcore/beep/example In directory usw-pr-cvs1:/tmp/cvs-serv26746/example/org/beepcore/beep/example Modified Files: Bing.java Log Message: Clarified usage of InputDataStream Index: Bing.java =================================================================== RCS file: /cvsroot/beepcore-java/beepcore-java/example/org/beepcore/beep/example/Bing.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -r1.9 -r1.10 *** Bing.java 2001/11/10 21:33:28 1.9 --- Bing.java 2001/11/25 08:00:28 1.10 *************** *** 25,29 **** import org.beepcore.beep.core.BEEPInterruptedException; import org.beepcore.beep.core.Channel; - import org.beepcore.beep.core.InputDataStream; import org.beepcore.beep.core.ProfileRegistry; import org.beepcore.beep.core.Session; --- 25,28 ---- *************** *** 125,134 **** try { // Get the reply to the request ! InputDataStream ds = reply.getNextReply().getDataStream(); ! InputStream is = ds.getInputStream(); // Read the data in the reply ! while (ds.isComplete() == false || is.available() > 0) { ! is.read(); ++replyLength; } --- 124,132 ---- try { // Get the reply to the request ! InputStream is = ! reply.getNextReply().getDataStream().getInputStream(); // Read the data in the reply ! while (is.read() != -1) { ++replyLength; } |