pax_global_header00006660000000000000000000000064117477356150014532gustar00rootroot0000000000000052 comment=c3badcad689b273f3b98d9c6bb7e6b50448e0560 jetty8-8.1.3/000077500000000000000000000000001174773561500127725ustar00rootroot00000000000000jetty8-8.1.3/.gitignore000066400000000000000000000005261174773561500147650ustar00rootroot00000000000000# eclipse .classpath .project .settings # maven target/ */src/main/java/META-INF/ *.versionsBackup # common junk *.log *.swp *.diff *.patch # intellij *.iml *.ipr *.iws .idea/ # Mac filesystem dust .DS_Store # pmd .pmdruleset .pmd # netbeans /nbproject # vim .*.sw[a-p] # merge tooling *.orig #maven *.versionsBackup *.releaseBackup jetty8-8.1.3/BUILDING.txt000066400000000000000000000001711174773561500147270ustar00rootroot00000000000000BUILDING JETTY -------------- Jetty is built with maven 3.x+ $ cd /my/work/directory/jetty-7 $ mvn clean install jetty8-8.1.3/LICENSE-APACHE-2.0.txt000066400000000000000000000261361174773561500160410ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. jetty8-8.1.3/LICENSE-CONTRIBUTOR/000077500000000000000000000000001174773561500156645ustar00rootroot00000000000000jetty8-8.1.3/LICENSE-CONTRIBUTOR/CDDLv1.0.txt000066400000000000000000000406161174773561500175470ustar00rootroot00000000000000COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 1. Definitions. 1.1. Contributor means each individual or entity that creates or contributes to the creation of Modifications. 1.2. Contributor Version means the combination of the Original Software, prior Modifications used by a Contributor (if any), and the Modifications made by that particular Contributor. 1.3. Covered Software means (a) the Original Software, or (b) Modifications, or (c) the combination of files containing Original Software with files containing Modifications, in each case including portions thereof. 1.4. Executable means the Covered Software in any form other than Source Code. 1.5. Initial Developer means the individual or entity that first makes Original Software available under this License. 1.6. Larger Work means a work which combines Covered Software or portions thereof with code not governed by the terms of this License. 1.7. License means this document. 1.8. Licensable means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. Modifications means the Source Code and Executable form of any of the following: A. Any file that results from an addition to, deletion from or modification of the contents of a file containing Original Software or previous Modifications; B. Any new file that contains any part of the Original Software or previous Modification; or C. Any new file that is contributed or otherwise made available under the terms of this License. 1.10. Original Software means the Source Code and Executable form of computer software code that is originally released under this License. 1.11. Patent Claims means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.12. Source Code means (a) the common form of computer software code in which modifications are made and (b) associated documentation included in or with such code. 1.13. You (or Your) means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, You includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, control means (a)the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b)ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants. 2.1. The Initial Developer Grant. Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, the Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer, to use, reproduce, modify, display, perform, sublicense and distribute the Original Software (or portions thereof), with or without Modifications, and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using or selling of Original Software, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Software (or portions thereof). (c) The licenses granted in Sections2.1(a) and (b) are effective on the date Initial Developer first distributes or otherwise makes the Original Software available to a third party under the terms of this License. (d) Notwithstanding Section2.1(b) above, no patent license is granted: (1)for code that You delete from the Original Software, or (2)for infringements caused by: (i)the modification of the Original Software, or (ii)the combination of the Original Software with other software or devices. 2.2. Contributor Grant. Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof), either on an unmodified basis, with other Modifications, as Covered Software and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: (1)Modifications made by that Contributor (or portions thereof); and (2)the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) The licenses granted in Sections2.2(a) and 2.2(b) are effective on the date Contributor first distributes or otherwise makes the Modifications available to a third party. (d) Notwithstanding Section2.2(b) above, no patent license is granted: (1)for any code that Contributor has deleted from the Contributor Version; (2)for infringements caused by: (i)third party modifications of Contributor Version, or (ii)the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or (3)under Patent Claims infringed by Covered Software in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Availability of Source Code. Any Covered Software that You distribute or otherwise make available in Executable form must also be made available in Source Code form and that Source Code form must be distributed only under the terms of this License. You must include a copy of this License with every copy of the Source Code form of the Covered Software You distribute or otherwise make available. You must inform recipients of any such Covered Software in Executable form as to how they can obtain such Covered Software in Source Code form in a reasonable manner on or through a medium customarily used for software exchange. 3.2. Modifications. The Modifications that You create or to which You contribute are governed by the terms of this License. You represent that You believe Your Modifications are Your original creation(s) and/or You have sufficient rights to grant the rights conveyed by this License. 3.3. Required Notices. You must include a notice in each of Your Modifications that identifies You as the Contributor of the Modification. You may not remove or alter any copyright, patent or trademark notices contained within the Covered Software, or any notices of licensing or any descriptive text giving attribution to any Contributor or the Initial Developer. 3.4. Application of Additional Terms. You may not offer or impose any terms on any Covered Software in Source Code form that alters or restricts the applicable version of this License or the recipients rights hereunder. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, you may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear that any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.5. Distribution of Executable Versions. You may distribute the Executable form of the Covered Software under the terms of this License or under the terms of a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable form does not attempt to limit or alter the recipients rights in the Source Code form from the rights set forth in this License. If You distribute the Covered Software in Executable form under a different license, You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.6. Larger Works. You may create a Larger Work by combining Covered Software with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Software. 4. Versions of the License. 4.1. New Versions. Sun Microsystems, Inc. is the initial license steward and may publish revised and/or new versions of this License from time to time. Each version will be given a distinguishing version number. Except as provided in Section 4.3, no one other than the license steward has the right to modify this License. 4.2. Effect of New Versions. You may always continue to use, distribute or otherwise make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. If the Initial Developer includes a notice in the Original Software prohibiting it from being distributed or otherwise made available under any subsequent version of the License, You must distribute and make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. Otherwise, You may also choose to use, distribute or otherwise make the Covered Software available under the terms of any subsequent version of the License published by the license steward. 4.3. Modified Versions. When You are an Initial Developer and You want to create a new license for Your Original Software, You may create and use a modified version of this License if You: (a)rename the license and remove any references to the name of the license steward (except to note that the license differs from this License); and (b)otherwise make it clear that the license contains terms which differ from this License. 5. DISCLAIMER OF WARRANTY. COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 6. TERMINATION. 6.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 6.2. If You assert a patent infringement claim (excluding declaratory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You assert such claim is referred to as Participant) alleging that the Participant Software (meaning the Contributor Version where the Participant is a Contributor or the Original Software where the Participant is the Initial Developer) directly or indirectly infringes any patent, then any and all rights granted directly or indirectly to You by such Participant, the Initial Developer (if the Initial Developer is not the Participant) and all Contributors under Sections2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively and automatically at the expiration of such 60 day notice period, unless if within such 60 day period You withdraw Your claim with respect to the Participant Software against such Participant either unilaterally or pursuant to a written agreement with Participant. 6.3. In the event of termination under Sections6.1 or 6.2 above, all end user licenses that have been validly granted by You or any distributor hereunder prior to termination (excluding licenses granted to You by any distributor) shall survive termination. 7. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTYS NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 8. U.S. GOVERNMENT END USERS. The Covered Software is a commercial item, as that term is defined in 48C.F.R.2.101 (Oct. 1995), consisting of commercial computer software (as that term is defined at 48 C.F.R. 252.227-7014(a)(1)) and commercial computer software documentation as such terms are used in 48C.F.R.12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Software with only those rights set forth herein. This U.S. Government Rights clause is in lieu of, and supersedes, any other FAR, DFAR, or other clause or provision that addresses Government rights in computer software under this License. 9. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by the law of the jurisdiction specified in a notice contained within the Original Software (except to the extent applicable law, if any, provides otherwise), excluding such jurisdictions conflict-of-law provisions. Any litigation relating to this License shall be subject to the jurisdiction of the courts located in the jurisdiction and venue specified in a notice contained within the Original Software, with the losing party responsible for costs, including, without limitation, court costs and reasonable attorneys fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. You agree that You alone are responsible for compliance with the United States export administration regulations (and the export control laws and regulation of any other countries) when You use, distribute or otherwise make available any Covered Software. 10. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) The GlassFish code released under the CDDL shall be governed by the laws of the State of California (excluding conflict-of-law provisions). Any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California and the state courts of the State of California, with venue lying in Santa Clara County, California. jetty8-8.1.3/LICENSE-CONTRIBUTOR/ccla-exist.pdf000066400000000000000000015134771174773561500204350ustar00rootroot00000000000000%PDF-1.3 % 4 0 obj << /Length 5 0 R /Filter /FlateDecode >> stream x+TT(T0B3C#sK#Tp< H$anag`dY($*{*u endstream endobj 5 0 obj 62 endobj 2 0 obj << /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R /MediaBox [0 0 612 792] >> endobj 6 0 obj << /ProcSet [ /PDF /ImageB /ImageC /ImageI ] /XObject << /Im1 7 0 R >> >> endobj 7 0 obj << /Length 8 0 R /Type /XObject /Subtype /Image /Width 2544 /Height 3280 /ColorSpace 9 0 R /BitsPerComponent 1 /Filter /FlateDecode >> stream x]z絶3ǸeD<#Q.rE|tOrBBGHM|.U;;Jq84DspЀkOtx@|CL\y˵=G_v~Z~<7-iCg]x4"v6.\x믿zOe~ߗOG?+ǏPͫ\p.o$wGdF>lr!|ї'3Y8%~q?nD?\[*Wx`:ut}os.i﹯63o šc9".Z[W۟xo}_ft˘ GyM\Ez[Z[\3yU})g,/-PJ@ (Hy,+C`dDJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%N}#dkn͞hP_b.&P|m14ue˫ Ԗ76i)/8ly#_!iB{[>e9oZE[rAkf6[Vܹ[iMlXws׀>?Sͺ!Nzny =i5Y=o;7ӁpͿsxm&B ޼5BTzGq4#q ʚimr,zAfj1Dw5SzG h{!y-R3\GP90:Q֮zb{M:o@o9g̕신qu>(XKl/`{B/(#QU7eۻQ5QuH+m/=Zj{Gku7xniky=?7mz2Ћ-M[/VsYEO _;g;zLTzGs{mO~!=I?7 KÎ;] v V(▖=mҧnk-K;FSm: d5Vyl[kW֠uUlk ~BB]o;pQM-g`>3I(ewj Jo=qrm%z9r+Oʠ&M>_di_^~Uew_I(^SöVŽ MRZCd*eVU':ysCރ`{8ç= aәZ3őIh[ Vv^,y˔⎫1|^޸d*,Ͷl{Gz/2熢=: ZP/"cƔ[&cK:IzѓnJ967뒷,}Oy{\mf5pa܎+)_e0]KFVeVeU:pnܥ !N!AO( ~Z7)~ PF2J˛IU0wMʈu&Mb2/*R4h">3E)fk( Fa~MA,Fz66>6s7I&oJ@4wט*/MRg5,i.=R1" ֘ۗ'+n$aP&Oz~)қI}|fH`{B)aF":t @s/)(ev&<ơ&\lj ˀ^^A"$Ll[ޖ^襑^0za*(dg  zd[r^:d-oq\=Hr5j$K_;`4ˠizIW:9E=2qE,Emd~=.ƀ\|GG+S |];lFz;!00\l :h{^ =[oYI a4%BYiG@t?!$3<tt*dOnzzs%b6mJd*k _dSǟU>@b؜hzH/Cuz3l D蹓m/sB/y>1ayG/pӐ'lS̹\CjU;A衷ۆ`{h0^ކ`9{Ak{GOC. z QO6Ÿ8#yb{У(Ezd@X4)အސ:5*] T7R8PAp2dy! 3Rk=0ʵĽ&Ε2J?@o% Tvq1_}, FK).mzڛѽ3A/ qFۋuF&eĶ@ H~6 GEeK >:7`bZCg)%z4 ;z"7+F =)ZKO=IJG@C#T C[zWm?y=_6s3O{[Z ?{coŋT6g^co եtՍџ]LCMeKzb^ X@ӛRXyP}Ix=QȥCE&me.[&%1]FUdƽ_nmqS|\h=\Y n׹e#e5*eIлΠz 1yQ2F~Ň?Ln]4]AK-:f# ՏUZ\hU>Л/B+sWo͏ G-ؚKb{cxQ5*uReEN5#^u-ijIOн%=!9$\bU5Wp|lz?lі;B*?D!Q-?Bޠj"=Έ7Ƴ>9GYŕ'͡?{vQO~дv^R -4)>Ҝ;OG[&lTLMJK,Ç_f>C8+m@_Pp8k=k땕PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (3N/WZzy.D{ޢ`4L4zIo?csK7+AG7m> _,iq]/r@Ȩ,R`Ĕ|ow12>8 o e23ޅ/)ܸ^cGUr+K?)e-@܋Myz"b=fays]Z&^_gbsl~tCoeqeGr3gt}z;+J|& |4c&X‹8iuXZeZ}H5=;di&,桾Q7c)u:͘|Hz $?XfGFK jEG3կ碿Zz:[錂wk t6q#  IRG/|6&"vFG]p2c:Jtʲk2w)yJr:^T!SMv-j)w5o+&>kdPהxӝ& ,.m^ M6yDgϩ|s0E[Ptl|D%M봽.6 Ec%cPG2IUB/= HDf V֝{tאA v( =Q-Ȫž=(^U ۭ[%C4(9m uL2G"7d$ˬuw|OOX PYϽr;SuAzX艠^h:ѱCM C3FNBPsvz[;DmO5`y, HUWGe;j>j3I8'lwklP\Lt䭊5ҩ8Lß$ z ɞDZ@3&q"D&"cSu6BmS4jTC!Ūc5JP,У:B李BoO-*p6GpI$}Nzh߁lagҦgވ0=Mۖ8WlA jۍ.# 3&&-of{X{c>#! sm(譸P6~mLj3ٔȣN']5ѻqaJfךM *ȸЛxx yJR9Ju9#:W4JzGiC']^޸JiM\GT%7""vϕK-Rꔴ;S*ܪMb{'3z}=CrV(:wLdu=z tӂ g$bA4Wc MloGiwߥdad(̈́Q-Ғ(@E/EAͳHga\ =YlУ-ca3} (=aӂh{8.~ݘd ?#i&t^2Ԇ$K$np<*s@Ezw胉Zuh6sz@Ş!,C3=fD=.z.st63u5ZF&+Z`ÃYF9*:Ը3h:qS5wX֘.9ǙKOCPҺ{͛zgs=sqT'ea9i.;;)Z! to e`*rsPy;ГWz6P8OQ^֚i5ꄅ  BI=Trie7??c ph\ 5c0n2 =b8VDȪ<r.R;?_yxZ3dX֭&I?MEkfhֽt6w'EۣoEboUz%yٞ]Ohɬ,zz5=н+ݵlfR,~2~"a_k魮~V d_᭮ѣ_Q|uj젛4~N2]l-=3jh0:n^]ckOs^s_]y]7(%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ+am٢.Qx8{m`@.1vN@Fؕٳ"-z㕥oٕIvR/؞PٝV]=w(ܽ,V#Nͦ: wW^EYݤ9&ݭ=*czzOwû#Ntv3r ƅCAU$ĤTzcK;o_1W@.o\?gxV^UlrFg4kW٥:?Y-/ךjg\c6 vPeoCHYh{zz8t^"{8NU8Gܛ-eVYhpԣ`5/?)leb8Eh;~ӆvg0>2xSb,ܶu5M^FaoU+32PZs'&!қ0 /Ɇ#D lzR)Ma1a' UHۤ}'^M$6Ԇ~p& FЫzI01h3lhw'\8͌ދ!l-u{skx84SD/iʥmwB'UbV&ml} |>!3/dmYɴ5ٌLR$I@1&ԩ 7)VڦM6wp=KnMΖcwڴ<2<)Cӓ%y@f*({.&mNcBoT rQO2x lҶnB YNpUO m77^)лI8$ͬ~L x&EK0YYRB1ӧSe\mkӫC@IeZ:=ea[pM'ߙ*=[jUnaM$C=&g1foΉu'"-b 7apXG_υ^ףXBI(62#̧uhۜKdր^G[^kcM+3X @pB/aûy}}.V39ry=NBjJؼqSB4w|Z#D6~/m捝GzSD +nB95# 'zz5orˡLC-k,kP3i^Tn,GS ix$Mz'ނED=^ܯ4D"ҫ7aJ*%ROF"=@6% dwT+*U5H27lϫ#"֛7%86'ފYoǂv'q)ΰw}yƭGE$"L\ IyDZ#o`޶3zR%zuc~Hen=o@/cюk[ x>+[[Kܫݾx: 6]:Çf͎4R)Dϕv+x1wiM]@&&K+CٞӾrU9Wc ߛ[,JԬ\g{TX Gz>ϫiCņW:>^};5p%Q56moFm+j1ԧo#j&U@e]aL;@Gz72a{8 8Ap=wc3#Pnz抛g|bg|`Ql3ɻ+M^20$7M9h\`Tq< Qkc'-)UJ6|Ʉhw Ui0],qTP\!X=6t\?&e"lg|㟃^|#)ˈ;H/#Kdm,hMUgۀǾտ$ZzƇыqG[@!4lİГWY%3l*B6׹TxOo_z<^GOx囀0 Ŵj˨b㊟g@ \^%eSibS9Gzc7dI˲=9JV͓^]͟F*eF+^}QX^l̐=ÙHaWl㞮y!(uZ^}S„+] @ z?՞dWΪY^¯}_ L,{H[hU$ a#*bthĸퟮ:B(ڛ\XՋ(z|PB(A[-gx aCaܨ\11ƭsT~;D_{,9AfTԴPmHB P-."=`C)n]mae'zԤY슼wʒtXMȅuka sՒzW'^LMUF~iSТs⋌EZ_2 ғU"ceD>zD)R撡jt'~;N91 J5򥵥'6U:UmǪ骱t3v?CIK_.m fNvP]0[{m:4ު&J\[9z[qH~[>rqݬB.7\zUo3w8գ#|?mVJ+\x0|4̥|jؤY Ez>yRњ/.\ʗV@>؃Q;m0mUsaW;pjٗ燎ьšo47-'PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%NKSQso]^MOJҴD@9d  z}vWe=^mbbuYnßm_???М3$jy+Im:ܶ"~rO(\~AvL!3.jBib9s񊙎۫VDS&>stK_|6i|Oa.ɼBN‡;WC2(o{7WY)YJr1ao'aӚ6;zpd:ߘ!o7'ן2۽Ldeφ=f{U`ҩ|^ ;}2`9jqz~)_wmU[fLJԄSLs֊PW..&(ӫ߭ۙL~9oDٞNr-i}BDZ΋ђ4*R3f 10a!G&?$M3l?U ~לڌR̻nti%?͌># {}^ Z\u8 }z3٢@ivv|%tZLLޱy 53Mlߟo\>]xוsj7ky{|`Bo8ga zݱ'ĝ%3|zɚQGmB@ {pO϶\wvكuk-ĬCΞĽ:TDlqCGo6[z'o-9W c 1|eܷ?hA3?geVkH*gqĠә7?}n-K]Z繧^4_G? V qeIS^hhL-Ƨ0^("M[CA^Jˑ^iq:L]^h&٩iTNxr:3Psɦ҈-#M< -6K!ֵnf/JH"=QԘCx(ͅ4x)SE؈e +n#O*"/C {M;ۛ@ff{zKHwkfC)ғM=N43EU#/RsHR ^(D_HT;=Y/!݁BP9vcLS4MkIXB%)\,zO舂(VyMP\*h{<56s-8.dOXf;B:@6l]k7w:z K==*cD"Jb{wpw\~a"1XF[ 艋L[twŗdOt< D$BW@o-1bAOE +)e!J==. >K)N(ɭa?={%.8:* Pߞzx.h z< \g{ZQkDzĠSk;zpؐc̵ǩN!zކcj,+/ *L"T^uq/Ds؞8=CgOQVC^6*%%&ϝ'ѧ%q{r?6]BGQŦ1^$اsdL~@tFsh{BqảGVHW4 }ܓiIg~3k<$(+Fٹ{Deߐ,M]OkdBg{Лt:ۮ/q"l&Dž\_^ATУVz6{ ጸ-Sh; D*\vUV |⼃  (BqVcO/lɤ zmNL[&6MC4pIi }j}>-Il}&Z}bd&rs;mXw- C;r(HES9rr~f{^GOl/^5b=A :rSzzR90y/E5ތBb8E"B vly=15_MxZ,nǸY"P⪧% =_VG8wc,6!&$Yb{'U4n3zyP율$"@/@<=krvs&sm$E-yFJQ#c%Uϕ=N1((z O le; = uZT]ܫmh@Fg'˟<*.w\ʅ=Lne0 7MzHBgĴHO0) ^57f@F51GMy [l Q oGMj aZ.屢Ry"1ѣx k(pq"jSlǛM*4mǀo$KG0˥TS蓤3Soezb[ޜpt\豅ݰⲕ=wŽXo'_$7*3pkaK(6xe.4)VT) mښk,5e(we)wP^B2.@% ]H1|<#zB1ۍԮѳtӢEdB&-`ZC ,gQ)EzY8+[(Sv BXlӈ;PM'n̚Xz롇ݬ5ޅ!=&295'rOlFh~6 Pq0ۃN =׊qj=Q MR6 腩 ^?r =@(q<|+Z(W.(6)qx7*N0M7R%*DO0y<z $K$ֱ4U/AE rّ^@Uz(JXmlZB2pm4j74XYa?G');AvLb{wogǡ=δ2:@p6@`ʘ^G٣s{z]>7΁^)1s:z;7҃k)-BG K!cXF"lR;#ς[IEzw.Ę=ySoC. _Ӕs 3GE-"={ =hHܳ<<bcK"=׫BxQNLOCvW?4\{V;M %T4ӒEO!0DB؆1I#:yG%(uGo$58IHw#=#9vtN2u7y$J 6w~-|Br,FhNxɥۣf:'MFє>G8ޏ$u9ɣ^I==omz) 8`:yFG^vt^>'I,@oJ BC/}$4B` lo7{zd=*j5*"|c{1R8=lY} i)HwRb{=酋U\'J#&`^=.[֥@%9ߪGF4PLbBO`{ЋMh{EmD:>BUrtF@/?yzT ܠ44Dzz 3't7} ѻ='4/T=RFZb{ވ@o:<&{}pR߹-ћ\)@%'pz7ٞhGϭ]C_EzmO BsE=zn!z.knr#~֫:ir¿14Ke:,ۣ}m#B\Phb"q={ 2&ǿ8\lsi$ ҤG\KqdGFzc z#W_FUeɊh# x@bzǸVRKmmSjG/cc^!aUԹb3zy.;j.rmzVԽDcL6i.RɊJ:\Z7,ޑ l7 R# ayO-FՁD)VōF|쮸} jt~E<ӖwcͬU$#T 1ғ񪎞p1A7wa}#bz>louO} Eol+Bky#.U&3ٯ˻I-Zw?a@`1B:Ah*PxHJ~)xf `wOѣ'N;NQ eԎ_fgp;?/ݏ)[DS$CuL<5Bɧ^cX 6G[^COV{.E_hD[騬g_l9GHI4YNŭAdYϵk6}l}WJ7B5VUlQ6s;tgShX:]Dc^=Tܢ>:)oN^|&ސ|X:M#lݦ{#֦Rh4!= sztɆ]]:U|?G[&-eʏ:k/lpٖSAX/戏ds96=޻_Ďp_Krwѧtqyew܃~q8e|#57x> _}xr:6O#?Żxקz>PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%' iZA(aŖyV>%ϼ12mlX<},zur𰳽.V3zެA9'2NbmWcTUG\;#xƪͫۋ :=wVrQ1^I@w+>NUvag硷zB*u=[2MM&+]Ez%i¤CbX8ezP5 IsqrFx>;aYX21щ9f;%20_pѿ lwU/.<373^PҴ2 iMiMFʧz ݶYM]ο+=-ѓcÕWZz1ǷIn9>a"g^ ?HeۉTuT9=s77/(YȣwYz[ޜ"Bܛ_SuinŻ𸿓aRk j7KKwWK+r&IJ10+2k,^'d~4et_x ~iޛ*>#VFG ko73ۭ_oYtXX 󼏳wl0(; =F! Ԟt'ϘʟP WU4.b8/zewKlzqHP!r6H1,#-aE60q B==SΦlA*erߊDt>Rt}&j3^]Ү'W솗ޡUOwvǝzImJ_YKK昽aI! Lxvܨ+WL@j͇f;g =c4_ƯUbn/*, z|Nz#%\eZw,z:- >cqm"#`)n:zE!#}ȑSDq_''!'yJyݍ1(󣉷8\cwmIRλh#$^bS%o{i H S` FzVΑ ag78d}m' ӗ؞(=YghTг2E.Ez'ah7L /Gc3l-N])P({BcJ[l(2KNeqn3+K:=q1 hDb>a3z# qJ`)=Ȉ2tLOn,9YoQiﴼbje &<^snS:oÚ R!s)=Zd@٨'ګ(y =RlϹL؎h'ыQb{e>(W HMQS*Â3iGsCA1=K< ؇.7HsU^9.7Co"_lPއ1E=&Ff2z9"}o9QzRk`8M#!bL{Bo֨6YY}W4MRJ"~޲B=iIWuMmsK)䐹<^HH**AP >Fڮ{;lEzM'}߉xf{[<7[h{@9;w%X6-ڞC ^P0|`c'1ͮ1ǽ2zc3yb®(+=w X$ƽ|#]'L'HM =H4)\ k.켻@O\@o18^'0۳Rk!n;`;z)\#".-(!ɇf=t((E{WXk@o)CwkYlOv` K=TxȾ-BOJ/*z]#Dz/ /B3Ɣ ez-|T= a/å  +8i#z;IB^(~D`9yWxSJ$^Ѝ@rbVT/)v`{Uvmf<1U1A(H{5>\pLE&z,ѾgA)A^sJ\c'm1-%nꀸ=.<=pۋ`F#=wK0ё@bYrd!c_rzWRp'CROG/|6%ùSli*cضט2л#Nn?ƽB:sW^b{tQ =$izP BP},ٔ[i?O 9A#=CrZ,btbHdV64=Z1Cm;xGKZ2.L]ؘaPXGo-CuFν:IN Wp,YJ]ř HcT0;&J1"q^1 =2IOBo#lXkl`OG ϩ'?vV|BZ{yyܞtjPth;eNl7-彆4yFڰC>:MF:%ԨxBOFGFEt1xT=yd'plŔJ1NjB]2&LbwIs!%2;zE-M?sN"-< =@Ez2Mz|N5ݱwLK8;++=%@N^0tz7!U@ ! ^B 9o>r{OP:6CGΠfUv[z<ڨrkGQlluFjV=^KqOVu*_ v!!ף+' ܼ=Lc-~ ,hQUA/3RAxKe\8ߩ\rZ}m1 ESڞ$|\] סG~ͥ#nXs-&aO!/H#Wa{<4u![,(VkWtQ =UvQ4ًDAW% p}Z ϗV n@+I`>!MK<_U}<}(z2x0I4_K+FJNN>A7э-mnRđ5C|(fTuzC=Xx!þa/C!J@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%ށ;;w]|CS]zvaJz7%\H#{r 벸^s۟-eV{)PYb*+m]Sez z]d[W3j$ӧal~/{.uxQ<_ cna5.s:iqyO?zu,{pU1$Jbn|e˽SY\oQẒzO+7W)efdc>4LP#Vxy决|"B=w,ӛh]˼bqKUKwnZz ޜ^?*񏉃8jy85Nᶵˌ@/Y]K9BA]}x꛵Ge6|vw\z\&1|Oq⍅L)}(e@=xccc{o+G?VZGZ±> ysoFPV#{5ɊȠϢqPEܒV<~ nzz[Dׅ15FwS2tҀ6xW17rGeiK[Oë ?}2гŦh _Po9fcG. 得 {iT)ˤ b5QHٛzkaˆGqC鿪5_"b+7So""W11A=M"`8OԼ\G@6_F X;ǿ*v^E9QcIBVh|!.Ҥ,-VFEeymAVZ-GmC4dHz(&J"a2vJ!%T$R[߁޸p-u"[c"SL_9K6I-;X"衔6:Ԅ^^ H[UzeGةre=D/p8}hl(\?"iS"|)Df!*IR(io)=ۃB^ܵI|ȈPm#7(d"%J}QIW"{x'UDq=BoIJ {JN[z6?iÈ.-r3PF<" Q@Q0Y-UT>{&U,{ }NPv^5vPlC8ȋ߲%cww#zQxp3d&\}!er. SHK*tF$$ڒWd{F 5zG-`^ zd^Q2G-u"ۮ"y>"&jc| 9VܯqKgz|QۄGVgwfGYqA/CpYǎ5dk@BOr ]umGzAPj|{EحYd'X=HSI VPݵM6 qzѐ56C4BycNT`Qnժl)6 18!2hྫJf.=bJw vǥ訷Dc[<܊CHs vl=stjO%8+(I+-8~AN@g{JѫM:lOY!>k]/a6ceC#y 6;υ0> X[c F,ηMJcbz#iqjտat'Sz=ҁMפs G߳%k$NT'=y,V!ೕ虎 C6 R}COW{eaJ϶GP9=4MË[B9V4/Z.i!wÔ\{˴AnK`6]{)ed{jˍev6 szlS!+'z|ϒzRix̖_K"O < ni{F=na7=ƴj=%p8yݱRz\^GԤ !!c:d{e"]3d캴EAy=\r5ftTZܡfP o9#P KhY(;Y s7۞d!A 4?]֨j2Szy8' FI탖cDkIZt>r Gn~ԙN)Rs3u zb&*5zX~g{|=:ӺWt9I &zH92Kx"dg^b[aP1"3 E36orA/DI5޵|ACԃU£/l!+j /ڔBp:edZW*ٛ2/QyhԿbtgxX:I@e-sL㖌1B?rX0"?(L!u<7d `x66e˹GǼU(/9`_0/JԸ3u-G8P5OkWd2LLG=7Sܤ(&8S-FI U k<~Tշ%McMMu}Y2QCO}p^I?w #~6} JnIu*ldKk #!߼e4rJR"O-!&DWq7 -<)'SrOToУ;ke{==(N{VfI|Mſ~*_MvHŰGIsW#68,~~!?%e ixDg0ZjKp^ Oqܡ|iӹc2o_3?waq/~vT'lN{D>^Z2E2KE/OGn1 Cbglϭ؂9.F0"ƳK%D]0-o׈81 :hwD7&#zEyzžy=~V.9smy,65-#%8AըLЭjfu"KoAG=I;z#5J+ׯmgDعt ґo{|JYW+]ݢ'>Ǟo9nr/]Ϳʬtq݇P/{(.I,I@?Q_.Js\ףG"H "H "H "H "H "H "H "H "H "H "H "H "H ׮µ^k,Dg{x.^QG/6|u!S\/2}pձ\k[޲~d c\Wrd6&CF!dYzlRg^5~w=r? Yu5nʄw.L]vR]p 4١4Ci*Aʴwпt2' {5wѻdyO˳ i"L{vvyy tvk5zi7~.vL[tv75zxކ6|zP)_X>]~8;7Yci3bW&}X&b:ݕ]d{/azL0w ѻ9mi]o?^383#8 Ksz0}vcsj^˥l9kv.~e—a-Ich\[99j>cVƙ3Ki/ٵ[q%I^aj^f0L'+Ǖf0Kd/ =4"n3w?3/0]g{ 9nuKŦbBH8&>r#?=?e}:2$c5A2w֥S&BoS&˝ϗ;uᮃ70]?N2 붸 Ǥښ)8T+UCpИpE,L C>63t˜ SdL&gg\sR4T93WGܳ$C5S#a^z ݼ #9e2o1nj?u; ;SU_ϙ3f;ʹc`vגzA2cvr<):$3Hc4ɌP"}q tiuo Tb(ffQb gnjD<<(ڳ/|DSϣ!W Y#_Y2 DPزy.vѣߛ΂ҡq! J%65iN Ygjn^Cn>6Z"$Ž[#p\r5{]м\kڱ@= rAg="B,ڡizlOC %zH?(DSe'.@w3@c5O0ׄYTF7mT~iz{aB٣G#ƴN׏퉞0dѽB/Oi,Qir@ >ӂ]N7 ??##$ B0 ҽ5^DŽy3~먆=:~5Ut"ˊ3%*F`=}3 )Rpz9^[`΍&(Al:fWuRH&D/=j?R1 FxK'=:&W窷0 &E2l]RQjϥ7Q+z nI f܅z}r`pt[-WܛGŨX ic%=1UA<_QL4tDzx. Pk2kO m"^2L.v9*W=Oz |G+\PPf0 XHAp! F0}D/H JmBy숝jD԰,ѳp\iOQ=\C^z{mSBܓ{z3)Q 2.M%ɣ ܒ=Bktn{D {;M" qoB?RS d~ ޷^h&՜޴W',$Nc_~zۛĔ^?;.KLIKEā^vH=ru:zi=fvy.gߦ `{? / ?'8S_G=+ ^%zeOOkղ57Le nN82 ?I"{I63ڴ"5[/K[4# ReE^=\t燸l +8hc4;R>O8 ӛz006#c>d!VNO="&9=ܜ-7\t@zIsce{nIu̐s1ѴMٜ^Er[/;=RZ^^Y~e "CLcUFꠢG c*j R9 \܇9؞UΥ=3=‹ךyr@ύ!N/3 ?ad/ s%֍hԾhYk\g!7l@f'MzjE{v+u "tʤ]M8isCP#g&OJWʔ3" __662۷Xx'ۃ?b`C݂@S(~OK„*z7f4]kYc ?{=֜[cl&z]O %ana8rܢ!H szXY#sm0~tA'}NX*p^fJ)8.zx7g4#A]e(3Ă{K^M}u˟ *xsA(yL\lW&yPfk=\?b\sot܎yDZ`ڴ4YȰYV>!\cdS̘D+U]7J6S0*HBƎ[O#]lTaEgP$l@=Ds[+Yz*6٩%ͣ^_7ݼQbQ69!ʤ4c&-8iЏ8'eks:Eֿb*k)˵o*?;pNy8`qUHB_C>z4Ыܡyy$_b@7I=QO@C@C5Q׷S2R\ |jYC冞K^yIGa%>)MR~S_Sʴ¼+GbBQz+g47mz_\oʷ]j5ѶX*\~?H}h}#H "H "H "H "H "H "H "H "H "H "H "H "H "HXǵ_,awWb޾;/^O>u-oFBN~;mmPǏS`y^ K9!71L!1BU .Hta  s.[<ґ~2գ.&zNEswWPgȳLَKnXW\Lwl[cIźCV|.,V6c](B ފXR^}7fG{vݦ5L.>H 1hWWusw>r~rt~S_PuK$[apW7|i+IϥB3r᎝5`*BJj l=s73\zA%f3/ŜSwJ`IΌލ SVU,le#MwBj_t[w)ېɴ7hơ0ZSʱ'+J3"?K 7/s_v MC N%[S[7zg)s]!$CY lMhCI?(#< 5<'Y d=Sc=eװaEv 9 hP@zTۘ4?6tli-WcBw Δo LK5;Q =z/x']-^+­b!Vzjt\Ɩmpӯ@l2$9El<zX#[B)MCQiƠV&{3#c?U[+z-znU_Ân5hտj?xlZOX`{f=(Rs4G(^<"VG#Dô,M#:sDdl`@?ƤHui^"G=(|P~V7mȑ^8K_5h8DTD˴*W(cŽ%ϵy'c:akE!\fy mzܤ"K"UeAMGݖo 3Y#3gΤPߧ:HD6K ǚ,,JZzEyKjXx=VFsVFmR'TM#Y-lP&X*uU|:za{Q,*( kA:y]S(q'D'm ]^$|Ve!pa 9oemaNH←]?hSu҆VG#$УsDJ7V5x{ U{p/tO]Y>#_'>C)cqڎ~۰Oȏ3Qt J1A؆׏=0 jCXSfBw@py,m ^W`ȗ㑆' M<1:2o5and^ogI⧥̖| 5+;d.XC=ۃƋ+Ao傞h @Tr' '/U08U>!)éղ9b'?~^>gԳ}\SPsJ`y2ԙ2c /3fIVI3j0|}؃ `aD5&*qh\էcju^׹~XВp[";h3d4>Mn96{=#MѣD s'ݟoW-O.vvk}*vўJiI)PgNnun87w?=2yz).gu/G*\oݍaTm?3tr jKDj\Zt:+_S{CO.[Tf~A9u7;-dT\#$Q~Ųs#MӁGɗq=|ubUx?z<.y%ښm/6_hx"=[N'+?l|k= w>'z7/zډ.Ţ3s Ӓ-ފWp~ܲ3s(4٥[ڕUz>~s1rbϭٸ6`.+\Lx^<+Y>nuisKC [Lc< Ƈixmz+ZYZ,TpQQm_>3}+瘭,-, %Ӣ6+՚~݊텩|v~ =ە=fN^d D`nJߘt|3Uu^heΥy.RT2gT݄^7Uœzzɿ=[c1$m0g{<KDjڼ)&+t=D}^KYs\7*Bo`/)+{dG[ИWhr᧏g߼3Nbiѻ%3w± SpN9s_},gMQ@QښuCE=fd]MT*>a~ziY)ahrokyf@G9s0ym\wvKg@vʫ3a#"ѣo^0qH7|V5CaT7@bcs07`oܿf)&q+V ۃ^g^@/d'^lm%R*zH|/bAw҆I{k2c74]طR.HP|^Uz!'\l/WR~t@zz@q@f= ~lK`ttCtcDo6Y{yM޹R$HZvɾqIA!ˬP:sFf ⹶޻A:rU{ lWWpe@ -_7̮'KqR^A1W#%DV*'N8qIPh =x!#==ٞei}6MpY.k ^^/9co{AKb0$'\ec$rI-%ҦP43ֳŽMv:Ee`{UX܋MTÎ`Єn>aSsa0؞9➤sEe^ )$Kpuʜ^cl;ϽgT2e`,ɳ1prZ,jZg{3J9S_BoWQ7kiw3i{=#yz.C vwSڹVYֲ4 i$laq{zCc{q9wb)3&[>+T ߡvҧf  {fNk@Fub?W<&ec~Aۃ|O Fj&ۓ 3!k7klJbƒNua7X:݁q{'qjFv^ 8˹H={\)W w!i1N]^0u[Zb\Cę@OBd'zZy.#|CbVaW|rSd%v )K%}=ǸQ+D&4v8**+^h(ݰOo{Ⱥ SGQ|YJ ;#[|\ـtimCgKiXgBDъFs~*ztdǒ˕{lu=) 9*} ` Q,yXm<Չap^e)0Lx"6MhNt{~Whh%C:k;^b$JUCuR;)\vR: ՜b)pv!%I..dŒHry/k<9ǁ#`賣SQɭx5U'kGֵdYáݲg3l=ms?q )y3%>Z&!PI -L"CaaOrPxDgW> u/Wњ5NWVŅ@5:U} HD| z=9[c\=e3p-ʯk{/Jrь g]z!^~Ƶ/')e{ʬzn;~հSo/}.N 7o?e:mL%z_j)& zYUglw\Mlŷg7Xa}B6\ԲwƬs,Sz^~"z̯I%=~1_s_&Δwڞ3ڍowƇW&k/7foqG/eޙ/+$Qz?[~U=y+kzsU^囼sg8fm g6l*We#߬^ZyZטvYЛ֗wA$yrז?S}a]ZiK9/6WP{1۫92=3vM-tMP[wGz.1D!1$ȍ!=/p1z@e1m~hƓwy8z/ ךoSe3NqZ@E/i)U$ɝLAqnu}񮜻DxZ;&˂P?.j͸qL@&m"z} ]z6%.Mb{U"1m_ʽZ*|쮷*=z99*MYoYT>9Q6y3J$ӒL|saqqgIzubEBKbʎЌC/ȵCWnX/ =0tvO- by%pt2LH0#,3~#_WNULimD1HW%yqw7v,c6ɱߩW<1E{Nrd.Op7VO c͊)Ѹ2pKgʜM?-my'FroxBLorwIeJ5d}y|yͼ= OC+zzʜmW JVMRMqOmMJ'BiuZ ?j6''c%ωbPnEqMѓxG_Z2*Ya*/}=|(=i2+qX6=5ZӎIL܍ؤ,5Q0~o5hC$vB#c{\l,ӌglH\8l{;z?zgzzVwE{_M،z_=lދN 4-wG-䶁^V AAOh[aIlO8n0F`}*q1^[,{qD`:zg=Ц%JG8"ݳDfob<LCn^uLmOHmMӾӣ޵ف抳VK\.4dṫg&w1~ٴ=K ݻpLI]E/̃:3cXMˎ^*zF辡:KHORa{>o8A5ڻ1j0oȆkZsL'Cj=}9[ۿ/̕U z[Vx{~QyloW6@3 Vfbq-uAIK }P{V9 ̴wƜ^y(zRm:z?СZ,[M! SsΦ{<7У0?':=@T⠛%l7oыьz!sdd1]xn"%lco_n"ͤ)k> =\^Z5Mzvlu{4su=9= ?^^ЗUeRmx_2֞>zzKH3ϳF{}NE i>kaζ}z *OΠ'&\ 3,8=O7玊@/2us驅g-{lHQ+Y~^߻&Bgh,#TxB-KG< yerg\\' T7dWlIGb0gda#nRv% }wi2tW>hQ3k_3pn nW1x+bkǜaܝ-C~+82=/zuٞݵM/:sWWiu>~q%o{sqNr9;:/$oEP6Wm訝S^>h>?Y D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$u~$'/Vj+{}W/'`X~BT9;R}m*;_ympw0Do{ ^;l{a.וڇ\E6cXw*ڗMHpgNnք熅K>\ Cg3U4{aѰw;K1|X?^47]0|] ^ 17,i.VE}rP~o l`o3|n^?[m,1"6TINk >,f̳9?fXޗlOpUbT -tӈ\k_=&tv{>*\ z {>,^kӳ^k4e8vȺ\s{&Pfֺucu8/jTL°?;\lf 4ѳsGL)mW#49oyՃqO ,c pt7iCAen \T.DSsvK -ӛR3AwXJ^$aPlFM&D}li&63mbZT_m3ٹP_3#u+b{g7hIyt߮-r,?Έ !hvΌד|ZXK~>C n5.lxG;!@l{Bo#ao&* l͇O^1K>jٴ'szDGIWaqMq2:G4fL! ΒŐoBdf= BladdTܿ5jtXQauI řzQwv>PʟrA%!̀^^y_"Yee +< a~5SCtI8V4"뵌3&jhҷ'5y_O qT'NjK87X*.K@@JO+D0嵒sFp1Iʷ٩,Yȹ `v'E s=5pjt)%# Ԁ2 JT**sw7z|\@c43 1D[!+a8#ziGOaF6ޤ\HLdat/q&7 0^NG|U^ > m)/~Z r3*8XIʖ\Pb$\8 2l;zC3$KO^xHRq> z2@C//OX>nfe#m앬=bdcZeO~I&֨A#+?\BH2j;Ֆ I. zBH,UVq1,0֐5liu_A I᫧) =5.kLJiJyI=4`OgO؀Nއ-S=r:eLOqWCQO؅ZyG︲+kI}jA~A0CWYL8bgI*-1У-%1F*b V:W!73HY=F![%Ֆk*LGϠ̈́-@e뽜dϩEC՛\bY^ũ*ɪڭGSDfkKv=k3H_$ ī%'52O+z%XBdWKo@/m<b7;waL$sz4Jإ =e]0p5FJ==n}Wl=sٞ+&zトƹab>v[LhK&Xcw F`)wTQhEAoa%oI~P-Z s\hOo=3G@=`]%z7ޤ\$d{zMKX Fw#mɃwyMG/H'5RY44Δ A;z楌 uM͸$ʶse{SНw׀Z\[3r͉59Z=)E׎Z4ᖖ;2Ny{tjehw-t[ 7\4tZ#a==:Ÿ|X"a枛 ^ڀxKYAg΄we{ :e[pxn*pC+f#1mr#Hя'$s#Za}73AjF# aGJ,DŽBoZ&$DC{O9HQεo,}+hxtkVf^FI+LQg5&qH$~i _1P_gr} gnG zcm/l $ԷDVk38[gB{P.] N =O]rnJt.am\&44y2zշWat)xOT?"CRQ=e ,>s=I-{}{WnjbxX-Ƞ <̒M \,:FeZ t^cz`0 f7+ICSjU?BR!M) =#}>Ҵ=cUKK'mr+!GAa3v"#EKIBZiՆxb{g7JϏLoCsGIƏM{zYqshh_6$iK]K`M^8Ɩ1Kz.; ӏD2-JZnPMpL3GF&dQǺ/RF~83&ICct\T/>elc8m]ժtq&Kќ̮?2BɧGSqo4GG| koѭOMQz_pfkȕR-l lG,j3 HMUߞ`nY_X]}ue݅zIWVS 3Y.NOyf(])YȰސg1ϛzSW][D?R`K;9o~\tOlgV֗W{gf%ݶc$i97>^6MZ__>$%Nh~$5bg?eC~Y=s7U&ڸ^6ѳS c.6[JUwD46d?'Ƚ!Xir_Oc{'x|(Mwy=*|0G/\m%\_mVʙd(ڛ* i>I]gV)YkϙU+Se0ymEalmiK({(17QsB#`(wRTLoHcO&@ _ ԁoI IP7C5FM*sI6{,eLgP|ݎ2j@ixT]^W=̔BIO7SY3TOB C@r&Hs>лlo u6vLtмQ!1dlA5RNfO/&.KzRZ`ildGŴoP?mx[.=|{a* zy'&GI uب gVWX'f<51iow҅SkL٪/ݎGpGEG@U9*CQ4UؑyE+"4XŽUX^EoƷIgv؂nR=w)i_ʟfze$ uY)@mvSc 8 ?Ϊ(@OzL0%0++Dxcۆ2U%ADbRX9%H"d;zALg>g=72p`{d䯩-HA8 ތѵ('1RHZܐdTe(y`nI[7 M21'YpS5E^@oufW9NUz;lǸACEE:/q:z) $B|*I1.DJ15E?5<9~!z`JFk=TE P"zDK0E,{ɑ()HKfEfDhHuEovFb+6&8~q-9|rcB~Eu=\3?QaMy.kN^<"^z>NǢ7~.`{=E:4ȥ:; JΥ\FXqFߖӐtD Hп-۷QteQR v^KCZ~j{z&zS<ש鑇kF~7"+?)9W& MFjt=d\]ܛ\.YEmMKۅ^N Cy9x.;a[qn $5k-wJ ѓ^g)qu)Ӌp?s& km턡͖(L C.9Л- C϶ e*:=M-W\!?[\(/ؙ>aM"?+pX#hn-#"rwI%)@nj1W/+]ʜ]OCtjcq}B:W2l4 `{Վ@/5l pm C[==gUgEr{Ϛw{wFroaE?P)r1`Z/ Q2FRν纁Paצ }<&fkٟ-Ě^:W-hr"'w+aysëbQvhGA겔:\{vg׿g~!vb8ySPۥ _K¦O+o$K6:y {_[.f7}|k=io"ṕ^bR>򔌒Uݫ%wx~V Yalm]X<'?-;,M/MgҺbW^6L3g"LWfb>z.͒jVrfҭTO=Uauxe<\Oϙ zz{v`d.~b'U@_eӑWަJ\3%?m:PcC.P~ c{RAm\LaC RiPjPo|ʗ+{~Mv, qk̺""H "H "H "H "H "H "H "H "H "H "H "Hh=UkRܼ5 l3xnLoDmIJ\z0wdej&X"XVWj ,.F/΢έ[6ssΌw޹+{odKCo-kĸlc}gmbH;(&Ť 9Z4 ؾB/k{5E`^ۂRkXu05Vm}0`߬B _dhafeS ؉y''ÿ'2*룋lrȮaG **#"ނed݂ҍ'.:W̜Dc,cFYl1Ḭ̿4%.yN VHO st:Gi E 3nմ+qm ` F#HKPU3qZOUTޤށlP@-49S5S۴ dv2ި%У>(2(p@O7%L/Fzz#16?x!b]KJV?GГ̊Ao-@{T84-=%-IBIP˻ ]R,=z'fˢEi)P*`h-7CEKؖ %T erE/R\5Zi)sK VypwB*!eBңXYs[%B/1^/jo9JMk%Gz 5(FLZYО[IG"zѐ*SдHr#5",'s|۹ =Ƀݘ'Ry )+@bR٧gzTT K{!bOmKjAoO{"{} ?Q8!Uq鋥Vg#w*sHi%`=eRx(2;T5V;RN9;YtoW-uBxT(irWԼ#yQBKMj[r[u/RT| 8= FitY*_R;.'@j[~~s =w˗1j\nÚD 7"H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H >@,»-AjeU|L~2/\Rb?뽾/g 51izQ7U @ϗvi/7Zͷ<_̟,^h»>wX?zN1mWV]fM_̏yu5zίjrz|5 [R{˷{79.Wk^9_(:]H+5ڛj;dݩrݡf^mD/v|GBzj;-ioBz nQ[ ^Iċutu4/lNbl8+Fw{ǾN‡qÏYWu2l[EZf2qo|zu ] :WuSW'Z̄^A VV)]+FB{e2vp3m&`;PmzoeI90#BR:V3w2s5e sp9u7acgM&rʧ6E}YgBo\ZF%j9^I3@2nYd/w׿?Yw= }¿(*{=~C&YT:ȆI|Qf-/ O4e+H{_@dC B֣֧wbn|m\FMZ8%Ǐ3hWC|Ύx5Dp& -~xU|!Fk0mȋKި֮4o|"W8Wh&xrٖ&!|!DU')Y'uut@Uz$UeީAYeGy~m[О^']ȕbS=RBk`AbTT -.$=h9iufYdC8s_'T zC%U^R4 >PO ^.޿ T$*,-ʞ3Kd襯1Zݧ4Df\ =ď*t@/X4 @OFt ñO%&^(Z'^ iOp*QO4f_\B">iͬSAk^@i7ڼ&Zm頧+ߤгa6 m8xSI+.FYg GI`KԎG@/kn-=g=RI7N fm) =}ާ'!}/ Yq=ՉUMP'IW{fH:]U*=I=ء{xwo蝰Ռ^,˶9xHBCBSz\z(p:@oWq%N k̝pTaFYϞ!KoGNsmƐkovm\UOk42zW6hD{do?l.û(X=~嚛x.uK,`9;,lY$cd}z!Jǁ=B,N/DJZ}.G@Vr.MYgۑ|,yQGOvvГҺxF~hs#TõBe=ĦrB:eG3zA{zddNO,wJ/W8ZvLsGAoG; P^ؙw[D dːĥBte4z'h/]רihұĚl{U{szr J=xGo=fq۾=5Wp9%8o\@ gZC zjzV7^%cʒ#i dQi8 z2E WJԁ^">KWB,wme.Hkd S"ỵq#zBOȓ i`KOTM%57 D,G2BOgt0򚾆iX$āDtLѓ &zlCú5f~CPq@XeОN^|NalٵV=1&GvGOzu9H~ NWiFmgؔDF.߃R!EaB_ș]ujER!* fB$>aiy$gOZ`9]ur˜hOFZz_xv\] s{CU{p=i} A6ize0MiY_C:y9. p^{/9z*pk/ B'A~Wu~o3R"Gy0:*MRc/PXsC[X^ =>{$; ?bK&d5i(A~z ) e~a'KC;Pxux R5wng9Q#tUK{! =퍄aa?Ӿ u[ޚd,=-yzs%qЫj%!ZTweس . +!ܜWiC)r䱨wG53zD8ߙӟ}}:1ʥ zN18yJ\Zbg_J'1P:IbFo"|ږ4^ۓ>'J Yoz(]2N8:rcCXu6|F2& *s& "cv.#֬o%X]/ B9[G~Q>)֞?a?uYUcs$`p-K>wFo<$;A ?>W?4@3-STZ$(v =`ӭht߫=l/:6o_HyPl<zHTJ6>*=NqPR_nГl=-sNj8{y7=+|5{}K /Y y% Hmjo놗 mhi}ntcxxS#シN._{lǷz6@gnV}o*Wo7цktZFͦqFfq߸2"H "H "H "H "H "H "H "H "H "H "H "H "&eT{Cu^^@yˤ$,-{g` )naa7Nm9/ow :_6\VތUu&-Z.i6Ppzʛa1.`өf k.5j]z`LF&l%_\r`^*sNoj_Ī曍~,FO]otk? .ӞO8gcfvUs lًGOI?˘S" o%PLK*g Ë]{CxOUzc*oSP^7C3n[7%~SC UO2c.UMeFP!²&;8Q"qR|VarP+7ůz=V=ΘPiKuBwP1W|Sq3#/e,`n-)3HnK:W (}o2y^j㚒ܔ˩:ڡ[= k_g@ YX-e(@'.+\HeW#"nCGuB dc)gIZz,ajeF`|¼ۆi˻:-4sI;J-j)P5s=zRa($d-Sl%%cqz}X+eRW&ݧ!+y^[1h BSz(M&Bis*W;`ÜzR9C 8E)Ua Ϻ%~7m'ҳ3텪iУZ(XR_DWg_COj=ZjN3zw+5;JW\)&"~4$$ Ռ0RNIYWB~ޭ%jңd=57-=*_نP'}<)en.j,7s6W(`Mvѣ7աңnxk*H15fғʜ!~R^5)Jh(=j= HoRgFPifQF./ѣ2z'-=4 l#8BϹQƼ'KLaד'Fh2P%Szd0; ߫i(#;}΍7XZAAzqSz@OLI*C{5U}EBQB,wN^J76Cǎ)j4.2gx~.Lrne1B#Y,zN8(3`&5h3iO Blzmo7l5w̍Ȗ {B=*N{%2E{CF2?6Sz5~6Tu}QYA< PQ9C? c՞z3=_']ˣQ:zs\[#J =5) _3d#cB؉3%4 ڃ35PUʔ=Tw5|U4uIPw3L19tȄc&~/=ay!NQY*c&лK)'H;9`QTs3U=̞4]Ams 4CN75-ڗz xʓЇg=zeb:iUsS'C6a6")='eS1pS7*b<=*=F%T4Tv͕y|^ o@OMJuɁnb1׮ =Z[Y7<:(Q VB!@$f^ =Q>u5_Y k*66~{_޳b b#gz.qьtEj2Rkn%yyʢG@m[G/߃=D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ \&~P.]37SK"OF.);z2cڿ/e2AmJWAoH~oz`"cNKZy(^هV{LU|Z!duK~?v̘"nҿ\."i5mf}B糪~_t@w?We2z.-e>y=/o p#hϼ.PHW'.*Fj6aV %5IΤ՛@e#8*SkHR$* /V7[ӢGF )yp`ظzbUw|*D'ď&+T=Ku;_ VuxKJ^%ޔ%$koԮ)j&&8#ɫ="+!|SS VB&A{buZl2{XV4 ID`%4+̡Ƭbj7%;g˯劄 %>I :zZE%jB[uproυK UhT#fBY@ fMAI]UԆXODŽCſ!E(]Ys$Гs[+z =,c =O1;=R)0S bZz$Ԃ:Π\z@n=c{ô!'2IH.p'EW|VlE̥cPBns1E :LP&3hoFoz=;'~.8YxDo o 􎩥-H1BI"i6I4RX;G"3[Lo|߭*񫢊3@*лYОTlnz ۷Mt=d˝~^# Ze$"]ϙoA3(w&m=Е[?$tV{h/<;\^-vfz~%ii=31M3BOdk0i"MHuU- w 5P\h-CtB˻ CcH2d~8TĮ&"q2=}G:"K'>tng9G[=*\;'VXXWBo %iƂPQwt-ړ-X.=WvL1,aViwA{E{3zWz^Sz<˥ڰ`sIJ蝑25s葠흊(؇.c!YiImI_Ak+gԒ,f`H1 z'DI@+nJ-= KGz]L n^ŝ){-8u|#8{@[,W #{ҍ = pg}N^_jwKJ>=e -G=L  VVi8Y efvY4΀ko=hY7#{(QUbd,r?Q;z%.+0[a*ܨlTk@qq'q"B8N,2%Zqq'h?]cW0%c =_jC(z|Y.pND^4ߒp=pwX.FJS,B %n M|A9{FJ@@% })"$9 ~˿JZ:vq_V;BSA zCK sč\Axn%ͅb&O`54&YgK4Myĕ =ydAbBV+?ץzd!lzpY 3zj5CXc‰ooh/_I(Im41 L:Tɠ-%1剦mAB-W0ROJ3GRt I< KSzt =g_rOVCxHa޾jOɢ *U 4jㄘrQ:A%2+3ؤ>c8F VB< aOɚ݄2r>wcmz'8٧0Jפ6gWtydJU$*K!9+J?`U_xD($h/'A{Mψ9=__2F _z qz@4BWiOXy@ 4yf(ʃ%jBo;zj\%zg Ն$:fi qy"{aW6Г܉Ŋ aY5Mk>-${m4}ݘM_Y'=__~#fWX)+2b3P!Y')#+}Mk>As895; _[0@6[JaH4= =hv]?m^k wi ڕ 9~m Fi; XωG4XpXd 1m+Ngn@Oֳbt= bēCOno\ z-{6~q e =uM^" A}Ijޑ"7[򫏵1Dz sz󋙚|ɺW54.wLo5_ڱ]K,kJesS]h϶-퍧zws?˳;k-rȧjWĿ{v&'*[~;ٿ_.优bS&[ӍoG -{ƯѥcY>]o"BYb"H "H "H "H "H "H "H "H "H "H "H "H  nb꛺+e*_v,o?t D1W jWSmQjJO3U̒q8^RPse\L:O}%l&.) e" d^zW9W>:OZ(EǦReNo39ΤF1B{nÛ_=nfW9< G;3[4(V)$p !87߶ȓoiܨƇ}L6UZGʼn̺02ePN.,ȌyѫB oRCa;zO5_i@#G\\K҂{sZJYYª` GS˕~G *)2BY[- _%/WǮޜS&= У, tҺ)U;i(eFAzP*ِﺩgD'Yhr[no;O/dBU{-޳)=n?O䌦t=?zԙx 6 $p)S+2RK#@ro'˽=xf+? ozLL;^2g(8,=d=C9!Uq_ql}N ~_qgVNdA{BONmS+< Ugi`]G#Q(7;(џ_?jI&27e9Yn˝$%q4Kod۴y7Tt2˱/0x&K=^ΕH7#d-=rac/B 2GO|-.ClNC@;S$(8E m簨(R XXs]H5 W4%?NwܷiBr~[鵜b{12C^z%(K:Iu^Z%-#/Uׄ^C,ۖj•KԘػk ǘ.;z|BОəˍNtBIl!sWB)kg*#@/3xQ؎̴R5N)ءKJ>@ (p'57Ϸkoi/k'B2ő!?C+s Ph\;z = D'-R1ŗd̴ə"RI⸮ ~j׋% 荰FqbD?BJi\ E{ EeK'y#DGRɞ?)3Ȝ0]e9w=r--CMO%6~SY.H QzpBϧquD\蕢g唞AOY.:={cd&L<=>ҼG;iDy$RnzMҨC**?dbC{?;zV2zjo-'>R!:V*؎ў#Hړ;Qvs~z؂gSzDY{ 53D?HgR!Z-4t8jmGfsOɄR WPeDK^=Ηqz'YЀ$=[ccl\q{|Jj=X(AUW܈T Ы4N<9۰EeV*9awKЫeSǝHL{At}InN&8,ã rV)=\F*=h'zF}1&#!I*r)B=M$J<'ri/FFQSGUr~e"c aFܦ$c\gXS9!^m!qcIv+D".\!Ezg!uJ{l@HxAƳ==1sJqz>\*3ɨĽPigo3zr1-=;=Y.eZdt"Yўp`2 ʞ;MGj6S4? ג7DzڼOx@ZW|e1P?SVq^;=.?d$kዏ^9jd@=;-e\\p@s[z:푱=:0H={Bo~핯r4+0z\gM#F_7d|B%R1֣,+ ք|7C听cJ]AF Yho,3{=zӘ+FwGB猻Є^׾ ,x=z1/sУ5g z%JoB=zRX25@ZȊj zdW![vA{IIԨ~B4+A/Sz'9J<|owߪQQk,d} =B-AWW]k| )ơl#ӛjSOo?0GBO)j?"Ut=:$[ڴNNeuD\'cQIK,l  !ul=ّ |wx ǟpyG+=l`p-EK]$|Q{:![Ƈ(^]ٕHYuZ';1!I [MrOքm?,mF _)ўD Ahbko^F)>6ݠD&}@AVYa ĚK~ 9!y7let"rgGBMK+uHϏ#Y?}dzׇ?QОB:tHL7[Fo49)PC8} G=;8hj o/?)4wpx\b$|]\޹H?XzI`\Ͱs`hG2zSJ2,ۻXqꓷGwk o}'WEW;FalʉzeG_ }}++l-rW6ѓ):?Vm^a[gT3| īum9NY^{{[m+iO&tsO7:ͣ}g٪V̲^=Jm(6lӽ7+/I {,IE2;z隓mƺAF7js9Z%~V߄oW,Wʛ\NoGui?h3Eznq>ɻF&O[Jw6[~#_H'Q x핽WiOɌONrNeJՎRn)%=+ӁI}p7Nor1x^akXsW܊/!Դ;Wn=g,7|uTK[EYA{&\-y~lWҳA|O65K@^2򅲅w*5XWȫ=;[܋^l7K>Nh|g(Sgp9$CU Z*RĸE_dޠL|Nv2>Rp6TITjp g=I^wï&l^o :zMFq^iTT $RxSItHp)X;U x(u=@[_BćГ*zې-Jtћx,էҿ2 HS-?Nld`SةJBg2e% ;j_ٚ>pH9][wJ\"Re6ܾjnAC-) %lzV QhʆN7b|1]enRzסW-8<3qRGw&9o=)&B,%eAe^pRX*boiQBpL*Q#_>Sq.}V4O+_~Q$U@ b.^%ڮ,\ږX.l=M'襡3K#4f=vz&ihֵx:rs[XVQ^GCgő:pӤ5sz֟Ổ2(z#􆜡h2$8{^jcKG8$FM3KJL>ziQ@p >fIEZ+[ 1Er tD 'i,ὖ^sKΨ!'RcR`9^c ^ Wc=%3iq>i$ƒh렣 Z'9hM [zg=HtB)WYi5=\h͡ƍ0_]߽f㕘Cu~IEJ4՜8x@qה!>*#ҥzmu3Oq2J:n6N +FiB fʪLav5H:2c5575˱EXNWj_J1זLq.{E*~OLY@*Ljs֠&+_6f))Zk~y$X!0B%^ 7mM'~?cUsrF$Cjܜ+w7DހQK1[{;:z{cϜ ӄ^HzJ(Do3o䅞|uR `N=1YTBOH=!9 ztC#s?6gW{ϵE y]s smƄZyA&Ɩ06 fkgAD zd,5m~S,jߟk]wZh ׇF腠4!}KDđ[y-ؓ ^)Zi|/%z$[$rak\("eCz-=\b3sO_{ Dy?kmf@H'$c =n2IIBO-=nF۞۴J K܋ BQhfK7'F@{.j=}%MƐmw83#z 'LʎJ®cV!v vS C\aqNs,#\~JGl?ʀ3._CV=6T9Pharsz D)9(#hZ&  }wˋk 3@ʪOKpGZ) 1_U8P,Ws%/KIN V gmh= i(=ƷD|$bd08SN $@Q1\@#I|uшz6l(D X\Ptm==|{'m8qg SS'½\s+%Xj*ww$FȧʲM4sz8ʟ[ e~WG[]aKCVj e.or_?8bM]ŭ֬t5~\ %Wk.ij+ݨSz7e.g.\ %ڽ{sRp P]ksa7#[5n6QZwmznӸl<,XӾZ,.Z!#,."H "H "H "H "H "H "H "H "H "H "H "H` }ľ h]g_2Kl2]֝~c9߄^|B^O7? Y*JCe%SuݟLɌq7uڛDp3֛@l-#usX`2owQwқf#j@o_-ȇ)\OR^-yX/idf.ϟ^w2ǝ^,~z"̶7=TWc)z:zsSrv%#&&6?|g'rGoKn=)w K\Y5 +.ޏgx>o -^{5jɶ,zٿuZ͇muݶѳr; HWa1k{ǑVZoFzNl f[5U8S̓w_&~Wr~ 1ʋumNOӼx)cY-=EHC^R/(*UzŠz II0aV7{LodQ cnuO{Ewwi鵽R-n;:@f<8|( e$Q/1((J5R|;]`oK]([ N˔RL :\0<upW)˔p^u Q0?{/uWڋ nmϕ2jzjs)IF9=\I xjSen,sR&CgBoA7NJK%kۥl^ص-Džn)#1+9wV8axʺpeZoV{/sLb &OD~19H/ڶemَ^Ihk2m>7NaZO#K)*'GSmAQ~cQ WD!\ɔ]LVgU@!cYyI2Y%'P&)4zc)0NSxת/+U^)A0~UP Śm&OD"M0!F񿻵/9׿՞2/Y 31{RhJKgNk.e@ !Gj7xP2A3)Q>C(slj`*(.NALo τ 3th,􎉹ReңZwF o(AK%P;DvG0hOz:3cp| Ӳ1kgT+m>&/HԆG 0#z'a?Dc- ]9s =py!"RqftAdezG[d)@Jkb1ՙ lcnW~L1*uYmieN!K }1C CwUuCg_s =:cWk'G(d#F2L!:A@ {h$A 2zHrh=ZJbZJzNheBϜyޘ/e"B8\sqRe#  uboM:;r!z=fڛҫ8Уvubn)¦״C{'p'cǗk荜v4!HL]׻byў)}6ZAK0وy=Z.L)(jBOj Q4;iN{'^ bCH0֍bRbx@:) rAOJz}@σWHVNgvsft{DJZ?80%D]~CڄKb=xU߉ߥ,ʡf'57-}'mk^e3=\b.ԓ{3RH`vGX4,%Am*BʾӞ 7#ЃvB˧u! 4-j^\vJ:'~psx$ =85#^PSb=D]yh/ : #CBOzZSGHgF[j91'5(̙ly =2zt:w @̵g}X$m`/{,+UR>~&HAI`n=ܷ=!=X'\^ޙo݃^9kK0ܣKy|$uIϽ[Go(-)7\g:QL7\$=aՔ <zt;z ~B3g52ጞN$A0ܮB D{V[z!Z9[XڃV2\8[zr.]]9=qhS^S)Kpm=(r㻏%.41eԸo$ھƄ *4}l 6f%t~rڗO-+-s+ #l U=';NbYO{V%!՚F#xG=)Α/Mh_aMBbSBJF{ateЃK`,@{NXUxJF N۷5 z[ *~e)MbrA0ڱ?&y"2G?sQ /5I 2$T't2E{F=>3Ctƌ%HH*z'8&Ͽ\FWWbt Lo+Q)៊} 3z5dkXMd;A{'P#GxdLh/? 1ǯhг36w/z.?Z/B߉wYU)tD}l?:%Oq1urO/H8y|%ygjQ {gG˛g nE֖/{^I^\&Wz1~d}1][Hu8 |<ɐ ɘ#"q֥eWE|hn=K061/mN E[nˋddk|-%3 D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$@PY ͧsd-7zpUFG07Tod?|?R&N?e“ٌ6KiYzOx :MW5}S>1{|=&(,YvFzogǜ!3E=;M(ZKzF=}B82ܨU_@wLDdRU6 j@/":fKrJ b^~䩺pa7{5Kx]]))&r|fұm"@}:.#Mrqw]fP@ދ;hG'Uk*Rh3,LTfE}]CL1{(~l7~Ԭb8 z+-5*zl r)(PG,Wټ_K=1OTLY T jQhzQ|ɸHo3<ғztsz.+ۍیoFz`NlH!]y62*=Q:މ6 d-S6J/wDѣnX܎d[ћP1JҫՉr:JKfXt-z5o]S^Q(ufPČWW; ۚ*GUJ ԒWTZz* q˥6T&XsziQUQ.ijO$)QZ(z[%6oniGZJAU1zEF|,S4= āvBCvODzOgg};{{7qxɸ_l@$ D@$ D@$ D@$ D@$ D@$ D@$ D{cDz:n_%E( ܐ2b2@9,X!f;H X,-'eb{b q6[}~xgoɞ?>[?J@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PGq_?<=Y&+E@_5 G,/Ok6ɓgiT simӲ]޸kbQVOk~H1d;8-UܞwY- [X< M:lڰuo?E(}WM9/zn~|Dmxy8l~Pkls^&ĴlA}Z/\-ЛU36bsy1t^^|E}Weoh$aM$l'],}Eh|Wl܁Wͭ]wVrbtKL_3VA/ܲZڝgl~fr?lxow|]}q=I6* `z4'MBw۵EZRN&^+B/.jIM䜷6Iȳ"R:$YsyFOkQa^/@v@o-m G|A(]? WKʤNˑ5>_ EZkGj+ޓֽҥJfiV!Ijtahmr+o'is]˃`s|ZIeQmZS>osᯇoP6.?|گIW o-jy~\XzmOj6n5u)k1³2m2G ]^8:y3ʤei+WwvްvxCY6C3Ы|R[JjWBoV}4=7AqFy͢yG/F!\4(|@j˟JH\ =b*68mmː׮8k[4Mb1 :5F!.rS,}'bҥ&o {]5E]X*j^? *pS(grK[wMWghBᩐ/n%!Bs/5hSfk{HM ==dS8D.77 PZj7瑯&ҫBO>ÚNd&|%mRg1qMBsSȈMC};EZv9B;AL 4-"E:MEx2HL==EU*ezu퐽ʣBYyF)w}=i+cIJ?Br|yǖG%g!moGm~ զ1h9r['U8 oU{CJt$/jsNʞzlx|U]Oc4zd0JEMB4ƴGi,JKoogL(A2aMZ'9"i=[3;K`sQI,L焞ѻOWh:zv{zc=#|وJGC:2Ϩ 0ԧAKhZ=Ɖ/g`\O41V9#:Se%WK o"p;z{_FKSW1ym{zhB"DdK(KhΐF?skc]zXzjtaL2=fy&vqHyZ^Dztd7\{\GJh Jzn׾D]?m,syq*+=c`>(?Sx[,N~iL:4\TlFc(;3eFW@-\9plܞv蹕!{c^)QQz\)2B _15j2cpr0AG-bw%M[ͬ=imOWQ=޸Ћj-e$vLjc1$tPWrB,' VE9[6:tf舊_X*B{zlq(ז-cȞ\Y==ޤ$8p2q?ڍ`,MFj\gIqC5SGq(2GjGQ؂9Tد#Ē$1QzOfv{D_h޸N^1/z^I=ēsߤWA):朞 :z^d QFG5n {I8zhl*&"NR'{=֒vj:\AW=HF'\l{sӐ>*&xıCX)Y B/T]o /,C! zp#Y' ًWZ}Epz57ce [8-Mz!ݑ~/zOd'5ң|]_ C0~@2s'댏;0^O-Spܺ`3:s$E(oh.c@YL oK~~jl;eϤӽwl{zL= ދޢqt8Z' =JDx{z \j 3 B(a%lDevL7WˆÒ[1H7B/Nƨq=g 0\ۉpe L er =ʣ:9ghzD򲅻EF~p &3 Ie,#rd!{: I.po3K8|uahē%*zyumOo*;zjg}i1f߆P!:E(XzlA/4Y9 f4UhH> {=}©josYG,ҋ#/RӱW)u揾4f7+L hRKQcm,w'(HX 3&Yϝ+«Pwȟr IzmDX.Ӆ\IHE@1hͻ=H62%[!fc(!rBoD7ln^ok~i鲷XNj+qIg Bأk֌gz3Qm}rz:lPfLf'{q[P[um6ڏށ`ZJ>QX7':q>+s/Zє]d%~KeM7CUG82(3TokKK'NoU;uZ=ը=dX 18Ыy\'s/ٖ$K7 \(/ҋHDظ<CT!Hc3EKm,lzooiÏ}YmԆ||yDעc3t>!|rr 3rb6sWH`>R+xf-Hm>U.hseUe]dXܥ$0>xgnͰL`.sYsW|GkflK W.QYwS|u1.SY{-Nvkf|}fƏ;Ft](-,_C5{R6?ᇹ"Qe>~Mx #||F_~WEe2kx.mr_2 ƅa˷^.^mz',KN*֔ҽ?{\b0Lk9{n Ri6K§~S q9{7O]H,xD/P+|ii_/Y!핳L7}B/o7-@oW\zX3M\}q?guZ){+l8P~r zsgjT`\=#=ߗD!Ze,n>s E;og؄9GQ[[CWɰ u|ݛk9Ȭ|&~gߗ]$kCVQDNA哵]'a]^GڤƖf${8rkbov~J"Wx-ެ݉{;˧ #13M؊ u>|L O?^>OSo]bޚ; MrG7cp1 <`~YO5i8layȾhܑ:i1,^2do]"_OZKgA|0+{&G{_w'Ja$|θ_ꥹeSXM-B^G[>,/eS|Gb.l=(Reb+f8|jƯ޾?2&k( ?o?ʻDx4B9ߴy 1sFm8gOY].^/YczE 8(|2VȠ|7DVc ICٸ"%7sJ'q@2uZr ML;zyc:R]^}ӓEjl;y(+"~Gh [?RBo_MEceR% ]Wo ׌dOVVa+lJ$X K0qB'IPl9tDTBmqeQ|:!P_?g]ZGp .'Lz\eٓSV ^S1Y?/9rs8{׍\sw}u*>J,qF%Ћ!2C؏[W|q' wH&gI=2Gim}qč~K RGWC/8Dޔ;l.Lm.V-qAGb;l!fI#=hDB|OVw j+<$T Gdn_eВ[m5z(QQH&$;-.f(ь3у1z9!Ę&|L}L11k'ӷ.^;6#RPđz=CXa¦ "1Qc%s×>Nf)OKC.3ҫ?ޛ9 A7AF'n&}n&G#;'ȱR]p%z!'tLI݋/BQqPb1ԃ `4#ɥɌ6-[T:8䁸/G'H=zDǓ"(vq[z8yEX^=V=5)f;iޏ+HjwSdO=s$œlYgZEi$|˜$֝9q3q pǼ^+ @,IgE[+'8% Ӌ&/[~STЃ4St?h';2DjK=c)uB H}?KPHo_ XtO l-JO>T\$:8~D!Q^ޗ3zd\+b曖5] (A9=qKgeX'8A$=/9r-!IГ"QI][&@fOo Ryl GJ|(ozѫh|N69~pHiST1#{!b(HIzL) l $}@B!n{z_"7\z.㔲V$1ձ"ә6Q1z>szO<6эPmJe&DFzM[BvOPf˞~mt@'QFO٣)G77؇z9޷TXjCJFTi'n'Lt#GEzXFpf'?zMgG0t[Z<z9emrsz)Hr)!W^!{Euםi&eXY5%* =3IbY\ae{|wY"=t`'S?^=>cͥEzuc_c%4F2ǕZ =%$YkÍCQ^~ӓ0o)!NqN[zoYNNϕıPzl90d%{,^}Vzcmpi4_SC9=ZϿvF<z "=#v*j+ =T'C\5˴'gѾ빱 G)Į>a Ȟ"cS~jT)ȉZ)M8dAz؞l֒Amu)0J31i,2ն ="brWC=Kc[+лyB/86`,Uh_#@UR(6sIzB (Qᤓ={7zH-ȼs!Ɩ\d"~kw XuDB$Sz(2eF]/'h+ٗ'{t7mG$/fGnG: !28N%7 6.1uq9e%_O&ǦhNpK.1$.e_N#ؿ na<;s*rT3kQܣ\ciԳޤ [#=.C\ eb-KTr@r”7`S{.CmY"${fyah9v5CNUIuxBn)#d:Sfmn$DD,hkGwiqF0"!˲! 2=K'>@1FwZ1'3E]J d  ʧ?ʷ@'%1]y ˔Z";Ћw$y^4N\77nk~^:v;"}rK+Ѓ#tM==L+{zNPyzд-~?>39\D6}$6k M@"bʝ.HDzL!úB4^ͻ{ŽEze!Z\GA={ =0ӛ<+@秔Dz,[?!*qIܑ>07M=TrOd;!&Z'}ao알U,> 7mӓ>ýO$i#9\65 (oP˞O`Z@B""!per\?BUsc_ o {dnjakͯJ[èK*,@Q[VnLaI&T=ExOwtb%$N8'j[|~ Î!$L3zIY%*,DdXᅞLЧsNY`^^m,Lm'tq]zhkɐl'ỡQ>z.]u\ <뾥 }2dӶF?L fS\ſ5j6}{6rì4Ś5)9KaZɣB2ewq+E_BzFx8O^T0sigm9HOfFJoް(-ha܎-sT4ދHzFo7+zWgۭTcZ𴣷=(v쵩ޏNOmUD3]şy36xQk@<>`{U3\&. ;Ai}>r|._=xzzmşKYa_ۭ] rs϶׊[lKWRî~ :.Q>lexVXOK5z 'Ho蹡 "8O)=+MD@Hz3zgg~[PwyzM/t79XGD6 0X ycuv͎ď7Jo#A}TwORPm+$CC,Jo#ztNf^<5|_Ywz8X{8p[Tڰa_*{^@)M> stream xROHQ6Axw )vuYm[Ңgߺ3ӛ5œ]`鲙}v*b{a[QÓ'a?dy֭S{=5ڊ^-CT#hsM9s1F9 1w7;aYf ]%{w;ћ9 \Ir< X}I<>Uw(gRVzWOelπ~v{|u׶>UEP>,l%KTn)=J+vp,ZSk9xw"zmMWzmʨ)(ͳDf[xf8:罊ZIE?9Z*UVPog~~\?A< =ѯ tIsQIi!3NTc)[d@f endstream endobj 11 0 obj 704 endobj 9 0 obj [ /ICCBased 10 0 R ] endobj 13 0 obj << /Length 14 0 R /Filter /FlateDecode >> stream x+TT(T0B3C#sK#Tp< H$anag`dY($*{)u endstream endobj 14 0 obj 62 endobj 12 0 obj << /Type /Page /Parent 3 0 R /Resources 15 0 R /Contents 13 0 R /MediaBox [0 0 612 792] >> endobj 15 0 obj << /ProcSet [ /PDF /ImageB /ImageC /ImageI ] /XObject << /Im2 16 0 R >> >> endobj 16 0 obj << /Length 17 0 R /Type /XObject /Subtype /Image /Width 2544 /Height 3280 /ColorSpace 9 0 R /BitsPerComponent 1 /Filter /FlateDecode >> stream x]vWMifZ.SSG<$4G  @ ,zPAFS!~`S@QC`2A@)@Ds)εYOW~{{>8<3gfٻcwV}tON?Sww_~ݞܗs~?S\麹ZĬw~}_儸(5?{#ooth\x?p{yh;/DurLݥxbpJsg߳Q}(;?9t}o>/NVyFzY$uuLu^voyc_x6>T!6ZWYfPUɞO{7‹w܏>]&!_<7R2"NHWO& d閹:Y./~1~>7 !]Zf/+_<uߧ?PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ \&/SaJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%D?~L-'ݲ]fT\fD+ aJ]Bc˅ߗWǨd풉h\){&1hzh+[wpޗ*g^ǦY+W;SGh/ҋlX!V-_jr̄_)pVJ^\JVNVBhظ܊__;Qqi1P lGWFoT9;.3e)ҋlY EDzc-Jod|6_\O2W蕋ˆ^YlY]: o8z˭l<"G zɆwrT1٢ΝvW)-x5лceB|Kl{ްݩrQ|8_.6.Q^3`9l(a||Lz@ ՂWBoGrDՃz- #C.d {\_,EC:=ٽ WbsO/Y\qDiյ0!XrGuzfH%YjlP@wrCrAhE]dm\cA|ggz;$&\:n+m}-z4\N!"Kpl{=|K.?lLe 7 h)n@dUZelmLh:s? Ĕ7 ))WcOBMyNv۸ǚ=vڙ*c}$gRB$tӞm&7'cOv^lyPUMjγK{7m'O>p.-_6WM>ozRy}'Y lڤ~6vJ%KIer>ъ,6qeBi֒r-[cLV"JVO м kUlBI! vm٦MRޤɚƔҹ*¬޲ڂ^le̸q^WCOkl <ۈPROIkq[5F-\m <_bY%T6k!ۤu>oږTeH'p^)"͋0y{=,${+%u@ nBl'Mpj vO2y۲ә%7ОzXX 9mmB{MCRX8ΠfFJx:͹AȠs0v y. ⁧M;I]oW`Bcګ^c9ؙ#w9P& UIu;IN4Tl%tӸsHЫ^BoJ DM„g Ϛz>+?[%%ڛʡWF У-"7[9W m-S(~gd%̈́޴ʣaU/a1tːUa*`7oֆZOz8UZ.kQk EUD큁#ۮ;hZOAވW,w'z3G쌔gE.` ~~XEғr!+*fp XGj zhzӮԱ\Ũ`E%MJKڍ^֦hATIHe :exA^GoRw 2TO7M&Gzyr+~3ҫ Ӝ9-w..H,wѳ\S5fgpQ԰Q1hUdz0vh@j ͡6H_@ ˕c?+SqGrQm2;b3_)ZRŅ ﭔkL ]*УJ-͡ÙB.It>bE xފE9г==lɑK/w/mwy a;D(k^"5Թ߳aW^տϧHoah}VocK9+hDa9#G{ I9t~ϋt;4 zYhSM)X鄭#=5Zwy){Ejn[9-Bj"=iHJ..TLVXpgoH- \E87\r)Π ?GRG{&f> v-*)"A{1 6ЫЛp)炞2{İ'šX*qh/Z.1:z34˙AjaEHGj//1sٳ\M^7!{9A&gОu܁-\ ,Zb*Kؐ[ZԹbgEk& oy+aډ ״G˩O촇I+Ei4DWB/RVd9=G],w.z#7 J_# (6Ew%"=tن9/d[ԞcZ#":zte(2"Pϖ3>ҳ\z`aZKz<@IO+4ޫ%}:aK9cv[iA{%/<2K{oA/TZ,zŖRgM4OAWV'bx«ޤS% pFaZ͊v;#z3\PRCotDo#p{Տ ={ٜd<})7Ҧ7'**#WO&=[4 LX |x&EA502w;%u.=Cnp3vdaAp s=gyxIfy4@̌-5(䥼TmXi4-䅛 ^5H;v~O?<)GzR-6`:iaG{z3H/jWr52?JzWT2/M)'2C2+@GY`cD!2v3h;批k<|`-sHG1˅FVd Wk,P^^_rF=szXϐhKĴI[鍧f=O-JqyFs =[VoHc1Մ,҃EhjXq -ku[rެr i&8`ioI zvĐ\oYEo9jI>|'M$Hnyy2M݅˭)[ej$htY?C{iGJ;dVw@z١.0S*-ȭ&+З~@*GNQl Ĥ+۠i1iѝ,,?Uz@oCP]F~UiP )6`F*F9E}rgQz/3/1u|71 ٧ODo"2IPzu.Fw^E~9=AP]Mߧ/howmx?ѣYu\o1a?#=ڻKhKmt4Jep4sFoLg̓C'># L7r) v~|q3`2#fްǑ_LIK^>>a_ͳaeE{2OƐ}#8#zo=wYODmJ K0VzŃې|==˶ =9d.@ۅwѶ$ww|\as9a^nfNp34\f@?2᷾8dy׋QzG !~o<\ҋcIemI@pI{9]yI}Gdcٸy H 3ݱypC7E\%2ɹRlE?cw̙CG`/s'{Kzކs5BG\5AxU5UktD*X[& le}[2z.EI8"KMf `)"%ZiWH,0tKOkqOr%#tfڋǶY\4'AH †2"(NGiϸIO"G앓/4 A$ƓG{ s.s-gu'+Q3\"fyԡM,b/SMܞzahiFz0jBmEw${"a87j#yH5H8C{\g$oeО17bX}lGD, Of/}g@}]brIɯt6U J˹'DnB/pclk@:sKWGD[bd_kH!s= BK}<ޤGBr+szzTi\UԞCr4{!4pC%" c|ы6 (=C,ڳ ӞEҰz27aP =4 =,7̽|grLl^jH_2>I ^ނ^, &M{V.%28|@4L#Wrܨ,o I7;Sli9XDKD#:Us9Hm Pr{opܤ\ֈz#B^!Zj9'^{aeyJ;zRrE{ z|EINJVu+K:!5lrw-UG'1\ WoczܩDz^ (l_봇5i{i8IU[ixϥh={kko$Zn[>o WmsK 7pOǨ*=1:z}ky¥AjYn^ޤ5msEo;%h_b?WqG=Ipv2om;zIb,{5Q*"g&-3\C_k@ܲMe}*?+%-_W"]R{zX3FzTRM$6 ޝ,<' J!CA6 xAÍZخLYnmNMA镽ߣ%`%,7be%%͡@d7 %8F吂%U6Yқ=UzX9 gI^HZE& a]չ+A4#%xKA==l^4|@@nύB6Z,82ie0^.80! hHwkWܹI). wlMJ Kxk1~ߕ[C {YƖ[πn'aٓvNAl8:gG\KmE?x‰}9[X[[[?T.>AwgϤf2 Gľ-KtzBG왇^3D; ^m×3|˦/~Q<[,-Bx;Ҧ8PW)_>c|Y2BB=苶S3|ZrZVnsZ3WSwtU0fJ:;vD4,~DG%:E+H1}Pc_P3.#S9_[}?Fy4)%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%Po 2]OLxE]Wq!{3哾^}yyQ?&lIoe(_ͼSm7hhLz4 & .i>5VJ+kIpx3 {^DWyƌcw_lhrLi\r^aemH!g+[ .(؟ۑ-R^{{^{[S<ʇ}zU'Qo}?R|v1jAXKNkJ';S NV'pS{#z츬xzN֗qY|czUC:l85zMl,'+n> |O^GohHz Tpqk k{ G͂^v~!zQr;'(O";.=uxpe}xsǢwR~^7dQI| A,cQRc ؉w᛫z)k ijlm?F{cO&; U4Tث2Orzd5>-]y?^z}{osw{:keȪ6C@i\讋0i[$·z$zZ2UJN+,mEz7k̦1u4G0Ia[cʍIkLmC/q.3O>y[o uUUΧ&Lۜ{]6ICi$kWB{~3=gzb%ho!\7aLcRmEii9Ay"`8CcꆑMV2,k7nZ{L 2JfGzM6l ?&-d9oA` 0eW7KIkykٴΧ*Xhqf`Im\2 ]" WɠN&/rDD,Nѳ5E,&Dz֝^*m i!CJ!S@A/Ez.7O'pGn&s›UySAҠn&/NU=AsB/Gq_Dyfc&^#%=ڋ@ of=WTUm:Mzz5CMMq/;om99:ˍd`xcnN՚hUqͼO޳+Ƕ/]/MGP<iؑ"ڃY6mKtO,oYwXn}6puQe %0~%=;v]ݶ zg^Г? aQPA/@ӫn3\>k,Ÿ\ ]6wh=^TndҦUVmw6za*=+T#rؙ%^1#DiOZ\\ڻ9УTB0=r3қLZbA,-6.h'/u= _~mgZ1WЋګ*\r=6ogf\C =i:Ku#C޳'#6pF*rÍ<ƥQF%?S\\Y&=>< czzY鹚0P:rR(~{w\ ו]0d?ГCB{r{X9'Л ==ygo\u/ KX؅r0t=y2$b`|~ ~oS[t^+6fMz#qmcTGO X5%zoRfǮ;"H{Ϥ(ȝKkMEe~&NgC{u.4o:L7i'qFߢf^u+.Osf+yɈL*4-GzVѶOBp(W]jw $^W[gšw&kBSy%##ml@hEF X 0/-~Jhn2 YWq{:)7)澁k=aTjBmYQ9 uE{O%J@YOFI؀PMCg"IsGI;eJ`0Ď̫{Ihu;[yVdehǐ!/SC!Yggww_|7z2%O&Jk?L=Τ{ᅹwtp0?7kYi9'E0PG?W毡Ȥx)e-qŀk}y*t8uxO*Y)rGgb31<{f1 6$^/Izxp9Y\wtw'92O%>P~N$7+ta=d8F'VRJ΅]9 %;?C)4]v_0/6t.vZ\mo e !Î=.W/Rk_':NBώ3.֡]K{(K3NM NwuUJoLJ1͢/L@}atz'MrSqGl22%^q܇7[L"yWݯk2qNf١mۊe*U\ͤM)nmb"ڂ˜).5C} !y[]%% iIeDytixNDBdmb ܹzj$l0An;T LKX[fo1vFZo;|]e)X$-Ca\= Wz3wJB#9ƞ Kb3?đtOc'}7U!zp"rг < GgAӱ*GjkL-VBFemԹQb'ފz#1;z:;I4`irYГ#Wt-n4yдFٱйDz1! #cr5I *4G ^B}x?x-we'#QZ,v~zlx2.9,}zbM{lD鸲q.A *RېעEzmz/;V'AU\צ"MaZ8Ąs)%9 kmH+HzKjm.FL䧒*b y:qDm;.@ zc"qyP@Qm^-OC+[>^=HgS/$ib=eڃ2&Wt|AwO@}+Rhܷr%?s|KonK_O p{ټqW!j?TTJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%m%ٷld;dӣWr|e54r퇗jLY&[]'답rmņ/1E8ޯO*GDwpi5 Xx"cdW;dMZ6,0T/JvTqo,{z{NMܥvlq\?K^+^vN:{"[ΡcZc%oA/\0znYQzvhZX>Doi1=|,˯IqN,!zz)| zu!&!h\o0* uE7 awDmX|?aW[ҲfXJ E U0-H{R{5ƕ7n҆"iL [&Ё0[h6`wZnRKen{^[^j,Ɣ&U*#`IPOhIfM0k'whEz^!g{nvMڃj+MJMPIenr,o IWܝI('co7=onCMn-0IV71D{Er:ͱ\U9wt6mKT^޻_EH()hBmɲ)0+BMOD{-YN$M^>7^cAp Մ0 | 9HmpI|mvEzpifΓVژzb#= m꼾m7lHE5 {zM&0Sv = &rSmi0Woi#+LcY,,axe5_aw+&jUB#$RBi^iP.%m:C>bcz)?0n|iuKE{ze!ΒB<<QALC{j{Y,,(~ɼE,Bba==Z,6Xh.[,3Xb X5 :XxF|3^\{>Hr+ طXzz.Xf>X.B/D˕Z|>}ZSѳܠbT^Z@Ie{XƖ޴ T9lћ?CE˼y \,\CvQn&{,1T#-qɈ]a셣WaWF A#%sCO~n,$r€Mbڀ=pC_fL cݕ6kˑָ0C4tqk0r-F :ziIY7o@o'DEzj+D{@B ᴩ7ZcEHuJͼA=e|o^OOqģ8 q9D{RzhmA{qG GfIQ12IQ{&s&Mi`X-_=^)O@8K&*RG1[Xy[Mҷet|-:çCwlѲq6yvv^;NFJWE'yHB0ΒYey"C`Y9IF<(͓x`KxQS/O`]nҤv壭MȞGC t߽ &KQrX>BFzƤ"ogg>O 3؁M=FPq8y*ȘImjWfx [,/IU9_ wBQG4NC#/,e޸!x#bàE%*_ zNX [ 87).ڼ{ j"B}{K6+8~1/G7:.'w %ߺx/EM*>vҎ#٣yqysF}Խwq 3*PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%P[YK,_c̙{}fcH5{L̒7`DzL|L.Eb<&0`21F$kӋ+32l>\+7mYqV~jAejq&E ġVrLh<ENYLA1EE ?('pk\蘳:Nffι&(C90Ȅ|[7ȗFVVm?p(zќ?޴06׳r;N.3ƛ=J|b5~VEȟu3~7NbQ$gH0{-&KWjH)*&n|GU/ w#8a?R9V?y˰G@ vTDgeir7l0'{^z[Œyp akc $œHz$W퓰 |="HH847i-LO2nyaV1!&"i2?I/aYRcQN䓠KL=I[,eO| H@<+>0ܺwy@qAO(bDNKscM/&|K6KoiZB/nl$wDV"ҖrO>z'uke%zzz!J \^)3MfEW5ě\$-d lIiEꜞpϨk*Y "EMK˻B?KO$+..+Xn).ڢP oc!v5sDiG!\ *;abn2n7vXRޏaE0/}+?M#=,x ft$<}XeOdvcChd{==]B{)n3=ثNOnk^Ô[ bqɤDeDx)z-zrbp Bh8xAKz,$ (Vx$Ng XTh0$D㲀b;zWF)tF8iD6W-A~="lg,|T77rH1N{Nk4* X)Yi 1PiMv^0^=CO&p.蹁,7{%"=:CKK&uڋ|eçHhnP+#=dGЫt;{E"=M:z"94\Tzj".@zzc%[h@ U8&B^tڃ^!fDA^E-IQ F^_kT)"Ř6JEzWwY[У)гk#zjXW&M"ka :]FI[x \8_J_~a!&U䑐Duvzis~czziCYX|УNkȈjp wH/d{\N! m;/:BVѣV): G,{-(dDMT$޼\,dG,W KIԉ3~u'Qa= M˭z0:wO >Phʋ#=xk&u1#k\+zsPޕc҉ۢk9¦wX5pR[q"@?&'5hOLk9HkYM =11{D y4$ocK%cQnBoU;v7r*l􏹬[Z,vSK>3= "| -\gaݛ&\HCk9VJcXhОÐ<^IO%zX_!(BpC\O^%%^c ϫ(N\8x]wo+_/4^yK/135[qD-W6>3>z`TnB`fȸHDP/8 zы+c˥gUG/ԓ-2(4DE;)=DMn8Nű'+Wgd';汩&e/] 2K:CfIffK)&OW{}DFB(`'V(2ءHÎD}&9P,$.7:[< |UL ة"xS;G2g)fw'/ғ!'0II_Wf!" ͟~߽Dܪ75$BHWѓr V<0#3GDb8?84flx!#\kzk JH>?sO^~kic3y'Jm7E5+RҮl豅d܆ qו 1{S%y~/1yV<Hŗz płI-E`h+o&1|T-?E^K\ZjWN땍_r3{.;ǠC^Ț ogGdC;$~[ !Zz4ӎ^L;xX*)bnLj\XzBv\bnp5{>'OONNxE*ڶkRG;Ѻ*0Vo(oJ-#IR4$be8ϧ]?x{cNCOz/<3+c~{J=zc;偩[.]nSғ-Kf#З-zQxnbL^jpIC<xc[.U~0,\$ 1^‘ЃL#zwDIz%'bwk^,ӊWm‡ KY⥹L?;ͼZhyUnҒң=REt(0lm ۉ4'cVz:\弒y=қQ1N$%p1 ;x+o<;|y%$^Y?Y =wT철7 /ʛC[H$)Z^z_/Q޽3tP4<2#}/qJe cP UBWE>B{m=<`[1pGעNO/6Ko-[2"UBOP^$hW8:5,@Ijބ<5H//]jrhy&d`jYbն+-]-C]B!8@FQDm2Cwa."!Ile5$oDG˽'8GñI=" LClysnl F#Ӌ.]{YX򧜍==d ]MjM_ꄪ~i@Ofsk^#L~mVT!)缈E?}$=ZoBl^w+wbԹU~L Ix\Ez4WW8L{7GbOKq2 Jzk( >)vŽ>d::Q-811y`J oW9`2 qZ{ SBZ4vž&̂;Uee~]Rl}ejbB`ad4T:U͔^L6Sz!) =3f"dBS[5y.>rٵǩS,L=c/tv >-cNJ_x"blzeW؊y'3 (y#e޺g_?;;c^FKzCh+mvyNnbeܤKB+Vx4 U"'Г$JlP2}BK\=Vh62%Y*@6iik:@@x妕|]Z߰8Fؤ G-qȽ4S (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%> w+66]9L`e^?ANLrWfLG@B>+)̏X+2?*7+{^͈J#=_hi"6 3֡} /&ػ*I{ui' =Y$kcCE,kfm =@-:z :m.[t}\OQzeB:z5[U{hZ!@ z2J@U$Noˮ.Jmv)q`BM*2:쵡n,!ҳh!tɼ 3{,$S38?ܣ5OO>%s${a dOz: ]CjgrXk;)=hK!;:Qi\iO*:h#`$-,Suz =iQz+;O5ړK>B+!|<KrK =ǐ./~w^VFhuK@2܂߃7QD^]?W"\e@ӳ)kViBj&5DPhm)|ZۢMTVб{,3خv.B+(Rƒ'mSד/ĔZ&/0]x =1xAde'6.Ic(H69O$s zIVMX-G@Z+d/?X4ש|>_?!uW%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ;@0(6;g, n tGV18}QF8gYeQ7].Vqb2j ":oY=b8JG}qArGHV}g+yxv2Sщ\lj ǫ|{z={1v f)׮%D6*cNzL閵jM-vvu\}97fWuZ$HBÜwRo%F+$Aetr܂^K>KeGX1?{cGb(ljYT ^4(x]Ûl* ]D@Ҏu}H'EE$Uf/$#JXV ,X'頻{v7&93sou>9_WUCqֽ6̠NH9:*+M 3Qu=So{9ǭU.Uz˰<;meߊTykMܵC77<=Hzz BI 4 ^tխ[I3kՒ|3n~͍N~ӣ@g*5q*C i}E/g?:QZq,İCp% WɼL zc7+DnAk5DŶ 1q  zWdHesz􄫐^=`{Gs̕l7=\Uzdk•^Yn]%87{Š{EcG$ft.DVÕeV&EgWB4ڕy]Yn]E+!lwϺ37U{<L]37gLԙnc{Qv'B%:5-;Ƚ.YP[} f$ICrYF{ЛқdyuOsJ\32p6ȖX|Uɕ-{M]j55ʇ ;=2IzzN°~n YVﹶIcup;z*.^-jaz)Cs6]u3lI A3נ=93cNۿh.j5fHwm_uzunZ]K?7BԖЋZ3 OBR.ZcQ .00(zt\7q F0.X@o"ٲr9,]k_%Z C+G.@ @ @ @ @ @ @ @ @ @ @ @ @ @ M&0pj쫹UjpӛY=LK?aMS\^ +&G=a"`_ީkotG^Oᢚ;|+7 cG#_v85A2e9qXL8٦;j~֩zhSM_a0a+_-vA ٷř#܆=uuܳ$hhxj.cjۻTN8/X{,zi _YSzOg[ WhWs[檬MMKR1jBDb\i [?j^yDIqwRF<`nJ&w[ƩlU]́*}"+ k"cI CGt@&A5m}a"?bn<NjM$;vv~ӣO=zdޕls{ANmRH6FVDN@g1B*D }2iUC=OۻgK: }_cIZlov2 CL0v%[tu-pe37t*uynmf~ԓV:"ګYheYIsH&D4F`l WIoiT"t5ras]XqVɽI$WfBYʩۻvZWгdRCEDri@֤h}(ϭ2oyW!?BBL;A$7ElIJvd1\a۫#Z"G&;k+櫓U9joT-zUGj{^Gךh1Kp΂يl)L^Yg;#u^iPy ֶ#o{%!aWs=@@iISOoe%~]+RD S_ыk=i||㣹x1,_+Mq2{evcl ![ӫ؞5@Ã2<ԜBU{0WxzgN9 |,}7 mσWm b齬-{l <^amyvpJij ],X<4\)z vI,$xh-MI]+7!U>pݎdL$빌{7{z%#E*ho{оE{̮u *jL`+AeF) 1zEٍ_i3 .c X&( I[_zc,CoʼnL}yK~[YVPVˬ o!Ӛ4;cwS;wSoPۅ.gTJܹBXw?, &t<7O=#@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ pY.zbgkWZ$JǮסq ']aouXs-wbu&_Ы;wW$mzfq{.w.F]hRnZ/goYxNKm];]m[,;[+#Uv^\\hQN֔^S j-st̬[%=m G6C;zK䣨Dm_6\Uoqsvۖ:yҮxBaW;Sm&FLu j 5Yz6':oFsW]kzpu9Y?>^clōn׾7g5jٲjWVq [gpᰅ!l:3te?;yѱTG:˲"}K^W' ~ǹF5Vism{]#e[4e Awu*=tiMcZ7Rc$w.5soɍBoWg|YڗSjtY^gLX0budxh RrmƤ&Nc\Ygs5{/\pƹj{F^JI3-x*-3Oo8񧸶3ZȨq ]9\tØp\m v/O .nZd9h ~c<̎qɎ ۨ5Effr 6׳fBB/6&aKe2#{ͪ7s5гE 8]\eNK 4XWqqrk|z^ìnyR_Oz$zi^@>*Oo/楗P6QUzS+3y5+!wV;r8g&=h#&ƄM`1-Ipc0tMr %^:<"}G/>4Ɍ$[M_yzsыA'zULaܧul<=H* gyWw=5~5=Wh2Ӧ$ pѬxzx<ۤ6w#z nݵ %};&L~sި%6ჇU0frEȉ^`f£2u5wѫLhjz!Q/B[r8bο@Ol)9)'OR͈%< /|{EQ|'dRnN*=r*3fd2;_bWJgԽO'X){z~02آw>rRCSKE D5%mOCRP+*c Gwm@u AD"*nҍ>zc}0jxA asWGB`|ۼx :K:?f3:ω{)􎱡.  1񦫜ӛu`+>y-yF[(75dZ=*&CŸ1fXX (1 D@LRqzt5 vc1p4[1mOrw"Pby?v̷S©4^vT5OVuZcW`f81ghӄxzeslQۡO<e&|7k5d9(f&i+YKs3u5-#ݲ| [B]f~`3dRFM\-zɂ^՚Kϫ.9yض^C!FUk/vuA~|9zgn]( TD'==wlއ; 9Ecl~:`K\so~?O S) .`'}'~ =ι7zӋb%@ @ @ @ @ @ @ @ @ @ @ @ @ @ wן?=ioVJG+4[K= N1y;Һ>;gfBlMSgv\iM'8'{Io9P7otZs#mcdۯ2虒[tXZ|cjr|֎6zuM9rb8}IO3`AxzZ?m.~_z7+#ڥŖ+4vsfg2_^7H-/ɶe|Dd:Ǘyh8/@/_怞ϩ=]F^?B`u[-q3-N ГIoM笜yoEo7#|E#k!zz^ M;crD>P*a.ω{v_e3vȔqoxkF)u8{l|GFȟ:г #z؞Ywlo9WAe້rշ2,1Or_( ﹚}Ƚo 2%WVl9CNϺ!Bo / )irˬiqE%RcffB#;Mٙ4+4i67(A]= :@K ο1oKFu緒f\m"+&6crdڸgLU7bЫ|i^lD5z"LݚҺWx?-Q/Fj =ĠQĐ{g҆meݭEA?;t=>͎{Pee+9;L~ I]:z&4wn,sXM͝=&OF;+E"cb_22[ ˼%ANwMpG4DH} FTjvqཎԶbc%X|& ,ͨ_7rG} ^Ih==vĥoTO\)0sNMYr;ߤGyCI:oF5w^K.6AIU9Bk&!Em4P\6l˔IYsOй0 z,q )pP^AEOO52j=J.$Ja*.lmEϺ )/%x N\ETSLìv`%˥. wW4u[q5)RK&Ig`AJCӓ@6^=k;J6 jGi $[#zt T*z/ˬ{4&r9\8LZȲo-\x#*2#ƣPse {zz=Xv"]KKz^om&&mGQhBxf#UQYQE bKV}AWN\f{LD/}ӳ^'vkbz>;oqGG2rdƃ,-:k=JGϐ @s"\[`=Dj#2 KF @+IRuv0f`{DQ fmAoIfIb3wLsYC).RLZ yV7-๤c{<#U! =&ЮC WY4{ʞkf ^ATtB$C(BP3;PS+p!y:kk^P宻|]=ySZ F)ϥU^У-zS>'3U 5DZE}6=Vނo5&4\/L{|ӓ%#ztf+*<=Gг'Xڞtפ0D wzpZdSft@A]<61/ }|PxcDǽl)qK|,>xlOeIONP}5aJ&B#M)Vق*UORܵr7j۫=qg:4hC?C'=Mݫ!`9k= ڶ.A(]h0CJE^[j@JZCO|Td= chĪs2jRh*ck\Mς{=ϼ4yPl0|'G)"{UމnŦVtv ^EM@ʝSg<]c,GsNیG~IZ> (,s5Ⱥ,ٱX!c-ع?T~[f>RW%yirV I#j{Gg=pc={ p~&-Z&omKA$Mo4A =;s&"Aݡm̞n^ x//N 6ט瘨y{rB=Q녂o.z(8oܺwjiwj =홨V, vL_sf9oϤЫ㒘g`"ʉ(ѿ@ѩl+s`̯?xTy˼uϓ?-lZBH[$]^Sz~h5+htU>BA]}tdױgP7#?.vLK轋N]{C kR2w1{+ݻ=^q>>@ @ @ @ @ @ @ @ @ @ @ @ @ @ ~YK9 S}ly'~ Ȓۏ<85鞲fom֯i> /ҕ&fh ߢW/iegdZե7bNe\fSoBgK7>zE/}xX滧秫m^.V臍O`ʷ˽j` 辖1Iֿ[Hu+'>&'͓9:AbUǮ})'(twovYα pBob{FY):.lO3e& L]|3W湬o/} Y_}ƲN@;.S&<>xdt*юcǀ1kȜE0s[SӔ+i'e!4ֳ~pmROOx.gO-' ty/ٞ]f LH;Xbs\zzҋݿ5~kMq.wļu&w+|Y^Kz/_0{/#oVCs2e~.z|ǹ̂DRKo+Aʟnw4 82t1^wwg>ɜm{ZS_\Hy㳂YwnnvD[&9FIvdzLHRm5~!q@3*c~ bӭ~r^ש1}_3`J-™c4#H}[5$bi蠏3SC@7Lͳ'j3)Y0q/9EPt^d.z?ǭqn#!0{tԜ{ >"ü07#o&ԩ+™_A#XN*BB'5)k8Axm๗Ev+PK$!77#[ ߢXigЛ mE CTJ=m"!oa9|a,> "q`*iI0j Q;!O-L=[lS{jb{aVDƢIHJ C/k4P~ ݵe9I6ԙ;A( @McQ#'"<עS-5SmL>~ U,{;@Pdvx\AuFJW+\kԯ'͡@ =ÄH3;ށM"lp= 2g9)-gADTʽ==GS;.PE95W􈶜qăI^ҀUjN&İl|_U쇛 <ՂI﹢imUwkL6FDpCo5`RƢWI z<'OL}88p3l&nN&zӲd&X"zDj!)6BZ ۈ^g{ A~ib{24)2lٞZMOJ_-X0R17l!-+}&9?^xU!=(`GAͤ^K6=͞R᝭@k՘C,嚓c}JO*jDN1c~s/-x}lnb{eJЯl47I}_$k=/A[Tۋ==x,=T6lp&gs9!3~ !ú(УF֓b֢1:d*#1roByLjϜ H;ŭO#ݦr%W4ɹ ١F,y@UJykQ^5@z%8d%z%a,;3*P(ȧzjijB1*M XGԙONknm!n;zsi0*.syۣ EyIV׵GU#obVjvh ؖ,;z]U~#OJD- yB= 'U<,zD"F Oo?sQ<=Y3e{ x."=r$u/ݟ@Ϸ|j,JjAď=tFF,6 U̹z-Sw4_D =9-a3Uml/w{t+zŽ\'DTGLIZ,6j1}c89oL'zm+i2zo^G"K<큶G7X' z-Ye%esz3P,+[.VnQx]֤T :'RZ S^aRZj,5PMrmSQ9τX w]Q9K==6n:ϵ ,:|7wٽ; ^APR~{zYGiyz,z+R70ju0Tsܡe,>bpNmWlv<1";v@ Z]jaȇ襌q;G#I9+/!WÖ(7b.hZc, EvnqODBʖ˳C[3^fkW3:B/EOJuT&zD 2AsK c:ub.lO:4OjG6'zl/֡[6nb2YgkQ9f9#lv+pNxVhϩrm&5=:Xc$S-ިx(Kz'Lxvޤr5o{ӞGK/{ ҿo͎ox2lMgὑwP&i,mto-h|d{qiW@#1. 2 (j7)ܒ{< W{SLKs :Do򂂍~$2@|xK1lJsNʅse c߷nDHQKb>zLV}NVXapx.) =n5OW7 k39wܛWoX9U3 Mꧽ0⠊YTXnaGN+98Y'trge̎z'ՙS&ON#m~ncuvhnYLrâKXuwqČ+erfIW.W&4ww-ߋ 򸤜ӗԇ| ,3jvjӨ=G3?LS::oؼBegnYsveI\'0@8XYw|>BpcﮖOMz3и y ĽӞ+bGkp12ӫ"y=v\~ַ=*K/ZݚWX#;ϔеӻ+CV~?y.QM9;ʒ\ӳ}p5+NU=f^m@/rEǿ\۵s]u7aM My:d{U45-zIҿIAvH^g%Vv=Χt{jDom 7 4K[;&㋍% C:<óM,`sJc$Y}_*ӵU"zz#{NjV2*^PW"]2b~lDZ- 1͔K:R*)0%Ȅ84;7N?Z h0QX#`"QD-`ZI}-<?#wpԹd߁+ҡȟ}<,j\)D/ͱa^0l0ü76&Cg`,q#G}{ = ٠3|yCZ.#jb{e'0["#ѳ< ()|GKeIWK;9\l(Os .JE[xbXqNK[ڎ fvy+,ٰ]Lƺ<W9 `-|M6זR3WzJ|J2r__ )7aǴb&+qS]A ێ//zK#zs504ؾ{+/FbɯFo47/Ӧsrկ!czc{]?߅E[@/ќC"Z8w͵Ce}/.s4=M:f˾ڵ]ށ,1ܴĒrui_,~mow/<űnQwN;~pkKf˥ae}#ٚ_En*zS~.en<3Ro{/cgǧ}։ޓl!zLpR&6YδS&@OJi9r_Lje|P`Ol7.[V{˓V֔3{q}97C+<}挏 :Iz{Ffښ 33۴YnKN#~1b M&r1|OW](q/J@y`[a6y{'KJ6Ш+ljkL}֖СgnvGC{KΤS=z ܽgt٘3Ƕ?P{iq:y+%ʌPհRw;vI٬JwmcR!ɺk'%u~koN؍pL=[%TݒA midR~'M:r_a4KXa )03tKYM"q GV:z>A(jkv5F zӛFlA†5so;^f4tfnvSbpKNVkI C#_Ɋװ| =z|ⷖcP=^@ǸE@/* /~s/x?^-?"/ڕ+tƆ}KxķF/g_q/u+ÇW>.k佶zfB'~o9vN)Y cK^.ͭ&#}k/cZ=et.C'SVm;^ڷtZuW <G>?͗99@ @ @ @ @ @ @ @ @ @ @ @ @ 58SyzNL=*-O1z3}^.&Mmڋ{@D{=t%Wfʾ.f+==w3C[r:Žng\斚ɳΔ&a8W,qLl)/Ƨsbb#4r@y!%rŨe} zwm\K2v6"Qķ+IK=gb=4b4@z"\B_d<5;=8Q>GFZH3IvN ʐk722-Ob#4$ffHye,ݶHh|cQَ v㱉%bȼԖ)d;28aSe؞cm7s6I][I rΞRbdF{c)h z5x4P[Іqn )H*AVYuH5R@yQj;kw'M0D&yZo<*F;VzxN[% >c"w]H6ӚQi :zmWPT4/uQ{!g#WOc*z6z"Q0o{0 {#Zpũ%)̮0f`1ؘpF踕tKܻht =u'ю0t6ة! jzz [[&+RcjL򀸶6^2 vO#xv7Z)&lĤX7'z$Iqyzu}g0#ޡ1Гxja{VI)Cwm=j暻Ot"kÉmCksħ^Q=*v۵=/$CAʇ<{ǯM,rrVMGol4y'˔qC`nYyz3厞{==G \B 䇝X r3r Eޤܲ 9Wo֒^U Q{A{s,SMYAzٱ;1>%MF: P<7C1"Az'9ʔf/ee}Jջ=T$۞%'(PY(fW<=}={m#lU!c#8 g~X>I 0,F _7QI\<EW=J( 2||6A %aEWTL8)4ꊴăߛKȞ9Cc!zpKs/EzV"Jfhߓko{*^ֽ*:2S+()Qu=*& zp ~1Ucf ULn-\:߳}#C{֫B|9|y;S,&sѨBЅ=.'\7zMriCCoiɾ 2=O1<;ozݟ]~Hifi)}Dx[h58P&#"d!:|=)%:^X\s -'fާcsD`eoqG8$˻?g];_Uwzn=nJz\3Y~\у@mwev3}_כ:LUgn@/-J|NѶB.^}0:bL 3-ȍ;lw3(lCg #eV(jάmn5E8E0*1瘞\|TIYH35oAk Ě[z8AzAI8osOO UJͼdih5vJA@Hqb% rC+У:̩1 J^҂-Ϳ2iۓ 4W_p0@==50imoI=fqqh=im@* >J2o=g )5ҜJU5,iXzzDSbK/5HP578@OJ^"Wu'zbGZ;l@.H1Y36^K "t=>,{IzwT\[z#:(4-=)Q[j.vc"LaJ"miw>CG=ÛCm/+VmVqsDoLMU%1GR8==ZCSDu=Qyj`m=[^+zMkure{@@@avj^jd}Tochޛ~[Ki$}۪z2"]A\M%0]_&pszzV j,  z4 :ZK6-snlK}*p=Iי~= Iƹa@o؟c Fmb{aj]E2x>=|l[ `{N3 3T.;cpz˱F-e=?;Rxg)Lsܥ9O{q 7V$-SLf%JI57ej@0(1O (Љ$p30ݘ8Cx4{1C_ĭb{5=L Ϝ1'\HN0}[v$M6JQVy5=ޯw3ϻ wdVfmkGEy^3/dmuL/DNɂDI=)^5梱9lИmK`ۦaϩ 8|_1O(%r jeaeҘл. WRZo|f-jp k ׯS_?~Fwzbzõ@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$pN LibGOݤʼ_ "fDeqƘ 6fbw"].F#Pd&SnWEp2kM-Rb82uݽOqRL(ʆzH-lʚ.{ hJP;Ӈ\.KwzrJ='ہ AکmaLRNFk5S_ۙodpIwd6iqH8޲Mf2.}4Yely";(j;A[Im՝Gʬ'ΘtNAϥs?i&ͨJ+6lz\uzٟhs Ԓ&qAf~EzǘȒ^ ~*zh{G[*+=%~^[&Mvٟe{?+{/[SR$vyve-mW^a?sDj@9PsCڞK0r%>Cz3sBlőڑ WMj1gfFck.3W;#c"`i^cRg} ,{I6YD/Ӳkfzݬ ܙ7Nme(Dory%DvjuzGwR[i܏'#%ld6k5_Ңg-&u޷q::7w AERrRd_2EzG؈1w&g'eJSDoL>lw=~v~/=~sR%f>mozyr;!I< D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ 1r;qXm;8LٙY~'F= _MI{w= ЌEe}[md6[/|pQwxeW>1|ܖå鑈/~iiUI'uW[wG?Uc׶+C3L zU3QMH'i㏠RH6ˋ˖\yLIead\-=yE;..IkL68WY_R376,ױ\,aHϥ}}-:ry_.r̨]h$u H6gW+Qeܮr{cܶ-볳Jo"zcӃiY.lo!%(zKXsA5ͤ =he}_zMʥ*ֽrkpt/n$z'W}>td ]䉇.l/>V?G.]M{I fmxH}@l/LSx|MZKzOk'uR gה#?|dzKϱloDzD{;,*؞5=Cl5e u{ptKg&}ev̶ 9Y5JcO}<}椳;TO&~Z2kK5NcBT7չ CrIfR,>O onMQuqT7Ƶ{y+eos)nim\ئ&~M$dsGsΖ-1sX'~eckߙ/:zf"\Aόr3پTm=-8|Ց# otӹxQ\J`Iٞ~V8Y%I;˦#*f*벤l'E+Nz%)-G1@6u|etR\&y1G,|90d| -cڿ ԼOqk{:)zL'kgt2[zE3rdwHItaL-|Zڶ޹_uz~dCθw&n-/ș<%paX_zz2]oEVE/4‰KGjۖ~R'UU|zfJo$f@T/3*Z?=*3Se=Gayǔ AMG2SEoRLF =QUֽo1%yِ7:z͡KI1\㫙~#0Ăj[@jF$L2: 4yj8jʌz)p(eaf"kZS =|d (`MΌ6-!VFe~ #[bOr[zr3 5w/޽ښw96Ω҆CnGʃJWe ,B!H+':;|㱰LfѓJh50z/:z(4F*lj= ǥ^-U+\e̥/Ha0E Z˔kjVe2ѻjh[zhAO5wAon驱A]"7+8ẕKEFzm,=TAj{z$Y M/SSU^\[Ȉ_ Y7w\ +imOcbBAPL$|nEPCb=JA &z).7jm/\Cyz)ݰYXneʵ›u7UK zـ^Rn@la]T mOR,y\@_sK=^WswXo5BO=Հޣ XL5W=NZx*{`{s?\kk7Cۡ}G~B~oU6ksLۡ)FdjRB 7wX¦B@zn^_sSäYh5rKG5#.a!I?'zm/tfzYGo:IDzޏsƺ?l連hHFtБ04e\ƨ& <43?g ۣ3`,lIQw.~yaL =1jh=I RyKqlڤmxsƢLB0H{FzC s =" /;=zgE/t' zBK2YȄ29!c଻q3UNP1-qÄQKM ˨L}TLWr~0Pu(-X К!% <? e{YlGN7-8ÔIחMC6Ļě_.*"УjK\P'E^/v&vl.kJ|50*u CX0`{c4Ci^0,Ql3qƆl2asqE\7#ܙ7-'()tGUAc="eN1B?q=BFKRRJbg{&dsaBxق^{Ưmŝi6xS^5Fnj)M8 EA B &-ccstOGۓ.ΌJJYXnʱM A1!a7oŝ}Z%EKnn zni9& |wc^|^]Ȉ.o%EZBo\Zm0MtR*庀~/޼YM&6^#ި_Z9KD8N\l;2eQqcAkp_p%WzC."+y.z Ve= Oo^΢3Տ7.Ǟi9az?5AdGot2a3lA+s_pJ [[5Eču0 I$[ t_pVNm K?ݰY^yanVKt]乎ЖpJͥ8"=0@$QfNuyJKΐJN]7Ӝ|@ٶD6ݣ?ֽ9sy+3kS:g uZ&"H "H "H "H "H "H "H "H "H "H "H "H "H 6@X h9ZkrϑY]ei3q6(z9ߏ@^=pԹiS ~=-&ŕZ^?hٔ6,9Z+aAգ Sn>հ02W/C2TE<vv!zC#Gm5N(Kz~xzrC/ "9 O(&B@O0 Nk{kK=E5Yo,rHeסG~ਹG,rjՊ+f~p&~݁o>N:zF{BZ8]A RjPO^1}aXvi{mj'7bz5 g,[wև@¦۞(Ŭ|Q-=^oRsEevj2,yÁ#]= d vgNyjЙP]V0懨S[0p6hǒh ߸wU #\5}'+.[22B J)lVX+ ..&,sXEma4-Vz3Y~ V[k[/lE$% @`_nݽ˛?Gɦvt_ ZcܯB{ u)xG=.d%DogWa鏢t Cq #'%{7Y%٤lhBIGF8Am1b(ٟ$/iě+$,$ƿZ{Ps`{HP]Lr U朶nG87WI/ z >!<4g wmkIXo.II=o@si{#ZA⏼z. +IQ,њ)H".X [_ےBH619m@@KI ӆzŸQ>0H8km"ζ3vdO&oTjsn猾zzA2?e=Ζ^[K/d}ͅO=͕;e{' 7yjH@ǐ *mV-GDOm..NAwt 4+zC} مԉ^a k.edtI*LT Oϑux\ۚ%ྻC6=nKʮ^tw}Pڒ!zk6A'FL .Mh1200i7iT^Pc 6UٞQSEoF=MW2&=Bih>ˌ(E^TK5Nʿ]"gL c3B-0ll1NH%=Ĝ}#;^}/w:{_4*;[znT#^O2{aB>fr@ZsiN @խ SR*S6q_ TQ@zT2D0l+z2)b;)2 n™U)pgʠy:Лy Q)*s}KSq%s0;5yi,jqkJ#Ke~w7pcCCR>evR~*rRx&NW+jY^w\%e)[ zO$any&ąy Q78ZhWnagMk2Hc% -lZH_rV?xW yܤ44M&ɯ_ +e3.o<±ncn˻,nYOdGa ۰3jfN;~9؜3%pF#sQva\䨮K$XQė;-+߽&l<]a!ۦl/ :V:D459^}- hץXsQ_COO?0؋S߁~'%^{#yu| C$ݎC*zɡgE~&w]5"}B,jVc޷f4=>l284u0.#Pu1bxWŗzf68J8l{5 > Q3"=x qtGKJуo:85o/W ./ޅ5+\Іл676mdzC/xv%7PVk1 P᳧wzZX̵"O@ .{c Լ_O$e"ᇏ}1U[m{AZXYZKO_)K\{ X Qٛjl5L^j}>4 S^6w[^w?3r$X)h*{+ɣ\7uEԚSPTx') U 6v- n &)/2Тl/=MG/2,~^Z_D25#BM#Ɩ3Y/`3B~/0L߁=lx3ھ8$AS]CorD؀uYI?e]sD/UXy36۾fM'{`d7ѩGbĜ 7 V˲Y4%pɾʲQ:4p~:AaH"ғX"#A? =C8('A=՗уA fr0{YfY~ bCeP6^av])6" ?;j; #*>mѸ&I=~~'QY:"rט7؎mL;Uf?gPwΊ{Tye@f!$!aƕXf^cL KAfzAGi{zCӹ`**ehV"DjHD^ƥU cwmY=- 0.7$YB5cQ'CFK\K4h|,~ u1 ȃ b[~c`{(@A2ЛK6乡]Is ==rH'a_@nO+d:>TQMΈRa{VJ Zx1=i׏L[m"إq6%,:Z/LCcj+\x@"Tٓ%=:M@'8i|B>=ٿǣ@=`{|2y,^ $u2HyږކC$1{7An4MIԗ'[ mI!tԂVO%oku~/؞ {ݝ= %7^CP(U"#/X|fdl@]IZ;gj .'k(&| X).{GzQ\BA9hMT&Pl"_ ӣ:RIx?2aMkNzsgC%[{⯱77zLddYg{^i3FB/cS4dYb#5O)]ң-3қVgã"KmHv&9,xbKsnCj火M+ 57ø> RC/\,L'[r֧]U'[N:F!qG/q=PXRJEOwD3L7eAd{xژA/ I3M<&ј荨-zG i5bf,ܴ ̈́^-m"8۠_T[_FSx\l&,Y\ZCQd2Hf^Hȳ s1I u[-̎#φXhb=dEw%͹5j#{r>'#1qG Lz @of2?9RvV,L%*R2b <Z=XnPC$=mXGgm1e'JUK6Fq2yuZ"hhLLF*3+;->TWP=}`9̿ڞ hdDuĺZ Wp5b&MУTL `Р $7)F\n7)SCIr'AjDldL[F*)zJ失#u4q@U@9F 좳7#و{-i(%Ǜ7#USq169MfarޙLQ^UmSuP!I1(B/LK8qۤm^dt#)_-sמmB`C;toFi~` Qgw_g4 }{ˠ|l_Gפ o:Jl3õ}?/F9@k[wCCZ>7qAl7=;nZKK/wGE7WyOkҾNraa"_3ʙky!M6K\pL?x5O\u#CZ>3J ;*p&{43#aRۼsK:@n,SAc!vf8vg, 'rvշhlucLQ%S>TzZe^{9ƅvy[uh{Zu'^Ib}d]|wĥ70\[\LeΎy.c]r>Mx)!.O?q{@_wM`6gMl:H`=%~u0a?5?cC$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ DAɟj0 a]~w`lXTglo5{|ġsf5_ᑁ4ΰTٚ$ '.ULrԧu>w8lװ8{zo9Kve+|J +5p ,fv| )X̎OC?9٦@`gYlt/v"=΀o>1z'qf <<^h|[Vc=A_#67 1Ք=7hw==V\qa{ k NיCZVuRsOg7?}5w=e.P:-C} 5QsmjwA{w3 ͷddW8ِ*ޓYhP/I*'Hlw}r$ËYEoo[ưKÑsL1 ecЌ[ћлt$+H"4S\HXhW< !Jv]lY9g5Dr 3z#$CX2]bvjmY$1Yv z5 _AFnVL1KC%i-^!Rܰ{R\/'jH"y#VΚьU o>JtiE `@ڻbOj݅AzzP #KV"QClf>@Z龜\Jg Jt`Fz2G4 Q.3)d&%sӖuXKB+!lDh!9]r~} &bMGW3e%}rWN) *7X{4EbL I&r┈Nx'U籽5_RPz xU9rPAHAqD{LL02=!lƹH,+,E)DzTmK( 쌧B =nHyLIu7ɤ\"?dy!i#Kq$HP s_d1XjF@RS]}aQ0)KrDk{I4LToheBN}ӟB"KgZ0m{7st#a HzUقu4ѓfgu(CMYb)j@N5w HqQSGƴX=(М:sr"Zc'Ф8iN߀TKJJзŝ$V<.J/GI^uT'm@3ZSILiݠK^%xL;zz&V$\IH*%~#%ۣ{5Rӂ^M?om{k1?\_f{.ZzgA2=rlZ乺Rast~#*[23 pѝz;==&Nb2/\:,, A?tƢgavzazS>PaTTg=M7G<p,X$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D{?||WC"{ǹ_ l:iS3;w٭?Jpe۾IZ$"w%P?z}ۜTo JiYޑ@; G8}e|>Xgr޴XǨfw oͻsΦsXz1PXL-W%ZCjpe>>ݭsV#kc'= =p?CzL}=)v"q4l0$WkAz8Uҟa)<罓ƚDSzIeY>B¯=A \byc9Oe_f=$neTb yLS(soS\Hy_$("WVoj{֤j&xRny 5bx7TqD 2d`nh\PAp,CԝZ,w 'Htg'xB+f/GuR;WIC¨R*ۃ[?SwV$*ۢ')Ph e#C&؞AQK/kuSXOdz%>?Gg{I{KzO=:~A3cf  ;)^lH-CI(*\uiQ=p-=[H~=Oqjw٘2-=b}QѡSϑzxOwɡ#kƻʺ"jV9@oz=UƎLI QikGenk[h+x t Je{)j3bcvk;NzjѲ:lrKeωXs6GwA/؞>a;zzS3Kԇ M =h[zAq?9Ȗ}"^f-mK}njJC!zAzpθLGOf*eݧ|o{\ns➪=V1Xjkny\u' ݾ+Pd|}L9T{˪M5,=4Lw9lo zDoi{Л\FK_=1x7ba{jm/YnE荟<1%=Fjr-bT>*XGgIN{Z ՠMT8 oA,0 D k.SDOC0*YI`_oc҃CgKC/X赆Vr=l%.l/ H`'Հgg{z:7A/%IUDW_s鍓S?)0qRw<^J0Kc"9i ~oG 7 e5zh@p[Z4RhDŽɮk5^?J}e_57TAHdw57QKOǛXk%^&z_)e{a{f^柏12ٞpSj,sJ" ;sDϒ:zY~`{4Ўuxj]e#=;Uk)plƶW,[Ϊ"!$MS=I }9|ڶn'ѹS  T[[zaM.)`jnk{=ӵ0ɫ8I=ܦ㏤mAQW6-W|2vy\ =a~Ny4{c)%^kf=Py+)7gX-x|302 57I [l|v8a'|y>;rf9GHP^5U| zN/ [ڇјx5G6=އ8ŝb)u2bavc[TvXԘI^)!s )1uˏ4׌=J=ŎJ 3n]6@ J/&x\ZdJwJz+345#%af7n = vCߥ[dva.zL4ǜ"ȳax{f$&&_Tꇊpן^FB¼ Qu1N2L>E/9_yǵ+q?TsG]dWT%i'b< Y㙯+LY {U<pi [E싶U< mSCG5c2Vs \&$-3(}3zcAtɸ\mRm[8 w3x 5g+ͅӥ;ť>l.&2Q2kԲg IY '&$;#'&9釺k!}~2Z ~qy<鳰'8tn?P\ۅNyy}L )/>etK/,B))n&Nnw:4aޤ\8=h} h\hE~m;rq>yCuB?Z$|}wwxb>^.7&65w?nz77_ݦ}W7=?֫ޑo?K;E;_>zq3@+ޝGxL}gfKO#˯S|Fjm~ڵGb?:9aL_Ԭ9NC?;MpD|> Ҟ&UL{q4L~vxxG%7=3J? |9NTn7-}'?ɟ{p_ɟ}/u~ssS(GS$TşkٟTc9?7N/ |BO\g?x^_/?: xqߞRp(bxpӶ?¯OKO y`i5c>pduWz2g} !z Yl/`Jx'[hGnt xNDt:ק PV ӬAOPsKe<^bJH$_;X5W'aUڽb6ypZlyu3O+\`ڤ_MϢ.VMHf߀vKUqxb`||Ԛ~pƎ-}7Ԙ,]]̲KzZ,%37xxJ-%篠]*<1H[cX@cˡ(Գgg]?S{8 }[p][Cm!-31[[h#-3{z|zʢ嬹7-]9¶Ž(+MN{C'[\577'/3=-K{4hpP0|?H0_5 E*|ox>Ѐ尕0u5">Xf!W!)l3#J-]`wm[uzL$($0]a>c~3{H.6gŤ@xW/@o'\->>;R4C~aE-ßy/$EO=A-+gItu2]t{BW".OIh}qm?sId{80b)Awyy0rF2W8\GK|mdrXJAf s Yk{gGDғRRm6aBu >FSyPF퉻Ebu=:1PCXڛ3UMoFɲ ,dZa>+!r<t1 "|车|)ݨ3^bm*%rșyEύ!ZN WCGbis1Ί2V[zʱ = +[XBzqGFj!OH'jBЉ"2$&arjJ1IF֭Cͻ]kGz/a@qzЁ+H~=rP)uU? UL7Vw}z FZ҃lֿDOaܤP 6o=7AwX"tTA4^֔ SZ:(2gQǂJsEEB eʫ\0mhIK%$Jܞ#-=T,wH%Ф :kGcr\)NsD iõHAd%D^*pAovr.krR(!$풙$6U^IӦeO@Ĭ2葨jY/z%1Bwٛpk_UCڅl+dߑ $Iiǐ"iDeOv q/alЋ045zeb*)= 轣V/tkW%ӂ& zwI_mzJLsM1+#1ʘ[Yp{L:ڽ 0J7H^j6|.#z y #N]s? lJnSKckɚE˹5z##/Y&5=PQ{As B,7Q7Cܡ#+k lYYb=}Q8^ u@GAV,h.JFN5xz(+%D{=Rg*/we&y;޸_rMhː1"Y㴹J1V& G,m0ttXZ%bjޛ9c/v]~PtFzFڈ̍yd>XjT5>_AsɷE^cYbhaFtC_9(QsC^@lA/uDo[EL֙`OO⽼r`k0% 0{s7TQs}*5G0 (lM'aްDc;]~\SͥřKzsz99\#50݈6|za!  /'*=Hd-}`pl!{l0OWʸ|JP ҭPQ"J iRu!8w/y'Y>uvr *Wl]eՒMnCpH$yɐZǓOl@蜭ɜs:k񋭠@O&^Cvs{}*Egx)FūVyB=q?~͡82DIb,>J%xݧwS:#;.?@zdh 9vlww;٫Ѯweϛ-ë][MF&?^S]vE@KH{e޺b/+ͫaۓv+ J?cTn7]F;  _m޵@ϯ]AoiVϛv'ֹ z3&mO??dF6O6W۵F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`@W9*G endstream endobj 17 0 obj 76067 endobj 19 0 obj << /Length 20 0 R /Filter /FlateDecode >> stream x+TT(T0B3C#sK#Tp< H$anag`dY($*{+u endstream endobj 20 0 obj 62 endobj 18 0 obj << /Type /Page /Parent 3 0 R /Resources 21 0 R /Contents 19 0 R /MediaBox [0 0 612 792] >> endobj 21 0 obj << /ProcSet [ /PDF /ImageB /ImageC /ImageI ] /XObject << /Im3 22 0 R >> >> endobj 22 0 obj << /Length 23 0 R /Type /XObject /Subtype /Image /Width 2544 /Height 3280 /ColorSpace 9 0 R /BitsPerComponent 1 /Filter /FlateDecode >> stream x_K~W6& MGF5@6 DTLSH!ȃ<Fټ Y>:F@S H PF7-<#(;J=Ky\]6Uwgp3OWLB|>;07 q_7ͯvI^dO ^K7>O`); ;._g=ė_TPwDv6?xY` r??~?ե5\}s\;cs̕???/_G|` Z2!B lO~_(Fg- M(Wx3+e7,<^ hUzKCSvU{N=D6kSbƒ^]mז*ktUu\Ezbwuc>^={uv55׏7~>o>@rCj;l5㋃hrIZgekiFf#/81"‰(t{[gtdͰih/CoG Fgi΃u^̋;I( =PHϛIc3+Ӛ-sP%0D c 959邹1ꜯ2f1uwOwRɩ~SiM*;iS\) A%cZ%JsfD2i*JT̶Ы7 |/QYy&cRj+j]eueg7 (j"=Wy_;pB/]UUHjT2LۉVl_BLCY0p^"W ~=a|n_u$x`^_s~N=lGz"l7k@jA4f^DyL pJ/a#=5پG#hjB/=~y`5Q .CTTe#d&Ba#jnGY2UPJ AoƧhoHh/*mc.PsgxD{ zȟ:ѓF |-=آ!zBNo)3.'koIK\qV7tV"=Dby-͐Ou2W$Nwy^Wssy؄e-0O+EarlBwD{W G\p4@nyR{tB04_Zjq5 RYѓ'rXU(^^Ws ^{\JYa#1OkPJgIzP$ȟik5娶:iOz2|zbz5v#OC AQ۸\-\B9{Q{B N{!Dyq=5wܛГУ_oMŸӍ1wc\Ս5X#܇XG^G@Or Q zt0^ d_NÍT2RB/P( A§eTf F#ԌZJuC@{uv1NU zQ{n$}d"N1O̱t H-캚[c a9K ZT_6{co%#5,SZ iꎞ_;zRo耸c]\sGO,FW n=AK-$(liO z=[C2H³H#z,w]%8+B6-g~˙oq2ʯ$2sd6xV: ѹq'}Rbѓ\ћ/jeR: c{ztv&Kz,T%CbE-?b*ݒȉI8kn^M„('5g]u糝S rb$i5 k8QPs =Q}zd5 ɫB`$2O^_4]X5 ռS^N{ɤm7k cI.bf35"]ZҰ+&% nA:uL"j, 8y_bozL G١y].B }n҆B$Ɯy\3Ya٪Nbx\Ui> ipEn :n@X%ezߤ%m{/a d@_e=59(E#|"KfIZk %z WcȋeeSrgZ>.7Yk.*>/hBu i~Z8guslWx}AÄCЛxiF0{k ly~dZX,}^Vy(_DŽJ/2)C>J ;$r(Þ+z&|$yW)2 {""C&Mr.P"Wy5m=S^ڇ:"qޚ!U_ _}gtav ޳g vɟ<뽇gT9pf|^PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%P@\@In._Դ ۗcp?'K>tR>*}q{3/*@Ly'7z4mzHjt8*=W mG"_9lYIs+'z˺nk-Fd+,5OCs^,oOoLo,[ގT+{ 相}CvpƄ1֎wOO^'âzDYD 2Gho&M\\~oؖZ ;!\NC‘nEeWt]떆=cb=8kgaѱQ\{8$Y-z@HY/"F_x\=䋌Uz4Yc zGNAXhoeq%ñSrJ8f<,`.!ta‚kk2ް0o vݽumtF;@D7.s@Cq8%-i}K#o矸h5 Ɵ'г㸞)Xl}|x6ګoM {,ۀe~\l(otbn^5k"6* o~=R>< rhvfA{i[7 kE߆]ܾ~C =/ Ȼ:˟O{,PnC[\uˠ+,M5ʥ,VuWYҕcG!؞^ Fۦ-̂p7*.q/ (_ ͦk1kc qɀWY5ݢ⪉a|s/[Sqe|(C7G]G$.yH9ވ#=5껹)nC&![⋒W镗*O*}:3w O.Y<қz =Ze\$ ##%s}]Nw+ S?5g %#w/]H=8F%CJ8ws&gCZO0}9UdzzhN|xa$ޙO7HG9@rշo " zQtxzrx!uu뚛y 顐\7 g'x5*]oDlGO :'cs:J|9}{zZ2C% yW7OezT~2/ٕ;brŭn#hw}'fIo9eV87 WmB!/$!ym kxz}By<ܼͥ9*)Sz뭏pަޅlK3q@8o1-$z##ɳȗ1jsíYѽ#kO=-r.IƮog^(T7(^Χ߂^> (>o ' j^G$T!ڛEz8ηmuLx2lz>#FśhO$£mNH6ӎoi.19oBLƖDDɝ0e֊bJ/u7}4k.E dOFzTKsx[̓hItEVRLT:pңGzb#fOS{)@xI\.Bo6\M5Z} r}74{P`;{FɝHF.JI)#c\=[1=PMv,pl T/3?=Q@OڌycvxeTW>>ޠ2vڣBO!/b'q!{ݍo4f&J5{>ٲ!n^ʕgobM^}-E٠2WYGO4kJQ{K#)hЛ>Jꙍ-9Lu@MA$Bt4#zwIiDƚAK)|WscLo5%FE^> QCqJZ V`D z;ߛ\}:fv/-\_PH!<['iӛ =aD/G@*90[Pse,y3ԫie͕*blq:I,犳Ё}PFyOomk8'T!|&9tRc Cil="R)Ћ6y2+:@Oܠ/:@!u걈Ki( ϑ/s ]=FsOo:4J*`k8f)t@D|XDz{!jGi/ ы:!#dmmf\4G9q#6u&׈e0*iR1smod}a?z*L-"̅^|+e{nړ׮YBO6whWT\7 V&I2:ہAg 0vOOFjBWbpiWsV9?;\$OGAk^=3@˖AY昙`^ᨋSG(pp2[B_ baD?/,1Z'rk׌(>2f%5]ኵdFik9xfJAy[.ӬT6WMГa5Wp@e+#R\hA!b2bg&)H{^ꉸ x5Iyyj^2`o>\|U̽8o=35YAO d &J a"cu<&/xOyXP\=g=*6]yi͌M#e4kn =+H5$ 2Ykwi +y=FŢГR`C/v˔҃.>vt܃3~ 8i?3^n9k!_17 +eN}F4c#1׸x- o9wWUekۤ䤴 #Y# Iӯi'I5!čs8v[ o*ghOx]s]Gci^ګ^{>[JI[> [3?p[q1|ov4[ c޲U:> G5)dx O[eJ3pګe{8y8zXدb}e8(z?BQ2v'gG)ycŒr4򀗉A& 5D`p`0u9-WPJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (_v>:|4봍>:-kQ\rZv_%\YdyqՙXVz==V+ŝ w* UXHzq]$wE|:,V@?U w4,eyXdp@)WXtKE*R&kq܁k$0c589^JQ&xtl RslBo\z{r^B~_!+X=ٗզV '$qЫp[a%^;h_^q? mbT[HZsrUr1G\Fz)/޶Q{.B))߀sptfNs=+.a+[f/jO?irWV sB|LoTW|rUv'%<\4ZYIMcrX3«~pc~xΊ\j쩿&܃W8WA);؀y- .=+ZszYx۪t1Uh>z'U:z8`\MqJp'-l1nܲM4]#UB蔸.OSeH??Sjh3h5;jw"=FA2K6)0dOb Y5C!n].C| ^Ro{p ΦH/)[z8BGa0 H08(Ml?Ֆ$f{ICoW. C =qo}'#ZqI\sC0P'S3q Uў~!^JHWn/]ߋO0s,QZMqќTw|~I/s gRKjHO#uf=8¿:XYa1@~<(< =rN֓2Tϔ(76.-WO F^ .Hc>CWsE{&{@*/m{zIrl&`+⇉{oR֛=N YBIIf8q+%iG2v)I O%8MlxaОNw +=:ְ ;8;8F7p AHnLt͒l[m}+%#z V(^L 02pZ.v[[e %i=4K;̞8]× =jOGrTN)N/ګGM3_H 6[+cрZq3IA%=+:GzkЛ{z#A{;ע^l5Bw3T<򨽅 &p;z5lbРӶ/qNZ ƚ+`qRs29_HӀhkp|&={ P{$ޮ nG2IS eJLi|ek.X8YBO:uVc~9:#=./z$@qQs#=i{z+V_m:0 b O"V4a',I͵#zBC,KGet6mb#En`/x[kiำ'HЁTN{FG48¬X$+LK_[7)â,GjC9Ų_#`ڜiR^7Rizq)v0XY^aTH]1U6ӓLҊBoN';4zLc,03=f5)rl Hߣ'6^0hAO:zXX{ zpqRHC̑%鱼oEzȜ^4C(4tudٺГn ʡJZGWqK㽔s푁be̶[wf=A/rB8X>$!*fa{|Sf{e8R}ʁUD3T{(Ɏ^1qQ.ܮӗBO(z OfyG)H3ul{zo!V x'.m}%cz\[2dΑhMg-ȋA|7--] C.= ՛>E=QDĔ L\eKz]:zhevDAOG,z.ŽomNJX(r̐+fkLLip5+>xW\tŽbFBBo#(\J2wdh'BO %Q6# ~䎑*E.BϛF\]2Mkcxjql.'M ~mZ s ~}tF/e2'F`r[$ Ơ Y1eKԞ45Fz/c<ڠL/)ݯ҄ȩ\2̊ LSd,O/H MNcE2H_UWs~M7oDz4+ЯHS{݇Ys_G&|Rg/!eM"ֵ*j[icStk6Be4w.s8faQ-+'~C Ң>R ظ{q+cЍzL\$xs{R_d0Awsř|mEjgz|vzJQlt7_8v'O zz|zz=*)88͟hY$n𶶲;8^4]ڃ+w{ )G3i z{[J|d{i_흞dq/vzsDS}A{([hG[G-i6~iRq>'cLruytkS,Q ݴCg?rϞZ]Yw/2PxQ P̏3gL샻>2kPJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%xg^?|QʸbO7NAEcM=nC"q2]׍c4"*JoI昭 3њ{ zu5@G!Yn֎VWrJX}u|~gF0VώZ^8ov|eU5D\ѝjuXE8Y͜Eȉ~p{^VSq~9в4KG˓,IOjfqb,Z%kw̻҇x+Wq6)B߇z?.%CЇ2/YŁZ,C:I}UKA^F+zؽ'c.QΧBeDo|{6A=DEWtݚǥ!zRsE{;̇IkHkz;a_s.gОx[ ꧏ?8tQsz,UzNjD\ƹOJ{:zW?k A'4i55k8mtfރKãc =aWƹ]8]˨"лc^.rm었#i3C8pڌF-IGzc.!3&[9QX"Vqdb / 5Hg/ğX@D_k[{?kub-$-./G|?Kh83=3:.d@PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (wI`]&EJ҃yU'ávqwi-N|=^AP[Ы̼vlIܭ f}Rbo9OƹazevSҋ.-Z[|vSWW0?QDz)knf_<IrA5EE !<>[͕$EYbiNK/'X{]o*e،]疴i3%ZjoN(;eW=݋[ЛGw#fKoXZPBxzXnEQ7a֘{Tzjn_ydaPs66j\0ۙ Ѵi xdUy U(@ޯs&BH<'OvBPk!-5I^&>M7 }H-(6yzKqlZu 6sڭ,5aʕ+mGM\479vh$a% tO@;zC=k=s蹁2}ͅ 55sBm){*ë6JmΞ.i T:\YNOqpWЫ0 QZ^lD'(tLt ގTWBL\霈ˮBkb(뱠Z{bGky"=֕yўO^I%]͝`_Jg Np =.sTO&2D 0B =Q-<Gyor կo5h$勛]Iu a('Q(S$L>^jcz:Th|6hZf92- ,s<-lu9#C)E)=J }bL6'EnQ{S.j G:(B{B/Έ9^k7ě@ms)Lm-`eF?:zOw˭izz9AgBvDy"kj.iv'ʕ)=Jۂju(I;5g_65VhR$lk6{T^@2٘YA&.+L} Ÿ IHBf8GoBnEhͺӃE'?.>rdiw{R]3n:&sR4w&<9{s%<e^n^dd+vVP_&%I H-k;_m!iЩB~*]V/+}u{I[HBgeo6xBp27w*-[' ?,;S%'hBޏ>N6Jn6J+{:ʄ]4)/3/~tTDuHpMg߮,_я]a{ C·3}KVvez{,.o5CWxcg [=&> {C`gO vRF'N x>ZḵU{ݟ&^7/ "ZJK&JJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%8+cI1[?N??,;z,B ˟k'Vts"Z)X4Xpt(Y#䲰hy|@[ٕv{mYpl{u\Cu\|V&FYީ[HPo7ھ57nYp;U= `aUÚsk 9z͈^s$Ͳ 艣Ca 냬h k5߀x IUJ~3>Q, XuXHXW{G#Յk}|-tsMxY{cqiwvHz45.vGo8:=Dz`%dzrJn<{C <C z'^bzIu&1;S[Օވ޲~B{J{TWIw%X9[MhswEe].vz#,)(RLuLOogF5Jˆ϶)ko [6,TW^a) |RB83Y( !DI{r/ghnLύkS\]WkXnK61ۦE=+_bi |b2Yp҄$TB/2TMǛѸ%n_;bNAa 5n5p`E!)]!dA%rTÖϒP)aifL W]UwX%?BF`$:ƛBcXڟж߹Gwsn Ǐ|dgpk赩vprRSYn75.p __wȪv7vҚ;4$X=W0:k_jMIq5iqnXןǀ쀇NgC Uo.)}៦'n2x@KY0h8V9FzG'.Fs%uR4~{]%ɤ]R1࡯rBע2'~]+%+nk+|_g,*ҥD:Ϫm~VT⸉'%Z0sw;JXGiѴbK^pM'DO\A/渧Wɂ3ǔf':no8H8)c-G& ZmK[\ b|&"OMwū1K nq;%Ss]yA|.! GA !X<8[CRm].Da(^Q{,9 Jу_4zxэDB{K} ש낎|D%-Wf]mxDE_g۩7=MiJjL- (x'ўSI݁{qAGOiHpegI-RL#t)Ykђؚs,?k.n ƫ5zU4Ĉ87cGȠ'=<h۟ 9Ao.$MZ 2D_ /\~ Y,c7,I:y}tզ=@e}|=BHnuD5ϋ* Xu.mBD֊^BoYsCm}l5PXBZ QBOcc`ݳcmPN{J fzH0Y]I豄`mԞ4;zbhʛqb\GyLtVО:rUVIgh.y6)}I7XJ$"^^'Kz=G۵3=-F'Vniڃ8 =&znTs KOsk5*qDx1aI}@kr=\2{{V#>hOͯ8z}0uV!FWA{ E:/($ 힛˱^S']-Dkh5:ztpNw GoWIO(t bu} (/؄TP^%nhI/ghBoJF$Dzޔ&"2n!h(`vb5\؉ ^ګ8͌@ %fIH{ Q$WT5l;ԓ؉A{46m~Bzh݋Qe"yuE "za2ui.͕}C맽B7Ss9gq! 1,l.HC~"=5Dۨ=.׀2upٽ<_$RsIs<ңͽɁHX9K={^kܘ^{2I+ 6A61D2C͕]'$aC2; b]5׵eNgeZ3Ĝ15W&Q0o3C^{EĈ^asJ[{1N=2BSjGzT[瑞 voDz'5~n &I+ć=u>[KX˟ĢyA^Vr8v&SnUX*m[lE_~ . M'VLb=5W㇙/lyϫ,qx- kأˡ*mȫ 6%LZDY}cg擎'>奅+i] | cH} r֭ev)e,?RKx(myaY(nnٺXYfNj+/p<ЋoFׅ^̇-_/' w{&ff6yOWD=!RolTׅbF;|y}Id&wDEZ 7;kEkOӳ+=3mj؋mpzv֍||1>] a?𮿚#~3] gAo`ev: fVv>Ɵ=Z8tSaC`Eй 岮,8~N='arA) L~~̱h8#gz^ )3o+%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PSE] _Cˇc=E07/[Nϡ ,6{9*bE A-O--`i)Y 6 \`L묡Ho&rxYˊ|(C2zk¡\^[5z!* n51VV._EUzUVbJk2 V΄D yAEĝm+_vA ,u6defVG,_؇ZMy1q C9<ِ)΀MBrzqx)4zKcB]wIEX4 1a=`ʋvoʇ\ӳ16T=6dS.A^:@o<)Nb@zְ~$+m:mL"@oy2^Epe|= zL]ҳ,\_jHu@/X2|{GC99݉y r^\>^@{?@^l1KnO*/~G1s|ؽ>!P1Y ވ!2.f7ɣkKSۻccEgr]^NC <I0+pv eX.99Xo|NYYR:/o$9<'S O[!5cr>1Xs/l;_ګRV4^ydC ͽCgYݬpfiIED#<gCЛ`38,\;^.>1/=~'xϜ|jly/ɪZZ_e} חqKp|GUS%== ^L-h*Ldkp4y~ZʊCa~ AL+ny"x,xiE|T?_oW} cv`$oⶡ1\`N{M[_z&)}zq⻥E3F 24I~kmY{Ӂӟ!u t -4|"7X>, .Y]ܛM_zv">o1O6|#;/&-a,k*6L Ĥh57'58-,2X@2lOeB{Dŕǹm7zzBSⲋl_\+Oc2Fٴ6-8}/gS,ۤioN^N󲌐 `IJ.W}%g*OЛ BAf#=G WaTl M H"=LAh5D$ q}WsԎq$1b Z1_9[zq $NXwZsEͥk =& e\>WB 8RG<ҳ=P=<41==C{ cJ?Ѓc' +#…[G,VԞ^ݫKm3梽rU7F{|gWjC*C#zӀoICmnŃGp8XsI}O!hj0*ޓ՚[ &ራ:W;Zd܊aJ#vͤ0Cx"]ފ蹁lߓgIDWWe#z=׍^z`xՂ>HL`i2;%54gP-Ge+5'7W!kBmngHzؽuGK͵R=yؕ|5W^]^)+@ = BǴ!1SL*jǽ=5s^LI!5f&S5Ԓ3VAXuTQ :b/d2ނ̓P&_i؛*w~,A%!O>*z Tţh*qtqZ,e]Kze7,6j-7MKUn%,`8$ 2A#3.`VuّG"ݕ3XI[ mnWCϕ5v3CT2QpnګMi,S5nkVVIe0&(j4/5 ^t-9T i!Iy+^1I7ȣ7p*T!Xs,Y浹Tj.kX[.M81q#ZO&9V%nE#=5&F*)R5sZ<%] ̝8j5)4[+~EMy P`D{dW@7yJhHҤ[Wi0/"CI/'qˆEqٶ7 'Dj\`; }si"䭐7۹፜7s4ގi W1APm!]R9kd9f ''U^x~ٗ`⽥}ŋބO|AO~nn} zȔl6M;Z { RgTneno `i'"Zq'"j|aOamA3?f`Ro x0]PEkL0 E7 03 E=9>6Xo҅1_g?J ?Y'ӯ6wA֫wndJ+r7)XOKSKX^'7wzړn4{I=l9vˬ ӧn1=}C'YĈ󭋽75=zm'MLzx3.\M99S=M[ot6Ʉ{qgT } ~Qs3<-PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%q=?ѓe|\C4VVZ[Dt ]';KN꨷R,nԳ dyZŵ//:b?8-doxWqNޗ5e)ǃሸ(KW+V.vb3#FsӋ덾ƜbShe˸/[m5y="3ɾ>YyTk)qC8ؒ, rs__l 5拈mťy, N~QŖć((zQGKz#zo5>z٢-DiF[,⼣e}t+o7Lj dx5xr%3'\I7X"yKM{Ι >WmSĀ巫7X_X9:l>4mj_!ynmg/ wYˌž¡{t KbJϾ?zIiYΪ 6Iq1[XdzK) Fz8nƇD9ph%X=l]eX/z#OC$}!|q+8Da%pal~w;B{tޗZUtx]s):tUso;]ce|Wd㇎^R<Tɒ^sհ ha)X1rFٙ6/p AfX_c3v np֨F.[ u'[pTWT\>o'޲p#rؔzyqZBD1ۧX~'nOpK#z-7/SǒdE/#N-JB2K\p5+"Q&ШgX%LDk b'&ZNݾAǤ%,, }R\d<nt"dW(RUq)z5Ja "8XM|.B_244WZ*¨⑫z؄GȪ֐{s2^];~-d= #w) aoaS=4:}x5\"-\2M* AS*9*K(3퉞u5gs4D܍R=v(qI鈥4HWF_yG4Ilu#Oonv=F,TNca7A/\]OEO"j'!/Pl =qzz^{zy(GI[VDɉäTۥ}c∮٩. ٞ"O5*I]CO ~ϰIQ)YAL+Ka{IתFA}.jj+xۃ"j"ZFّ=jԍS+ZS˸(;,Z^?Ql ,|mZOVC 1'GsB"ʈ^sqBru&a(RU1esyAna>uԲ2= vY<8nԚS!zsS˕߃FcEo{ U/B˝Z:5VjMbL6uvAFz zx[W>* t>jCKDs&L~kN{*z -RujOO /+] 7[zz;}G}NA׭Kxa>*;S>M!ehB& >wp=3\|{mp58)kF&-~:9"[%5gٞ@of{MSש2r=~=D/$t"lz4@14Ǻ8H3w"+ztI]ov,OomFރI>n.&tlzil`\;b }2F,lqO`{\DzQ5-9_O 2ky߃}Ƒw)`{ }dJIjg/*~\1ScW DO:s ,KO1Z?koM7N{=(جtբǼ~osG># {;cgg7wLBrP^֏XLU59-I<5=Ӻ[D!0;&AXrN=%KVnFane&ݮJ-wRYz ͌"LABGa"kJAEmQ*@/4N06G[CELS5S8&\ǡl ;zf"ӫy[== iT,5RF\bmi7+`Яuγ$%zZsʷ6g9@*+(a|˭!X)P<=M} z4iw̴#&h]r+In#V[C{Iex 'fgt=WxV*'^܇K-4b'J5ΧmЈ-JPauZ38 =y<_rz;\0>b|]1&i'tu赒eh jtIR)x}%׹\`Ȇ{z`2n_Ċ^Nb5IY Vz ?5rR/xK.g ϟ8WB{| XR zHYdG)o&cRpz<9-_-:uZY/ycԦx'`&#kȓ6ZE|U6<}/l/,3P9KsTfO2U[K0s %cAZ|Wnjq 䀛%ߧZ. vkM ϊK>2ztζ6d kғaFs_hA*O԰6Wxcl\y z=s@JWķYJl{L+?mx2d}?m]dΘ[q>zuOZ!CɛW=nxu%U{}t`/lk3+9;zOÛVtN=M{292;/y>?=&&EtqfokzEo-mz4szAJ+@}Mޯ彳I?`H{8vWɥzmMKq#Yw~r9{Iވm л*r(=)ru5EjOf{m<^Sg؟̗wXc+ߩmiCq2~lw{xC=>*`Ycvnx/ZI7{zlz>dx$e8%`:e؈ =͐D1 hA5>szs>Г1*M×bgPg;7mVݮJB D>$wo x=ICSv7wԢ3 !M KRվ.7~ bh:Mѧ#eT:_Kͷ.'29C1~HLԼօ!/̗B odƧC"9Л#2u2S@o'+[E^C|?z5L(~OC=vQzjK| V7X7(\0șu"x;p>A:sy(8tWmo=lM>^W<&.tJ 䏃/ w=\HOæ8-^Ɓ-aq<$M|:rfm|NσoQ, z̈&5зB+?H"&ѱɅ^yLM~of{3oƟӴ++ 8(/s{H<Ƅٴ&PSRªX(n/]d5$P(>xo,'F"E|w @Øa7QXQޭvis#M')W)4S ʃ=N{qy0Mr-aJ thtP)=KlGy3ey-OU܁W]5NaHezZ3@+*o@J:!)IoGERp@k YЛJE#q'wՎh,J5=JՎ9r37T\1%蝙N-_e z4^LZ&KFxM<zaw\N2G~IlZW\&?dS=JgT@!d }<|iH^#E G9D>)_iS<j6<Ia.eu)AoeN'!:JD5͵l 6;(m O/WN&R,uRoQ==ilb =v:Pө5 ,:_=E]j;sO+Yd;~z~7W%Rk\gVW:s~xۣ=I&Fk5hл8vD{ WBE9==1725OM{; R?oPze0".1AQ7MRg}AQ TQ"lX.Coy-9loaq:qI2I HC/$8EM:d1PBߡe:v]wC1&^k,+h$Aム3@Bksl/Y U=yJ݁kz=4HTؚiMgCGZsAxʐ=jnˤ^y*zHW |%˜nL~1AϗB f_ B!ݒʐE*8.z>ǥYO}L蠟Ǹ^V1g\lj!r@֬9zȿagC}huCة/./(oMRo{tjzWϽ9ۼMC/C-CI}5jպ(^WEzDgmB*s- (MmT"l/\{QcIJPXj>Wޟ4 ߷Wc*==1צ=cBF2t^3T4|$IQR@4X=M+-iն~=DŽ۞'nw *b #䃖U]o{><ABa{^o{욍X5lo-㴾rݟ,{o{9OoJcwh\\z_OEo zk@oGm#4^O3zfh6glݗa8*aq5[cc{9#F,~=G\z -wcAHU+I6^Dz#30ѻ/zYSEzIxO#2PsNjugafio2o]f%.?&=uR&mГ#>e;c_{a 0A(nNhdodcZ.E[F,LkԊoB85.ZӑB(IzឞQ{Kk%zZ@UaGg:ddapӗ_sZmޜkȤEL =Bc hDBI?W8B81!N`?zmF37 l=nu>75Rb—1]{-Vs\Y z25(ГpֿpqvbYY MmÂ*fQ#JLl>WDr-wꎇUo{{}V5($jQ1B*7ųjz~i}R@oTV=*tig3M=&A=]nzk˃ JK?:UzPS݄179"$J\A c͈9N{G,@! mYXoGm؎Dʑ o僤M Zo^3NnB llH¸8Г®u&|WC&WG#Y-z 쌴EI4?4 xW3~sbs_uBDOQRXUYm@dpр,4Icvz睹`Essϰ'|^3o%z2FuQM lyfE)? =.譯;jи?Xî܆,̯op 'Þ涞nf_z.pyޘec_Fؑn_BzC2dyӷ)ێ={[ < pHy{!Wʳ_K=b-#~ijK9JLx/3M˼{߻\oi>?O4K D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@g.ɘ33|Vx7~G'"ڬzjuPߜg (ƹBeP@M/Iz:]-~(g1ΤXޥ褤*_KoƴoOf =KL:[Uz=akޞlh26ΚX_PSH25|U+&&b!._?טi^z1T_PH{%\3|If YOꑵ) N >r>۳q^cȿL{wo6^v!#R+ᶓqCerjf!y$*WY%}ڇ]\k['zw b}G1OB-D#iMjEzwBsԬmO,x ]l2{ExEoڜCUT= WSKW̽Ft\'pܽ=a>FDVoۓ׾ w~$ 5Y TPWQcNt>uf %]S>\ۛEa*.yj\aDdpr0E'&Mqw<*W$M5 '#* ՛@aep!"qIM!t-N~AқMSI<2nOHj)B(Xv`FZBV'7FnZIb e{Xt($}XPR*O0#ev`V-FC#7NSȏvKTDMuc4T؉XWPKL-=P˙uJkgĥ@K{˧_ЪzzA==A4<=pjKOzNTZܹ;K7b^<[c{rq==IVp7 3ܒQ)8r4neC~Dlzg/F8Z#\10/&G,.8={W+zM UɊ) /3:mFO?VIL(鵢JOdTl@sqsO=4 Qi]p"\*MO&b{4G! eE7hzۛrg}>}mOh1\X0l/:ѹUWP$=TM^Jzj>gV_0}:EdZq%IOo'@f.~Lj]2}.,Ld .Уg4 r%gei< cK7%,5}YbgA%MzYUhN}:y)1ցƾ F,>:1C7WMyۛ,hce-aBvz*;UUBof98Wg2yLa*H5Q :s87},Ӵ۷\VɓO$7؞-CKG= q^EzX>L[ PG?f=Jώb{\$9f^%ŴFTD3ܖjyaOtyzTAC2lrz5b7ֈZOyV?G,TOy4v#E rl9mK55mncfgFvr>$Bu==.\zzq}Fp@7b6q==߫)1W;`e=㆗0(ՔA:XzXT x]z++tBO v\^]1VF}to{xOJ/s=죢%QOtw!F*#] cAj&j~Z2 Ig>ph_Z.3'WjQeq6YC)Y+a8Kmvlo2cqE~ӡǁ!((=~zz<ŒV>'VyaB"WUnKf݃IjO{4 6/M kQ{z'wK66`2)S#qnwx?#z ?aFd'_L'ae< GаPLY61LD*KPo+~ QVAlՂ@ef߿uH-o$AB'o.<\dsR*VUg}o}o0]]h6-ΚpmnbmGCOsR[7sy%$)PJ[#b My_*ͼeXN+hG׌sng?HOpZ:]S7>9n՞{k;HP'Hhubk kn8>^!Ӑ4+ԹVS_W0?3xnT.v>^s˨?+֔ew)]#j?=>-hGgHΕf{6M{.ߣjk_@?{ ǩg{\O}~)~y RtW?Ѕ~#*}q9Y/$]Y)"H "H "H "H "H "H "H "H "H "H "H "H "H 6{\9U.)qܟ[eJrgC|-b fBiI:2~4C Wv4)_^X˲ѷ\9|k7sɑ"y&4[>vS/ ^oogoWŗ:[el(a_>߻ყk›tk %Aޔqo>"zz5}zz)7/\c>BE}zz8[(O3zP9rzF%yvn~g|7nDWYUGYmCRz.73԰ҿKBtWhl5,]em83FFZO~<\s rAgSOo2=N߰ԍnT-Ҋ.-G4t;"mPvDsnC~ *BsIݑssՔݱF*iS_Ϝ{IGxrloJ ==T#ed+!*zH#+eӄXF9" f6 TN W[|xBa55m^r$rxƘ-~X()CgVT](e#3B߁*!~#A B0)W.ץ_o=mD=ECC$Fb&_ *6^ɔ^R_qM$sdJB`wr\C[b'I"qgz\K ׋EۢO1`ވd l j2lw CdݾN'eM?;sDe4m<1`āSs%B;pET 4xv2I&w_AQ!8x])&u]yD]=чՐvDnXMQPУ.л'`{=SQyˑ, L8@O7`C[H{t^.'F;PTkFez#i7#IQQE Z:m3ƚ@ko؞zй4c2hBʓäKuzcy;pEO:Rt5pFE)[hD-$h*IlUpVHODXSѓd50zavЏXW rs-.Xy)-ɶlOϒoPJPmћNKZ&]S۞5Cu{zfaĂFF,'szG8Zҧ~/\JZy+mD@O3m`,eNr[L^[. Wu9"[Wd`>Z6҃{qU/9 ag*'Qp8#l(ФfZjǰk42 bK7qwWF5/e{ M-I 23Xx|&4s@r/zӛC޳ZB,<+#J&j{̚djz.b&[cL(\uNf[^I+gr?amE*9t^K<`^v~ZrdKL=X=YeU|\]㍄+1r6pc{d{n [щ{wIj.8^cz+^^b7e_  5x/\l)"C˕}osZ?J-L&I^8GXѸ;}2&.nsJqEMR 1/,u;VG-/@Q}4w$x\=rQz`Ɋ zt9y$;ls{77]o PWLε}hR^L8,k4dIY4Zwjl3GUܔ`um^r^j_z#_Oİ1;|}\_8Gs3ql\䵑6NYa~ ܺ c睳v?]sOGIf,>n^fߔjћ{nz[y>n/BOkO"ZD&ObYi~-tj7lqk|Ko3?y%9^2U1U c"H "H "H "H "H "H "H "H "H "H "H "H "H "H W%pho_{[k0>(ռmR}ӺXn _o.ϡgo::^7ZB6GHHsřKQ1Cao{=ŏ|kj[_R]M%o:zoE].BrA[{&-: &)-iHLW L"CeFxp0!~L3 T=;z7*U))IF͞1n¤Eo$ESHHa:>x,ɔF)M)6Jh[` % RFn3 `RA'3FhQog+vL}Yp7C%f;n :oԢe[I\\~"z5DgBRk:ҡS% . p{8@u5R)"C _2UNCY2CsWջt)iTTfz%-pʑ@D`xD+0L"s} ,s-WSJQMY1Td޸oĽQ@`,h[I#[z<͏xf~/}o˩G\{z- 3kP5¶)`{;00Bdn@*=fGm[ u#NZU@o{Ø߳GQ=/NlRԣ8gC܏X&sE4m圉#IzÐ2& =ZkF&؞5zcKrmqrV-lOkW}`{,WʡMI*WSV NC==^Ho=ә`zzff˂F徠q0b{5OX}DrmOͣGKkw,0$Qܬ<8{䗈(Ca36owX5lo^FVpbmC-&EsxpzqWm+>X77Ldb:f% z#L@!,>s7hM2螠 AG14J8.ZtlI+/Bo$&ImZTY9.R#^tQgQ]pQi5cmGclxXS]=8zrrU.Dp9쏉M"ṙ1Ę-yzzzT}Q =LZT^C{ԡdAfE$?(%+ VbW%#&ްٿFZü񽢧(r4o9tsJr֗T:k_S)>pvzz͇d`k8'\E/Ʈyz<'Aa%89oX.ʎeg%e_@vԬ)'tJApħ3|r&͹/^U8H0LfsVMx\0yKRNL'oÅ?^_y/`o3wy[3o0{ޟ[0Ʈ9 |}^mW噗k}1`sxa} ) V7XIFX|rIE[{yu>=&/1~oOwz_qhe^Z&ɞ=]_=,[~Ggw}}a\Ϟ^md,g}grt'Y4ޯ2T]ty=W%xj$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ | ׿FSsm9*DoͿ^H\ 'Bí[oKB\z^ߑx_ &|]ZiuUy"lPb^".HpsҒAOc]Ir[Cdٯaˇ-AΆZ'n~$k [[D7|to`I-PzK /@pQh>`q~ 룻϶/}cЛ뷧lz9%<* zֹ' soJz+=k:Gs$zf;GzQ锚}>9kNJR[̬v97sKÞIoft+ G=ϪbQ5C ߯律x[ыCLE ҈eMZGhdk} 8ogz z BqOOg<*=O/f(pP(KJnq^VL\%;@+z5ָ>]%ɣVQ) xNd-$r\+'ul"fD2kYO &Ј5b]-9H{&7a$IkGD'bzYY;7EkĢ/j%[&^MSy>?J0/#l]D[, dr $_in+/˶g0=ܤ:QQ^ " ΍ƴ䏓aI~z |#T$ۊUD 2jR""E* vk 2S}X@խ΍d M\+~]'FG( ^#CBԫ"z^dnc"6fv =g5m8a> RSUT0zZ>L -lP0^E`tk#2/Ў^1-zU/KDSYlGwVb[觉N57"ɡ6߲=0h^SGՋjlhx8$95P?!POj 襒ekafw ;-oanA Nnb,zϦن^"QᲗ$P Aгvzz)9"wjM+=yDN!HOywE/=1I ?!-Wg,o[9 `eǀBGG'@k!YSIdr'9Lyz\ȀS{Uz8 }:-^*_==,Yf\2h+Z ïϤ3uFJ xzmKFj1# lMn[r vvazztPb7Ob:fڽ@6K EcN0*;Pqz⚈EKzSʑp< Q=i`Mkm{/5*л&RicF}˝,&TdąA},=Li .'zb ;:9{z^ڌi]T6o-{9#T@pʇ.=5hrKk4P4p== sz:ę0$&zOE|n## ~dbDHf g =4Y*H=2$0Z&',1Uz {cFO>;Wƥ8%M"TzzX؞ӳK3\XG/G嫁^{+d#f!=5M<|B]G. z b{<"hb{|˕MDI4Ȋm =\@>2\ Cß#rA@πB+ ~*F㋝yT?Ə;᪵oB¢4*49`,{lS\f|Az5d_-YS#I% Y-Cfq!I^=nt>ap,r#HNcR«lO^^C`nL;ma y}cXuIsuxO~z@=z:׸]y==q }n]f6o}.dCӓm50XVU@/+v@O~uҞm>+RT|D)##OC{,G<6A7r-W{r~GnfNEuЙ[2Pz2Skӎw,Ezm+}FtqozȎX 1.`j;u^厄O/c4& Ğ*uZpr=) ^>W˅͚@,Ğ5!nFB$7<=š#u <ʨJ${ <04416,ł ^[2t9#FyVq8d'Z?Zp'7zyE'DCB% ޡ1vyހVIOt's#[vt#NeZYF9.0_=>BF&Q4j^`LA; SYx UͷJX_?@e 1ԟ=wZk]sxq+b6O`C'>{fK|=#5VhڼV7>ГN\VDwqww8~ܑ^=]NXY8S6a[6ϵ8ryOOGN=y 's~H*Ʒ|[D +b<8/y6iޝjϯQU,s8'X6lfʎH48{)./~e\u9\1oo_`+?'OhZP%{!\}׻zv@$ D@$ D7@Mk F@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ DD^^B~\߬LGBTkY`.T StJ3o\//T}m"5djΆ[OZs ^f >{kmήлA&"F8- %3v`{U'l/-:q;Qe:{ptg):z™r)\z9E]=r~8oukX:}zb˚]aNp?M?aP-56޵$רˎo;[WIb N ޴M%qM(Qs'ԗ:vߑT_ K/)/#[l DD!IƵJe~3dꇹ3մԯ mdwpDbԯGE#7~(cCtnTc?wg" &!c^eG{D= =fj.TϬAIԀ&"JG DGwbov ˬhw !U$!FS2\d{6ނ#U6%( @#Ü+wnRyg%DDƳz\ݔhbQ5:*{< UlHxOh聠C/EmqJ#(ҍ;)um|NJ[Yevr=43QY 3D8y?I @R1;WWfB=ITJE(h)z@OWSg謈!2htt1yT{zT%@T?3HcMӄًۈޡr{;tƟ(-\`0(+ n#ieF{ Uz0ĉ7Rvz[==dr=G;٩#RT(J2;UiO@Y7!&=JKDo*z61AGM=GF 1h^w,g$օpu%do0qsܯW֚C+Ȼ; @TI(n ˠzoo}Qg`{ZN@"A_E$\*gl0@X9 􄙧4AΥO*z(lzxx*AMaǸ^"1dc=$ h􌚍Lfg7eQG͏I'QHXn=|pFO`:_Y';\ƦMAz; lctLQ3n{3f.nhq? =@O )='sẕ@#go@F,snJ+{ۣsB˞XO/k Nsٟg }9zI=Z <=p[./MH  =J]˟\aO/{e4,z5pg F,\o՞g_Ӄo}=\ ~{RW{65 zng!oT G^ΑoA%yo{;^! ;^ǂMOԏXXޜlOkgjZ r``8I~чydΎ2lq 0υ9=2Ϝ;z#Aᶳ fZ-Ӟ^n9x@!qP~Rk?C. hc4A 7dxRgM혿/?bKƧcBwx6& E-WGJI/=uV혺T<J8icX)C9-wҙrߔ- WGk-U9=z< \X:xޡ祅*<=a B٩.BâY*ۜ%h]gлzoM^a~˫;YNF5K[`3g^EsXJM ȢGler==)7&%SlXK]b^j@~^AT9]l:)Q V{Aߑ%WY ^c"5K5!l2 B4\lyW:́b-yƂm5%ߘ_|+j~+Fg`N%nRHO{,rza kK/X/3oȠ."/Û&yզse㎹삞Ɉ^XΚ;\U+$w $R'Iݫp<|siR=g[5ܾ(icyz}:ޯ^.zzT~ZUF#YwG6K=okJwٻFnݱ擥9?Kbq 1^@o;I+o$z^ @E]/]vC~TrfOla9-/7#vzYZJ`S;Ã̛UzdG\7-moNE2d[wzt':zK?/;8Y-ɛE;sVo~?W+Y;cxb[,ޘ{Wt9?59x{7z${ңk vޞ=`!^%`Aamu[iz2+;7լ̧fq;k>qv%~lF;wמb7Q/rW3Y'\_ r xñ!&oFwש1}e3O"H "H "H "H "H "H "H "H "H "H "H "H "H >MO>boF_M7^qE?zH]1l-}?YŏAm\k{qg@h@T/GΞ|E4>-Sha *cQUgGcWsz- Y-w-aWP xzU3[Y)0޺,"&!n57̾3ԍj 2iC,\.ByqWgí ȿ5Gg Υyހy4+lc-&;hV37Liq(˜i;E_bmnOo0p˼p5CƳ-W79^([f0_rem12 .[E/B>wܫf8]20Ë$w8)Z>M&u/ȱsO>n=BzkZn\n&>7^I̦fڭM"`rƈ=$Z! <ܗ/QXz~6GR.Bts0p)uEnemH脓'";~FKrTL9!4;bߐlfRH|B/y?Pf~U}9ChO*GIʃ#ziMV#'ƎecSy|<NQ0=Ed#&)(╀hx,* *LyG ee14$ ȏ}2ƀK Nd=bŦ(uv>fΐs7sSݧӿ߯L}s߀֭LQZώu.h;)J+$:ywE/I^!dUX+'p$1e W1o|uQp5䎎{=l H3h4 Xl`l~#N·H%3'ΔVGF1@u1q}3"+ 6y|/m8k5$y߻Ty -DF{%׽{?$]1E=XQ{Q! I y[Ѣri3ibA+:0V~O-UY=]5'ܱ%p`Ez8NݛxJJl /V Ir'-XLNX]4AI DZ咁ʈ荡 "RpIb(K mRU%.#s?@իQ0ybIBK5W5䶔g)'HѠ@|;^U˥!=z NGzz`mo@[@?lעw=:vaF y ET5m |Q}w/{κ >an>Huo%Nj{Q\NfҭlOVv0y)da^ʼ轠%}~U:Z˱n>8̋2gx\F n,(!CZ{Ljb"mg k79s)r PCl;`{D*Aԁj<_:ˤU!BzYO[[eG7)ɒM*oXu(MؒTyB^2n;s=#¹F'z!==p>VcǠpe{\ZkrBl`x._ si!2虉[lR|UKL=|j+B zK{uSuzhOHKn握T0A #0I~P)z-):u>8k%zS+#NzN#V8tzptu-Z>lEORz{:cKsӓ8G=P=.zʉzrJ\Jwrș1d ➴ cv&÷8S0;>)z]F䪟`mj.!ΌEo&G73KG'4;44{cC &,3䮪ږ(L[b ],31@[ 6" ܪ7r5~32y2I[)3QzK0 ~m4+A&zUrp!z#_~Kh\<QCC/Մ-[HZu38^ b/*Ĵ3{`\C|7>˼̷AG>h <3=vQW#?cLwƗ=~g9.F9σ, {طK F,4ybKiygIDt̊'?LSO_ &b 6m.xq?y;<6:&$8UIצ%zkw? WUO}&}Gƹ}]>d^Eͣdm^trNE9~ëjuqŞM:UAz/›*w#һrmV+m{ZLOld3Ҋ[}鍾4znhE x%N~Ku L D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ Dz_|MS3,dܻ{1d;9w?ֿ޹.KѰ ZXs?W" ~uQx\96LZV]C3O8- E2{ZK `ϴRvç_JEܻ|T]Cޛ9Xg4B|gC5l%[ޭ+d{}Ň}VG>vX K,!c~=xjY˼'Viœ˾kq6cpx`J@h8IO*,:oDF'>[~<,7C1T8h\g{{'ZdzA:Qc^+i1#V gVC};,|% Xd~9O>~ћ#T2g=P+IS1~O~v?`i)Y}}%vʿG- j Yۯ\JYŒ g4Hٓ]DGŃ67,[JۜW&QehE}Mohޢz!MBfaSo] bI@EaT$O:ʰ#Cz\Q}w<%T"(b"lz0DO4yS3"MmGC` Rr'ȼ|߫дpXCC1Z 騉d%~=!,K53ZNHxhlr+Jm!TP>iI/Xi{r3F *r;pAeQ2GI@D'u9^iN&9u_嘖$7<G +Sk-z( 5 Lo@Oqoe?=g|'={IuC-,ۃ M#Xu^EN@M(z"DO 0 HOz|=7Rv f_'Ⱥ;%t?x]Izϣ>q.z1 —r%$* 1Zf =ٮ;s;zy%=W8Z;& K艗eR-wเsA`{]O|+R[e =w%=XxfS[ O)~l{ } jiCP$Vv3`!c ^6w{%1)z,<*gCI?^J.Bs]ݱ.8[7ǂL-ÎώUd!NٞEo}y!]ͱF?K,^g&i%kfϬi,#2 (;ӎ^{^q.l+Imdf's4zv*p#:ޤfAǏz,  y6tN¢JݮNBvTx]:Ln3nl9F{ %l"ܹ=Ws,6Ы-:{+= t"f.ע\TEGw4Vp5&9'u&rw3 IyAc^#h^ƫ㧗hmb'Aw K1~!Q%Ab a\kXn+qaدJT{* ZOR3}KkK(soha4L_"˜4kM`pr7Eʧ.y3T^S˷@iR_@O~Wp{:V@{qUלދ\⹡~'GW?*?/ҷ-CzJWTJHv 7Kg4^ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ |Vm/?=ZֽYC"g/kn9bEz|FhpMVvҞ蹥aʆ$YKKJ9>Zziskk5[5 6nύYV/R23hΡgﵽS~ǫ_A{]|yW7ON2RZ$8^^z~rS7)o3Siݒ՛QTMJf!ywze& uʻGMWkXpelL|RC?{R p N_ziz]N>Q\laf~4Xlo饡}EQoBs zez7mqzRC=%7 7QO7F7]#rgqo&ա?9[L=u3G6z:m̞Wvbd_=bs[N.=3r~qg\mR+c:Ыr?aƕwƗ.ӳ''ݧ~rqPz! +Qi5}ȓqܺ0Ȫ*%OqkLk mLܣMK?Hǐ6J[$^\Gϵ)L{7%$C>&%Qa$k Fu:Rߌ]0[*B|}&G~碷d̳MIKzF6mE`٘nc6y%i2/l /fdݬ(x7$['2"KTۉmLc w+_,r.kDoTiwFV ,/s\e Uuj_t{-Vydn7weĚæyYՓ)6=͝U-H* X|'z(c-&?Uu4m/HnwuQz ))dv֘v촶e MO]>sSӎi¿m'w=$CuS'8-d\dS@|z*#$o: Llc=&]=mzo^+ y^nk =Pe^xLNł| cž63Ճ8vY?scwWofMݔ"moK6" F`qxD@vzH=g[#GXأA&6a3nx6|zGvF2.^;«awo{zqZy \W`(!9-G1LA׏5=^Xɂ^`z@ᖁc iVu/5MمUj=qO09FC(sSPsgV3=r͕c׬2=(#736$Iʗ9Ki$_׶t7Ӭog~=')Ž`{lޮ)vhƔg67low.#v]IɘaHx}骊bHGk;ɼo%z4zt]̸3;υ:zlfzXσ{MI6$w^VFՏ>" };e> c]hv1iiH̎xqߋ^8wW:r{]ys )z}jCaISlϥex%Ի)lA/+-ʤǮ.+E8d .39Z燵yAǍMVl 9ц/4O~Gmh1m{l/s1lzlHw:C +Ib2IPfMmZq7t?U|maG٣VANw}Q;/y !9MI5o|I6vL V^eˋsz|u?9ɍĔg?*:+UVzbA)&(yHe}'i"57I[>3ɔrGO7N°uR0 ٓaubҳn3O8T}f6KnA>Fxכ;dbFˑwrc LE-+OA/x3Ds˷21:oQ1`]~ETTV:qN[b#$4d >;/6%ҹi@:⌌ |%OR`fѨ@"uWG`cu[)ӦV=O-=/?lw[[\yzK6PnloXkt<6.R7bU3UcLJ7/gWr|aJPmz3˾~ g9W1&c"H "H "H "H "H "H "H "H "H "H "H "H "H "H "Jɮb~u KO? *,N*IggN5Wݓh`{TE/N5K>YLW㼟,Qƪp}Ѯ\Y9YcṴz-﹐bl]\ZC[, [, %XYk1| ؞3*6;˿s>,e̙CUΡ5w^<3PTiMQS].Vu=VB9FGlVw/?R?3=VܙEz]zsg5dqi,CkB[w?+ ej;Ui-=euYϑxHSOC|޳ŮesuhuP5-,r]:+ /DoB±N̦,PUv2Cz/=$#zHp[ylQЌ?niC/)W!K#5)%I_b?NBSI >t$UGE픈n뿌5llOal[$ w+cakl-7hr$,_ow}T[Gm"W&墧R$&=!&ҀBΞ9'Kc=!ykv/xo=a{Л}g/ Q@f)u*%zT%ɡ(kIȖjBB;s*=qNObÐ@Z׹|'L;z<:`c~amaDX܏֗jh@jxv =^O4^O{ ۲4sYg{.Г"iG/|Xsz=#;&*\y|:5z8Q!ʨlAA n==V̳LޮQ=:dAJ8sz׭9a6,i.!V&dQ:zLQ _@i%oڎ^|%NggcwJ`TVzz+zf"zB>sp-[/zE% Z]Ṙ# -nȄ[ ~Vȁ BĄ_g)0w#lvt%9Y%8Ю%8|i`c6A4Ce )ܿl7.i8xNgLlZMMu賭-݋5Gcϼe3ZC\LG+^Y=!x b&aשK'~5=6=8x,K٭O¡?_nM<4-sN) X,F¡ 譳zg~gexeoy}Eig/ah%~;.2Ns0d[g{̶8\yVkmO#9η5W]s&bؚ/߹6eoosf뎾7g{}kyṰ&G1k/^wuG}p%X.vkvnjw' ƺGբe+E/j7GEO]5 ss+WlhA+sEzF.{CDZwe>>ί:zZBfZ$^]R1+[Ñ<-w^XB6EZѺ#aYŜ ,q\2ontM1X`AoV װH58\ˇl'ÂgW %zXwk։7=\rn~Vs,ʞrnD[K/92,FKI5 U"v^ z'AoXT'9u_5d VS-n NӍ%ĺEZici}=vIJ{Fwr\z -o_%zZ430F\ǻz^KH*w~M4=V\s=\rz?`>x3DLC'A/@o=ו%$?ŬaU"=vk̪ӡհ*:zC|ۛnxl՝]9Ľգ%1Z͉Kfꌕ)J}c\w?y5wYmۍJ3Jcu?-Om=]X[l c^2jLya, mC~gUI<5r8! c,K/Y뢫W#ҪވC\z=JYm1.Z +QYٌuw퍵FERlNF+% ;TGIkie{VۑIO ۫d`46~N;TJyu4`sS {0l'C9 =Yk~4#z%zvW2M]x OD?k,7f݈ܷ|cS]\%\TDP EQd֪}\<0s78'`<7 &e;q,LJGzGi h!]`N HC' @ R#UWք'#)r^NK\Jd衤zc@Z@O^mP\z (<:.`d{\pN/͌% ϥ[ ̜@OԝDmC Kƴ6 L8f2@/xnOL҂qE$ ?a0h0{ϵ5LC@O=X3DAw̨l =K?T_^ #x(B;i *a{e {A?dzaVW`{}o-Mz(^߳n1Y=szrG'\o q= =? G@4//x\r 'xgc&YXwqoe=\Jܓp#I$=f*p=1W-lOcA%ӫ ô疈Ev`{D]՘ġIz1GNٞ腸7 ܏l깨/ε? {F@b{z4D&Ы)lj%Qbe U3œ*r^_xX*yn05/v?إ=z93piI/z QI˖1^<6NHXέN9p8CW ބ[YpE@OmqO6,z,o8myPCO~4R5-fف\b71P>b|d ^e z* bw^͢H2Uœìpa\Gm1S^`n}3)O5Rh^S_sou<I{KOwkz! 20=VHRV3Yqt`׉KNnfŮ~ɍyC=aϡ'{ b#BDAĩ+,=%lvClLfE0GyOE-N`fAp6CGIܽlAϛ6Lj9]q:CpŮP-~f4xS܅ ܣȚ+G#pS]D\ =D562Ĥ?ttnMfN8DxLE2m\DcХw;*9kGT4$/du=&Iqôz'i8n<Ŏ MΓ ˤF$.O^!V7Xk"Għ M+CR :Oh\^'OlKY4Bxe:UVkM݃ #0@m&C1ӚL(2 F/1b7vr?} ܢea S IhEaJF3t椤K#PJHw;#k YX hĞGim[Tvn{d-&DoMZrt]1,B"5W4_jBo:O6 v,År k͑G\$7Dgrz('ZWej5n 2'1#1ʙI$QQ*=̤/e{qkn{=Lx Y)zwz޳ng = z3/==zRjp=[c * rODI2] <7ARIEiF =:Js 9䬤zR|s1vڪyle\4e{wA'[/zr9sۜJuSL8=,ELvIK#S_KP5S?E^ @F Uuzu<1{g$@op݈B^eW"@0RsǥOXhq\ܸg{zz85vN7'. ksKmq$u2^zf(~K8X@H_[o#x80R L;=.8[Aۛޤ{`{mg{|T=49=“:L%*sٞF3~vzLOq^s,zcAxXc\s$z W731xw۱RbY}r3gjho%{x+2 ݊ge^/ɌѬ׷#bѫ>;f]ZZJ?I7O^onyA긣)VjS6 l]=tK,|dr>~9`3?KVHKf6mj,r3R>2Ӽp}ܴKQ:Ð^S s~s5> 5lL&w+W;5 wIx9 c%ۺ/ݔc==3gXlo8SgT}3|)!Fhr9=GCE-hoz8vK75QVCݕ>5Fyrj݌SZ(צgW|wp):#`vmӳӋac5-ά?'z0O\z_-.m!sgD/qv¾K<Rҁs7?隡N˚;hW_ϋcY6\%;Z-fח TT[:hXJ^љq_6Ϛػrroeov4XJ|/LP-&UHh腡y6q=qG 3ptpӠi=0s;\l IOvTĺ]w*;h/փ#ht&ßxa$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ |$V/wt[ZՔϯڏt^j5XW΍ŸR 'Ȱye\mvi+m/K+83 [!ٰp; J̰> NޒͼZ-wĒW2sV)˵nV>--<0z:6'aEULKȖ6{z@%zywp>Χg}@+y*,!u)]< Y,[o{.+U}(aANK .mz'!YzÑM: ɻto.z%_B,<Ϗ,*ϽN}[쇹3>J)h 2hN[r`{_?S~wcSusUhkQL/B@o*ZUfq_>8Mosܮe5uG7+ hD'5] ?a`f%Of$N~;lPEjeCnkXmi莴?珟}Quoe,|mOʫG&+Y z|8(FA|Jn* 2G4^.z>rɎU@AAaW6[I,sgqIC|tkNOGO+i1 *=lt 6oSg۔>})N֦G(]K'M]MM0 kcV _G( zfqeI `b j9-C,PW:=_L7VnȎqޅ.%J5B%vGRt^^vE;v+fdԨF!#EhFj-l JH:$%6`C2We>M fͨ(o%.$T<0uVaGy,4g= =?IvI99axVyj0yo/Qk6sI!J*$Q 2:?L 80%0=æ%$SziJK}ɦIwm4B#yn'fֻT5 ,uk %i&-ADSBauF;-Xq]BƔf p7ɣظN(KF腜Ms wr0@ʏ}%z;1Gzz,cTMBK鴈%̅aJdh0WZ0VQb;sq(Spʲ@-:NduKkȎO!;NV32"'q6Dl:b ˰AM Pt>tԠ'=1nq) GOD(>9'CS f5ޗL6zzuK;#=8"j;52ޞ.SD$Y%2L30uLØӳl5k]+>,*M[B΍܆6( tk0==3}-k<8OGmRBo_s) LzU 3kΡy.j&Ľɍ>?=V\vNa ,Q08Ħ ,<7^51qz@i7XHz}F㌨;r8&:ϥ&TXǁjTծAyRJ7۪P|@lOy&vD@ʆdS3?y,\ d9w"Guڎ= `C;pq2] y"mϝ$ja޿NJAzumnG'tPB@׃aJ:z;^osEq^e;z@H雔Л@k5rynWl-7#T!DOq/Bp&> Ylw$ߡ௩>(d+SZK[V DI?L=5>;%0dMqaиըx7ύ6,}xOo/mQGi?dyO},/M Maro/NRu;z`.zkEIžy3ϼ馥/zU_[\C uޡf-=!Z 8yc5:}Ґ%,i mYKO{K75V1_W| Ftׁ!o9~s?yK7ڌMdm+.̙[\KNAój!Z ta|T)} t4lXeSpeUG>KfΦeza?g,愑Z\{d,J2[Fc:72uUWU>Rt{;w|έ@Oe;e847/-t7~ @1Km`BO(ZFw5s163K++%QuQZ8Xqmp37?,xP9=sc3V>|u62h4X0c NШ l`a?Hn82VgAoXjw_ >ԯ?FRC㡗?bzu}|xxTZFoh5Ʋ+H iaVDnfc5`lR͙Ēr7N=%%:GE% ˘,:=+] X:tkx9|J(5O|'jJ&GZf"KxO|7vQ|}UY~>$@)KLطL7qwo%I7i&1a%z)Eo= 4t~Y:j }޾S ҫS)9FE$琛bd#mNma}f; bza\ =.BIyvr[ VA\*;@c58N)~vrPo%8^mvH1 ֑^~5(]i6m!/\*8!|1zI)ݛ"siKC!"zM^!5KaC}Z(J`<+H˚%qBamv31P ᄐzɟN@&@O-~L=N,zl7jiu'jx)\H#?F4j$aC@k D*CxJQI Ij0ڞrCDZ, +$v=DbK#t㋞ZTr@ 5V1llz< psH Lmlͪ"+D)ӭ;b1ZYJ/sHIH|r½szzJ5=zЌ!zԿE-@3y 2Ы'\䁉ѓHO:A70Ӷ59lbqzLy)ṑAM< 1lG_ѣ{~+&xmQ`8T23KzǥMNd:tAo{ У)$5jسRoz\T*Ћ9(.%'UzG"=NEİ1TcMF~^l0Fzj俏q46蹽1rl5=Ռ-0Ezn=AzsGC6þio@0n zXm| G;JΐV!&=榣v@67q=n{ܾFzzKwfjDzR #lW"ƾg\Jѓ#zx=9H{g[#q2s,rcng lmj p^ʨ!TvB DBU7,Qz,)q[N^d:#7GǢ[d{)zᑋl$jBeԺkYc NDo{urJqzQ-5ꭼ$o-SPFrߓߟRL1=F-lSbV:)P=lO)4*Y%+!Ru $ouaW4!##z=8W :?{;~͍y*0W^ӓ+MIË:=|sЛ]X>#~G!-0=[LzJ @/0<"@Omnw6zu./=4Z]Ӿhr#a{V1U%,/]WQ=i?šY׏sHۼfjsO=[TMۯLMϟefVWhNjt;'%`.fk2zg"IO= ?^{/@s0Gzd iێH/ Mp dL \jgǎyUW"OyQ5mpC^1qw73pI3ø>AҸ̝&٢V1[f P<_jZύ.Br=G29g_k& 2Zm U~01qkL7g. H" 9X3u?bطzF00{1ozs:0\fލ;Pء c~WV0լgRϤYլ#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`!ŷ9̎Z1pc-/G`8Kߚ8M(zk1/x1g1O}c"g%v:8"a\Y߻c%i_Lk^$_+iu#taG۪wV0 BP 'VtadOK$Ҥtq SMM/^P+IO(^Tyi\(DoD,*dke^^2ۂSteSq\=\)/;wqwQS^vdh{Kξ}T.N`;vj40d 6)jy.A'mjs^X+Z2-Fjm ={7tf#3TZ9K/[&sV;Z0ѫ76Eұ]Qgx;оL dCF6]MKDm2Ʋf̰o#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F tVM>۪\,33v;#88^;=]zȉȗughMBғ]xS*ydu.;v~*+W]߇)i,wA,,[祓_E2ѝ !4STEo.ޗ-gl-V"yw,5gƓcžPeQ k'~/Qd m5ޑ98Ug2ʹLp$,T}d#z(FL%|~S^7=l(5^x C8 Uo>k"Veio6Td'踿~>cBwκ3~7Ykmoݨg> rZNk?Eoղc> E/6DncKЇd{T30h#j(Nߟ7Je޸CӞO~c<N8^k n] /x𿇿HM CLwY\)%J[C=i;ґ粊ַin\gl !; ?SJ>G_dn;mj wݥME>q\LjDe4Ypyq/ ') /{e^N_#7/NT ]s4٥1}%]5t->{zs.FBh@/+* kv.K swv_!g!Ix^^ :, խ[R9so1׬#06nZܙ==C k==(GzeOv\dI<]YEnd`q^|'Ή.ml/TnP#VP^O@r iִNnZ V/v=mGz@"'ڤ:&ؓ&)|(]u ,P7.q9kQ\k5#=^ӎ64t[|&dĿnZ j_nH .lDVL"3kS;/96ۉ^D/wzzb@h+M z^.Y /f?s&p*卯q"_t"W9{iMkuoҽ.)['w둞kgJ[VZW&-t9GJ[ ]H/7}#f.kzz'GfZZnMA N \W3{Se{ whlx*)Xj^Kn=ve+^ve{{aO7wR^VoM_G OO÷-ᜲ=Y/רsmM3L8[?N=/PguOqЦUۊ| vERȜ$T[kzzmۢG<G"WRGz{z~Zb{x<%OG87)#q_ҩj_q^IhǴJ~/j5dp7 ;f:>2QЪc^V Z lJ+CKy^OጎFVnJG0$LmjR*w _\t{E^8hDO Vᤫԫ@s^ɮi0yc#ҫ"IO&X^,Hqh{5͙Dʱ:;ziOOz:bERTH{ๅZ lml5nonG~i@OKEzAcxnr8H/@o =Aq5a (&G^? l{c=55s3jp6Ӷ;+bR=X=S=dܲ$09]4DݯK L#=PÛō AZBÖsu+'崺UI*)ueJW>d/ C+~:km9a6ašm]L諷ë#L`4/ Aw2W$&^/uF'N\yZz6 ֯s?}_ٻWsų~m_@{3Ty+Ht?U~~5e#`0F#`0F#`0F#`0F#`0F#`0F#`0F|}'tR o %*[b⒪wSdGV-KZi"^U7Xy}bo`q Z]\)ڞasS|ՆEz|e]P(9>bg-x.kZXhK`Co[Gߥ?Bh˞KqҌ`l+d)Zްb9Ed"7eG?TS5_<۰Xb\O Ng5ON:s9uf bB_*d5v'eeqsx!XB%j>}k 247~8y{} zcdy=2_ps &2:uv]U1cRχeĢ,=h~Q9?l~=fu c۟z9z,;&g}'=VfP5*}!{g}~V?Fٗ뭫ʎz zùYzɊ/K1;:y'2gw,dx͞kAz v;1MO^_|3m/^#fC,w>ԁz7|9У3v+tY<-o9r@jvޱ4A ߭q2ثiT͊¶wazU$޲{ՙt. oi] n3 eiHB3ZD@ nt?kɳIɰfxƁ7^؏׮TCsg"Fc?vA _(Jf [4WAGJ F}'z{r.F:ܝudщq kɧ5=k4hTV 4V^rG#:ab::?^1oC=>(nUM[Cg%Z '4҅J Ds/sFT~fUyQwsH%rʉ^[$NZ,[rEWQ MBݗӤ"${؇:J/³DzzLP 98@U)9ЋszZ9"Nգ{Y9/a0i|jZ%TYͩ^)ș<74!RWA؝i%5䛉qW"XQbG\FjQm; …(k?#ZJ'y)b%Z_e =YhOO=q-z[[d {jzf<6{Z4ҜTBx h{_mErC=L)ҫz{o%G-TmNٔ7zC 4H,\4=i?adY١ 'H=[<"t~@Z口)!E.+:DleN.zq5Гf; GsHabOoѣsE'^wNO]#pz=q6S&lGzml| w>Х g=2f*D*t\L\6Z'^ha `M4s/_nWNhQ I(W=No#ң2S"Հ^^53M>/ۓJNE8˱sA 1UB=d$| z*}O43/UwUPsxI=izx.О+i6rOMZ^{AuqP8m+&ӄrI3AOM.$zR/Ux=\rOyz z1q"5ö؛6yVC$-ғcj};&Oa3l=7*6 Hz)šGV%x«O5BEM_9<@vCh{/02%^ȓ遠zEܳ2Ga,lEz5Ы&eğ,5nd r^Eb+lhD.zkoR(޼͍jи7-0p/,;m.IgTSs5=zD ᣦVߑa{tnPG/TJ{ {n;e{K0?4z.Bzx| ܲ"mK0i 6|OO2ge{t1ISiԐE(bf)-Ľ)ŏA Tm^.Ui>= +,w"=^ViurQ(v蒲Vcms}ߊj@2DzC;JZF=ɎȺW<5 49O).o{çKw~>~-nGzĄ=ur4uy;Ѻ(#1Z3+VxF%Ktr3 MDXWdgxVR Ž6m|_5; Cֽ"l`M\jŜaC&yx?碇MyU=DI)8&.qSWky*.U lAa)4W+d;Ϩ7ʼ /Q&dl@\ ^A=9Fs [éP;i 1DĥͮrBa3b{cFoMEW2MQmm=Ô2 _ުQxKaoPr"Q~ㅞZvcbZsIԚ,؄^lAラ}ewIak~F>]m,ۮer^-[lZ10 '2ˎݝ}Zfٗn~vbS/r;F?xX~/1\[rȊ/P6i5}~z}_ ]o{hL6\4E?>ƿMqŒ?>}ս>lxB.xn~7-Tz >b}<;|os?zvx^&cNBno]9R;0F#`0F#%I/=gіCsY0F#`0FC&΁c!pCzv/>l/daQk1qA<4KP-rYT2qzjKX4^+ٰ [rbl7'+ }ݽ}bk|\5_8'am"]UOq ;OOi!_,ƲeX3NpDs7篬G _ k z9yb_%\}v}^Y)~8DZN/VYXE7Dv 7ߊ:qN|>/{L/-zC2zڵ@oƅ:bFOx7w z=n^"9F_Z^Ӌ[yXAzT}ϱ=y$s:ءl//Ͻ9F#zZon*ު= z;m{"+7rן[:U+28{N~u7U{:ې7?RE"@X*xVzg]z{FңMd/7"}p'{vi`múFwT`}{>V*YҤ͊,n|3ܦh+WI_'%+ 3uzEE@o`Q8P5lr:1P}ej֮f3ve ";%pUgr9{Cݔ5Ics QiA~7ey e(YP&[PFkqvZ>b/^S^:>Ǹt2_~e HҔi/dLڍQ9}R~67 q3KQk,R~/ ;yB` 6Kb, YϝDqM봛T0䪺5B4g#=||&5θAEF`6n|ȠGf˚h#6[GNh7W!_!8%I;+$<!Y5-)6pQd%v]Я?4]U^&ɛ| %j|u <*#|z\%J Cb}rQj<+wif> m%"!qUSgʹ_G@*Cngl$ȴ+ufğ̀:1DXsyPyEյuof0b,XgҧUMFHz5w꣖Hr:J.G^H9ABw5OK֦rدICqwGUH c.[O%``.9fP&JfK1qnZYʽc{> 95~&ej^ңCG`Aml ѫ6'y1NDyŐAɅ[hftuY"bm캯zz Joz@Ĩ`7ң;o`aG\öçAw0jck^)z:AuO6 ]#$s[KVbP&[) !:pPC1 ӗ, ijѐSԬiS8zp#ʤTm*M ϭɺ䯀fp2WP+HO#6p =q9zDfJg<@i&)6!zeҕkmij0}F_^femONgj5\)5~I_t! w[ýi+Fz6%#vTd=vkDfK12i!geb}w< NqSIbU'z^s{^3૶ 起=߭ 'Y /dv_zqG< /}]{W6=l-SgpRzΌfO6]ozʭh{ܑ:6ؒG#5]歜{^@:遞; kD8R_/:l\Q$vDϞ^P`&{+]^<]-)l\pSTWǸVCEکs; ݌:l=W=^']HOwW?~.}In{t*M}M:޳5\==ibQ1z=^fCv(-=7݋{?|ߕ5z]XwzQa^8P= Ξ}]KD=ǼNA?8\C[R9ZzP=nmovt7_{,rJX>q#z\H /V Մ.Ք͋z/*8M=w&^+ "==Xܣ0N{4+ɝ1*c@p{gгi}62Ĝo޹' d{P\#2w)N@M7>Tz7f?Shy;!wM__gИ6#!/+&S%`ݺΈ$gFi*mf ^n\$hc.&l//>3C]yߏyxT6Afu]DݽkNte>}Ø_@<+ |)2Jk>/xHeZwSrR_ Diy)>H+~Cbr(kƅvҒ8|VT*x{/O~>$?pc_/(.A(=ʎ`|4ś W_pٙNKciq~Gg4v狞q;leU.,xɲgn_D3q+{ǟQ^>i17^/>Oz_eg]{{16|bN6!t,3}Kb*4Աy}"S]E>ל_*^/|#EK^qrd0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F3&G_ endstream endobj 23 0 obj 90139 endobj 25 0 obj << /Length 26 0 R /Filter /FlateDecode >> stream x+TT(T0B3C#sK#Tp< H$anag`dY($*{(u endstream endobj 26 0 obj 62 endobj 24 0 obj << /Type /Page /Parent 3 0 R /Resources 27 0 R /Contents 25 0 R /MediaBox [0 0 612 792] >> endobj 27 0 obj << /ProcSet [ /PDF /ImageB /ImageC /ImageI ] /XObject << /Im4 28 0 R >> >> endobj 28 0 obj << /Length 29 0 R /Type /XObject /Subtype /Image /Width 2544 /Height 3280 /ColorSpace 9 0 R /BitsPerComponent 1 /Filter /FlateDecode >> stream x_~Ws}0 `N"Jm^ S! 7yLE @ɫM Ak$e#qbA0{CADlE)^MOW>?ӳ;!y8{wS{\p4q7f첉1wv/>}|f._z2?>;$u9}kf˜]i?w6իuO~;?a9c ^C 2ؒG?_׶kq_lrTY{[6bGJ=N(?R!ہ@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ OY\ νhso}wި&-W]׆|jӅz}^(̓_6k8 + iv}! Tԍ}==_+u97d]~uETͺ GʸPyNzҺe ;ARY~u5~يߋbmo=  ?ޤyuo_?Lzm>eHF_Kzľ#A@Kt?޹ ׵՜o#z[[vs ܙC^o{JYK ˖{|g~WYD"zϻ_u?foGo^yKzt3}9*9,)1?.^FG.KOғDžu⒉*fNXr쏧fR}X4Ke/U3l3b:sqOOU';pS9>&n+]6Ic4W3uGų&Lf1􌙔LnjnZ\Kc&+qeL?raJz%w)_zfrL2 vW 3]IA<˷TEٿ[꧈3Nަ]y$՘lWҤ41 g3=P#iT۰6>)|9=|T/^"qbUfcLTVʒbO./)B\IyyOT6*l;Ea>5dFQ"!bf斉{;&g^LTJ2YɼHͭ)QpW޴x}2qTQ)`&}}\5&R 7Ie@6Ue,-%U&9wK[͚iDm2"ݽ(>.ܬyQp QM\EH:֨U Oty%.*xVDžNm}!I*tqmc_n~'́dŢabîW\VI\QXr?5-"( i̞.Ns5!4Өq=} uDg򭡗c䶴smp ٪5Tjzu)C4wf(y3U(Dւvm[ j{$TPWI!4 9K4 ,-dx^%z29 7}Y[p'%7q:Qfzp2K# !$4QGof =xAUO_ =`( MtD4)C/z-yzKj[CoBл |TdLQzO+^eRK.<=BG{N &E4IlЩw߀\O/om c2z7 1=J\B=#%VT2=^K4R CqcN囻򦹊i~Lq4*Y˙T+YUހ^e s5EjQ$-Zg$f."aI]CBoB@Gl(FK^1?嬷EO0gUIBM܃^1:V1y(^+ ch[.GJkôJlOFiw-+%SloL/k>1q#ۻ`ڔ|oi{D0 Y77ʶʎ^E$Tfc~--`]̎oLD,WfO5-S/=z:L8|/aE=n0 ӦN-z55- zjL*cgö-,m7GO2ir[ &r2ЬFau 2j͖{.~D z='eW/؜l۠}^\iiYZVk 7Mݷ·g3ǾScy:s`p< zͽ}%od[ezd,&ZF튢J ˖lȌ<=JwȿӨAYH5|eKY}pQ!GI4|;){)Smhwc|Lؚ,Jݒ b fыܔӘᷛX[iiv`_Yo{=UKm~8,i "}&zԏm=sFYDF%sAiN!'Kzn$ƚP9;&]¾)0aRG&$cZD |c7D>"Qɳ"ᷪd{Փ P.}S;;H&RV̯ Zci~czE\aXF#bյkʴ9&ޔu4f&l:aG%gwt:deGFx9>)h0ddZ"ML fУzS,x˞$3Kg25ސ3Ϟ¸4ᵜ==Sƙ#/3&hvyb0w ov =S2/',}\Ť{7VL(oQoY+#z{-IqRZXA;>oxc9kHf*(AAOs[܌w^,e&k̤[5b`)l7mܻ *ks]R]1Vxs%n7ѠbOr;ʹGUʠC5F{z~a´<$E1ܨa^a|xzms>_/USFn6.?wko+1ባ`{1V䖌{ w3\KL=V.uJN.t{wʢ/ =$#?b{uON}_ub]/G[ږwOFսΫPtDMmu~ŷ^iMzʎ#'zy:NtYɓ}e׸Mץ-/=%.Y8/n>5|07Gg.}t }o/ T-0ۜc}7F@ @ @ @ @ @ @ @ @ @ @ @ @ @ @u^wO8.`?/,yR:`+λD_~d%]eM )?/"]dUd YjqQޖwn1_CXgP#ɮ|Q6}vFl;7uT*Nuhc 7 ߀?aN?ҹ=A|0_Sq(WK#3U ۅ0˦1f5/|*;ǛэUsNZٚ{qkb0Q~ h{qL::$Fp=!LDa$WmɭpyV8.斞?=ď`tx2X i!xgDar6<rqZLm]Ēѣ:лjSNoLqgՓK{vR;\vs^] 15PzԇP#c˽ip\eZZDK{z Ѣk%) )N[zUDӸGi |d{jB@#Zdm&r>9@dLtLAo44S6v%AE~ =PΈ4cA̴ÀMԙ[zmЖdq)4{r]["=D/zfQz֞^Oa  C8mK/=:h*Į䢆_$͜"mov E\[Jc,jC;A, dbH\qeT~ԗ*oK K:xEb#E2%P F _^kMIT\UOEN0@mO줟Vw#C^B<[!i0-쳎j@\R_ @#ĂrHcՋ A$8G#JfhENh`rBF3UKRO P("K3S{zuZx Kzu驓-[LڷEN`.ZTGeyd==#鋎Ձl I<#WY8OJDRXV9 {)1RLؘ@ AO7`g'}'fl4۞ Ιa&EԤ=cC\lJ'*4czχ<zbC(@ =C'%]+ |Ljqx#H-DsW˅!A<Σ8pRE.g}އe+O|[~[GOGuEGo~QôXGWmO"}-ٸ|6L!^Coӈ~jIA?dk];-sy_zɗB56zк2;YO[F{]K@ZppαΆm<#zWk{iecq@{ Q{s-\2F,0K>a:z&#o4 1OcI H9ǒU439f]MH&(Op6G%3xyb/NK ]gӗNN66 >α2y.ВMB1ϼVѫq-zr_+_ e4T "HTL{6|]E$5} ]kce{<}抻Ivsr3˦'Y62J$~%I l<"..#OnSp`An˿*,@E@o!R 9riEvRqN LU,d&akpx>%T"=TO ?<[!t@HT=LC,5uR.%T9uDjёپ rCNCHGp啫pNTRE26i'#? 4jLR,B79-꠰ܻ$ + YAP;>PzʨV$m7ZhCB/J$Y.i`8 8WQ}F ɡ"9q3]iU'ES RB+*(.,*=j,B2sB˳Kb+˄Rz؆Iy z𬠶LP=]AtV'R`>Zz;fiDuüh!^UPZo>"N(̗PkjV D-Ro;ղD/m-|ΟK@$-Уeʌ=(16"|`Ϛ^9>>_})d!B(j ^Jd~dż֥R&k[YW$$H%BW=&^Dw4Ej=j7~'*VmQHaHiz~kwzЙ^,=€1^Zc.G;4zYߵ}1?N~sٞW[ Ew#[sc<(ܑHnuv,-~I%ݘtd\ Cb't 1%O4&1KsK1gУsIhe3 /^^Ҥndzҵ%2^U730/$j(2%MRӘ71EM؇gNR6u/2LT15wϪmbګFaƮ-dzS$L]ܼ.Ml=V X/\^OgEcjבF7M #–~oJrE+O"D .!z3ǺKU+nv`Leɬ 9JV5g,te51B:,A7*{cz͕*&2)zRͰY@܎; ~˷XEWL4cZ.#R'zQf׀k6KOi =:{?4&)(E2j-=!s F=X _> R㻧ǘ"v)фz5Gn*˝M;Z}m4tr`x|] =zHAHrpiX_brd]OϪCs/]B{^ zd~1cnmc zs+s%^ef`D: *Oh9j)Sʪ͏ra't\:7|oQYDžr%)4S𹶡XU e Kۚ/fUV_:ÆĹ*{\0ȼ\zzX`X<EI9~?>$oV8f^sX 1ϸ`}~ nQ;} N߾uE{5z~/vOӷKcu>^q~DQߥ?"oB_GR?YR|_Y+۩GzEz"=8|s_y2@ @ @ @ @ @ @ @ @ @ @ @ @ @ *WygssʛG׹w9Lzٌh]輠Rw—\Xx9ʼn[kit̎U/a'~m޽9ՎiDG1?zqG=D5rK9[ASj/vqVhhC4εӵ_F~,OscFu6Igqp^t%o›}+\{s L|~4=YCϗji6W7e;⭻!*,lZ{CzŞ('x\pJaz1;7x[rh]g{gZݚHxң_% G .ϣRQx(֗C2v2-Ϲ>{#?@Bol]{K{DeܻL~z[\!G^x]:\blo.v+>ZºK^$|џ?>.=iY̼(rLW8S5>RJ%f?,[W!ฑ#JBHpäq3M믻?ycyNMnrcnIܞ!gh ~Z0BN7܆^nn!"e'Q5|1`,9G/"P.q&:OHpZE9=ړ)SQcZsщ肹sPE9ySj]n,M5%&KȘmkWh禐]4! ~J9 Q"gc?D &R9 s)zY\+46ˍݝ뗠Ii! HL[y\}! 5$m$z~iz*C [-F E !g@)m#5ܖSKޱiщy +3JH[$=ۨlP0AYC2|z)8 u ( -,?Yyzhƕ-mIK[مw+Ya*OhCk\ #6Y(41|zOOiVOcL2%ەzZ z B=0Git Ȥ,z:bxa%xz5;1DFcdH* K Uaq}tq] CKB%^\3[>zb=rOOAMTP)Rntc6O !޲N"oE#m =j/LD~mou( zD$t L.=)4ǿ91>t0:y=C᥺!gnAqN-͸^JNm=rF:2Do7:zH KW|m;dUE@~(/펖މvȴnARۘk!wۤ1=e=ch~F/z=0fqxf)DA+l0c@#$yʍ-3:*zUӓX TAw]v4URKHMLj.@O&mMz#e@=&2:@zGW'GdlNr+kbqk{<;K۫nyzHn7hVj 8}HEw:ÐG.ZGh/Z[7Ya&w{^c5sk[Qp=%/`{* "4Ύ^ĸ7fl5@Fİ=Op~и%+4\= z|17'F ܞ^{ME$&:z̒ms'R,=:9TҮ=dz7XO54Bkŭ+MГzzI}5-VU E6ۤl/q#h%PȰ>rX[嶶N]4U*rm7[x<TSQ-s O6-x@WW=msn~hV?`{zZ1Wj={kcߣ(颧wе\MC09=@8lfn冀zz{czdzGDl̵Gs1쭐Hf ]C {5sE/nϖ#IG?QD^ѧnwdK0ߖi4ӓ}#궥mҚ^ )fySڿс^2si==Bϩ4Z܍iYmS`zzD~Abi ЛPexz5[jWpQsvK5L j#'7f'_M!uݸ>xa+؏rM%vԲrǖv\TWOqRހޤH1AE6{my@0tddfrR@M<)R۶Iun.;eefuUDOT :4o". @ygw%2WQži Ì㭎xcSdj2=}=q=sG0z+DxP\Vemn$hkެ𶅗xKF>6M/=ٗuYmS S'-21__rc`q`~WL8L&̤:$0$kscrG0*xvWl1~|lwzKr~hպ!?z_Qoi?Fc]MΫ"IB37WOf_=8(e6E/yBMQŽ}K5ɸowlܑ;]of'}ܚƗMv&© ^@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ |఩׸ڮrt@wch\3ҫN@'헌3$gt4`=G~|m˵om h/ߔ1AіiwKC,9p}s Wde#-L}~s?V G$)[}28糙.홳Z*^owƱٕ5ơE}auʜ_͡]Rtd82n>c_S/SE/j]{cz$,TGa9c 1W7hsn떩p47Џ#+Dkul{C!uCIGV^s^eVt-=ԙtK7`kK^opUo\Udhz?}8@wO|b<ǣcRyշͺ\9>*}C`]'C!-Cs)][1LNԟ߆y$ /1X[_^QZKdPos4b;z΁Ēu7*q;ܶ~V~?fdlK gm5i{63z5rCrZc[r>yKk:z^ۈ`Ó>E҃{Rxr0}h "m=sjx3pM_Boqf@ՑןR˿ i\EB mݳ/}%67 SP|4n~IQw{G @ 5T*=Gt? ;1q1ͯCOz3׹2[~=ͯN;(ާf |$9{&r?N'.h*8);ܘ1C8ԓjRK;ܛ>7|,6"9 0U&]^*G⚟Vkss݂i=_ %ٕZyd|?a1\}== wᴩ"һ+фKCpX.#m r.?&8W&.ʛIeYS7D fVGuę4AAqC)ER :1Tcq,0J9 %,Y;eD[FxB -$ }@AH ` !zkDn_"ɢe@7b.x*,;+IW]KzE($PT2=$Wz 6"Ӥ|*Lz9h =ah*˨0B)Vd/Ejvaj7aCR HsAZ0R9H詿9euNhS5ոېCD-:m=<}WY҆!dBb2#b[dsJkJ;Em(Qa{O]eF+zD@O-Wl}("G(p"ne{a`fsR>#/2`D#*=f-4^;$TZ.Szz%8<=㇯%{s:Н6JG6ؤ`( 6w{ŶZ\¡gROlea.ޝ0HԅWҳe9CQ$K@/bW;aIt&a|LFٙ5(¡4W)00˘@{zxa@@jeVci`&8=lQ=ǓrCH9*=Np"]WA/a" -IPfO)ŔIe@,DR}̞ҳD&s"AOЕen=CLY<=zAr*AѺŎZLҼGNRs4~|lKT9~F5аcWcn2"]zj鉂' l S}'f)j=U) Lz&†Tt5: 1g;i&ӌ)\in=/TiH8%dP^ 5bHW[=ⲳέߙ#5`h ~|e+`Q0c4N͹LØȐ&nvK+X"]p NФ{C rMěk|$S76Q&8yzWT04K|ɣ~} Xf!R29=IPW) ` xQmWz*l!f}, mUEzq$q ^ӥ%N>N0dMJI@ I#KXBM;l dzE|x*ul|c}AϥnUv/Q^svKW7Nwsݭ֋,vj7 nOTOWYgݿQ9Oo,ZvBGo$K7ׅy{G|@Q@6Q/ZW_}}w?=?Hoy!5!^)T9H_{sUSQ]d;T\raԢF3 P>"_&2CUm3| @ @ @ @ @ @ @ @ @ @ @ @ @ @ ktGE'p+߆//78'7PFsIZ̓$VsyW>z: 漑sZzqiJt֥q.@oM)JTX(Ӊkip6wi֠lDqJ֑xN ޽g[W~X} |zz0GSz+g[Nm,miss<"[d3uO}D{s?^S17gI˻/E/++:z:@#*{+~uWSmSfZ֚bpt3$:7؞jPW#zJ1M Ym6sVꙴ_|yFݙ=NJjOҟ|dttgS==QɣL_P^͓/O/{[#?"Vp[8>1Oi?7g9{BOS8\*x|m+ (]w.QPk.zҡ{sw`{|zɘޛt87q+~ [/Kzq;"/\V3֝%C&LBzG>|?t>>")1{(j=8$ cٔ%s&/ܓp"Ӥ956:,4oLʑޤ0,e#Ց|WCAY{h0۩H\L﹃>hӜ*%K$6<.ѱe&.mdO1GY 'Nͭ[h\tD)3REnXQsġ'&-9zAԛ$_+feHtnF)1zɸ2ձġIW 6C/wsoYѻP3S˱g"EI<vu zՍ41s\}3Q kt=ѫ(v?GξI 48bk!&^ZuRa@cDKqm},.A/q*%V(J#5|Ǣb.eo^.#5A!"-҉1s>C檞D'̂P+F$El9DEezjMmH?)*/JKf'L)}$Cn@/lk4+`O2hSHlz34-e@Q7J@BPvz?M&*G=".I,fKDHSGU ͂M;{׹97cm/|S, g FPR҈3@]26e?Wo)p)̖!=q򣆯 w6렗<䍄zXG͔1*ݡeDTDYrzjԐ$B#zz{_(n:"zXTr:GھDi ~J`IEcdAH('z1WyZmLV钞@LJ{5cѓ(YꞂ BCh i9`c:^jdSW?|[=^k{>}k?>==`{8Vi;4W,zLG?MYkR{z<~驋hZDoǠWb۞'QmxU2MDOsZ͟ƞ3PB)k [_G"= x=eRaXM\aVږk.ZnoOdhw Cޡ\fzG-=V0aNjx.mP-yK)5d&mBoqG -Oצ] 6z~x}.=^{=\4lkK."Br1Vl{Z^hMfQwerJ;G_>r:z{mEVmL/sZnGHJҵ\V¢?=0n.!ݠvF;cah.+^+qg^ҫW1kVg,èArK+DGr}$!yv)0<צTéXV؋VWlέ;x^>}!qjP/USrJ&Ju^䷷ᘄ< &8 ciFwOF}9ǁgNN^e2js_ֵ\ؽ-="*zV,*~opfr支^`o0^N\4g18}GqY׏$狏;Ks~6-J'{#z:AaG¯qa{kBu+cLhV'zHZU9g!^dđ}"+y)c{}@^umZu}k`7T} ={{c{zG]>[XKWv~0bgmlWs:z"-:u/_@[L̹j?[w\Vw{DׯMMfBuڿY*?r^]KPp)~~3Nw$$} 4Mr9Iƺɷ _1U7Z5C/_ɠL̨A\3Oج8\[H/K(UrYngSiv83% <ęS7k)|68>57'2UyedlenpR3MՆ(>4qq? D }Kw\JT NۤG-|~/-esZQj'.[WԜu۫GvN\0"($UDmLĶ.`H K]LWMD'&Ya6zvј{h^H`LPf88@A "R[ QeM04@OZ"lC$@sIˆsJ(ܚAR`3NVQ%q4'jh\C9BO=D/)o#}zN\^9L'nl,{z/=4ң 2BzU҉3"HG.%.6hH@/H7  U1䟠6E $@]qsi"3#imJXHEz{z(3 #MO\DE$^ѓJW}L'XJ6Pݐ b|yATk>LJ L+Kݪ![큥e@/1r{ndo2͔́f䪌7z]uzzM+yEJn 2z 9b{͘NV<XeX:%$v6w$)AP$ z=O7f`IEJWv-qKo04S˅^id{|Ia~*lO]M:S˝ZzW11sd2yƏu[cO#z3Eei)/WGDvRzi%^\da*G cG F=_ c/z-7c]Wr1&B|k[ne#hlٷv%u-pD/b4I4{y&>†?hGDt3zތATd2y5qxTi aoHHr8uڞ[G/-ͭV5~Z\l1*~.|6?J) c4-"z{$P-W9 dxm}F-WA[FX4/< "x}.<[@Z$wkEd{r2|#2ST#fN^"d|[5'e ΡǢ pjXYr7t*7Z%ǪX>6Cka:z,tj{zpkzb9==Gd%G#z\݊g#@QSdL+o> #8|=y.T4뢧-\?@:eǑbe{-k0\\}\};]گ}lX+ iz[>s#e{Uǐl_"khEs-zI!D=;ݞ`{мVv]G_c=Z=ORجur1%Z Cة]Wo)Q-}XA̲,WӓW'A]vMzz'=L*t{73,ikz(If ] V%ňyn8۹-ȋ/+jO+Oӂ`R:Kٙ] ,͢3N۫xL Ѭ8_\ixA"t˙eny_c19DI7|hW<ۼ7^א@37:"){fTYn]|@h[tv>jjsp\e{8-vL`^ыG'z?" A~{&.i9J*LG&Y5ogՌuK@'ފ>"/Y3)2E)9)mE]]H17ы)wT[,"DFǚՙ݊R3ɘ@8z TN~媯\ߎ`tV`[9+W?]eANׯퟘu.z83ӭp`Di A,X=QɆ~\7gov J?vk]n4~iޱeVv& Sv{Ne^c o>,Lo@oBEatޫez6VG<8nWzﮨ;k_ B[=xeY0KV'W\,Ow=M\=_ n p8⊧c|QH ~vpշkp}ݼn#y3~*Ƨ.:M<8Jz[=<Ǜg4(yw*sU_]M \5$i~!~ @ @ @ @ @ ?>iHe } x!i @ @ @ @ @ @ wC!.ş/~(׉\ 6_scѻfّ "6dVCHrJ6Цӫ\̕6!dW׆4=mevɋY A;cK8pץv%t[Grs#%OWR S:R yyq{ıUV~;.Ec+*{]znG2fd{ѱ]f&j_}HƸOwvׯ_\%uSZUnFA״Usu;2>d+׶_.5fsCq~2OT۶~RY[]jiޭs=C/#v17SO?&֩.*ĈiOoahpM|&nd{7]|uaFzk[<הN_j3675Q՞`9CKk{ k?V2jطn,,[!eO챲믓k|#$O`oco%HOuq^j|vT~#f;H>_W6d%AR=g!s~;Ft2om̒v0.flR~[y7Tpry$A 괛3#{ voCwȥc/H*+=y6 ]7^}BX^N,e o_66 S [GrxƁh:g%&?a?KPPeBEʰ߸'\jD_)lEN賱zq( k{\93lf˄njxS!z}.UZqd% f ufS Q柉^xbs?iSXT)deyJ92! =k!em߈g|B HKt^Rc{1`{үCz7zOA=ݑHy>d1 T{:C!#F&2$,!I&?bqGdX(B .>D$Zr&V٣ƳZb-_R;ۣ*jLJ,>.hOӤP )6^#{i2A 6W_E# XT^ ^Qclm  l01&Op%HaKTQ_'ctUʬ CIN/HvSFKq0<B1[ h%QI.|e "muT]=򖵾9󴢇>qPRX 7\lPt;Z+AOpr]qX1eTlpq)!CzDO"8o^OB萧SӦp8yMO/+$7EnLjLւ(c_͡l/s e*X[N}:ϥ%tِt9A)~gT Ej̶D1*e^A~ѶD NlO^!Ŭ& C@qW^FNQ K֔=cG/]LEBz)8th2UW^{B9 C_je{xQL@'oSp `b\ugz2(3š'`H$z.3q9G lz\=@yzhZ~Ni(幽I7wMpm{LYɢq|zd2f0/.GCYc1bOo!']ѓYң"DqSdF힭Do-1cUC`z=G㉝JG*ԫ⺧-e++ۣpgG@l =l[CO^cExm{hs[cz 'by=OCk rhR4sOo9 <۷{3u#\H3SWG{ `f'PP&= yNӛ9zLl{wGo=`*qfrk {³J<kg+ä [7lxx큇%;s ]5x![a+z8jOU6;ڽ#V.ɚ?o^=yz̜=im(;i2S쏠\?ZܘV{{3=t<lcl4̵4CJPualϴr]Pb]*"vE PLt cL-,Ƶ% La^Nq^m gG->\O'bݨp!{b%z(Z"k~\h5F`&م3ੇ%EII|7TPpreFP#[Pү7Zcu~iFnu41e 9)vjNiHԒ'H;RFX&u{( IK=zFmxF34nL>57oڝqk\/0 J[AtU%e&w&Dil _S{ f}Gyxp\5"1Lɘr?*N,+k&UD ^p ۬4>oȊ6s.n3Hs3^F6+Sjx"8p rѣԘiyQfi/^7J[6=1xi"7[}y40w.,JiF f3꧜E:DqHWMprī&.rgX˳Q )yթqP*&{qDG*o*Wb&oˤ,+۠zmbTBmFN?/H XRY\$qZҋ;_kwz}ogoWi׺&,iaۿ級LU}n`(s޹ߚ&*0%$=u&R=/wwmL x '!yiH ([ƌgm{!yzR aLoԣ#X>1B9=xȭҰ=.nEB=fQiQY^MvbHxn+n S[܂QD=wQ뭱Ty7d]Uֿ֥ͫh.Kerͭ=B﮶O9(A ) |ft-ڙ~uU33ds{>㹤YZrc5E=fL൩#tfdl3[ĠTD$˪ݿE#4B/WuL"ϚQB:boІ8_:mLvET<ˈ!$ja b?p)c ,BgE-\TQ˾nΐC+ة%9힔 zT19ԃNZS9,|Y5HA7kf(E/Q_RG{HoLFfAD;iht$VDo.zh"^D. D?6^cXߗEУr1޾p2±*=O pZe|_ Å*oK8)x)$@c0G ^#@ )8z*EFr6fIy5+%q\J꼹?O/s8àWN^rڗP` "*LnKZvkzu(=EEBlJ=d$r OϝY!$&@ ^Gы/mC}E4<L!FY;s N"hOHBRf+54D6^lsһXi䄢i;zΔ|}B%۫GjWGcP]yztd0&Q`QCQ4Y1Sy @jkHP0[@]J$qL =@ hLzmg6)GTUNd}'z_9kWG :emG+l1'|'F3Fӈol;]ydZUaUQlOlZ'bg5l1g=D$ G|]Q\ [( Ee8#)zH޻&ӈzbG%ZZb1Sw#zs=@5ҁ^ccswcBѻ^>`lMlV]T4! }.u[٘y!қ$(5ƶ9z eOV}./mg^vh8A 5tkƢ'U]gvmJT+G c%$)z}5N kQ,F#G,ys]̊gXWnԖ:hkpqCHMgG;YE/sj|5ߠחPLRN5VRV|RP'!htw~KS yG,nf%T ^{:C x-CALueV 25K9(){II\V8 J:2"gy_e茌~ed{ \2LwH;@q]'@j՘SHY?T:ѯ/xsG/cJLX3#Sad&%?&#Sj 4 5wdi㹬N^JB/=/TWsY= fE:i مlH)v%è |4s(nrf5F Z2o{eX,I@d$9UT Go7 ~UfiƱo\]gVwZon\]o;\Md7}M0W^#K;mBb>:u)ݝ9K_8<& F"_׷M׎ysz|\9?.of\v,'y&K+,k;H. UrIk̙Ҧg.Pפ3cO96(<R8}gvgem;R{h ]I1<}MccTpMz58s'oG(it8myEaKp/ fL#6ù:hLdvXd.?X1?9s4>4?PWqV l:+%ͧf{Wօ\} 8T9*cWl3:^]#8[s7=%Tz1L|XpϏK=WyS%}bN}A>sۘ^7<]ݻs]yJ:{F_}nbg%q{Y|o ѽ5u/\[cyDz.c1,[ͿPk}ll)+b6oZD(Bv'362GuoFE9;n#4NȊgQzpiGьxud9k4lrIsE-WуdT{#7zĵFGąe =.mAAOovQȽf? (;?<Ç=M'}CZ!+f5ёW ,[h7Y(c3jH#amRt67L pҾ(vzv0ؙއx@v W ѫ$;Yϴ^H4b84[m,;v'yWZh"]V{1u}˟OU g٤衽@om/hhyl#A,l.YD#[I1c.i1s &-T?ߙ iVTr=.BsLQ@*iG_3hآ ńf7CbS_&CEHx@֖z*76.Ees ̑l4kSm9GőFOI\"$n`1x|8 I Wb@\_FM 3=z^>)5Cz/?4X(>,I,g}=X8Ҟy`f==oP3;m ,!bgd2OA ~ ՞ʾb 28՟v=M8)eSh }W~E&ӥW3ϣ׷{o(voBwnKyzjiE^ˊD9gf{o4\AH{.C\zڽs$3۞~=465sK !)힆2|m';7y|E5=0b+z~4cr4UѢ˴&=Aƞ"7hޟw<=n+Rt:z!ݤ5=Jб<3\zۣ"0 C'qM+̛IfN2VZe c |adV=gS&tixMRUUϐCgjHBc鉣+z$W̑YMLx#,Gg /BF Ff"/vpWbV:Hι>b!‘j)*Ɋ|_g.bZ-RNua֖6>QEWBj5TZשI߉Q_yOg0Ӹ荤@ z<9eEri2m!7kLinL W4sۤͽ18[xzOz۟q qѣzD5yą|ÔLx˕]2wL.>d?|9JڜTה\zǤ;燉8!M|'O)db>ws k?KZZXk."rtэn+Dܜua;D? SLuV̙%:y@Wίvx|8~䟎ݻP;Ρ2y}Wba6wU̯&yLn%D @ @ @ @ @ @ @ @ @ @ @ @ @ @ >e?f[(vf&yk O_E*2kON?| Gؤ.{J6[Tm8qHw!i>TSޘcON2[] TņTl=p}zhOSuFtXj^v{gy3%r} Q|+:E>`'V ׯ`7lf4B<׏)[ $tFz/6vG0X^]`EO{Z}8?XMv>&ӻ*z;9\+Z\~/c}|W' i8v>5aM/4rnUT\^9>wM~2*UHuŜ(=m|3;S_s{h~*KMÞ-s2wF^%݊l/ی]ۜIAyeԷ'4ϭ)8{f#Fޢ|NզDjQ(Ls_$U/dZ|Z>bsr1z9㉣YTl"(a/.ZqFpV?س/gEF$)({mfVd|6^+\ ћ_Ҧ.ڗ:_|soJ` v(}/)'+ּJ(=~t4۝[? gPg(C4/QDAv!S]|dQ(X_CUU-gh2y)#W)zH/b:(:ڲB M [;&ӣg#8vR`BSSeprj2sL6إěզ VeU؊k9ɿFzzEh:0S,5?Boe#ŕh¤=5Kb*H^0oW|)m]VC7eciISb}]6uN"HK9i=:("4AaDu+[CRbmTxzt!bkN u7zD/s*?)Hۘhl^$l)z "!ҭ>$r:ѓloTȽ@O`JkzQP3sz" ܈xSƈNzs옞mrlS؅E6Y&r YS 36%]NgV4Mv=0uͽ<}i,=&o7b C5dTs QER;zvir~o:Cz7չ?Г>"3X0Ѳ#z\k%m9PF蹨4bt-{z{x kCTW4LdOS; k''U'ud2bl/;K|a]DF"]ns oG5ԜO\@A3퉪"DZ{ rdek<=M@}ZzX t#ĉs(`T==ib~3E㟁^O6WR&ac̮ƸexM0}.{#)`_{C]L%z@G Cp3NDOflM6Wx<#ZΦ5N"/Fa5I%tX%؞.^Dt`KsWAOm^z*{);m/(GSv|,Y1:w)z2"SPL̼{qZP5eyl܉=dchDȵtC{-1@I-͆w#:Ҹv\Y"I n&y좋߷ ǣʼ%ּ^]6ÏP\.CjǷe[OՔ8wޢ z&clu߾rQcX{R"x:KbϹ*sd We5,y#["wC^'0e/o=P(fڋmivg0IVŶL4IF2̖n7!q/mcI1jvLuR.5[6;`S&OddmydfY O)"qtG_(ճ𧃡]^WkO`˦ox!2^őDkLUˈwNTUG@T}ue$_l?UbO ͿtΏzUE/mK'3z#D䋯/o$݃hCl{Y^%tawG^FBN<uzT`=E:)L!8Zz"\O*q^C= ',G۞[Iy}Ây'4jf(wP]/[yquT~פ˕S ?Ыz\p-P]#ԑFO7ZefWtZمH@ @ @ @ @ @ @ @ @ @ @ @ @ @ ?2|Ee;חvo{dm1Zܖ.(zM!DTzQhHۭjWG [4|\۱?P(sE5F7 qΉuν~c|On6?ѭw@t>>utU>\=w#CX=p?N>z6ӳHi. }@hh2sDόqo4;c[COC;S:lK zʭbWttl\h/o4=&w1*z߹ Ƭ:rֻ>[vW._bϫ8?baz欂3g6e.W|8;!u{]iRɢf.S|#[?aԼcM̳\0ݙ6`o=MOY\@OZ}8vnjz siglOm؞4b -~P=?^[SzaE9rtvrЋV~{noxi.ذ=G"azOz^b{*4qq@.(#fWAkrHɊbo@;Am~퍦}.Q>B>4ZS^j{\g{ݨ|6O&_aq%7~qΘ|'3zU?߉=GxhV-L[9- zڵ;kѣ,Ol9=+{w(ĢA7fl)= '(Bd{Q8E{5v^!ֲ{l?2G=s?Α*@= |,eeI%#(;YE69D5GӴI~Q`;XNЛO#22Q?L8B }TwQG^id%HK+.cGCͧCx^Bu)9=?; tL#v1hBX ދ&sSY~| "/ 3C;=O ghHy JI0p%Vv(Zj~3]"}j 4%i=Jd4ϕ~DphYC3z W{kry`XG"8==rj Syz*dRchr˒D)m3LFE t0?@#K1Pԙp+(r"'&]Քll{-#ݦ>Xj]>nCOÒ=S}Ѳ6ˌ#5d>?8^>];Sg{ H)kށ-'m>i\jq9^M:8Ô5ޓY^CJx Y-^b{]oK]N;ЛxOv { cyn}?m)QRcҩ 8Xd!z9zK5]vO詹\/1Mz•>d2G{Fy9ӄ@?9$ΈE#f豨*z%1t{#znG3(nk1QS@dF,%d>^w pclC>wӶF' |IIDe{ [Yr5e EJ^e$c45d9WTH%Z[. UR%GLKܟI.e%ѝ Dգn-2tkCODhxRQxu5%Gt.IW|ltg.v-s2Y˯'hĜnT@lzIV1K]xHٽy.;hO_*t7$'IC?a,EiW3DPXړ/ PNݿdA-K1c_~~E :'ҢdXb^'ʔW慱˸%:lS=4NTm1z,Fwe+Hvi!yeýM mz\cg8Һ<~;&%f<Y@okD]lciWz#48\4r[FHvVQm7gEe"s7Ss'Q`{a@y=ɿ]haYf=)zW3[X{5.WA/x5,P08Ȅzk29"UI8 >tA6hK^ZT³q:koH8ډ#vsdmYo4 mMoE6> M}En?} }酈@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ O"YE(pLu=Ά |~8ڏ9<6U8:Zͽ2ѽ.\sc}*GI5&)7cw={6Zeֱn~l~zOdCɊ|8Y6kz]Ҙ ژ<:۸y2_[Gͣ:2NhLtN z?¥w\o6hh*shV(+<#z6iW]ޏ^۵Gnth>^ y~_KmtVfpZt^I;) Tn@43K;kzi6Y OLzVB:`T6^vixzGX=9ul2Z66Ȼ>_fjy@NPbZxu ˶(ԒO.M01fj!k[y|%j1\3 ^~ͫz..\ a@6bja'KĒӠg ߊ^E*,b)F K-T. )݌$"-lOvzz{窖S 4sm2, KXYp5v*F}Yh*+3YSXlʺ8{dh+.; 93KjLZE۴G-C5n*o&Hv'kۓQ,m)k(o8]vY8R%nGڒ{ lqPe{[=\wɷߑkN78BUan)N@4ƷN{z8ltJ=50)Y z- m=k'Qwb >Gei{e|#7zC}N mGW#z[P.ql(nmIWI^Y(iE%7ГaӛV팋xn+zMd3S#lү?g^D/?禜bV?R(KnF/Q\=5]<6;m.^FLg{mi6b?^P+z3sR =&zNCPKVzz,M;_T݆Q\eھZPCp+ J Ckj &38lc0t1N,_F;qF%Re{.7rq幚*O`Hfp+m@Jzឞ&f,zESY+GF2M- 4bU;.܀C~<FNsڛ u[2xˉrr3 `Y --ɅiAC =9͘7נ3hqpP4s5&l˔񞣧\A/4G,{ >f?SsƈD3U-GV'3`S;Yt2qh 5bI:ޙ Nixb5۔J\v?׶gU7'i8z"ϭG~M/V5z*Oo2KS ]",Fdg|3}ڽ=(gTӲ~YQXlcH-z}n|rb݅,d{~fhOO35-=͔,ͪ ]62z 9$>Y;VJ@c—ys0/Xa!Q8zD=g{xS ^A|5m^ba)޲٬E/ym헦ލ&QdYJ*آ`R#V˽*0m|44Mzܤ1? 9|W}?bk $:h)jJA(g^ǔ8S0mBiǀ Ë6Q".i>Yʧ9ꔩz8c3^IFToկJɐ};| *="0Zb,mV'5^0oT MzHV ]BfzO[UG%@/*>Y=ћ0e`k&zO]28$=UQ$*cGA /jwjlx;×͊Ņ".Fgq4&!Qsb- [{Av+W!%Ы <=^*㴀V3 \W/zu"zy#M.'1U$C,GE,z.dϒo>$::(pjo`_X~/:^ӟX#߿ e粠g.]۩kӻу檄W WqQEӇ+K^[f~i*.ǁ)DO]碴}=VG W@4 MU]>O4|?ptbpU޿^}fk6wEy=# ͷks⫢|j%&3w*0 !@ @ @ @ @ @ @ @ @ @ @ @ @ @ ~*qlaכ2ga'?cvξMJӧ.{~Rasw>*w);Wl>r7'A^soCj Ye{%\Mo:y.=&4VNtڅݸ=<}O_7lckU򜔫?>`ҿayK .-S^,:>~ r,m;/!9:FF ;=_\x:3VwW[n=N}Nlzn-n捍|0ذOwE/UF輧xTyϧH̆.|Gdk8a %o. vקdq-_Dgrh=#5?y׮|)|曩iGU!kŰG7i{v=oΏ,&#[wQ70v &>}֑lvhr |&L%/n[l;wl͖;msG;l&NDٛ-'d*Ra>@2a#7 =ur6SfVd;yl;_Z_-m^noRi6LkrV-@3lm~]sgXg?arFY°CmAm~橉L\̣Uw+?w2(W\ ziT_f܊ oNL[=IE_圱㲢` s@9=gJ$ދiZ>^BcTmZeu^Ȱi'EE^D9_r gU豛}74L HIt' U]AvT!H,z4kz &$+3GމoҰhs~==<.3=_)?t%E.A1葋0\K+y^BCQE"Л[D&!x OKx BI2(¿ Ps39cN0OD4xII1XqH?x.x)XJy;y7Kf=uIV%)S7"ȕ԰=)<=rYzzL4zzJ/GW{ksT;;kzzL~V\x.ݡ<\sCˈB3j^.[y~5)z)bEDkR׈=*'2[s==&/3Em $4k *s`t yC7s =<5Oy~ p58԰3uՃlEߢ=nF}z {71;E/<=y0ˡGJH;io폣C~yn򐙞 ESf_{z3IubWtđp*4us/܈}`Yoxncx*i0d{xg{У^;ƺsyҊsSÆ^ﹽMܘ(d`9z {2=x!3sbToD/=7=AǮILϥݫ=7-ciDo @@AGAB4kJ#BV}t &@ATl&@G0mDPm0nlvs̜ #g﫺s>}n}Y?Um {zOUu^yq{zG)r/:YW=?m-{#mSz`)dl/nuu!-LY!\ʠevPqs-S,ըuθ?O U+U[;Hsqs8 ijMB1ǥP}jjTe#8J3B9t+r!z,T{ZFᇧwښ!| z.=֌g[es%sդxIJbU{z澢:}>=z|:;z,8'Ȟ%ϟ}"z.~VqD/ٲ֮i0,Lj s\ 6{c[y2Wn *Sz>?BOv8>CĚ˖]o i0wkfzqtAQwlpjz7QrA6i6=~=6f&_;loVt+V}>>s5"]?lM OO蹓UҜrǫ:zcjجv퍃Uяw8:~05թ{l=cz>@NmχolE6aӽT o5\ۭh;K0N?v_W7奲'6rsǡWQ}G J$krMPxzCEg^ν-Jj'!K}ueˉ5LRc [ "Ѭ;Fg,J-\qHZnnQFŽ%pRA"څ$z$E̕=7p" iҫ==7gjz @y  QAҊ^o\ 'h9Se>w'CqnGpHM4%F>iO<,+WO;۫[2N7s6H(n=o{2B# z\[C@mecC讑zk](=]Oϐ)}UxtxTS3]5c@1>If hwcWAK^srDü7cѸ8g$ So{D}mb{FlȞ_| tIޔ=/J|+/5zqEo<~ys5pң(zEjTs;c:*ǀv Es#;z>i BWrZEHQ-j˄1cw:p 2n_?`;x[< =XŎaVFs [9!XQ%q#,}lTfUYA3CK!,<>kS?z=vwn\%:j5ΟQ7b:zSڍT5z\O/eĊ,qo4&tBR_s#7"R#6OE%Ni:¾"[zzj:޽0-Ƚ1i:xckW uV힢QQN%x17^H婢w4TaO4 чgsTI*NP،S^\[A x1wm\,jd>\ mԴi۞Zse"5sr#,j vˡYQAX1GRƆwBq/9H&P!Vsc1opzzУ``7{9ۦhl'mih~.֝|ˌ%T{jپwz[5W|=_KK/(kȑ3zOdn=OCvCPL9[{/eװ 䟘\Qif`zvd܍[j2(Ytk yှy^dxzP430;c3:a2(!ś[(,V$ruە!W],z𖞁 7SQoBK7#k8^we.a$W܇^dSnc{16/Ǽ9#¨6/@ڔD<<_nK_$77ksUі{==C%E{]ewUbѹҔ,f\h? p͖Z(O8c!W]-) sn[_s 4AQmYܷ5w,=sL!-5WS|lhw\&Z!V?c?zE5V\w~“@ @ @ @ @ @ @ @ @ @ @ @ @ @ MZs |D+M/6\ajթkM6ln<ǣc2i#;vH(>fhkns?Y o6Y_﮿Z[%M d۟!vIJ Fj#ny#͑w=\7\OzjYN>j}%ڄȼ^GG[o ysgewk:[k>ܯl /]IǨBI";R\:L >|p^] Pۯo1@*-@QciQܩ']|%$f=VU u:~!G7^)dKtFo/)Ͷכ3m t#MZ[R!) yjػ+ ֲS?NÝzw}X|y&'Лkj{^W"sv`Hob(=믮m-9٧;R]gu׻8#ӓvYAQzӚ\tQ%ic\W ˼߱#Fot]o{Ӛ{Rmovm n{lc;FOO.jz$Βꤧp!&8.Qz"}ݧ%uKgL>ETZ1ꇒmfSDqDs/l>ȱ#`{X@tm%>^lK1ۙgKr-]WZeHdmQfgtryzOlD{k~Ӡ22Gݟr.zZR<(Ķlw]G} =b.Cnצ v: [; =#f %aAOJU*[챎FNPxgb^PEߙr)%%T=d0=4ߠ1J`]|ڲ%̒ڎydrf^Vng{jC[;)|8q=$@B(zjG z {}))Do^ET,l#y=)bP2Ln;)RĚYTBa")2EkG"n"CӹLyeW>KJKwN4 ~Dۉ@r椿h.ܡ٢)2(D =4Z##ivj&(\E^f-=NjKf~?Ȫ] j4 50Ѽܵw %"7{xmxzjPY0"M~/l_m[ѓH衧_V}S~3YlH-dj 5;B$5yg{8sag. m4tC$ a.Qrjn.I7j42 uǎ=>ӒFRFẘGJ.mWGo&SV%1KZQ݈U{z!9Kl>;zXKI;>6F|22gRZ!}ȗyB'!2i|=z@y7wT= AWaq= -r!SܬM(>@EO^[vӛoy!C;!ڴ );̹͏Sk&ڞ/5}V5̤x ~ѳ=5K$(S_sA^@]%Dg{:z3@mO͖1LVg+zQg{%'v;D}o{aGAτ#RO}[Rsi䡧| jzz7{zӓ-*7?ce0Ǽ aN5zⓚJ:؞O#xk> ^}/umIa}jm)l/MFB7KAU:z5̪.1eMu5ӕ`@= 1 =ԲQ]ɧoH怪T#zsd7kˤzW8L z{lOjQ\O+zPbh$誋7z,TsYK(ӓxvs{CJz S=z-p==nEO/)lyۨ =%נ>n{~ b|]0#= =?j 㽎VӣF0{]˔ cF }qvO$j2TLMe#le{@׏cN'[jnm :8hY 1Hmz F&|݄J=}n?{ŔGŠgUw=zqRuNVL3NU+9ms16$G0ShNw-ZhlD. 4*T{$zI`{-1PUte3;djž߮>##rÝ/56=axjoa{s7WC5ډSᬠ5FT-Y 3\`_sfxѝzz@-m],@#6qCb߅Um Z#/wsux)/n2ehYr E\Ԓ/^Ô0 SQu>`c5 "CTqc&FaBJ{ LKF%"5(Jp )q߻A"z3 ^]GW =[~BA8+uXo!WNpf{ B5‹޲ՆbJj=e<e 0W3Q\37o ^rRmqV\5R TH쇄p-՘^ű̞A߇zĊ;{a(=qf0Ħj*f)"z)yaK0bRxy?0mjXxϜ{J:DLO!ܽ\Q3ֶ FU:}L̹KwKK%/Mq.~NSb.[)A}S K 0 .@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @lVg BM N/l1uxTkԺ>=;H4uc5֍!~=!}wzǙ>#KA`ul,Vo gXa;{3fkVj n~+ 7^cڃ 1l ~P^Їwt7g5#V++ӉAAp {3I۶&YTL,4=2c -zo2ZYw]?׀E2~ Bs 3M7hd0BgҵNT (Qb n_%@6uek2;A:PS==7%P@fMZj.3:YpCYu7珋"Yn81U:AcMJr% c0֫6Z˛ bn̗-}{_HXz@hX#:l4 қ k=`Tܤ7v{=WO8Ta5TD ΩS'@8^ NE{z);{ᇎs%3;-D~2@d6g@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ 1<9^g#cyWU&IO6RoIejE]\h5gu?^._^ѫ%J{7ޯWovK']8k/ԕƚߘ:=Ĕd M<޿No([y +;qfG.imoǎIRQCN׬j+o&z&=^>3{'$qǒuA6Y1-W"nk{LiޱhvlɍJx9+Az q$2>j>A׌GA%i:^ok>?ק>lfP?\5ǭ30:BNx<<ǜ||0V: ]ކF&kmjGI~jH5Xioy8~ב 7|b犿^+̎ѳA+ܝ#]0̺섏3[/ȵ>HNKƑ>н./Yɹ=;k-):̞ڽwDީxW\;Y7f檫ΟIn1Lر,DnQdeUbBÍ6#gƕbq}'*mψ/Uڶӻ|ϯxj:mg]azzl1g-o0(1͝+g^9Sra[ì72.yzNĄWĞ1qdG_Tt̃1r;.ܵӫ2|T^K\aHwojkN!3&MgaҤ N'ۻ +"/cs4U6žl-Lf*sɘ[1gf,O-z [g@%zLVc kNI a?d1*]A&q{qs)Z66]2(-4yhƮ:ߙ{^\qa{;q/QsCZ7+оx2c)3]6Jl]?Akm$^}ZRs5qhlR%es3KeCM][0!R]K5+7+Gq'];qmK/%EsL7/ݲ5UZ~qR5)x;=l%".Z͘Im)(eB ۫f$Ѣ4w9́Iˌ,D7}tu;u2L>" LAfC ==,J,}fw|uD,z/y,:53EhȶE WNB3G{Ԩ\5)ULͺE/* Ɖdz:^TeT+|N<_ڊ^:xzT OYaHM]@}jǎ-:_-K^|JN}ͭ2=z/Vm7bX)7( e) zeV)y\o{2ٵ{C '_ѣra{лiR:=?i=,tBÒe% O/zNb =H/\n?w Ϣ˒6^s1$ob{fdN7j.Wk !nݓuY#z8bS)T1#AJ5xc{'t(zdV8Nd:Qs6CJWno{p##55J*!c{CΓz]@ EӫhI͵==ʘ ~R*;Zi H)DF{ PEWT'Kߪ:SsaFuk;zV#fU8K *w}'Ke\PPsY۽9XjtJ5|9CD!%zEhT\Tͭ\NU5|Qj(=+鷺1Hj.|'!y_sɫ=ָϓ={~,z5Դtƅ{ǢÌz;,8+0Iz;v ot IYRM!"rBσް"ۣ QS7h(  !^uv}a`U:+45*wnFufj:+o>NT.v<-QB֖5B/\#˿Ա7&~N zez'=Z23FިXJcS@#|GBY[%K:Z1r:5YΫKp缂ϗ_dF& ̸T/8x{Fd,+yT˼17i XVm_,wLT*tN==?mg5MK>UmѾ|ٽXބAxi4[K8^>3{ yV2Yw *Hx(.^=,1yWDn(0pKq8DX.,.x3 zk6&oJXwPTT9K[yԌ\FLPr-%rmD 5Wd4+&63HB/b%)F7]2cެ{dA!-W0[◔Q76&xtA_(%s/wGcʄl.0q_=~>w_(?ඤRְKY{~_+6?6|+ ~ŔbOr~'|]mt[DipO^nN;ZzՍ=h8_:Ha]RElC qR l{RWkgkuzG5~vӖ̶$%gMF>:kON? n @ @ @ @ @ @ @ @ @ @ @ @ @ @ #F9Gu1G"fld#ywvfo?bm>GwMǸn őwcpy}vwzF~C0xYԛE;5MWPz~x}}ndTc[}FRvݭ'u;n;1N΋WgppV;G%߄^/J:һma;.ӝV @8>wvrᑚ9Mo5zmIOvkWS)ñ>ZGzeo]dP+x8'M׍_';} { tc@m#ߢfpݗ®뛆2;#Qt-7$\lFߩٌ=cȍ7m=cy?E6msm@)UD=Zh{pQs?]^ϻImϰۘ4rQg1/:;>Y>z(dݽܘ$FK1-GԸof4IKzISrVz (Qa.j怜} 7yIvo}M ӭ٨>lMc6ֲ7,CTo{vFV7kdPl_ڶ [Ƴ:;sE_$50[ ƯIEV]bblmu9S/f6G̐"`t [eW}]N轠lG*; P.VK:x,tVmzInNc Қ5׉k2^^m#_qsR[ERiy/.1B zl_[ћ"1oKm/z2R C/?O{Qs VݶՃ4^tB!P-K ԁJ`)B)"rwVM"kΠ:+J/zD ŏp۷Y[: 6ZIAiTCۅ:ps~3ECi\xz.W;3ZRTɥ Ҥh즯O#rC/E= 4G$&=/3r (6RMQO.BW7bH⊞z!B Ip4i!F  ] J^G^XB{:Л?bvƋe9,jGKGz >e{R,C8iK yz 2D(˷ʷzzL#B[H%D8^E_T6'B(qN e]Brd=}'e}J gk*={z)(Umz~_B=o8B"~)ɘUSE`h߷{'/ d68]EIU* ,XF!zz1|eq1SMO/X{E/RNGOda4ГVܻ2ePxc%. 0uRG4&g[h15l wB3O3AwߍР$zT̎jtD== +zVKf=+Iv8Ҫǀ47*ď=c.Ct &-Wk>#bB/%(]f4Z6\yъE.SRhӁqdws$Ml衲8bJYs=+հ 4*J7aLdQDo@8UhJmWfXWGA2UDvc^۪ʍwSuzb{ZB&]v\ѳ&LzRz\|krK|oz W𞵣WEބM=Lט=IA׬蹂Ϫרow4:T[ַ{#=!xB\ٞ= 5@|ӟnYޟF,O=xtW+Sz>&k;zF,t 尽uzCA*w`{TsGƣ5';z~ĒV5+aԦLh!L 舻v=Vd/Yz|F,j-'>p|ɟ- ?͡JYuuǨԡ=CEH[c{=9ܴ7{Go!z ?1%zßI'-{۫2ScKa{/t1"w`f٧I1ދݳzz܅ 6]w\5xָ{>(2-ջbrGC>j5Dj!ˌX=O:wE찣J at_u^=u]##oً*}\SUe4k&gjcHB`vs 6%51'5yHReEo\cHA/lوt˒UOT[U6Ke{9Eۭ4w,+TuJJ>jULnQN/dt?ޡV.-`Ij&Q璗A:^Rrf J5є ݔ\BڶuI5/ñ$%{+iʟfa:x4q-_?r +W/y !zIy~3Ycͤ_0=_lj)%)r' ݯS|>d5ihѝ'CS܋S'&Q #9΅^jÁS)?!;ё2zkoKAg#62Ov;\3 ^O .8y:V<ϵ{Xt;9L71$z$x/>1~+WʎAx C>hVej㿻fȃU^ҫN ]#1wmu_kdIfC,J.AJ.Wqc5w2гw?*#G\Сi2r7gN[.ڎy^`ܥy7Oly=>+y6n\..js\6;ޱ+xj{#tOl_i ң=$D|SzCg뀧nLu|j;h狭Vn(­ٱ&4~Xʹ54Z^&F=4DOR\ P&PԪ`͑o!xR?^cAMit'DϙѧXjHD.Rv(Cɮd10RR2S+RXEt{zVTY 诠\[5ײf`=lT2@E0c4YJΧCUlRdT O]TP], KK5ope@_6J :,LuOZ$U6+xrꋥΠ' h&]K;]UcĭtFӢCJ^q:"z)n ILQK>$+=EV=*5]1EYWmI𜯹.3\5,teҥSdqʘ VQ4t=pb=o{]%==IYӐDPkFYo=9)D fBN TTy$U33+˩ڰ;9rWAY 7bZ(z/kG*==o{jFrd]蕷2O =j"|mt){52@0T@O-2JD sѝ^'Q" 3wZȜ' P={dʯ%A OɖAϷ{x@Hd1*z2S`ݳ}A#xVsocVٙLL 4(QIoRCQaP'3[&+)elZH/a{3 O$vjS<{C&CP K}j!je< Jjvy/2Gc,hrt)QW`IT ׎s^sP1!pUSMZc{*PQͱCFuWXBi3]y |zGBG<uo9nbhȻVs<۞+zzױ*Gɇ)Ihvs) 5z}ͅ^Io4M{%)o{CU#~4wJzP= apz]=sRT=D_*zY7ތ[o|/[[zmgynQSZ䂩4yL]͍!'24n=/6a1FH-Ftb֪~Kp@@Ս-p%|]E\͸*FyfƤ0Z 5y,ܘZ3mmV[D+UѸ6(1@>Ŏ% 1Ygm?%:Z:l&sZ z~d\k}ODOҠt 9^ |܉KFZ6 "I]\-TZzOHކgT噗~`ʨͭjB ([ ˋKW"nnF֖aZЃMK -DKFDw>K&g z.?N:!|/I f}^5\go]Dvq[^6jV볚1/@;¨Eyb_d; U(GoJ=o2R{3>R_\q_ȁ$F&ezöJ]8bɽcv˧ ܿCN?MO.8'(tZOIjvF5xok_?3mfFe\`l?nte];{'}bbsw N3EǏOzBfGl(os 7-Mnu)LoIiswrfBbαg[Z?lu:|wý}ZW!.H-wjkωISߝd{6ar~z'hs=tu^ӳޯz^}ܙF˱xzۓ&xurM]br>R7n=;'*d\ Pg؟`(U4cv^OLoUFzl@o7z|zvz7K9ia)N &@w~7*L&>ks.~H`RW㫾vUelHm]M?NFvomf+r&LQyUKYaмd]6gtY;ڭН<~(r~mPBKk[7ɤ|3"m`4DZC3 'ޮKM>KEQ=pg x#8*Yf{بvW BLIv~-г”A̤ 7fT4w6OFKҖH;x:+&fFp̶,v3{z3+%,lmHn`м]á(pmzen"_lQy`+nR~a2OvC:z-c04[C(SnPt5bulOt[[{6bgټk,(6Ha4qzDFѫ똇m0!-reK1";޵ăcd RmS*<=q셎 zfMe{.Q+wU˿孴b_ +hBL-==?Gj""U?IJy*.QB$355X*#BtP V@\C/GV,[' B'm-S,Uwj-r{뗢@!YsqOͨl_&,Mc/=j.ͤC2=(3-~aQu=5k:/':Lwޣ-GHW :Qnk [LFa01W{rlY7Wh7c! 06)|^ޞaHIZk2i{*$ߪ_3@ 7=dU;OZ&b(jS\cɜn#.p^cfoV06ƖאV^4wv%Sk bkiGGlohӢ8,pژ9yǛzy!àH9"I -ޖ!%skUPFޜU3nJV y0.s䆋e"#}O񊍷rC'iҼ(x !Ԯs 1SVָ=翮96M.WW9D{CZ\?ڨE5p0JU wW6M+ P39 *3ʴ܁1Ħ5j7#:P٧^KٚYN#_bYA(u CsEJ TCi]߄6MV})[7~@;y'\w*O[|: =tL+\P3ׄra5D#?jcoBen8Ko+}1蠗lsG1ћ=K;G:xn[,SoLap'7BYIb>H'&&ØO;c.ߐ@ @ @ @ @ @ @ @ @ @ @ @ @ @ eؠq8<{}Av};O&;d3)y\ vS}اO_.k;w>bpKZ;w5|)>o|4[QM"oY]+z5d0ךOox^;~˦DC/5lO?ώ^zZ4>J|jˇ"G|ly]=x{rb@aŋ>lѫr&ŌmWvW5גϘ^J~Fݩ[ `w{zY=fz xt[Pn ԟӁޢU70@Mz\HϡzheLzj@yo{@vϻoYsXW74JWO4PGauIGi{CvT{N=#6ݘ` 3|DT[l{io}OfW[q2;;ٞܲet6yϿ;mM= %vާCv:soFU_ @ooGE WEln>dH:ʸ~ރ}9;qsC4Oj'u4on=hy˖Ϫx+M8$y>RA&R^XE 4MeyFG%Օ׶zs [CHѮvҞ^jG%؁{ҳ<0UφL˂ܛ $Q3+2bg{Z+E̿it( :P_(u{1OG*âQ< QK1`rS=$ Y(E`Dl5RloڢA.6yۓҮmu#@=qS:\66Gfqӻ=v7%Uk$}1'E?W1-QDZn`&ˣ d3C:|7!4yRgFxebv"]7CI4.Y9FNlȄ'E7xh^Th<4"r+ Dmw0rlyM)f߅1 \@p`i8+fQpP5lZDa`X p`2j1`tf0,ZݢXO gz~xsNyWhL~彚_2C~OQF& Л㈇[ѭP#&(Ԡ-'Aa5zڙsgeS&ɑ?Ru5u%=yJi0Ak+BAsHj$<7{ v3]}4@Odt:C& # H7ЛSѣdF/5愋9`];Zr>nTU!T(be#Ϲ q&mCibvTB fWء%-I zXoEutQ!A#؞콥whG\CɜJOn< 9:Tpw~؁_00-*iG ~DOB|彤tM<,`UZzl/Kv!<{Uqc.rX?@tN/pPu'ύQ$C q*Jl87d%DGpiIWy:?]_;z=}TBV)rCk|jѲTGBmA C^lfkKk0DR5{z4=r'$8r!UE6TSKsx.J>=Wn{ۣբ jsOU~A dfG7Уwld{Ӗ޶@GC=>LzZH.ús5 s+=F՜ ^3F!rjiF hl5 YYЭdTPƜ*fٙIe}"DM63,lsL_TԚ|3/]ѓnwȅV§ <zϯ ي^x11sX k e\?s(ЋS xOMʪ;) .ztB3j5bfb8[ ڴԗΐjA:㠉m5z݂1Tb8ћz4m=K@8q=^mv/Kvz:b'z(&Je%4 Jl0˅˳;D:CyR[4J7hm}tq`P[C2L'hTÔ%ceM O>+aFl/Ø5UzoDAwƸpO8 QzJJ-i=:u;1__ȁ2PkFO6c9HÁ%2IJ37`"r((AG$I""}n'_rŠ֫;<,"L4vC"f>Xx8z$ɞ~~鳧ƀ١/]lG8^4% J0#6Y`oŽsv}0zinz{ D7(A1F=Hy̨\~^Rvgp"v}: ^x4ē>GoÈGDCMluCKfyplpſxpZĿу}$?˭r%cflN*D}1qEF̕-H8dkl/()i]?`Kh9-e's?{ʽz+C>S/561.}yGOK-bGCqpPf\zZyfEop.m{QP=xX̵KӀee`}}IXIPq%!F~ o&ήFA 6|pxJzήtWEc~%x%K#+2@|IR^>^,Y84]t+Na#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`>& Pӵ~5 vfgĬzz_%My|ώa1zzP䍘g WmVaid:$C/}IuΒfL˪ƼK|o$/&Qu[hNwz()(fg*I'B2=WAOlv[]g"΋E/?5'"ћMx,AGC{YEX,Yٛ>^ ^cLOo D;^xW#yE|r^Su_E=pˋТl =:xbO+FD} 鵄|g gu^ 7cs wԕk]=rVx%=`vj鵻:垮To{mۗi7'U1 Jקxmta'7E-BV ݏ^g jmpmG4m; lO/_ȋ{%GhEOy;殳}8N:s8!5MMgv#lRRy?pY(n8E/GT_qukœ)S;F@/CC"+8vAun}e^B荳E=JÒC T\ \~;BBp3!pSQjlG(I7rd}c0!*I)TCs -tEF Yоe(x&ѽC/{c`z gGc+1: q P Mqz+# =~nTWnBʰ;D_`;`Qi0%^ϡ$f=:sÌ{s4#6^ʛ^es<}Ԓ!u5وz9]cTk(ʏzܺ)b5h-4̆EK,h"W+7ڇ+VPj"RZnJ,D;qRs $Xc5:qin 1 t g =,FTPnmK$__N=ŝB/MMŻԩ-Ѓ*.rFq# (RB\rvNPw6^<ʑrVfa)`9+kMs7:AQfy'a}"2,+"c\g=tZs}u1t śJS`{4U!hzB3YĻBL#U+1rLrz\ 6J4oll!ŃqCs9*T!N^0  1#ޞZB;wcv[z(T5M\]-JA/KT3 :fKA=԰d{.$웗N Þ^*c%w+`iRr xn==vXhADS * %_b_jZzOۣeod(.^Hpn{ۆd"=R^޷=Io/bjKǭ{#{v>)'⃮2%_>=ܓ׌X+#)Cg{sscK-DwzK-= [ۛiC/9Ac+CybTskkkF, }27.x.{7eIzG)}`*ڞfЫQCH"5Iq!ԠF%ra9.秈7wx3Fk-s%>7&/R\l/L=乌>WCzq G =7b }.C lG!sC9^0D:C@o6ЛfmO<^赞ހ `{aW51oprB n^3E=iB݁[z:syڤxntbPkla0glGLڙVy{݃ض{W 1`{ 68(O(bl$yE年>IKKK*#b-AFKo׏b GISĴ̌r4kQ{Fo9uVڽuX~fgM&њ۽4(MZA0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0FM$&GsOehR ^~҄'V[u8ÇݯT2eʊXytEūgձi[~Dzn_ފ^Lz=@ʢhKN3ֽKiPECړIj{Sc0'Xy-Z+[9D빌XVu7K5*.\ c{Biv{o~ C(u־/nN6Lf^+bȩ<,߸piž\1T0u>|~>Oayc7FGQѓa1n|\Gşފ_%ߍsnw*i4lB21Eխ@/gQTsL1ج=IGtG7o=Y9MqSM+Pѽ,uW'c;4ÆZlxL Ѯq3K( eOq'xVr=WnXQ]-7ժ@(Ox0"*zfI6;la CoXRQ{48=Gi, PYw$^:"O({E2,7rEt844xI=%5xQd0@x\T6[C•"a(J"[X|S|LtS?mQ,gwTC/Γᾟ HXVW#eJl9x^Mn;X5r@|˕}I%&P'αرϾz)jU^QG_WTx}~So;ܨI{7(YCO@0dzag^h0#n?`3Pj<þ|UhFyJ 0>#֚5s ,4j|zcnt;UL+@շY;Ao0@X$E &Bb4Jwc{2q: Svq'P^tdFyC/J ɾ4)ۣ#l=|̥"J^O[<<7kufFJk4*lODOo(υ$܊ބl1=ۖ푄i_+|-.5c&\+ivLG֥we@0khا i=}sX}.G氼s5k,#3spi,ۣ9ObmOqs֡"k=^7S<I3Suk#f,zqC}v=2{9 gQ\ =ްz zvU_:6*OapTߣ7fq.{8e>e7bQ~}m2wWm3]B鴈jG#=b6{':0}=-ZGFd<9G0#}xy{Jړ=GS%!w_EO;z(ӦV*t3'% K.ǎ.Wa "?Zh:rn> e3‡V9s!hSk.C o$=L;>%ч8!e;nF p>z+_* }I4>%U>鷾AC5ՙ,_fv<W2[xx sN2꽲s<3=&J+f\+4xNg&ѯk|V^&+O|ԿpN\I}Z~3imaW,jyLOlNb]?Q_3gsi<߶I X6.ǧ0-eK>6.ӧmK29}n٧X˖6In2nгEKpk$G2&Ic t6zAz &d3Y "_ ˅Бt.B@ !zğ|L a^]0O2YױpA>I-a0Nk A0慓ZBoKH/֒f18]<b(.@k{{j]YfpQ/7/ZL?{k:)7x $Z2G? EV*coWu67 -Z;Uǫ+m.dɚyxZVi;y6Zŋ%Y7-?s%GW&y);J\ﴛkPwOFiUӯVR~g 7ԋ Pfrxb]'&d}S^*ǻfi흒!鯁/mBmBO;06ߧt/.=<-K~Ѕd{`қ-}GEW%|q;$ttVŮ^Nv}wz /5췎mpT0d^.߮-xl^}qbAߣt KCHg;I껍ފvO ;뵾)U;{l]};n*jխWr[8jn\ƞ {#@2pLMM!HVk#W]bu}V;]qGM5bq>=N_Bޑ:f/k/l`k(N əlӈϨL[K Y=@Y3 ·eaJK䯛x-=JI@o "=ϟϾOCywbF/}B,e^W >U_ Tb0IzH1Ч 0M^_zIԕ=.B T"(Zn~\oF7~6S"D﩯IC*.uz{!7TC?JCT?)EAH kF} Io;1k;/<%lgxBDR. Xijj1/OH%+ ^_KK8O\7xqGKH?Ge^bEtJ(Vz*&ypd牼FCHqz%AvOEf23n )*|5MdM<^I2Fįoz@17;ᾆ\cYG_!35Hl|5]O٘xɣ8\i+ =\.@dJ: Xztn]i16"~ȉ@#zhc.#ָ)pBOU"$\z錤g BbR ʀU3Q^=Ҡ;žHF􆻒두5er1s:ЛBo94ޑS"@1Pʞʉ,zBR/]vzȒ1~ӝb\S !>[  \p!Tf,`q[D:t)=* %z"{R6A_$/V T% ۮ9.JRmAo_q1P(\&Sw[>8}B% ;# 0*I+#RJ\p~x xM -'z*07 ȴ1kl;/}mF, CzSqz(qLK*̦rrs'z+E`f$:5VmJ@zT:UzX\l/j<7^6kuݏvP.:z1ϥiR{ڽ^MKlbvωIWp"=u4V赞;u\\eKlOpCR]ad,9gcXz.&FY\ =rk<7^DΚB7ܦctTI:ۃOHgȱvOJw$$1ZNh(z8Fm1~OJ 6 {*Kfa}@7b!=1^r^&~^ Kk\qGCg$=i'iJ=,ܼO dY[= p7(ZYM`yh{_U4iG]ʂfj_A9n\-豳zzoZzBAY0 .2SVv/X \C*N{zS0@~!Ip`sHڨeV5c1q/1>=$zNz+RYS>`gI{D=`|h96^;z{dc)x8f5|Ȃa`~S2IDe +l/: \_U"J1k6q~֔$UKӄ6e2JO #Wa=1 "Ez5M{ۄ`eDMHU!,bJc/;k1)OeH4ڤ &qEϔ .4 D豚S:V B6PWN9yވl3e;Rn APEh}/{jl(" U:OuףTOvA׬;"L$Em_}{1qEggQ3)w<~+1& 1m*R6ɘE:f{7G{e}* V2yT(C9<"8mG(ݟek}z}smrWb{^ҕU-ڧa]sdqm; Wa{r}hzk5!6߫hniw~q{ent{8<&K.NoSҷ&m<2:;?|-2a:|JdG9D8V` ]/?BeYPſ;崧YE|Ei-OzZFp>{}~6%𼏨?p>6d9kTUrM`aΎm1=]N#wG=lc]}mK`ڐe]fxgQZвtǧkm $P}oƺün[I8ӵCgZrzl%x8T`:']\[H0xY^ulܑ8sHeQs]Lב8~&s| []>.j[CrF_К#|cg)0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#s2z`[0F#`69҂ endstream endobj 29 0 obj 89702 endobj 31 0 obj << /Length 32 0 R /Filter /FlateDecode >> stream x+TT(T0B3C#sK#Tp< H$anag`dY($*{*u endstream endobj 32 0 obj 62 endobj 30 0 obj << /Type /Page /Parent 3 0 R /Resources 33 0 R /Contents 31 0 R /MediaBox [0 0 612 792] >> endobj 33 0 obj << /ProcSet [ /PDF /ImageB /ImageC /ImageI ] /XObject << /Im5 34 0 R >> >> endobj 34 0 obj << /Length 35 0 R /Type /XObject /Subtype /Image /Width 2544 /Height 3280 /ColorSpace 9 0 R /BitsPerComponent 1 /Filter /FlateDecode >> stream x_~vWIo3)d\=FWa$!F#49U̜D9dP$8N&;*r]Cs+ ~k߬5cr7/{qa۵׸vC>6m&qIgL]?׎r- nіl5IP}< ^ yE^u o m+CHꤚI.\2o6 y}|}ҽN6& ܥ5e4\gy& Ϛ Mт@|hvN{ΫBFo9y2λi܍Iw%E- _%'M]XaUy\noliZtws /JNA¥^ЛFzkrR7)/Z5ReWT9żɦuӻ.H8KS+ 1[Lډ^j.Cۚ\^2hǵ6Y.B#z7MY+z\&yuuIi} UG޾vp%t$e^\BUV*sھn+TPr=}"z "07MCtٹrgX.AW]8zA@OV%=]xv.f~⨽f_x9:b't*=*L&h9':W(U<> ^ J\}tکd(1J;ִ?Znۡˆuڠd i|OQkSk3Ŵ1ّ^wmMs{w^_Ii0XfG{$ZnFy5ҫTjze9-7:p+*Tj.@n[sO{"kګ^jzgj'bh=OcEH/^G~z,?"=HOfp-#:tҢ2,xnob@Ձ^p~|;Q ,n*/{jzj\uyu}7`kha{kDzCcۚ {x(.fZc5Av'Cb W)=l(/*=<ћ=LzUbdY&n+;J]$E]=^o -zBD!(zhWۦqO%c_#`k=eM#0ryc qzX~d '2D|܊TY[)'|77`Anxkl1Noe%C6tL!z^"@\˚ %cOڇ^-z^exF*N[c,| X`f;oDZڵ35蕓Υ^2$WTyї␣˺Z"h+:FngУ^dk:GjFqѠf;ūozy.􂻓"ɜ;@Hĝ<^p:w5u7'8sۙT!"oIwy\qcQPkm+υTvE 1mM\]>nW/ hBr2qbie+ndP]G\Dᒖx4*c\GG/pOUþ7@&#KO^vU Z\w86}=vu%c[N/z"`E/_rQ^$/QHuG6z6HOTJ̓-A*%sŸݟ}c@#`0F#`0F#`0F#`0F#`0F#`0F#`x v_o5?y mրB>>Џ￸{GT,~Y0VN 㤜oҶ /v-3'fbV3̐!x}4Z||mj1_Խa)I[as4/W>Kg^{Ӎ'xI֯Z>qڀ8suH{Hv ⱟ~z<|6֛KzL!3[q==,'~J뮭`y4k|,&S^K A11 Q ]56n)6e&z!xz=1Q, ?n{b=Re^K[KHpmumި=F1ԑ^֗&=~t$j\T$˙b-(V11zo[/0ɖ\G!ac}}eIo= 0G[Nwrg۰eқľɥnd8z'dΉ2o0}riW{4f}8K6p)OuEyi1 hS8w5anyJ~sy]۷m챦OVZMK˯m}:m2  =5 .&lUyiC$% 27i;ٳtOdb^T3xbm/x ;!4QysMa;ެPs*mPWGz@sZh!Ε=R#0us#$uO!].GƟnDF{[DOaTo"6W$]$AIn0.i#5Drد޽ ki|}#jui&LpʴL^l0IOB!u)]$DoB*9$B)MH;NܮqCG\# k:; ZvO/i|FR}FȧX7_W`T!hou`'>SXü,)Wi@'x[ z4*#X!!!7RSX~==aBhesd(!\PU1T_'KO/rNoi!a礪㚫ݖ4o(fG&O E1tÀz î8Ѓ~J,_t1C<+jXu\"LMמ0xr/n*nPta8 ׀T^7CdfNlI3E$Tè$FYFzFDz|To1>Gi(qz0j 7/GJыEa=ڞ^*>#RG`HzZ*=ЙZEJ{D=;^V.=ܖx @\W y! /7=J.OFXt:I{=E{z#=pP@ѣG^^̃y ["?Nzz1͜R*xhMh+z!=ܢ**s0iDx-.qz9VS ul?+l&zk[AO 2Yu @[hi{KgO=N=T2JAwe:sd)uu,׋'T{o8_p[fWTvDF\ eGqXlXo>^lX]{}@+QM/==U2|Ny"=N0PmB$2չ$yyi+NXkD2R~E7NGmI%A/S͆b5@O1#|-ؤNFbRU&7{)0[ɂbC@݇zj-~WcU5fFPǟ{DT~,^S-=5n\% ծY%4[ֹ>ԹjZ!-)U"zIi,7Pfs˩$)>;èKn fkFz]}'z $FLɘڋA{!x^GtEoG'pdNCN_ܦ:s:0l_% -m0ViiSH/FV|=#ۥHzsUx-詯\*b%U^]w}\~"s" Sі+PS=U#KI\,=0.r]]rIsĥlOQT.Iƀ2`UK<9ho,pቌ_o"+$в6X_]s |!ޠ<@ȩ! [{nR91,M8 ?,+l:fZ{ջQzHn6eu.E8hJ}b={rl?/\oV7!>%R2DgCBc.&`k3:㘲I5cJw8_%NL-K̊ʽgh cԌ. -3w5( s-3f?I63ua[_)3,+'`LȮ}wS6S~&q!l[߾Y-S7ͯ zL}Uvu!LK ǚoyTfkxfNZ0t;@pBS*{1e{m勾: 4IģU!aGyz3|~X h-GzW8/W顿DLNDzЈ1BP/ 5dZ6-k%5K0‘sVImh!h_ .U͉T f]3iWG)S:z4. Cj,ܚU#DzIP v1ea\;Cn x č /&wL`kYyᲁ5}iW#{lԞyyI^ K!9=桗 ,wzj(6ho 5g0~EsQnMùV: 6ӳ/0zg'X/%2'.VJrL9_:OrsكGhQ=uzsz\?MƑعqh Eju k|EjE$O ?^NX+uOW@oDzC|nq$'KQjN=c,zVPTyˀesz7`S2. i9j)UH{|j詽L0cFz9$'&nf^IǕoCPhJę*>vـ'=ņCńqʒkE+Gz-=B_^:.B"rKF:2:EjFze7 w8= f'ev`Sـ:%'ЋU _az\~j܁D}Л}EA=hbEzKz3]i^@/3&:UC+/pX)Ң=RRы΂^azXCsT~>G3O7h[iʒVdܒh{KzhO蠐!:9m{\$Mܧ?އzfrN_ ^rt~VF'Ud};-Fs6R^>9J3[Z=HEICDzWE(%}%Yp1i*Stuev\?ap~OI`\#].>Uw{(g^H˝el  KYP;`5c̈rc+Zp· fK!F]bcGO^rXg[ |^yŏzgE=A'~3\zz!yOtn4p|^Gy  AC;wӽh{&M1G-hr}3٘%ڏ*6ܧpHodU}PAPRxZ6!9c}U^G՜)tzzS}[у@J~u5zhyJw^P1?=9+~Q9hoB6>_{z">~(U cˡ{6ڛע,]αxpNG핒L^VAYiWg⊋޲"IHxo0y#.#&Ǟ@оV!y~2$#F^&Ah{Q-%L#=,ߋ$DI^=U}ja>~xHЛ@/%la_ d栈:CbZ67`~ UԾoyEO?bE􀺢WUq9|#/&BcC>qza=U QztHOጋHoUP^r=A %GZ#ҫneL_~ObVx|uk~L}7 EFm[5?ObN|R3U#i8Fs%@'Ҽ8%=W^}=Ugj#׌= M]B_U7Deˢ:pg+Xʁ\zop=]YHcw9FIgg E B.q#~RB^=YÀ/Isuz%UB|\ B)A5cҞ8 ?8cׇ's8GGFz<*X7n 3hhWxOݏV]>葁#hmPw}|IY \bY`E?/rw< D,QlO)N;φ}aփ^N]Y^S'j20eH8R= (?dXRVZl7b޿B?z:x-9z sr9׹\S{1$7igq';re!0W׼=:}[9 NLM3F^m0h,>w9X6DGӺ)n[E^{)UI<;ڰ++T}^hK{*c"V/7Bo;Q6&ܑE-b+=>tZ\P[,et.+s=}:i&ˌv`u9=苾*SDz9J%wHֺ,+z2n-^6Leԓ\57+ f4/n2񌗓/,i,i={esb)ÿl^x !́kӞ hfh{FFy҈s@OH{[+)Պ t{]ўo|O+0Z:H/LN2jcNcЮҜ:LUe8r?Z } .Yt,BFJ{/OEO~KTΙ9Sis{yWcOm`^H 05';+zȥw 6ppe [ ~cV^oZž@$ ~#0Ϊg(0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`j?Pst-+Ll-E\dN!k7N>¼sJezl&GdݜY/ZJ .4(Nﵴ8J sfҽq%3k,!>(ן hJUlŸ&=ny| X}1{kf\Y f[\HǾ~s>,$z̐{^u>(vIog`Rq7+Lkޠ0!)G4v-w[ICTٻNMp?mgO5ُjs\q-B{IP[4tЖ;ޠw6^Κ^Ԯbfr.+'irҤmQW|FO> dشڠN- 5_fRҀYװ~*z\=i]iᙂn3a3 \J/\lxޟS۸yv}up7n2~M1j'aЈ Wǥv΄.m#=C 9O66. \$MR'뚤 p)6^Pgq<vZΓ~zmoyQy鿶JPܚQ*cuU[_{-Ш/Pp"/w.CkuA!}"m&)i;|)1EVS!Ld̈#z4 J9mjZe1WuկPm Z(^gaJ[nZ,+ zin$;V*&)jحQ~|p*ᒲ柤:uVj"i(t[͖=!,ЃnEVt!ΔED+-bX-w' C(n7T#kPP=aetvǪMM*TzNT奓kI=n8+#t7 @'͊bJ.aI,y%uV@ϩ0Ԓ^z^`N/ze7o:;-#"d'ƋBK7dS5WШhiN19&Un<.J~*ѣN(hރ0 %HQԞ ~@N^q1=ywk oMfo2_p&nמbYhDziw$GmЛá_gmƑTrvуcڌ7bAp9A9"Iw/Pݾ;$EEBB9x vT?&Ŕr<}k~/V# Eſ"@}>ءj-(Yd:KBlvDQgssU<)7퉞D zeT.V+z쟯ͫj ѣ\ܴwKsS99BXm=iOg^7zaxi>PN.e+/]pkOkXS'k/ءk2W+FsÛfлJx׹**z/.e4%E}H]Qni`F[ݝvt&j,|.x{a ߃^ @3E]<6?^_{x{ m=i`iZNs~ƺr@?=zSL`fo&HtPuۀT*~qnGo3ᎵFNJݒ Ok4Tn֡$QG?w]h\\!< ֘ͤ=N0RMoq6jIs̹Уߓ/ፂd}-ݤ9͵=%C*;e)ʈ1v8ghY z#=(r7V퀏.ّp 7ia[.c4F$wQGp餽I3 suHZ#PVYO!{z,Qu[Q{Q#Ƌ#'H3 B*߆`eIV9wpRqT#̹(TR(ݴuQ[/(1=2gus QxRܥ14PkOS,,)lNlZz{zjk=p][":UIre25wg~()W=]\c;:} DQhzy'KCyMI{'kG K~9խHt(CxR= =l-2@Kx:YdU{w]!6/H|.9uWɃ+]0L%7ȯOtWl<aڤ%jޤ^{,\-)|sRY@q|ix,OB'w Sa [W![9xzs?j=DW%*[u,2ޏ,@;c`ǵ(6QƏ@qF[lOt{68q9C.}%5;{jyH{q)u>kk m>dغ6ݱr,6S#ƍq!|1_W;/Nh=/U뻻촬z,.҉fHqn ]|m,]ml9٢l/תpk;3;eBw|7t>_nR \/u"W-E_ x Y2F#`0F#`0F#`0F#`0F#`0F#`0F#`0o 8;CC6ن#0c,?p (/teC99!}M8o^G?ݭ=˙qzp48M =?vlQh+!X13fÄ8YPiɬ^{o7h&OtjIkozO{M|f5ט0zRa%vK*bFBU:U1& ӯ__}a g>i=!27QWm*}ʡ͙v%{D(R >NfAܯyMzԹ[3:9B[= ѕBs )`ctZM`˚ߏeZ60/ۘMRfgE;hդ΄M˘M>i&Z\iz-SFzȱcA/=Iy7 AõsR[t^ǧZs-/"F#= ]<\hd>b&+7*B/.3{(Al zϙhLNOF.2H;]+ظzОrfWKvôTr$j#p3APx#AuTGn2Ld遙8-oMKiO3 + ~T=6A7Κ[0or5ތ`6W J )[O/E0$QgEkpqDK*׵0L_euЫEOnK#=d^[@FSqD/;#z^mB17v 5t B4\BY"0ts~d#=jޑ^cjj.-ʹ8kH)0qpn;}kHz*:Ixw{4=af;=6?Ч=XkayJb7-'zl8~u)\ wqA/Q0u٢$w{EQ~U.kNWb{/bE4 ʑv7О1h| j_s}' {O'cNۇs;UN#T'iAZ:O= Z+m-G.D{=;z4>(^ri'zUGz%z4c zϹ<:d9|Z ew8͗cON9~^HO hYuG"io=JL5z #N@HwGT--\Hl*ʥӥ}ũLY3SklˡFob@j'Yˠ@rQ`Uv'qbCχ>v}  zHo4~0S~şN=Pb(8DGh<Šu5-GV# U޾ϦH@3-۫ZOٚ::{7;4],(3i^8]LM=e{KcX˃p#^{2)Ŧ(冎n]ی"l]{ݻF T%{"=:rK6z>|I{4VH[w6")~GDoUkpSr5J-anw{zq?D1_a *#@O-^ci`%=^XЬ+BOf 鶈{8V<9=\Za b12ZI>i&nFkD82e6uh#kϑgg@ji9h1B= R{+zS tW­.6v3=㮨yu.h5Xn{]u۹DsIM=rDw5(ܴ*XrS)*A:juq w$[,"̾?U^As.*k[\k$' pJѣFCaUk^xtq'j}&Gq&ZiVt "Q]ի7%' pnTH10*⥔ȗ7>V l_‱ym (ѣ/A$k-Kz5{#hjE~zFOFt΀xϵ!gǰkD&*5ʕ_tZG7ע†;[A$x 6x}*=g OPf 'xŏxQFuy?U0Uqj3ԉ=%SťF8nĒ־U>㓲+Pk)jr}Ig eAo?r5.P} :c'v;XIEU6q(?u_v蟱=PS'%YnF*C] -ПγUwSTIx6f| yq߻HD ;=m4xI՗t[a E:Ep}C@k[}IGpY[wnt=}J'; x2~I'S]Qܲ_Z~|d_ u{z5 x?뜗xvZĿ== ϑ7=;<$I6.1AMlko+=ޔ/&4H7yxo;^{ CDwz,=୑HOړ7|ᡖ!4D<һ'z>ap^LrؑL2z/&m/=ֆw6M{g(zZ(mWzYiօ?MM+a Z(Q2ڃv,u4,yuYxY+zB\5 Q3\fkإ~NjjG#== mKW l] 4Іs= 3H~dI]aĭ ,zMMtI}+5PYm5:WX^2^V>"(i&EYnc]A&qsb!WSMgW^N! }/.jOth7O5AyұS^q@Έ6D 4zzT z%c;kɒ8p/':\ˬPQ_kDe?- Sc@)ڣWY44H?-l7:yHh/;E'kXW酣w]r(q)=pxW]VO\.^ko/@B{ziT,U|4 jrޑ8 mCvI} Q@HӃ.J[X[,eޥ Ӑ+nz1Z,eOM8BR÷AUy==2;5Fz B!X̙rU碗h< \C8af~| zXE~.Gԥ M:py@: x*af<Og=Gz,;  =8TRz<A#zS*6:/#=:,elT;#F/=GeLj=yx9ЋʛD}>[mw~M5 IeI|Z)rL&G}Ԫ^{@v{z5hhI!kǀ ˌV%zyȻ%gl% FyaQ,3J)jy[CJ̠%8~Rνp2ľ5vkIqF?|Ng0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0F#`0Fdxo nJCprus7mMBoBOlm|(iQfB'LE7_f  n|oҫwz!E5T&-qL]ޮ67Y2s_,_moZ4ֈ]RpEI*WkmumE{rPwyNqYz^[0ʯ_)=cf+!<^*< -7ޅ7Gac4"3-ne&/7^AV|p kGqMt>ZﲡjY7[11;^w&?ڼ>r]OZICOOd7C(Bi#EzCfs\8Xkzpi_L(y$->7{9$/@oӉ^@-lң6H9,/^o7=>|z%,=sWeܲ#a3빯9Qݤ`, gg}kV͖غ*ߑϣWTѨjҺƁTwB4:a !K{P;W|u_q-'5mghG,쓿dp(}\gO#N^8Rv9mw.*P9cJW͂4IOo MJZwYsyq#:)?n@~^%0<YNMԣg{Ͼ! tI"Ґnf]ZpIԅMh/A|p]%cI |W& Pݎ;)uׯP"~ C2'^_4(\(}NkZ!m<[}#4 .m F` u;-n{PM4-7mJW\92w zE4}҄;y y2E XpGFMWYZ!:f]iv2d0L%ʹN$ I ߟhd):57{9CP-E*P(` \HC@@d Zcݣq\8pl *D ∽ڐ9lvݙy>[u3oo꥗=I{Mr!zC[(U7%RP8 r0_\S^pDt(?#L=!JRα2Ic?QmTF.SeIM$"&lgyÏ d<-,yJg1nn;$psvcxW-bG%szl?AQͰ^* |Iք*WfeS3|ILOM:zZȀzCvgǙt@y<*x2* 00QK1Uy-=nE^Qi#,r}^H@L j׎i,z=;g(I7WY :L5d1%Ԏ Q?4/Ing҂+lB& z ГjWSFv=Qf$KRsx=Z[K/iPdGuz0piRU10EY|*!v#D^BQ,F/E=^kϥD 9SO-yGI qOa4z<+֩W9VڛiPKx_;+O=7q#-J.E̜ NgDsQY Tר䢣Prɛw'M%#ʡ,YW1I"|_ۅumO0B[z(ҳ_' U Tt\]~=J,|mKg0huB 9beuZGϥS=C4p\-bQ{^(/? rXO3zZh z k^l .%wN=J.X=_0k/ڣ̆SrY*{E[rڒ寠\=oPL{][ݿb{iEz^ f=:%+[z3;ZG)%@ڣB< ac[Rڹ[}ՠ=WC65;k7Ud#zu.}%&Tj<$5;z@/ zal5ތ/FN{&ŊBܩiok{l_C{-S:Bio⋿MtjswOKO%7z*Nӫ4k9w S~6ތެ;}hK.qH@iO?C{ - 3vݏ)@봣siaډ?jP5qO閴hy5Umk9M^{m{/=Pk𲨥Wn^R_{HsLJ  } yq[r7SU?WU>i): iOեK-B{)!#;A{G-qUc HNgg 2@@/TqLl Pji\R =*M { CPxFJ9Tth詵U6Q'lܵ4klWAd <^{H┒A>7T_m չȅ9%=d=vSJnVPkYwWz<šlPf ]4uBp6Z3B4  fn #ƎA30* j8ޑD}2zY/z(;\mq< %^L<‰eqiD,.7qoqif6z+h]0[7rT{#V., 63'*w0BYCCoezMM%zTBo]u/ˡYLysSٖcRyq BzC0,u3F޳by=Ap|9QLe>f_528!v͡7xH0,A+2 G  zz4W(HJ,IBD[&i{dd|ehz^1l^~<41>6!]{IΩΈfe(-2Zn TJ,PBo ~&ȟ|qsIwFx |Y"3=TD CC_Voj_Kŏ̞)MP %N 9o) P}3M^S.HGm@qWmDL.ۉ3׋eћpNHl}`\T1 %%%Qߧjnnݫ^޻Lc)?^WhmV=\Y@oƓ"WD{]t_׾Kj2[jwc.qo!WeyU}Gh1ʷ,{6`d)]; /1Ǒ@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$UY/{MW2QLK;%~ p4}]߂[{A>Ka0_hCxvT}k&2IBjC5fv=\O/u|c 3s^i7loujqoOgfk>9oNpB9=Mf<:(;DؘKѻV{|u$]z%t.Pi>1OdlμLvd4^K6҅3n `70AۚitV5Ejԏ 'ھ՟eQI9e<ȋ61q6,+;zIx d笻گXz' -k/3u$m 4qR[6cngi1}f^̿W{c_%Bu] |N/\1|JsvaX7:] ׵Fvfe5R< KR q~G}Y5i+xlQ9< -!z?MWi~ˡͳr-o8B֣t핇)uc3,^ 3C3[zaI9w4|p:o(]14++t&ޡ5rXEmiɧAo'kS x4[1sy'ǃ<9sK' zc=䰇Wvg U[gjy?ť8a"bkD:HF3[՜^fL' ;66U;.]Y0*26I})7QV+[zaM.zz6УӅ3 S39`f n ;~ǿR0}l)*%&4_²b@(xdazI0#0%xa8m90r*x㳁v8F [;leP6{G N<}MSZ{z4ZzDOn^5 |:{ ^$/ X6!N' W2G-U:u25ݐ=vi- 2Mzz{7̙^tԺ|tpGW@{l@P-;=YjmQ\5XR-WAozCV~I@x `㜛GTBF!97[X{nR"|M{rU N׾9d(zڱL]R=rI{z_Y@nBo% ot7ɣ9Ox"eU/ T3ɓ= ; ϴGj^R8h[.*<޾a$z<wgNb')dؿ@H^N y)sÎ^XQԥcc䊞v3]mwަiq-p-Ҡ{gGMLQrz[ 5nǽ2 5ZwDeǽ#z$7(^FFZzD6~2BP%mkٷ%w % n'ϣ^<,X;mk^EGoң? i[{aV iOq- )ڧD^yBʗ~!u;V-mSC{ }d%<GFֹ<^R>iO:[kt*n=RYX_G\ } bNwn{*qu8!#aqѣnzlcT84&cO4 [ %|ąt|FOړ\Eo]0;m3@@Z.%4Fp4mIDRC->5c5@1GOSJb9 2=ݢf M zz/0 hk dF7*G\>2t~mcB0!20z9RREf4eUzly@cJƢMO/Xr_*TdƌR17)mLbXwjfX%x3 }![F&Öd2RzIaDחF136aqh>KTj66$V8EJ =9XRP!i' *YnH1韫HOGĸf2M=ڌ9[kXͷfCyRj3c徭xyeH1 6W{ m5$zJ/ e#GJTuCzf?/ $~"͗FRf^GP)|f2y Uh-yG\zC-_-E$,2kĿGr&Ir ɻ> 7Yw}QIW,.EXV||߾Ά]/w'}6iJz@s[6^s| ڴyYS7;W3ܥU.{RuF'ٙ+Uݼ.zezlG& uin|eƽ~dѧkR{G/qR_AQ uٴ^O=vwmج\uM?-:6-_|Vf-qyy.h<2"H "H "H "H "H "H "H "H "H "H "H "H "H "@ ]zK\k&I/~a=g6t_#e@0=ͤSs{fV'MfV,}-+l:z͡𷉹-O{2>9ۯ-/ ΥDg B\>}[f>~ۛ,,6,=_)VMe,-y&Jș ?zzbAoLvISӄ.hIu[½7]8fA6K=R 2[/p+6sћ0h9휚+}~ ;7__Ҳ#vLa 0[# '.i*~}yjs8$ U.\'GOT/%࿴ae^xAri93-.[z=K/]zg3w*^vxٴ_=LȚ47frL̪0fbsvixlCM]G2<,8"IzE6ɧ'1ɣ p . 2>&rpD>&A0enxZI)(0ʽ-81>6uy  LO˸R1z3/Q{ᗏe>lpYAҢ5L1(pU.˘1Y2&9,BhwDù/'\;47ɤ֏,Hb!z|T^EƒJ#S=Mq&IYm$; C8 5TxWAoDS B5ÃHjVqog4fTc, OQii_>&<,,^HÐcZz WKoҠ[@;[sH% 6֠EJC= ]$3,bV&7yeA{CRU(5J˸>=2?ek)@Ks B`@IT=fCm. .Cؒ|㈝TM[zؿQcCh&SZB;UcQ%BDCR>ApyU-W'KNT=Y֨6Cm '<6΍#s{*SH^\A9V+5.`/MWb7WWƭ2¿̵̸޴Dڣ:iVEP6x0'rlmS! vEgAɭGzh/tK:$C@ ua8sQ\:b!ff'zYG\VAwT<jdZ#GUܫ~<ٜ*V _fΗJ.\T1%zb ؎;Xuh'Pup'WpI w~\Ҏc7GP͒@׃Zm&q(=!ytȩ^QΈtƜ˦Rgu%0zT^pCTwϨ;>h򋛒N{zc'#Lsz4=r7fǓhrZǙˎ=[c7^Pr Oy8(F[˂(o~Oas( iR ˤ=ho==Βs8s3z+i<+z]ҫͨGSS7%qs}٪/mܛX,%G@ֲg`v [G^15Bɥ\r?~%zXz'ic7QBOm_:ng[oWk5 s-Շ4rɶ)鬠Ô)A{c2Zs9÷PkZ,Ky3s?ƒ~@6,i`ODO2VN-nĿΛYh 荼sJRrSdKeі\94׀+ubGo*Թ\*zކ=g#iEȉAJLڳjyL9Ϊ*Nc ƅ<*mʬqչm_{6ƾx3K:v%wʧ6ȇ=CRՓ9-:+O'(̴!= tZKZPs[zfKNJ. I͠2vW\CYm2ESgC} `ckorlI Jɕ{īѳ==뜞z=J{s=؍64poh~CH6oSC `;RNr[fJ gTa܎DoU.aPUV(r,CiO=liz[ޔF 21 ޅ>M[ wO~”%IpXSMN٢nDtvy#̻̤"nzDRF?NN% &Sk\E0U:G*)u3\uݨrś쵖vT y_}ACzYtFN!`2l}^isGXc֜=di`{ =S:^+n 0KL];ٹEC?W#s|zB^=dI1,^R+EнEa|k|{=OhZNad&[W*=XyxZ~J!7p_=7nϜb ^ !gڛ̓]skEm_"d0 >{V!"r\ElzN!}+Sz6V޻[euknP+_g_ϵ_K,]]r\/nd3&:ٚvv͎h 駙BsCNc]nú;3zt(#S_g*_}WZlyhWט_ů_7곾wPͿͽ2{;q0"H "H "H "H "H "H "H "H "H "H "H "H "H h>:z h4i 7t$pMBbڴL0[/-gG5oj{3prm~pVəv[rۭl[Y7yzT/]0=a֮s<_#goI^ڿZݙ<Ɍ^LKyVc<T![N͟=l̖aڷB :s.Am8eFϵSr/lՕdG%9iFo!1oڊ\Bs g/\q ۴^0=Qw3z u?mw.n4"^֞υ7v-̊tIOio!A'VX|(nOϏ氣IPY/w=;qsW>o^Cljz,79|.3΄qVSЗapk;8| mocٿUM{xzsǘ q+51bcfQCTN'{Oo\Cz3//.L}zwWG I%#026Ct[` JlS~!l_~I'DZ+sbƖ\i')w1M=}Y[?,3(+LԵ)bԚ #-^Z}[38u1뛏K<ت`RN:u?Ț@AW fWqŨɸ1-1'EÛI 25z.JjK?`gD\abC'nTXEoo'-+y4#aʚܕШNƖ)#wq Y'zmD3l< x=>3.\kNoNCm0i(\* z#!#GU)Yh YJRf8Wu HSVӐQ_LMlw+HJpFᢀ$eLIS+8Qpf%6#sl/#l'$zGrJ hb*ѳF&S? .yZc2M2<  5Mf V~:h{.d8Y0M,j *Y!zb =8#Og^۱248~蝶[g衟~>?,9/v5osĶ+BqzG\G֏x7;F7\@cy+>УI<<Ө !-3gLPTGOx:C~O3_QP p-oRR ="$A{4CZzDY:jQYWHT[z* qRu'sK/u=NfӣXg[zmZޑћ`E;mV艭_w Zk31[-Ku&3N7,uڣZ)GUeR7ެ.҃yd3I2FGg,c)n=:zhjŽF{J==ZƽPv#-T-5qdh&h<=@:kIg 856.-Թ-Unurް{uAΜ(|=='Nܽ@M"(f4;z^a{ b=]s%oV{%ڷmYJ+f%w^ݖ܎` ѫV{ЫQڥl\{Q='4 B{+P?7X F #(K}OC֨bA=Z˳~~祸E۠nHMp53O{ziCdAE+Թ$c'#Nio2jk !,kO׆O7+m8m9ݍ񮵣''f\J47GV{=J.2 {gTpƥ00 F!z)*~$z8Wґzj3=Y_rs9zl[,[tK$ c eqx64\7Ih4TP|0ؐq*„,4J*NVnP V>c/@@=A ;VgM)0wTNFM&ң{UߠGXhnB/G):9~RJNO%E=mi!ZNf#gN I{=7dI5f%o 2M,2J$؁/y =Lo H7U >sf5uM rgy6i:n3jyo[:E|=NR)D.o=l 9|R mUNMzlw,748~B ޺}kNU~>]Fڤ-V&;Y ɻtҧOo?KaODtpW}XN!T}pB++6DdXqMx~J}Dd;3ه:9׵?W6 >i5~M=_s*cu5ƛsgD׸5Goc"H "H "H "H "H "H "H "H "H "H "H "H "H  sWQc/R|{!rFo̿Ӄo9g[:~9;ӊgYzLnIwHm g'R8?1ӛtsʅbsarV^RO+H1lw[\^!mgNNڼkr&>^mrR?#R76oWYhN953釥z3.s>&'N/6+~(|`%qPr?^iqY[ 鷆e#E{LӔ.=r!hwROe~dpQ襚"ǽMy gEUL~-Wxp1gVu?eJ޽C'7ܺ g|*j﫢7*p̤q%sh[^1l ,u.ʡ;0bGMwC3֜1Kk_~N7ܚy5˶Vss8bn@#ASĤPe#&7Z&fwV9o\p&.G,6hܱE:L6#$3v}GT&;L}qݚ'K=|)BvO7(y7m~WM5eRL+,qƟyc51.3цN#t90iG!01@TDox w\)_d]&Ra'"GzK&/-!cTXCIE rɵ]\}\u"BfYd!E=<: &\@o[~)ab Xg_A6%LeyWN&#(ER[Ds\>Ά:; ')MNa2; N@7lqlŎdrUX_,q'!VTӧ^Q>4:f.I;*w'3ayv Iy侠2{p zp]FN[7{۸ JOVrI*WkNB"%*J-{;+z@*;z޷Ԫ1>wGcg%q*jLn@0!1‹eZp!!T`[x%zc1J3$ۉ<qzR`6.&gh0h]`ToU#KrmЪ­la-l\ udlo#!ȥf?VF6Mh˞@+j L5Pa2IݑBC 6#hYV[upJ3ܱՄ4 `>Wp=y- QʹĜ^YOX} JnR442=OQ"doGfJ{9q^ aŊC*^n: 9_ǘ [-D8./M = ~|8)~V3' &Skw3R!)ÜKn x*ɛ.7ͱ b wAS zͭ\  #x=WTQ)?Wex szu[h}衘 ̤U]5&zDâGYW-^ j[]7%Y&N&JX]Gk|3v\J{D -|w@̈iS-1U--T:7h(Л/zA#i'A,ۗу~xIUMv)hQr;z@/cdB&CB{$5(aFgq%QWJ{>$)a-G5 =ށk长J{o亝HZxz[sICWrڿ) w\k>| jhBykfeGˢjN% Wj[r{-H=V;رq#l_m 9G6Lp*BuͰ4Vg?^zh酒 PrDKƏup@in=Pr']}n&C(_K{@KDjMFDe *u4>o-zj==ztjuţo\7$AKÌPj5DOFy*^-ï*cA@۹Xy AL X- OsJϩٌ^rԚUZz]&È}0h~= !;*aDԏCWT*s ݨ&U!: ~;e(ozmVR@U%0pxV<܂#}ݶ8zyV<Rz_"#IȨ; x 0ɤd%ϝVz)Nj3Z= =5uK߱(bAXѓd\a* zX{J?9D)VOv+9)Cob^k$b0^w9cIs?m`&KPiBǮU?:j!2`UPL_1M j ޱ ]F\@KIm3nwx3s]s`>znۼo)G= RPaq<o ^Fy=dك~QV^|FL^&_AGN ڃ^ ,5Ƃs*Q1DWWCrӒ쟄g?F1Gn?krLp+R^WIp^/0&1p3+ dڇ\2幝tq U˦~N/[A53KP-G:]ozr(zF1_l=%cSז# }hKۼ୲7qB+#쌷@キ{:UEX|)c%1F5/Yo XVή子Ӡ ds2ɤK驆&U/}S. mtDӁo`N0wO()OSSe}zjG4͛,Riѳ}6.\^HPtՅ=IշDōtӣ1餋u3DZ SGOMjtưmGd㒏Fne~~|n:_QI58?t3cRO65wU֗o#"TV/Wo}[*G#sުTڪl+?)ܧYs)umՆHo%]v\H D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ D@$ DהS~_Ӝ^I+k`‡]ߊ\~4r:OXf/yoŒ?Ϧ0F͂ȋYlZ7'(]٫lwͶ|&=X8?E98ŴiNoXa8I#GgqC^^n醙?)#穧3;lf4դ =jc*vFnAe-L&fb菜/ρ^1웕҅Aa9-ƾʵb>VO"@x)ϥ–1OezeQ{cڊpX]EYl/>gR4+-jorc%szR Y]38 GvqIoyֹn,V*՜e>ќl!]D=]l: J򌇓UqofDkr[\۸^VĽp%9 s!| Y5lFs"1!þ7-vܯYz+=fQ#%K?~nФ6-zc[ʘ:U"w۔֫FMhiy'9TNֻ>{㟽?mb=T;ه+XE|[>#K.Vi=sFZnimSL`Ӕ, GyR<8ֻ!Fc e_CPpF=Y*zA֮:D"zdy4mZ2~&g)WKՆ O5sOok{k+A%I&A|Ei z5x =ˤi>VYKOڌPa=G.CXsG정66Ľ)WNbBj[QƝJ襝)WIO&Sg(7DW|ZО;ĹO UE,EG guI{I8:o!Ug۲AǠ"13+1U|:l~͓B-iGz0 *0B[N۩~i/bJeIu:W;Prm!Aj⦚-b.<CҞZ`]=Jpt(Ash== G#Թ D[/wS|m@RC'$sPwGsd/={zYWBptB Mzz Uh-/vZŷTң1ƽXr}27wT1 ?rERqcWf=kPkʌCG/hd8kS5`JBkϺ@-fUrU׵ +{-=ZR(ifu!fir;Ȅ*Ou=b6STS,HY.=}I*Г|Վ^WktTׅNFtIFc,7.UJ=bCq!zZ?|BOf5%f qj0;UTrE/#1p@s.HZwga3z mܣ)U|)+5l*4+a8)Rr_dдjFǢW@:!,vv#vX@YBO:ݴyH\u%wa@'z]9iO5*9uk.θ<'w8PESE!QGRsn> X{ +R;z?niN'q/ y*cP׾yZ˒Go]i_6v ;{ {i#gzbV'5VIJ9 !qDJ %ϼ6͔\2Ժ=b~9m=nUK uIWí C}Y;.Ƙb~{"̝˿jYW"yƠ-)t!☄NOY \aӌ?eǓ۬8)="Ui26Cѣcj:?ۛ_n>9ષcmhp9aÏ3#ay f\^`2.[Eu@cYU ۖ\<|iKn'Neo=-,tHM|oS֗oohR^fkd[br;w0Dr9 C)y U;]Zdھ rU,R-gEDЛpf qYzBoej8=lʻ %OqcT2]fBS zz[ww.{b-~5#)"JMܦ.+x^$QA+o 6. Қ"rjyހ7 L{,U=Msz)}BhQ r <A<klFqE{5r4͏E֍,)}d8ܿyd;?.}ܴZY;L]J:'kmZW94!\n k~HЛ>]K"%9/;vfչ)yI궮H]Q#дo!(s W:kn6G* nMݘ"H "H "H "H "H "H "H "H "H "H "H "H "H "H "H X"kqyYSh7faqi'ZDpKZEl3^a=M,}bF)GCK0-Y>Υv YO+K[0PЪN%wm53ͮHlR[܌cصԞ "j;kJ/ڐL)CZmKړU:-qaX70Ϲ+Zc㯂-lڬ1ut_t{ϗ[͠wXr\]MkB%wfqϗ!3QrO,kT2גްlƽ^Wu5@/Bj f%wNςz%SrC%nˬY 9ǨVip e"uJnhR c~DHʱK7:a[gzj=0a 1_t+rI<Iy7 CJ<+ 733,A4>7zK:r0celfp׵I{kAp{9x7[8N{I28]8cQ;;8X1Aީ Vީq5Ӟ_Ak'G?C2AShΥTEDݓ^|uٻD*w-{jXrK Guں&0" zMZ""[W Lx&潕.pͳAoXt&]Z( ?~-.#H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "H "pQg|-y[W}^ o媽ݶ=7|a2 K|ЫIқڼBU?p3hL5&H/{E6ލ֜{g훟|@j>دP{ k%U{{z{&ʴފ;ēZ3?* *y{땁]D +x.Ŭ|&ggNszYz~~6ZrK3&;4Iw˭M@/u"ki1rfszN}a+sgכWo3zZR5'N.Eof(z9$A c!][z@Π[_*s8ce=5Z1 .*IPtW/v5ګ+Z,2/]:m&qS&ecܭ!LP6(ho <*(.0ЫW!-Wfw8RcDUr$EŶBo~\j;Yzx۳*Dg-^YGp/ 9ImGΛ:f?*Q凉zj'3GOo}jL+K~e)gbqfj/=S'\@qa⅀AQ(6 uxB|> La{ͧƄYg):#Q52K|᤾q3^6S?0sS_Z7yO8yfk24Ok%%ѿ4N{Ыoe2O\@ E󇖡zyhӣBpT>/*P{"z@Y \aتL'(X([p9OI zH`7*SZťGdQQ7uгQWB3JΡEo$?i@H S'^0~[ԝ^0BUfC1hRCU%dk)&~dSXn&< 37ʵ-2rj_*̞pSni3 ώl/=*pTR,T2l'/KZ -@o,JeÆRw6赲l('Rbθq;m rzRT~ H%+&*UmL86mqRŔ.*핞^ m_‡C"Z-Be338kӝԣzP?DX@ogKM9Aر@+HT]g2!.EΆ=b71ƒzC5mC›ԃ[z6=x^2mAHTLUNK9iZ.vyS"zd3"K@9Yi$.1S@ 8x!vLPNz/w=#\DNQKq˺U#zlkǴ7Eʏ%mO3s_ 9l[rL%WTEB#=*GiPux_ hϣݡ@<1S%\/۲szDث7s:гDg[zܲ%ByïDے{ʔ/DN{;z;eǛeiotq~~0h *[uDTB'Ng7:z.u`}7C{3z_O5P7=nf%w1)^yȈ%pA{T}̋^%%zpt[ ^YAf?У"9Q8Nc+v3_%! qoPp1V {*E{\c%7RV{U(zVP.$-d7=%严G^OГpEρ,=Z Jqu?a'Ruitƕң/zzS؎^JވFuJIjZܷPrxZz{k%vվq_s (uA"!H1¸/ c@yG߇q$;gx H<¸2f@`/Age_P)EVK]&&M޺e䱆Ѓwkr 6+֜yXi3$]nr1QkH/ҿQdOރY(qP~O#n'гG%}Z;^yxi ᅪW0ks ͡Uy0s盵 YŚ4XCdm=RoL {m E}I\FP`e;Az6't|{ Zt=͒ ase+ma%HV,Ɠw uK.m;f)+66ygt3;$^pVMh{&/-;l~SwPY?o>wMd]O"bC!;ڬ~m [`7aj%{ˤ~0?r3nx>=n| ݥwHoUhʖm]z\(c zr3+%<> zQsC{|lO-{}z˳@e%=َ9loϕ lwtuf7ˍ ʖ6j^cd9ܥ·_?Oߠ׌'V.&{lo}(=+A~O+{ͽ+6#[O|Ъu.W0"{]kWۣNSs^OX=g/vNRDdi@OFlӛ2 JW~6 {3u3G6^w{RFIi3[ ~u6mfEx _'Eh+?T#{NR4e8 @}@h=m!=DõЀt_T$R%T$H4>~dAOB$;BpImC D^gcQ Ȑ#jKhd=~X:q>*'8ՈZ(m%=zSAӥ փW͋Gr_I= Ы艗vY= 3giS 81/m.kyd1Ɉ85ΌԖ8tEE'BN>I3鹸̕c,%"C.e/3w(=LQ)b1KYa[cB"qNi%^ew-I, I? 3"D>45qwQ  ~"Kjz+zl]S*Єfg(_1{t:^4co[?5]FC~4-2^ַMF϶k؏l Kz޾CsCw?#+ ̭B:d'۽ z5e%Bi_D㥺s{g9nÀ^=V.W:Yz.{_õS2&a˸el (d&ݘmh[b죣f}<ˢ;d'Xy{0?XVٹ!=PTъ±pQ}#t{ȖM`>U4z/7&%o,=!ku;k5|ȾMpv^-|gD@tnlXΆzdQ6]Fǐu K^ie׆N.?mXc7#z8D+lQg5vBkrvNP{9B/^*7}q9׬ .Vqz- zA|ظ:*+٣ك#w."Нz)m%| Ùka[r4g433QJ;-[9n9cd[n ŋ!  & {ac@kKGjMhsK74< ;cv .g.ewٸzNigϝy +jz&?OݯI7e*J.HJ(ﺂ.>e|l}2n6?7w)U"{hQ}ag_3-h yKR%`߾ar,˙/qr⮥/ v3~+_^noJ '@|&ӂL|V⏸)o 4t /4_9%!qmu N3蕤޺fE,{ s ;D(NZ< =sM!ߩr-5%pnLУCD%xaS) k g-IR$t)G#GË +tC&HMDQp _67CIbMP6ލ慨ݐI//fh: %HՊU$46{ nso:.R Vh=rq҅-n[/{Bʼn_KO"{RJp@> |D6 pmyq[5T>Jq1"nF )x!\ gpC|-gFNQۗNOz %HY=';4[4=WBusę =3MZ^rwKHb8%0ſ$=Y*ᱻ'5z쥬O =q%K'{EҖ1zZ<]Rbrϥ勻) t5zztz Rݴ?3[J[c+l/gAꛞ |v=W\7QC/78+!MfmUcs A/id/Aq-֨y5=o| z0$2\ʉkhP"LߠWRYqHm啐`Q, M\Cp#{!q F[CKhR( ޣs1 Ez01iDA4 w9Hܰ%#rCk-˕K{_UrsK=+=W\{禴l^JB&yz,ApNYrmwse}kxGL-C i9aQű^3}ТgеKZ|ߣ' %F5X=$-=gVe!g԰;?󂫊$5De:235c;zζ^\ 7 T}bܰ(x3|QEl,W}$pGЍLwUz ] G=nbz(:8EX(q wԉ|I=D'MU-=@\Y̾2ֻ/fb0x5gi&xO1),E$!cƚJEO =DSi:/ DZs =q4.h2(E9or͍˗י:,7cSm(E0c;g e?ό5$Ы㕸xl]\7f2]F,Ysp_מ1G20R'DD}@O YjzCF=.r[?Ơ-$*ozH.H/Lv'nm1*x`2gY =x =f]hYlC,똸NDwD2Ȓ_=  Bێ"_ʒP:# w#|\]cD{,Cs?(i(`@. ACHxq f J7gL !-,( &>jӗݡGN~-SOŔ#D2~+o[;eY[^!S|}y^@ 唾`\q0|xoHJyENܻHxa=lzHw1gt~9K 5y`<+xv E#j̧!s^'@%&O u!G<2^tz_0bAhN4(@)JOl("q͡(ByFDH»čۨz%D&XFm Rc SֈNhĩ@ TUч 4rp^#փ J@ (%PJ@ (%PJ@ @VJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ Ll~<d wrRG*9pvB/(qO0B/Onlձ`;ϭ=[nZI3Zb=)k?SJD-=-鱑S ]#{B/K Bf5L`I/Qz'([4"{d}oMq3UR}9UN/ž_L{MSu8bUl!ޞWRV &lc'oٯ|Ipqʖz78`_qw=U8IbFG坯gYN\=JP_ ɮ*z$ {35zM_.m0FzX,HȕށX,f`gXUMmJ = =:xeVz[ w@ToZz>C0F >g 艏*\M!14h'{ V5 U+7JN(ѳ zmvREW"cd zY~(nfxj{\p%p{<)S^x{sNycۆ^+{pvJo<^znxl<狤s |.0ǽ @Go^6]V²x֣ 5ʨW ڴs]K/zO=ʓOdʘ۬tKw4@Y[7+^@tMC=z s[+ir-v~^)&fsKpy'x0""Wڈ'q={YQ;a #=[ ^Xkcq0##񗫲7n]=/~>߾4391]GAKUgc6RJk@9u;50?I0jTK]Zބr?:uQ-A@6!ai8/zJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%NEv<5چN]gr37'c*䜿s90FKPǎ4!ld`#^En0_pVyAϥ:58[G9NLk#ଟI8"^"mJ)O $g){CoA 0R 8$-)9߉Gbhp)' g̼?ռL+ygհFY_y̬2X) 7,g-=3_ܷk4"l=K $Ok#{Lr:a 8=t-:v !We(4fԣ9t|Q=9DU+E$nzu =mR =Yze2 ˠ ;cUs9tw.|\1K Y9_c0 DٖyġW$㿆ޝPBÊ^BE[y4]C"psS[Q=o_Qxy>Of$8=0岢F/RW$ r\${ws˨6 R:ࠗFzJk^G{OG! k`531e'zE(QzyZ˒+ֲ/%#5 8dje,zqK/fPS.\챰\$,J  Pm5 8T[G (0襬jtY瑰,(,ѐiX*bPSx1Ӝ}de^s!sѴަqT }wKL =FaBqfɧ{,!4\g#/v sVl=iX'5' zf?CܤϨX뵧^0)󶀼g:{!~3Kp<od`AXj-ӔkOQS jXpҫ5oKzMƀNOQS"}ցIp e܆S P]56]T#rҧ7JȓO\:S8'AUdrPJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ ( _ī.|+*>os旫h |:S;/<gM/|opgb=D`􋸤 kvF/8ۋIJ$D/;r?v%"y1w&|ݳNo'#?O?q&u&iݵeߜċ".w$-=lhN|myhj̫yi{ENW~ul =w{>/މ3Ejzq Ϊ읈2s=كXY dz.@^W7Vь%jV"+d17޲l'`1N%Π5L >`耞ӳ'W| S[- ɜ@WD^ZN=Mɗz=bQz . dN}) \d/:b4RB UwvtX_LӝaʥZ/"=Wޮ=2mC c^Lm#-BZc:A#VU:1inylΊybsssЖ9cliwCSFS}eg^ז,)|\_~|:jlqݩ5 g*3Z/|d=Ec':=:s8`=gUsl %PX4@iUZUJ@ (%PJ@ (%PJ@ (%PJ@ (%zӷ4ɧ+󍙙]|;7uѽM/K]U+:*s`8 &sWՊQ'!ώF<+ @ӌSwzl}U"?p~:䞟ԏڹQ=E$H=<з.BO Ы*Onu͓.BO7OËT|]5X.",zFpxEn'.5qފZ# sZ6 wքMsO_b kQ'; - [_[ k&;]@|{-[i 3\u?QsM2qhأм=fvrc~!g@L4a9wx/(o;Z-|clHD9viuW=dp]ҫ_JX?|o_N|p\o{5=zʂ')s˫eiL9ՙc*\L/IpL<VA{K5}*A"E_B } c5LU~W޿LChqk%1hc(VX"k)m|4dmz,WWY~ v&2Ο ObMrP8(rhEixMRkMN^%6mzVxo'^f%n$цEw 1UDl 0ڥ*僤)&pMǝl1UbaY"hNѓN^ٙM$,Ti$kEhǓZ1lSg5r5QRBC|q}Qt8 />a f[+f>'Sk8,VtGˢ^ެT7BNRFCk@/۔+v3ۯ<}1AiXš0џVWzCqهYif+sois[j&†!z{AŪpGg-=L}lRyzef",[{ۚ3L'a eIOVڴiX 4yg06u:kw8*q?Kz 1LEQ9?VdYIӿhnU'dzN{A+[zFV8UCԿTljM7W԰"hR켵DKXػ=5i{ݗgޢ;m hd2WG2H_E762u$uze+t&<6BgG9#\%zp@ C$BO34J[\߰0"{@UzĕPmҫ@)DL3o6cz="Ybk!n?4sVȦ i<.Y(NA2S;~ʓ#cjKzO2̢ ih lZ -?ǧUt+ͻ  bL-b=wԀ`r{T?ҫB'-!nZ+[Uϗ6^inRHCK`luDV=o PZ?m+f#X@oE?%KK4+HzG"Ã<L6"{[85kj+[kKzkT;Z"Ke1Yt6z_b}J9q+ҀR^qE|{ickzba]{t:!Yz]պH椒V:^luzھB~\ޱVɴQ׼{R[κ2P3̙B<гPWx ۾r EvP͵sM^a[8{ꌝ uEظnm@\'N"wGkvQZiSID#?=d^yf,C,9󳾆^PzZzpRoޑȞNm4ƚ+rJoˡxOvG@`Q& PF7>jsw'C>*L߿3+c̫d+8[Z43y?&SsMū*&%+ˤ{t?zI4/s/<1~K3/{SRa9~Wa۸lU=r-u ՗jm 7uR>zB)G%:R-?cQ|_%.7^;Boqg1̬Mћ͜yß?P"zG{~/r0w>h@xz6bt= J/Ņ'uP&B/M={%t^e?S֮Coaz>j3^u&O:.0Y lЃf ^ A1$hL/jnҦZca-;+c2YMX$ޱeށ{ Bt=wa! J/n 艵Y"=bAy$>:nle/Ӧ{n9[2j=1^4̣Kt^?=d͋|֧_g =&=^Z=|#Jϭ⢙BuRHT2ݫzjXba7X,9֦#˨>2;Ef6c~9:QWRhL}텞p^r[/9ss+6w=HX2sэco~C; ^CkW.|=B32qiU-SXV`X%^\M;i?dYÙ?͆^~;*H*VH-}.],xz]F ^űyvU|*=Rz<P{ӗA9Ds#ej ,B^d8Wl^+{S;6FW; m _3{xv,=Y,tH ezJ[ab>dEޤ2qq> zI^f۬~t#n+UM(6Ɨ/ldŶ롈M})k6JN}V6 #`L ؑFz.8z#':.Җxz=W͆efj_Ѵ!S֎r"X=3P'æccƆae|TrWAZ =4i7ve-c4z02KFÃ=ʞCh˸XyMJOgϓSOXѓ^;sdꌶdzS|"zγeTvٲ k#d?u [\#e =X7"{y2%=Y(=U{KV=zv^=ʓOy$ 7em,3e鲀l`.qDܚjN5WI=հUܮh[27 )&PƳ?WE\=867M;@ps?agk:mF7!9IS7Zk3Wxa5z㛐{ gc~sq8N8.kW{BONڋ ;"zt2V*TzUm#Pc\&n+^ֿY|&n.M\j8Ԍ_;'j"'c[ekڱKE~zl9#P%SxcpNLm 61WO,6 Ȼ,jl9MJgk)ek8QzgV\8cDZqwF`kuˤ5g(3[/nף;w&\:9ST נ9ST נ9ST נ9ST נ9SٙJkuJobJlKG5v&*{g5(7r;Aa7r;Aa7r;Aa7r{g5(7r;Aa7r;Aa7r;Aa7r;Aa@U;AᗃFB@靅ְ9K\靅ְ9K\靅ְv>5]s~Ksi>KwI5EƫTֺJ@ (%PJ@ (%PJ@ (%pj$ɯ_^zH^8AWz="ГPrÔ 3 nةLVznoz)Uz^}<57 Qt_f>-" l .px Ү}n\w~md؆,^N!{E:(4ஆ E"{7] n>.| WM;~TzIH &= ܲLc~P&opdV3_F-GS,xkyFrltȔ#\:\:;7?ѵ􊨓@/m1ID5F0H7z.=_Qy;FS.W>gad6+'z/Ы c/( cN]y:}+M,5Ju 0c^ݭ/Dlu k˿ŧ`'ԼCz.(>{3wLݝsKr Z#7s2@Uz{bsG ]50>Ickq̘}@pI^m' TM'S}ީJ]PKk*Ѳ"6/=W$2-Hmfjf);*?A͞5s RJ5h~=W|Az湩Km=g}.%KzL@kWm +TsK^襥+RLh{jz}̹Kz.|Ws]doI矀]. jTa Ɋk,=s娎J/BF _(\KݧNe[y0}:g/eTlb Ky_긾<gͿZ̃z8LTYq칔ݝP^u^#yAEz.'{vH*KW;E'EX޵vt׮kz'{[69l5nvu5sπ|eϧr?|wDN?тЩH >?˟{ڿ?_oӋ՟v/3PrkG5V)  ժ?S '_C2y T֪+{ϥ.v>K*ZwJdr\]i.pS*kU.@ O.PyU U|]V."&i|_ӭ[Nmy"u"J{ړLPJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%PJ@ (%/T endstream endobj 35 0 obj 69266 endobj 37 0 obj << /Length 38 0 R /Filter /FlateDecode >> stream x+TT(T0B3C#sK#Tp< H$anag`dY($*{)u endstream endobj 38 0 obj 62 endobj 36 0 obj << /Type /Page /Parent 3 0 R /Resources 39 0 R /Contents 37 0 R /MediaBox [0 0 612 792] >> endobj 39 0 obj << /ProcSet [ /PDF /ImageB /ImageC /ImageI ] /XObject << /Im6 40 0 R >> >> endobj 40 0 obj << /Length 41 0 R /Type /XObject /Subtype /Image /Width 2544 /Height 3280 /ColorSpace 9 0 R /BitsPerComponent 1 /Filter /FlateDecode >> stream xϏ$G(&1KLeSZ^]|1"َ-Am/2(|;`v llZ\#h|3z{f'3]UϬ']A{ۧ_9}w]\؄_.|ꇿ}៽88w&XAl~'o:|W8?|+;%r|o74ƒ0\LO]E?p>` K\ >oЧr>ZZ 0gͿ*|~J>o>UAzU?}_LRoW/_Lvi@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@wDໍvc͋|݆^mdjckzFFμ>7_}D8^U^Y>mc ]-ѵ^giaRŸ+zK\ gzvt@W^7R^XvVu5mz +k.XʿkXW+ZoH.qq*:6F, z 襷H6N{^WsaYTq;p?Ý洭+\\{:ӫm?}1OyPIϙ߱?kzWe\Mha_X7 kCDz|[ޢ zjᤧJC5mRcjGiц257^@zᨆ+JT />^#Py,Bڽvks?x i\/({mp4vqIbi ӫ |x 6i'={:Rgz ck7}cL/OzC$R zCm|K-zi}%Vs5jjgSz!]-`zZ X)ǚjJ}Mt@zoaV\-z') eŀcl2agE!&-<^9O{w_Ո%z=D:4!S-"vMpti՟Yo-лFY'iOzGY?;ߓ##5ϵg=~1/\S]MIUۖI}?/YO\5%ꇶG'_fv| @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[hTnNH+/lOmݥΞ*odoYR"Q2=$tϻMk>IRR.r7۵srNҋ~عNBvLT/}Wˇ& kRtw2 woQ/ ]{W^؛fMϥ?Y )wCs}j⊚;Q/;W6g]jPbVkLa֗NMY=qfHW~{jnPP'<M^,o͒VwzYl7.2:}MZs;U3u6g)J6ЋtlRѷ+WE7ҋtze\>NU + Bܯ^QImZ[4agyjw0k= _)֥׆E_y5M{ٷԛoy7yT=yV{,~۽٣Joizr"$nS_eǚ{~bo抽r镝W^N4iaW!EVR{PERHz=EeѐW+z@׎7Y0T>WǤ4JN[Şw.˦{RyV޾G|֋zGӸUUcRE_)vL8RCS_hOiqN6<0+򠗿zӌ:tG<=Whn9سQsz:S5sY+9\CQV*cOan D#j1O?Χ9bP|9rE^jk L7ҋkeazTU_ڣ^^Uw0Ӭͪ'*sy%h&4T^*)p<*I?۽>f>)8N]^lxR6$Z_d4>یi:GG=y|3}3WV b:%+ :kw3](OfoW&                                               va^-ЗsN+RuB/k]~z3פf+_wY3yg9.L/r]ޯM5gT^]])`6czro&T2]ީڏ &6,)ߗ^N]hEyy]H<&$5w] z/E?n-,5dlFX.uB~1,/lMmZ~{[<'vXq[թ۠3O0eVUϒ-١qzLA˿7ߧʐmԩtd5A7k[K<+W$tYL}a46)-*ݟPw2ҕ+4{ҋ^ƍzS-%X婞2z2AvW~iޔM Ijx^c&LfhhKCO{(ںx};-58ʛ/hiLC/Z]S/,ʝwٖ4.]y;0nЈ7_)^R+?SL{G]痃@gkE+fwoa 89@;6XCH].?kk:g@pzU#{Z ĩ]}K";eZi=L{.::>'ԣKOl4;k4Tbr@~{kԡ)5VKg'jboԓ0S{ ={y[P=)ꛠ?0S;XsbOmEuQzj7}V iM@wHc[ jVK[)NI#͉>*ӽrƽŞuӼ"~3e4$=a#0u(!ؚb)GEaRgz,XG2_fҫTɬfݓ̴Ԍ:l{Sk g0ʹԄ襧;ֳ;7X)4'+.(+=  ;yj\jfǀ4CkjLOH/^FvܼRUuPW8Wz3=9繪OwٵN39=nWLO]'hسP?kg$~R;-6}y׸obԏİ>S_M/RMfe;JO ՟tyঞ:]Qo]ʋ9pqk2;K6RQe[q}-Kۓ^Vz.{jg_*nw{Yo>nϔ^,KzmP`z^NPmpmhr'qثlm^[NTzE2W)rKm.^ '[/j~5YjˤSq_nbw'0ĥT)azJ>RJۍP9ѩy|w?oи`z>9,)LvzTIPc J/Xf"cEΒں ?J˶*u,Uxom9?52eCS2$iRm9wE:z>oòˣ[}TF_lF7Wtqc}SV]x\r1蹠rnn]k9G#Ss1FbS35>+z=Lح^^yԇ4"M1IOѦ:bbilT;Mkdԟ򵾝ax &Uӭ^jgNz[gus:L),iֻAuwEKN*[z~Lsվk! Ea]啦϶)tw:^U,K{R]5%e9X\{'lam63>۵kr'6^B[C-Wzص\(V+UilDj eg'0ӻXsٙYԝۂ+Z@s4=$=:oz dz'o6ae2n++U^~^c[(.vg5WzZ~ջAoVzVæ\&D=Vz xX z}>M=5DaFfSNd}ngz;^%PV]{ZqX^bS4h#ӫtEVGs!mӹ/Ycb~dfjjJՌz!+'J5֝RKvuG>r.oyes&[z<^ s tژ%z[Rꖲ^ i^*ih}Z4nE0EgwR;2ˤWz]OzX#t[yS޵Zeؓg©ejdwy[].;"3bR驐jiy%~׊ޟz\3읾w\ŞÞi&H Z((õdK-E?xmiGz_zۘVץw 6?u[ ؂.]F]{XKt\5HmL%y6;                                            \)+qJR^|]UZ_ՎޅK~MYGA}6Tz0q\B>nzz lb׆jLz恭h揺S;p+YWzL5ws;ԝiNw}+*Lo~w{s[^R]ޕNO:ɾЗ_םtlrCOܕۮBo׳t,v+R(ˮboг?˪쳿q_w/^&ܕW֝9NkL8}+[7]^Cz]ej.k&ởl|EP|TR}:tb/ ;Uef+LK1|nVM޸,jV=պƞLӼm}軼 SD_Je+FG7)c'loj|DO'^zQs,'}Fل7u ZϷEd:ϻMOT[?-cYObk! V~4d`zAzuy߄Z5Ym3@J{0miAhzQջhC@AބX F˴WHSun}b݆Ky|Q/zzC@zFz0ڲsG[WH:uI%k}(EYEo9zaŨw.)Y?ԩȖVzZԋ+V5WC0&7 KA:u2bOz sSus2ӻIE>W^SäyǨWo:v/=z=z1kɨ{"}i_Pvbz'-GXSN+AOcfjiq{VsU\OZK4kn@IT[5w"5wiZ1ƞfAFH)il N9co]sըۛ\o8knSC^;M֛a{a}B#ݻAQد964SMP"x삞j5ϽxwhwJ##ePT۽Zz < (kBchc^WX5mSؓ >Wz'khNmras5ϕt7-Egz4cU,ٶ9KS]iFleЋ4[ Jؤ>7ԊSub0fLmOҘ^TQ5P M[·ߎUnBeЩW5)- OuXjH/npg$-RKzaaSM1]bHeA)f^ S['-Ҕ BU>L-5NJ-TW~Eat~>k2:gM\+~n@X4C!<;j}/5WAs{"izQ\̅:zS\ámlhz C=rZi-S?==(Y*ҏr>ͺs9~>wzUreQS6C(Şp.hzE\/1^anW|}}.4?s>\݇ \ÇIfn}L]}'zGJWoBz~Ւ߂z*/k-л61~/2T-~=Q;W5WC'֮K'Z–o4{ٹ^yJMZH:u9yysTBJ-?n2 ~Ks?DSwK7q7KzSں('W-]pY8^]wΆF @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@MعW^X_헯֫pzש)@,6~sKuܬ)aw=;8~cu*5~{j'io& ںɦR,4^,[ÔN(vY4e+zrK|z;kB=ƿ'za{t;z,w}؎)ޅ.TRcO0t}zEW셡U8F^pCXoM{ϥ 4ѥ$㤎7XĝhЋ}. zUڷnֻRŸf#ڧ^wH# Y>%Úb]Bq ]3Wzq֥QtNF"Y]Jv_l}bXzڽbK]Q''4kvCy,5yӛsP8Scju^9ŲIAOڃhW㖨#-|QERO4`}j/g^꣚ՄϟwQz)?ޕݣNjjR_=+vW\KqwS*!SËY˪/U@ߢγ}\X4YMZyk7j؃uJp}"o}Z#k~XiOz?D2-wKn<:nгdߧחͣdF힤[ߏz*\MHl2^R ^_Ci9ZzsMD 5ךݤnIX칃@qtߢס%}{YbkW95;*, zGͤqnzGҫӏ`w)z pŞPjŞFH{|9_ zIzz \KoUt7iSFB]쑚Qog'I.}hvf𚧍z7,vzL/ z\oW'zr3c8klCz2ޡ=ykIc5Hz;;n.MrƦIjF(Us8bѺ1IЭQJƚ[,ZvUVs2%nWz=^dzcg^Nkv7^CA =[ M/İHYW0ثӋXT/h-l5zO)\SjqJOnkߴk}%jnc݇:qRkl+s؍o^D6̣?bIϛ[jx7Fz\&>-Pp~ak+kӺW6z  4,Iʊu6pE E:XsEC֖GjZX['4ez+T{]\Q;M{췐Y>wO\ָ\vTVGɎz&o{K߷+L36:U]$ff?ْX&G;cIZ]mvvlLYRgW m\=[?ݰ|O[j[Bz+˫R.g}8'tִe/XR:#K`=B@3f`\lUoH]XYxt@_ŕzOcNBӎ|ja]~3l {3ivh]Kz_ ro>t;lBVomMtLyFx}X-lU                                            pY+Raso֕U:6wnc"zWxDzsqU|YWqeޭ_NxK0^j;u)(;˦.0lVvw4dγ/}~վ3K¾gAx [n/вk{:lkq|cL`qAL_OwZFvA9]9ֿI',.3{^R$+۽m;%Kr~RzwoZWv *>E7KΥ6*ԟdzm){WTT6R#MuJ6ޠoseQ=)qNz3Wzl]Ȩn(KuC0wZu 2;=W}]]y,W5okgwiq޺:ŷ\v&^8O3/XͻN>o}]іzݣ"ch;y2aV }nz feηe)Kn}ɔ}1^+Є,AC-rNqw[^kw A/FKyo}mX$U:5bS`zym[l&>DTd:j zQ+ӔTz!7vwK)G90my[kHXK-rrߩټԁk9OCj;yK`'Yc+z ժԖ eS祩Hc}^1=VsՃZV=A='2=j}Eibן{{X_VB8QJ顐Yի.VG<0M]==25.l֜|i]ExUQ KS֍?[] ]y?Wu5.3=WYz_vo b)֮^Z馾^_/6J\-Pm8ϵ/lzZ'MR[Ițb0k]Q؋-Zm|Ӝi,rjn-ϵ.ЎzS~ۖVg+K%ԀvH7*&U=*Xaɖ[zQer* ʏuO/?^y銚^oXsp^g=dUѪDһq%-ĵ[ߦIROCuH"~0nG@rgK,տs֫Bzso?Yr}mO1FfN]~ҫͲory2Nz'lzu/t'lUoLg^@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8~靺rc1.W۔gMƛXmlz7;Lζ׵yzGSffz]P^dݕpNvwS}w]C.8Oϳuv{Ôzt|>C.CL<ӿi,5E ^8jUX^HoZZ^ Go~t|TuzGzO !T^l|jӥ*MP6E&!aPw4O\BvNFqP0=Զ({\ysi.nR'8dwhz.diu+y=)E%=gjl]~I /lOChr-Gw}6e\gTNW lq&7:w|J/t+kݣ{fw.OULmgi54~ މuaukR~[-Of]jqY W[5zݿozJ[ouLqEMM}窵Au}$ZsJs^PIo=}ZђXjp_hCK/G&lZS;Wnju_fujNֹ[{1iVG^ٺ~ntyr=m{RW =V:Z~};r}`үggzW&VwșV\.ËBL?g+N_                                                                                                                                                                                                           G}x CQ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`?݂ endstream endobj 41 0 obj 17308 endobj 3 0 obj << /Type /Pages /MediaBox [0 0 612 792] /Count 6 /Kids [ 2 0 R 12 0 R 18 0 R 24 0 R 30 0 R 36 0 R ] >> endobj 42 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 1 0 obj << /Producer (Mac OS X 10.5.6 Quartz PDFContext) /CreationDate (D:20090318020526Z00'00') /ModDate (D:20090318020526Z00'00') >> endobj xref 0 43 0000000000 65535 f 0000430774 00000 n 0000000176 00000 n 0000430606 00000 n 0000000022 00000 n 0000000158 00000 n 0000000280 00000 n 0000000369 00000 n 0000084504 00000 n 0000085353 00000 n 0000084525 00000 n 0000085333 00000 n 0000085546 00000 n 0000085389 00000 n 0000085527 00000 n 0000085653 00000 n 0000085744 00000 n 0000161981 00000 n 0000162160 00000 n 0000162003 00000 n 0000162141 00000 n 0000162267 00000 n 0000162358 00000 n 0000252667 00000 n 0000252846 00000 n 0000252689 00000 n 0000252827 00000 n 0000252953 00000 n 0000253044 00000 n 0000342916 00000 n 0000343095 00000 n 0000342938 00000 n 0000343076 00000 n 0000343202 00000 n 0000343293 00000 n 0000412729 00000 n 0000412908 00000 n 0000412751 00000 n 0000412889 00000 n 0000413015 00000 n 0000413106 00000 n 0000430584 00000 n 0000430724 00000 n trailer << /Size 43 /Root 42 0 R /Info 1 0 R /ID [ <744318228ddce7041f885e61f7a649d2> <744318228ddce7041f885e61f7a649d2> ] >> startxref 430916 %%EOF jetty8-8.1.3/LICENSE-CONTRIBUTOR/ccla-simulalabs.txt000066400000000000000000000167641174773561500214770ustar00rootroot00000000000000Jetty Project Corporate Contributor License Agreement V1.1 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. This version of the Agreement allows an entity (the "Corporation") to submit Contributions to Mort Bay, to authorize Contributions submitted by its designated employees to Mort Bay, and to grant copyright and patent licenses thereto. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at LICENSES/ccla-CORPORATE-NAME.txt. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise send a signed Agreement to MortBay. Each developer covered by this agreement should have their name appended the Schedule A and the copy commited to LICENSES/ccla-CORPORATE-NAME.txt using their authenticated codehaus ssh login. If possible, digitally sign the committed file, otherwise send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Corporation name: Simula Labs, Inc. Mailing Address: 4676 Admiralty Way, Suite 520 Marina Del Rey, CA 90292 Point of Contact: Full name: Gordon King E-Mail: gordon.king@simulalabs.com Fax: +1 800 822 0471 You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) were submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that You are legally entitled to grant the above license. You represent further that each employee of the Corporation designated on Schedule A below (or in a subsequent written modification to that Schedule) is authorized to submit Contributions on behalf of the Corporation. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. It is your responsibility to notify MortBay when any change is required to the list of designated employees authorized to submit Contributions on behalf of the Corporation, or to the Corporation's Point of Contact with MortBay. Date: Signature: Name: Gordon King Positions: Chief Operational Officer Schedule A Name Date added Simone Bordet 12 September 2006 ______________________________________ ________________ ______________________________________ ________________ jetty8-8.1.3/LICENSE-CONTRIBUTOR/ccla-template.txt000066400000000000000000000176511174773561500211520ustar00rootroot00000000000000Jetty Project Corporate Contributor License Agreement V1.1 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. This version of the Agreement allows an entity (the "Corporation") to submit Contributions to Mort Bay, to authorize Contributions submitted by its designated employees to Mort Bay, and to grant copyright and patent licenses thereto. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at LICENSES/ccla-CORPORATE-NAME.txt. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise send a signed Agreement to MortBay. Each developer covered by this agreement should have their name appended the Schedule A and the copy commited to LICENSES/ccla-CORPORATE-NAME.txt using their authenticated codehaus ssh login. If possible, digitally sign the committed file, otherwise send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Corporation name: Mailing Address: Point of Contact: Full name: E-Mail: Fax: You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) were submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that You are legally entitled to grant the above license. You represent further that each employee of the Corporation designated on Schedule A below (or in a subsequent written modification to that Schedule) is authorized to submit Contributions on behalf of the Corporation. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. It is your responsibility to notify MortBay when any change is required to the list of designated employees authorized to submit Contributions on behalf of the Corporation, or to the Corporation's Point of Contact with MortBay. Date: Signature: Name: Positions: Schedule A Name Date added ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ ______________________________________ ________________ jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-djencks.txt000066400000000000000000000156311174773561500206110ustar00rootroot00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: David Jencks E-Mail: david_jencks@yahoo.com Mailing Address: 2215 SE 39th Ave, Portland OR 97214 USA You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: 27 June 2008 Please sign: David Jencks -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (Darwin) iD8DBQFIZT2ToF6+5lbz4BsRAs3wAJ9puXC26Nr8nhFvTZ9oNwxDFV/DVACgnC8O VFUWPZrfLOJesKa0/rYNJlM= =jC7I -----END PGP SIGNATURE----- jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-gregw.txt000066400000000000000000000156051174773561500203040ustar00rootroot00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: Gregory John Wilkins E-Mail: gregw@eclipse.com Mailing Address: 62 Church St. Balmain, NSW 2041, Australia You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: Please sign: -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) iD8DBQFEEaStXR9WPTAwnLARAjsNAJ4jBB6wCEqucFljGge7yrAMSrFv/gCgoMC+ 5hdry6ZjXRcUhQEyNz2F/T4= =I4Co -----END PGP SIGNATURE----- jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-janb.txt000066400000000000000000000155361174773561500201060ustar00rootroot00000000000000Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: Jan Bartel E-Mail: janb@eclipse.com Mailing Address: 62 Church St Balmain NSW 2041 Australia You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: 10 March 2006 Please sign: PGP -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) iD8DBQFDjMI6J97Uv2IW248RAmGNAJ9/krpkiYJRrJTMXVkL3cdnVvfU+QCfYFEh pN0h9U/xdFTRMFsXYFHQeN4= =24Hd -----END PGP SIGNATURE----- jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-jesse.txt000066400000000000000000000156251174773561500203040ustar00rootroot00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: Jesse C. McConnell E-Mail: jmcconnell@apache.org Mailing Address: 7717 S 167th Street, Omaha, Ne. 68136 You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: December 19 2007 Please sign: GPG -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFHacMO+jg6q+ULyBMRAky4AJ9CdNKsmg8n2aFcpQAvcEPXxEjIJACgrvjM C/W/GuQFfCJJykkL2jd9/Ag= =ufUh -----END PGP SIGNATURE----- jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-jfarcand.txt000066400000000000000000000156641174773561500207460ustar00rootroot00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: Jeanfrancois Arcand E-Mail: jfarcand@apache.org Mailing Address: 1800 McGill College Avenue, Suite 800, H3A 3J6 Montreal, Quebec (Canada) You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: /28/08/06 Please sign: -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQFE85cgaq9Frj/CIrIRAmuJAKCFgi4W0UOH8IUn+SV6PBHRF3BnLgCcDqqC Zokttk0bTHfwaa5TtxQbScw= =N/w/ -----END PGP SIGNATURE----- jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-jstrachan.txt000066400000000000000000000156751174773561500211550ustar00rootroot00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: James Strachan E-Mail: jstrachan@apache.org Mailing Address: 1A Leigh Road, London, UK, N5 1ST You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the public benefit or inconsistent with its nonprofit status and bylaws in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: January 30th 2006 Please sign: GPG -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (Darwin) iD8DBQFD37/4dL6IZr4c+6kRAtsIAJ41tfd3lj4OM6sIMfJfTOdYdT1bxwCdGgWv 8sfMxEDZquIqhVbfZU2c76U= =8WW7 -----END PGP SIGNATURE----- jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-jules.txt000066400000000000000000000156731174773561500203200ustar00rootroot00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: Julian Anthony Fox Gosnell E-Mail: jules@coredevelopers.net Mailing Address: 2, Tannery Cottages, Tannery Lane, Bramley, Surrey, GU5 0AB, UK. You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: 10th March 2006 Please sign: -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2.1 (GNU/Linux) iD8DBQFEEbh9SoT4b97cQk4RAnCMAKCuNGYLHa6n/Ot3GEdwCCLeQxsMPACdEhnE I/stizRWWZZkeLbcglzdQCE= =piHm -----END PGP SIGNATURE----- jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-ngonzalez.txt000066400000000000000000000156411174773561500212000ustar00rootroot00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: Nicanor Gonzalez E-Mail: ngonzalez@exist.com Mailing Address: 37 TwinHill St., New Manila Rolling Hills, Q.C., Philippines You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: July 14, 2006 Please sign: -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.4 (MingW32) iD8DBQFEt1ZxHR/ESK2w6H8RApbOAJ9c1eooNr2oN59WZVitJExGJjUvKgCfaKji 6etDJ6AUj0jTuSl59hUsWMQ= =HmqH -----END PGP SIGNATURE----- jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-sbordet.txt000066400000000000000000000155341174773561500206340ustar00rootroot00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: Simone Bordet E-Mail: simone.bordet@gmail.com Mailing Address: You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: 8 January 2007 Please sign: -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.3 (GNU/Linux) iD8DBQFFoniQJVhlFus9dGQRAmJmAJwL5y1loonhVQIICsparvjHMQuwqwCgiZFy LBDVaad1bJ1v1EHY901kPcg= =6rqm -----END PGP SIGNATURE----- jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-template.txt000066400000000000000000000151131174773561500207760ustar00rootroot00000000000000Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: E-Mail: Mailing Address: You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: Please sign: jetty8-8.1.3/LICENSE-CONTRIBUTOR/cla-tvernum.txt000066400000000000000000000156161174773561500206730ustar00rootroot00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jetty Project Contributor License Agreement V1.0 based on http://www.apache.org/licenses/ Thank you for your interest in the Jetty project by Mort Bay Consulting Pty. Ltd. Australia ("MortBay"). In order to clarify the intellectual property license granted with Contributions from any person or entity, MortBay must have a Contributor License Agreement ("CLA") that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MortBay and its users; it does not change your rights to use your own Contributions for any other purpose. If you have not already done so, please complete this agreement and commit it to the Jetty repository at svn+ssh://svn.jetty.codehaus.org/home/projects/jetty/scm/jetty at legal/cla-USERNAME.txt using your authenticated codehaus ssh login. If you do not have commit privilege to the repository, please email the file to eclipse@eclipse.com. If possible, digitally sign the committed file, otherwise also send a signed Agreement to MortBay. Please read this document carefully before signing and keep a copy for your records. Full name: Timothy Philip Vernum E-Mail: tim@adjective.org Mailing Address: 7/9-11 Cook St, Sutherland, NSW 2232, Australia You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MortBay. In return, MortBay shall not use Your Contributions in a way that is contrary to the software license in effect at the time of the Contribution. Except for the license granted herein to MortBay and recipients of software distributed by MortBay, You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MortBay. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MortBay for inclusion in, or documentation of, any of the products owned or managed by MortBay (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to MortBay or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MortBay for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MortBay and to recipients of software distributed by MortBay a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MortBay, or that your employer has executed a separate Corporate CLA with MortBay. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 7. Should You wish to submit work that is not Your original creation, You may submit it to MortBay separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 8. You agree to notify MortBay of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. Date: Please sign: -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (Darwin) iD8DBQFEnjfA9nwdoZUd8/ERArwdAJ4lzyXEi4zSlIiJwEAxknGPhzMRswCfRsdI RUIoI0BYmYpaETSqxt2oLFU= =Tr57 -----END PGP SIGNATURE----- jetty8-8.1.3/LICENSE-ECLIPSE-1.0.html000066400000000000000000000402601174773561500163220ustar00rootroot00000000000000 Eclipse Public License - Version 1.0

Eclipse Public License - v 1.0

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.

1. DEFINITIONS

"Contribution" means:

a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
b) in the case of each subsequent Contributor:

i) changes to the Program, and

ii) additions to the Program;

where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.

"Contributor" means any person or entity that distributes the Program.

"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.

"Program" means the Contributions distributed in accordance with this Agreement.

"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.

2. GRANT OF RIGHTS

a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.

b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.

c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.

d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.

3. REQUIREMENTS

A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:

a) it complies with the terms and conditions of this Agreement; and

b) its license agreement:

i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;

ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;

iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and

iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.

When the Program is made available in source code form:

a) it must be made available under this Agreement; and

b) a copy of this Agreement must be included with each copy of the Program.

Contributors may not remove or alter any copyright notices contained within the Program.

Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.

4. COMMERCIAL DISTRIBUTION

Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.

For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.

5. NO WARRANTY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.

6. DISCLAIMER OF LIABILITY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. GENERAL

If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.

If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.

All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.

Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.

This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.

 

jetty8-8.1.3/NOTICE.txt000066400000000000000000000020451174773561500145150ustar00rootroot00000000000000============================================================== Jetty Web Container Copyright 1995-2012 Mort Bay Consulting Pty Ltd. ============================================================== The Jetty Web Container is Copyright Mort Bay Consulting Pty Ltd unless otherwise noted. Jetty is dual licensed under both * The Apache 2.0 License http://www.apache.org/licenses/LICENSE-2.0.html and * The Eclipse Public 1.0 License http://www.eclipse.org/legal/epl-v10.html Jetty may be distributed under either license. The javax.servlet package used was sourced from the Apache Software Foundation and is distributed under the apache 2.0 license. The UnixCrypt.java code implements the one way cryptography used by Unix systems for simple password protection. Copyright 1996 Aki Yoshida, modified April 2001 by Iris Van den Broeke, Daniel Deville. Permission to use, copy, modify and distribute UnixCrypt for non-commercial or commercial purposes and without fee is granted provided that the copyright notice appears in all copies. jetty8-8.1.3/README.txt000066400000000000000000000010741174773561500144720ustar00rootroot00000000000000 This is a source checkout of the Jetty webserver. To build, use: mvn install The jetty distribution will be built in jetty-distribution/target/distribution The first build may take a long time as Maven downloads all the dependencies. The tests do a lot of stress testing, and on some machines it is necessary to set the file descriptor limit to greater than 2048 for the tests to all pass successfully. Bypass tests by building with -Dmaven.test.skip=true but note that this will not produce some test jars that are leveraged in other places in the build. jetty8-8.1.3/VERSION.txt000066400000000000000000007521431174773561500146740ustar00rootroot00000000000000jetty-8.1.3.v20120416 - 16 April 2012 + 349110 MultiPartFilter records the content-type in request params + 367172 Remove detection for slf4j NOPLogger + 372678 Embedded Examples need updates for new LoginService requirement + 373269 Make ServletHandler.notFound() method impl do nothing - override to send back 404. + 373421 address potential race condition related to the nonce queue removing the same nonce twice + 373952 bind called too frequently on refresh + 374018 correctly handle requestperminuted underflow + 374152 jetty-all-server MANIFEST contains wrong import: javax.servlet.annotation;version="[2.6,3)" + 374252 SslConnection.onClose() does not forward to nested connection. + 374258 SPDY leaks SSLEngines. Made the test more reliable. + 374367 NPE in QueuedThreadPool.dump() with early java6 jvms + 374475 Response.sendRedirect does not encode UTF-8 characters properly + 374881 Set copyWebInf to false by default + 374891 enhancement to how ProxyServlet determines the proxy target + 375009 Filter initialization error will throw MultiException + 375083 Flow control should take in account window size changes from concurrent SETTINGS + 375096 If starting a server instance fails in osgi it is cleaned up. + 375490 NPE with --help on command line + 375509 Stalled stream stalls other streams or session control frames. Now using a "death pill" instead of a boolean in order to avoid race conditions where DataInfos were read from the queue (but the boolean not updated yet), and viceversa. + 375594 fixed SSL tests so they are not order dependent + 375709 Ensure resolveTempDirectory failure does not deadlock; improve error message + 375906 Part.getHeader method not case insensitive + 375970 HttpServletRequest.getRemoteAddr() returns null when HTTP is over SPDY. + 376201 HalfClosed state not handled properly. Addendum to restore previous behavior, where a closed stream was also half closed. + 376324 is not respected in + JETTY-1495 Ensure dynamic servlet addition does not cause servlets to be inited. + JETTY-1500 form parameters from multipart request not available via request.getParameter + JETTY-1504 HttpServletResponseWrapper ignored when using asyncContext? jetty-8.1.2.v20120308 - 08 March 2012 + 370387 SafariWebsocketDraft0Test failure during build. + 371168 Update ClientCrossContextSessionTest + 372093 handle quotes in Require-Bundle manifest string + 372457 Big response + slow clients + pipelined requests cause Jetty spinning and eventually closing connections. Added a TODO for a method renaming that will happen in the next major release (to avoid break implementers). + 372487 JDBCSessionManager does not work with Oracle + 372806 Command line should accept relative paths for xml config files + 373037 jetty.server.Response.setContentLength(int) should not close a Writer when length=0 + 373162 add improved implementation for getParameterMap(), needs a test though and the existing setup doesn't seem like it would easily support the needed test so need to do that still + 373306 Set default user agent extraction pattern for UserAgentFilter + 373567 cert validation issue with ocsp and crldp always being enabled when validating turned on fixed + 373603 NullPointer in WebServletAnnotation + JETTY-1409 GzipFilter will double-compress application/x-gzip content + JETTY-1489 WebAppProvider attempts to deploy .svn folder + JETTY-1494 . jetty-8.1.1.v20120215 - 15 February 2012 + 369121 simplified test + 370120 jvm arguments added via start.ini and --exec are missing spaces + 370137 SslContextFactory does not respect order for [included|excluded]Protocols() and [included|excluded]CipherSuites(). + 370368 resolve stack overflow in mongo db session manager + 370386 Remove META-INF from jetty distro + 371040 nosqlsession needs to call correct super contructor for new sessions + 371041 valid was not being set to new mongo db sessions, and the call to mongodb api was wrong in isIdInUse + 371162 NPE protection for nested security handlers + JETTY-1484 Add option for HashSessionManager to delete session files if it can't restore them jetty-8.1.0.v20120127 - 27 January 2012 + 368773 allow authentication to be set by non securityHandler handlers + 368992 avoid update key while flushing during a write + 369216 turned off the shared resource cache + 369349 replace quotes with a space escape method jetty-8.1.0.RC5 - 20 January 2012 + 359329 Prevent reinvocation of LoginModule.login with jaspi for already authed user + 368632 Remove superfluous removal of org.apache.catalina.jsp_file + 368633 fixed configure.dtd resource mappings + 368635 moved lifecycle state reporting from toString to dump + 368773 process data constraints without realm + 368787 always set token view to new header buffers in httpparser + 368821 improved test harness + 368920 JettyAwareLogger always formats the arguments. + 368948 POM for jetty-jndi references unknown version for javax.activation. + 368992 NPE in HttpGenerator.prepareBuffers() test case. + JETTY-1475 made output state fields volatile to provide memory barrier for non dispatched thread IO jetty-8.1.0.RC4 - 13 January 2012 + 365048 jetty Http client does not send proxy authentication when requesting a Https-resource through a web-proxy. + 366774 removed XSS vulnerbility + 367099 Upgrade jetty-websocket for RFC 6455 - Addendum. + 367433 added tests to investigate + 367435 improved D00 test harness + 367485 HttpExchange canceled before response do not release connection. + 367502 WebSocket connections should be closed when application context is stopped. + 367548 jetty-osgi-boot must not import the nested package twice + 367591 corrected configuration.xml version to 7.6 + 367635 Added support for start.d directory + 367716 simplified maxIdleTime logic + 368035 WebSocketClientFactory does not invoke super.doStop(). + 368060 do not encode sendRedirect URLs + 368112 NPE on element parsing web.xml + 368113 Support servlet mapping to "" + 368114 Protect against non-Strings in System properties for Log + 368189 WebSocketClientFactory should not manage external thread pool. 368240 - Improve AggregateLifeCycle handling of shared lifecycles + 368215 Remove debug from jaspi + 368240 Better handling of locally created ThreadPool. Forgot to null out field. + 368291 Change warning to info for NoSuchFieldException on BeanELResolver.properties + 367638 limit number of form parameters to avoid DOS + JETTY-1467 close half closed when idle jetty-8.1.0.RC2 - 22 December 2011 + 359329 jetty-jaspi must exports its packages. jetty-plus must import javax.security + 364638 HttpParser closes if data received while seeking EOF. Tests fixed to cope + 364921 Made test less time sensitive + 364936 use Resource for opening URL streams + 365267 NullPointerException in bad Address + 365375 ResourceHandler should be a HandlerWrapper + 365750 Support WebSocket over SSL, aka wss:// + 365932 Produce jetty-websocket aggregate jar for android use + 365947 Set headers for Auth failure and retry in http-spi + 366316 Superfluous printStackTrace on 404 + 366342 Dont persist DosFilter trackers in http session + 366730 pass the time idle to onIdleExpire + 367048 test harness for guard on suspended requests + 367175 SSL 100% CPU spin in case of blocked write and RST. + 367219 WebSocketClient.open() fails when URI uses default ports. + 367383 jsp-config element must be returned for ServletContext.getJspConfigDescriptor + JETTY-1460 suppress PrintWriter exceptions + JETTY-1463 websocket D0 parser should return progress even if no fill done + JETTY-1465 NPE in ContextHandler.toString jetty-8.1.0.RC1 - 06 December 2011 + 360245 The version of the javax.servlet packages to import is 2.6 instead of 3.0 + 365370 ServletHandler can fall through to nested handler jetty-8.1.0.RC0 - 30 November 2011 + 352565 cookie httponly flag ignored + 353285 ServletSecurity annotation ignored + 357163 jetty 8 ought to proxy jetty8 javadocs + 357209 JSP tag listeners not called + 360051 SocketConnectionTest.testServerClosedConnection is excluded. + 361135 Allow session cookies to NEVER be marked as secure, even on HTTPS requests. + 362249 update shell scripts to jetty8 + 363878 Add ecj compiler to jetty-8 for jsp + 364283 can't parse the servlet multipart-config for the web.xml + 364430 Support web.xml enabled state for servlets jetty-7.6.0.RC5 - 20 January 2012 + 359329 Prevent reinvocation of LoginModule.login with jaspi for already authed user + 368632 Remove superfluous removal of org.apache.catalina.jsp_file + 368633 fixed configure.dtd resource mappings + 368635 moved lifecycle state reporting from toString to dump + 368773 process data constraints without realm + 368787 always set token view to new header buffers in httpparser + 368821 improved test harness + 368920 JettyAwareLogger always formats the arguments. + 368948 POM for jetty-jndi references unknown version for javax.activation. + 368992 avoid non-blocking flush when writing to avoid setting !_writable without _writeblocked + JETTY-1475 made output state fields volatile to provide memory barrier for non dispatched thread IO jetty-7.6.0.RC4 - 13 January 2012 + 365048 jetty Http client does not send proxy authentication when requesting a Https-resource through a web-proxy. + 366774 removed XSS vulnerbility + 367099 Upgrade jetty-websocket for RFC 6455 - Addendum. + 367716 simplified maxIdleTime logic + 368035 WebSocketClientFactory does not invoke super.doStop(). + 368060 do not encode sendRedirect URLs + 368114 Protect against non-Strings in System properties for Log + 368189 WebSocketClientFactory should not manage external thread pool. + 368215 Remove debug from jaspi + 368240 Improve AggregateLifeCycle handling of shared lifecycles + 368291 Change warning to info for NoSuchFieldException on BeanELResolver.properties jetty-7.6.0.RC3 - 05 January 2012 + 367433 added tests to investigate + 367435 improved D00 test harness + 367485 HttpExchange canceled before response do not release connection. + 367502 WebSocket connections should be closed when application context is stopped. + 367591 corrected configuration.xml version to 7.6 + 367635 Added support for start.d directory + 367638 limit number of form parameters to avoid DOS + JETTY-1467 close half closed when idle jetty-7.6.0.RC2 - 22 December 2011 + 364638 HttpParser closes if data received while seeking EOF. Tests fixed to cope + 364921 Made test less time sensitive for ssl + 364936 use Resource for opening URL streams + 365267 NullPointerException in bad Address + 365375 ResourceHandler should be a HandlerWrapper + 365750 Support WebSocket over SSL, aka wss:// + 365932 Produce jetty-websocket aggregate jar for android use + 365947 Set headers for Auth failure and retry in http-spi + 366316 Superfluous printStackTrace on 404 + 366342 Dont persist DosFilter trackers in http session + 366730 pass the time idle to onIdleExpire + 367048 test harness for guard on suspended requests + 367175 SSL 100% CPU spin in case of blocked write and RST. + 367219 WebSocketClient.open() fails when URI uses default ports. + JETTY-1460 suppress PrintWriter exceptions + JETTY-1463 websocket D0 parser should return progress even if no fill done + JETTY-1465 NPE in ContextHandler.toString jetty-7.6.0.RC1 - 04 December 2011 + 352565 cookie httponly flag ignored + 353285 ServletSecurity annotation ignored + 357163 jetty 8 ought to proxy jetty8 javadocs + 357209 JSP tag listeners not called + 360051 SocketConnectionTest.testServerClosedConnection is excluded. + 361135 Allow session cookies to NEVER be marked as secure, even on HTTPS requests. + 362249 update shell scripts to jetty8 + 363878 Add ecj compiler to jetty-8 for jsp + 364283 can't parse the servlet multipart-config for the web.xml + 364430 Support web.xml enabled state for servlets + 365370 ServletHandler can fall through to nested handler jetty-7.6.0.RC0 - 29 November 2011 + Refactored NIO layer for better half close handling + 349110 fixed bypass chunk handling + 360546 handle set count exceeding max integer + 362111 StdErrLog.isDebugEnabled() returns true too often + 362113 Improve Test Coverage of org.eclipse.jetty.util.log classes + 362407 setTrustStore(Resource) -> setTrustStoreResource(R) + 362447 add setMaxNonceAge() to DigestAuthenticator + 362468 NPE at line org.eclipse.jetty.io.BufferUtil.putHexInt + 362614 NPE in accepting connection + 362626 IllegalStateException thrown when SslContextFactory preconfigured with SSLContext + 362696 expand virtual host configuration options to ContextHandler and add associated test case for new behavior + 362742 improved UTF8 exception reason + 363124 improved websocket close handling + 363381 Throw IllegalStateException if Request uri is null on getServerName + 363408 GzipFilter should not attempt to compress HTTP status 204 + 363488 ShutdownHandler use stopper thread + 363718 Setting java.rmi.server.hostname in jetty-jmx.xml + 363757 partial fix + 363785 StdErrLog must use system-dependent EOL. + 363943 ignore null attribute values + 363993 EOFException parsing HEAD response in HttpTester + 364638 SCEP does idle timestamp checking. New setCheckForIdle method controls onIdleExpired callback. 364921 a second onIdleExpired callback will result in close rather than a shutdown output. + 364657 Support HTTP only cookies from standard API + JETTY-1442 add _hostHeader setter for ProxyRule jetty-8.0.4.v20111024 - 24 October 2011 + 358263 JDBCSessionIdManager add setDatasource(DataSource) method + 358649 Replace existing StdErrLog system properties for DEBUG/IGNORED with LEVEL instead. + 360836 Accept parameters with bad UTF-8. Use replacement character + 360912 CrossOriginFilter does not send Access-Control-Allow-Origin on responses. 355103 Make allowCredentials default to true in CrossOriginFilter. + 360938 Connections closed after a while. + 361135 secure cookies for sessions + 361319 Log initialization does not catch correct exceptions on all jvms + 361325 359292 Allow KeyStore to be set + 361456 release timer task on connection failed + 361655 ExecutorThreadPool.isLowOnThreads() returns wrong value. + JETTY-1444 start threadpool before selector manager jetty-7.5.4.v20111024 - 24 October 2011 + 358263 JDBCSessionIdManager add setDatasource(DataSource) method + 358649 Replace existing StdErrLog system properties for DEBUG/IGNORED with LEVEL instead. + 360836 Accept parameters with bad UTF-8. Use replacement character + 360912 CrossOriginFilter does not send Access-Control-Allow-Origin on responses. 355103 Make allowCredentials default to true in CrossOriginFilter. + 360938 Connections closed after a while. + 361319 Log initialization does not catch correct exceptions on all jvms + 361325 359292 Allow KeyStore to be set + 361456 release timer task on connection failed + 361655 ExecutorThreadPool.isLowOnThreads() returns wrong value. + JETTY-1444 start threadpool before selector manager jetty-8.0.3.v20111011 - 11 October 2011 + 348978 migrate jetty-http-spi + 358649 StdErrLog system properties for package/class logging LEVEL. jetty-8.0.2.v20111006 - 06 October 2011 + 336443 add missing comma in DigestAuthenticator string + 342161 ScannerTest fails intermittently on Mac OS X + 346419 testing HttpClient FDs + 353267 Request._parameters initialization bug + 353509 jetty-client unit tests are running too long + 353627 Basic Auth checks that Basic method has been send + 356144 Allow SelectorManager thread priority to be set + 356274 Start SSL socket factory in call to open() + 357163 jetty 8 ought to proxy jetty8 javadocs + 357178 websockets draft 14 support + 357188 Send content buffer directly + 357209 JSP tag listeners not called + 357216 Logging via Log4J does not expand braces in format strings + 357240 more half close refinements + 357338 remove debug + 357672 resolve issue with serializing pojos with mongodb session manager, thanks to john simone for the discovery and fix + 357959 Include javadoc in distribution + 358027 NullPointerException in ResourceHandler with jetty-stylesheet.css + 358035 idle time only active if > 0 + 358147 Add catch for UnknownHostException to fix leaky file descriptor in client + 358164 Dispatch from servlet to handler + 358263 add method for osgi users to register a driver as Class.forName does not work for them + 358649 StdErrLog system properties for package/class logging LEVEL. + 358674 Still allows sslv3 for now + 358687 Updated jsp does not scan for system tlds Fixed pattern. + 358784 JSP broken on Java 1.5 + 358925 bit more javadoc on usage + 358959 File descriptor leak with UnresolvedAddressException + 359309 adjust previous test for servletPath to include pathInfo + 359673 updated websocket version handling + 359675 Principal != String, fix for issue in property file login manager + 360051 SocketConnectionTest.testServerClosedConnection is excluded. + 360066 jsps referenced in web.xml elements do not compile + JETTY-1130 Access Sessions from HashSessionIdManager + JETTY-1277 Fixed sendRedirect encoding of relative locations + JETTY-1322 idle sweeper checks for closed endp + JETTY-1377 extra logging for busy selector + JETTY-1378 new sys property for the latest jsp-impl to force the use of the JDTCompiler when running in OSGi. + JETTY-1414 applied to PropertyUserStore + JETTY-1415 Start/Stop Server and Client only once in test, code format + JETTY-1420 Set Host header for new request in RedirectListener + JETTY-1421 Implement RedirectListener.onException,onConnectionFailed + JETTY-1423 force connection to be closed returned + JETTY-1430 local JNDI contexts don't carry environment + JETTY-1434 Add a jsp that exercises jstl. + JETTY-1439 space in directory installation path causes classloader problem jetty-7.5.3.v20111011 - 11 October 2011 + 348978 migrate jetty-http-spi + 358649 StdErrLog system properties for package/class logging LEVEL. jetty-7.5.2.v20111006 - 06 October 2011 + 336443 check nonce count is increasing + 342161 ScannerTest fails intermittently on Mac OS X + 346419 testing HttpClient FDs + 353267 Request._parameters initialization bug + 353509 jetty-client unit tests are running too long + 353627 Basic Auth checks that Basic method has been send + 356144 Allow SelectorManager thread priority to be set + 356274 Start SSL socket factory in call to open() + 357178 websockets draft 14 support + 357188 Send content buffer directly + 357209 JSP tag listeners not called + 357216 Logging via Log4J does not expand braces in format strings + 357240 more half close refinements + 357338 remove debug + 357672 resolve issue with serializing pojos with mongodb session manager, thanks to john simone for the discovery and fix + 357959 Include javadoc in distribution + 358027 NullPointerException in ResourceHandler with jetty-stylesheet.css + 358035 idle time only active if > 0 + 358147 Add catch for UnknownHostException to fix leaky file descriptor in client + 358164 Dispatch from servlet to handler + 358263 add method for osgi users to register a driver as Class.forName does not work for them + 358649 StdErrLog system properties for package/class logging LEVEL. + 358674 Still allows sslv3 for now + 358687 Updated jsp does not scan for system tlds Fixed pattern. + 358784 JSP broken on Java 1.5 + 358925 bit more javadoc on usage + 358959 File descriptor leak with UnresolvedAddressException + 359309 adjust previous test for servletPath to include pathInfo + 359673 updated websocket version handling + 359675 Principal != String, fix for issue in property file login manager + 360051 SocketConnectionTest.testServerClosedConnection is excluded. + 360066 jsps referenced in web.xml elements do not compile + JETTY-1130 Access Sessions from HashSessionIdManager + JETTY-1277 Fixed sendRedirect encoding of relative locations + JETTY-1322 idle sweeper checks for closed endp + JETTY-1377 extra logging for busy selector + JETTY-1378 new sys property for the latest jsp-impl to force the use of the JDTCompiler when running in OSGi. + JETTY-1414 applied to PropertyUserStore + JETTY-1415 Start/Stop Server and Client only once in test, code format + JETTY-1420 Set Host header for new request in RedirectListener + JETTY-1421 Implement RedirectListener.onException,onConnectionFailed + JETTY-1423 force connection to be closed returned + JETTY-1430 local JNDI contexts don't carry environment + JETTY-1434 Add a jsp that exercises jstl. + JETTY-1439 space in directory installation path causes classloader problem jetty-8.0.1.v20110908 - 08 September 2011 + 350634 Added Resource.newResource(File) + 356190 fix monodb tests for changed test api + 356428 removed timed waits from test + 356693 reduce visibility to webapp of websocket implementations + 356695 jetty server jars are provided for websockets + 356726 Instead of the sessionDestroyed called sessionCreated after invalidate session + 356751 Add null protection to ServletContextHandler.doStop + 356823 correctly decode close codes. Send not utf-8 close code. + 357058 Acceptor thread blocking jetty-7.5.1.v20110908 - 08 September 2011 + 350634 Added Resource.newResource(File) + 356190 fix monodb tests for changed test api + 356428 removed timed waits from test + 356693 reduce visibility to webapp of websocket implementations + 356695 jetty server jars are provided for websockets + 356726 Instead of the sessionDestroyed called sessionCreated after invalidate session + 356751 Add null protection to ServletContextHandler.doStop + 356823 correctly decode close codes. Send not utf-8 close code. + 357058 Acceptor thread blocking jetty-8.0.0.v20110901 - 01 September 2011 + 352565 cookie httponly flag ignored + 353073 better warnings + 353285 ServletSecurity annotation ignored + 356421 Upgraded websocket to draft 13 support jetty-7.5.0.v20110901 - 01 September 2011 + 356421 Upgraded websocket to draft 13 support + 353073 better warnings jetty-7.5.0.RC2 - 30 August 2011 + 293739 Hide stacks in named log testing. Various other minor log cleanups in output. + 352188 TestClient correctly processes --host option in jetty-websocket + 352222 Moved JmxMonitor functionality from Codehaus + 353014 TimeoutExchangeTest run time reduced + 353073 deprecated non factory method for websocket clients + 353192 Better warning for classes of wrong type + 353623 Added new methods to HttpExchange + 353624 HttpURI accepts java.net.URI object in constructor + 354080 ServletContextHandler allows to replace any subordinate handler when restarted + 355478 set public to HashedSession, looks like honest mistake and not by design to be this way + 355854 remove automatic conversion in favor of issuing a warning for jetty-web.xml that can't be processed + 356128 Moved integration tests from jetty-monitor to test-integration module + 356137 Upgrade to jsp implementation version 2.1.3-b10 + 356144 added SelectorManager.setSelectorPriorityDelta(int) + JETTY-1410 handle 1xx in similar fashion to 401s and 302s jetty-7.5.0.RC1 - 19 August 2011 + 276670 SLF4J loggers show correct location information + 335001 Eliminate expected exceptions from log when running in JBoss + 355103 Make allowCredentials default to true in CrossOriginFilter + 355162 Allow creating an empty resource collection + JETTY-1410 HTTP client handles CONTINUE 100 response correctly + JETTY-1414 HashLoginService doesn't refresh realm if specified config filename is not an absolute platform specific value jetty-8.0.0.RC0 - 16 August 2011 + Merge from jetty-7.4.3 + Enable annotations by default + 352565 cookie httponly flag ignored + 353285 ServletSecurity annotation ignored jetty-8.0.0.M3 - 27 May 2011 + 324505 Implement API login + 335500 request.getParts() throws a NullPointerException + 343472 isUserInRole does not prevent subsequent login call. + 346180 jsp-2.2 support + Updated to jetty-7.4.2.v20110526 jetty-7.5.0.RC0 - 15 August 2011 + 298502 Handle 200 Connect responses with no content-length + 347484 / - > ${/} in some paths in grant codebases + 349005 add javadoc detailing the convenience hack of removing leading /'s + 351516 Refactored sessions to better support nosql session managers + 351576 Do not use deprecated method File.toURL() + 352046 Need try/catch around features set in XmlParser + 352133 Generally resolve java 1.5isms + 352176 xml parsing on startElement should be more flexible on using qName or localName + 352421 HttpURI paths beginning with '.' + 352684 Implemented spinning thread analyzer + 352786 GzipFilter fails to pass parameters to GzipResponseWrapper + 352999 ExpireTest running too long + 353073 WebSocketClient + 353095 maven-jetty-plugin: PermGen leak due to javax.el.BeanELResolver + 353165 addJars can follow symbolic link jar files + 353210 Bundle-Version in o.e.j.o.boot.logback fix + 353465 JAASLoginService ignores callbackHandlerClass + 353563 HttpDestinationQueueTest too slow + 353862 Improve performance of QuotedStringTokenizer.quote() + 354014 Content-Length is passed to wrapped response in GZipFilter + 354204 Charset encodings property file not used + 354397 RewriteRegexRule handles special characters in regex group + 354466 Typo in example config of jetty-plus.xml jetty-7.4.5.v20110725 - 25 July 2011 + 347484 / - > ${/} in some paths in grant codebases + 352133 resolve some 1.5isms + 352421 HttpURI paths beginning with '.' + 352786 GzipFilter fails to pass parameters to GzipResponseWrapper jetty-7.4.4.v20110707 - 07 July 2011 + 308851 Converted all jetty-client module tests to JUnit 4 + 345268 JDBCSessionManager does not work with maxInactiveInterval = -1 + 350397 SelectChannelConnector does not shutdown gracefully + 350634 Reverted FileResource constructor changes + 351039 Forward dispatch should retain locale + 351199 HttpServletResponse.encodeURL() wrongly encodes an url without path when cookies are disabled + JETTY-1153 Default charset/encoding of HTTP POST requests + JETTY-1380 Jetty Rewrite example does not work in Hightide jetty-7.4.3.v20110701 - 01 July 2011 + 295832 ProxyServlet more extensible and configurable + 302566 GZIP handler for embedded Jetty servers + 308851 Converted HttpExchangeTest and related tests to JUnit 4 + 324704 JDBC Session Manager reloading session + 332200 Eliminate expected exceptions from log while using org.eclipse.jetty.jmx bundle + 347468 o.e.j.deploy.binding.GlobalWebappConfigBindingTest fails on Windows platform + 347617 Dynamically install/update/remove OSGi bundles discovered in the contexts folder + 347717 start.jar destroys dependent child of --exec + 347889 OSGi should follow directive visibility:=reexport for META-INF/web-fragments and resources + 347898 Close channel on JVM exceptions + 348652 jetty.sh starts two unix processes + 348935 Close A tag in directory listing + 349344 Passing empty query string to UrlEncoded#decodeTo(String, MultiMap, String) does not yield an empty map + 349738 set buffer sizes for http client in proxy servlet + 349870 proxy servlet protect continuation against fast failing exchanges + 349896 SCEP supports zero maxIdleTime + 349897 draft -09 websockets + 349997 MBeanContainer uses weak references + 350533 Add "Origin" to the list of allowed headers in CrossOriginFilter + 350634 Cleanup FileResource construction + 350642 Don't close SCEP during NIOBuffer manipulation + JETTY-1342 Recreate selector in change task + JETTY-1385 NPE in jetty client's HTttpExchange.setRequestContentSource(InputStream) + JETTY-1390 RewriteHandler handles encoded URIs jetty-7.4.2.v20110526 + 334443 Improve the ability to specify extra class paths using the Jetty Maven Plugin + 336220 tmp directory is not set if you reload a webapp with jetty-maven-plugin + 338364 Fixed expires header for set cookies + 345729 binding for managing server and system classes globally + 345615 Enable SSL Session caching + 345763 Source file is updated during the build + 345873 Update jetty-ssl.xml to new style + 345900 Handle IPv6 with default port + 346014 Fixed full HttpGenerator + 346124 ServletContext resources paths not resolved correctly when using UNC shares + 346179 o.e.j.util.ScannerTest fails on MacOS X platform + 346181 o.e.j.server.StressTest stalls on MacOS X platform + 346998 AbstractLifeCycle.isRunning() returns false if state changes from STARTING to STARTED during call + 346614 HttpConnection.handle() spins in case of SSL truncation attacks + 346764 OrderedGroupBinding deployment binding + 347137 Allow SSL renegotiations by default in HttpClient + 374174 Consistent mbean names + JETTY-1146 Encode jsessionid in sendRedirect + JETTY-1342 Recreate selector if wakeup throws JVM bug jetty-7.4.1.v20110513 + 288563 remove unsupported and deprecated --secure option + 332907 Add context property to ObjectName of JMX MBeans + 336056 Ability to override the computation of the ContextHandler to deploy the DefaultServlet on the HttpService + 340040 Support for a total timeout + 343083 Set nested dispatch type and connection + 343172 Check package implementor for version + 343277 add support for a context white list + 343352 make sure that jetty.osgi.boot is activated when a WAB is registered + 343482 refactored overlay deployer layout to use WAR layout + 343567 HttpClient does not limit the destination's exchange queue + 343680 Handle OSGi bundle jars not ending in ".war" + 343707 'REQUEST' is printed on console for each incoming HTTP request + 343923 flush timeouts applied to outer loop + 343936 Session idle calls unbind and remove listeners + 344059 Websockets draft-07 + 344067 Add support for OSGi fragment bundles to add static resources to web-bundles + 344513 Attempting to set ConfigurationClasses in jetty-web.xml causes NPE + 344529 Ability to customize the error handling of the OSGi HttpService + 345047 Readded deprecated ScanningAppDeployer#setMonitoredDir + 345290 Weak references from SessionIdManager. HashSessionManager cleanup. + 345543 Always close endpoint on SSLException + 345656 Disambiguate SslContextFactory#validateCerts property + 345679 Allow setting an initialized KeyStore as keystore/truststore of SslContextFactory + 345704 jetty-nested works with forwarded SSL in cloudfoundry + JETTY-954 WebAppContext eats any start exceptions instead of stopping the server load + JETTY-1314 Handle bad URI encodings + JETTY-1324 Tested not using CESU-8 instead of UTF-8 + JETTY-1326 Invoker names not hashCode based + JETTY-1343 IllegalArgumentException for bad % encodings + JETTY-1347 Updated ServletHander javadoc jetty-7.4.0.v20110414 + 342504 Scanner Listener + 342700 refine websocket API for anticipated changes + JETTY-1362 Set root cause of UnavailableException + Various test harness cleanups to avoid random failures jetty-7.4.0.RC0 + 324110 Added test harnesses for merging of QueryStrings. + 337685 Update websocket API in preparation for draft -07 + 338627 HashSessionManager.getIdleSavePeriod returns milliseconds instead of seconds + 338807 Ignore content length in 1xx, 204, 304 responses + 338819 Externally control Deployment Manager application lifecycle + 339084 Fixed NPE with servlet 3.0 async listener + 339150 Validate client certificate when it is used for authentication + 339187 In the OSGi manifest of the jetty-all-server aggregate, mark javax.annotation as optional + 339543 Add configuration options for Certificate Revocation checking + 340265 Improve handling of io shutdown in SSL + 340621 Added SizedThreadPool interface + 340636 HashSessionManager lazy loads all sessions + 340838 Update ConnectHandler to perform half closes properly + 340878 Integrations should be able to load their own keystores + 340920 Dynamically assign RMI registry port for integration testing + 340949 Scanner delays file notifications until files are stable + 341006 Move inner enums out into separate file + 341105 Stack trace is printed for an ignored exception + 341145 WebAppContext MBean attribute serverClasses returns empty value + 341171 Locking in HttpDestination blocks all requests to the same address + 341206 Stop order is wrong in HandlerWrapper + 341255 org.eclipse.http usage in AJP/SessionId linkage + 341386 Remote close not detected by HttpClient + 341394 Remove 'Unavailable' JMX attributes of WebAppContext MBean + 341439 Blocking HttpClient does not use soTimeout for timeouts + 341561 Exception when adding o.e.j.s.DoSFilter as managed attribute + 341692 Fixed deadlock if stopped while starting + 341736 Split jetty-nested out of war module + 341726 JSONPojoConverter handles characters + 341992 Overlayed context deployer + 341694 Disable AJP buffer resizing + 341850 Protect QTP dump from bad stacks + JETTY-1245 Pooled Buffers implementation + JETTY-1354 Added jetty-nested + Ensure generated fragment names are unique + Added extra session removal test jetty-8.0.0.M2 - 16 November 2010 + 320073 Reconsile configuration mechanism + 321068 JSF2 fails to initialize + 324493 Registration init parameter handling null check, setInitParameters additive + 324505 Request.login method must throw ServletException if it cant login + 324872 allow disabling listener restriction from using *Registration interfaces + 327416 Change meaning of @HandlesTypes in line with latest interpretation by JSR315 + 327489 Change meaning of @MultipartConfig to match servlet spec 3.0 maintenance release 3.0a + 328008 Handle update to Servlet Spec 3 Section 8.2.3.h.ii + 330188 Reject web-fragment.xml with same as another already loaded one + 330208 Support new wording on servlet-mapping and filter-mapping merging from servlet3.0a + 330292 request.getParts() returns only one part when the name is the same + Update to jetty-7.2.1.v20101111 jetty-7.3.1.v20110307 - 07 March 2011 + 316382 Support a more strict SSL option with certificates + 333481 Handle UCS-4 codepoints in decode and encode + 335329 Moved blocking timeout handling to outside try catch + 336668 policy supports cert validation + 336691 Possible wrong length returned by ChannelEndPoint.flush() in case of RandomAccessFileBuffer + 336781 If xml parser is not validating, turn off external dtd resolution + 336793 Tee data filled and flushed from endpoint + 337258 Scanner start and end cycle notification + 337268 Allow specifying alias of a certificate to be used by SSL connector + 337270 Shared Timer for session management + 337271 Flush SSL endpoint when dispatch thread held forever + 337678 Readded optional async connection mode for HttpClient + 337685 Work in progress on draft 6 websockets + 337746 Fixed Session deIdle recursion + 337784 Improve HashSessionManager for session migrations + 337878 Extra tests of security constraints + 337896 HttpExchange.timeout does not override HttpClient.timeout + 337898 set client HttpConnection max idle time from exchange timeout + 338035 Default acceptors 0.25*CPUs and improved selector/acceptor thread names. + 338068 Leaking ConstraintMappings on redeploy + 338092 ProxyServlet leaks memory + 338607 Removed managed attributes when context is stopped + 338819 Externally control Deployment Manager application lifecycle + JETTY-1304 Allow quoted boundaries in Multipart filter + JETTY-1317 More elegent handling of bad URIs in requests + JETTY-1331 Allow alternate XML configuration processors (eg spring) + JETTY-1335 HttpClient's SelectConnector clean-up + JETTY-1333 HttpClient _timeout and _soTimeout is messed up + JETTY-1337 Workname cannot contain '.' + JETTY-1338 Trust default SecureRandom seed jetty-7.3.0.v20110203 - 03 February 2011 + JETTY-1259 NullPointerException in JDBCSessionIdManager when invalidating session (further update) + 296978 standardizing various Testing Util Classes to jetty-test-helper + 319178 test failure fix in jetty-util on windows + 320457 add SPNEGO support + 324505 Implement API login + 328872 Multi Jetty xml files not loading if directory is referenced in jetty.conf + 329746 client option to set just truststore and use strict ssl context + 331803 Update XML configuration files to use proper arguments for startup command in examples + 332179 Fixed formatting of negative dates + 332432 Scanner.java now always scanning the canonical form of File + 332517 Improved DefaultServlet debug + 332703 Cleanup context scope JNDI at stop + 332796 Annotations inheritance does not work with jetty7 + 332799 100% CPU on redeploy session invalidation + 332937 Added Destroyable Dumpable interfaces and reworked dependent lifecycles, specially of JNDI + 333247 fix api compat issue in ConstraintSecurityHandler + 333415 wired up HttpInput.available and added test harnesses + 333481 Handle UTF-32 codepoints in decode and encode + 333608 tlds defined in web.xml are not picked up + 333679 Refactored jetty-jmx. Moved mbeans to modules + 333717 HttpExchange able to return local address used + 333771 System properties are not available inside XML configuration file by using the 'property' tag + 333875 Monitor public constructor + 333892 Improved JVM bug detection + 334062 It should be possible to embed in the jetty.home.bundle the ssl keystore files + 334229 javax-security needs to import the package javax.security.cert in its OSGi manifest + 334311 fix buffer reuse issue in CachedExchange + 335329 Stop SSL spin during handshake and renogotiate + 335361 Fixed 'jetty.sh check' to show current PID when JETTY_PID env. variable is set + 335641 Cleaned up dispatch handling to avoid key.interestOps==0 when undispatched + 335681 Improve ChannelEndPoint.close() to avoid spinning + 335836 Race when updating SelectChannelEndPoint._dispatched jetty-7.2.2.v20101205 - 05 December 2010 + JETTY-1308 327109 (re)fixed AJP handling of empty packets + 331703 Fixed failing OSGI test TestJettyOSGiBootWithJsp.java on MacOSX + 331567 IPAccessHandlerTest failed on MacOS fix + 328789 Clean up tmp files from test harnesses + 331230 Fixed low thread warnings when acceptors>threadpool + 331461 Fixed idle timeout for unflushed HTTP/1.0 + JETTY-1307 Check that JarFileResource directories end with / + 330210 Improve performance of writing large bytes arrays + 330208 Support new wording on servlet-mapping and filter-mapping merging from servlet3.0a + 330188 Reject web-fragment.xml with same as another already loaded one + 330229 Jetty tries to parse META-INF/*.tld when jsp-api is not on classpath, causing DTD entity resoluton to fail + 330265 start.jar --stop kills --exec subprocess + 330417 Atomic PUT in PutFilter + 330419 Reloading webapp duplicates StandardDescriptorProcessor + 330686 OSGi: Make org.eclipse.jetty.jsp-2.1 a fragment of org.apache.jasper.glassfish + 330732 Removed System.err debugging + 330764 Command line properties passed to start.jar --exec + JETTY-1297 Improved matching of vhosts so that a vhost match has priority jetty-7.2.1.v20101111 - 11 November 2010 + 324679 Fixed dedection of write before static content + 328199 Ensure blocking connectors always close socket + 328205 Improved SelectManager stopping + 328306 Serialization of FormAuthentication + 328332 Response.getContentType works with setHeader + 328523 Fixed overloaded setters in AppProvider + 328008 Handle update to Servlet Spec 3 Section 8.2.3.h.ii + 328778 Improved javadoc for secure session cookies + 328782 allow per connection max idle time to be set + 328885 web overrides do not override + 328988 Idle saving of session values + 329180 Spin check for Selector to stop + 329410 Enforce XmlConfiguration properties as Map + 329602 only clear ServletContext attributes on doStop + 329642 Concurrent modification exception in Deployment Manager + 329643 Improved deployment of resource collections + JETTY-748 Prevent race close of socket by old acceptor threads + JETTY-1291 Extract query parameters even if POST content consumed + JETTY-1295 Contexts mixed up when hot-deploying on virtual hosts + JETTY-1297 Make ServletContext.getContext(String) virtual host aware jetty-6.1.26 - 10 November 2010 + JETTY-748 Prevent race close of socket by old acceptor threads + JETTY-1239 HTAccessHandler [allow from 127.0.0.1] does not work + JETTY-1291 Extract query parameters even if POST content consumed + JETTY-1293 Avoid usage of String.split + JETTY-1296 Always clear changes list in selectManager jetty-6.1.26.RC0 - 20 October 2010 + JETTY-547 Improved usage of shutdownOutput before close. + JETTY-912 add per exchange timeout + JETTY-1051 offer jetty.skip flag for maven plugin + JETTY-1096 exclude maven and plexus classes from jetty plugin + JETTY-1248 Infinite loop creating temp MultiPart files + JETTY-1264 Idle timer deadlock + JETTY-1271 Handle unavailable request + JETTY-1278 J2se6 SPI filter handling fix + JETTY-1283 Allow JSONPojoConvertorFactory to set fromJSON + JETTY-1287 rewrite handler thread safe issue resolved + JETTY-1288 info when atypical classloader set to WebAppContext + JETTY-1289 MRU cache for filter chains + JETTY-1292 close input streams after keystore.load() + 325468 Clean work webapp dir before unpack + 327109 Fixed AJP handling of empty packets + 327562 Implement all X-Forwarded headers in ProxyServlet jetty-7.2.0.v20101020 - 20 October 2010 + 289540 added javadoc into distribution + 297154 add source distribution artifact + 323985 Xmlconfiguration pulls start.jar config properties + 324369 Improved handling of multiple versions of draft-ietf-hybi-thewebsocketprotocol + 326734 Configure Digest maxNonceAge with Security handler init param + 327109 Fixed AJP handling of empty packets + 327183 Allow better configurability of HttpClient for TLS/SSL + 327469 removed needless java6 dependencies + 327562 Implement all X-Forwarded headers in ProxyServlet + 327601 Multipart Filter handles quoted tokens + 327725 Nested ResourceCaches + 328199 Ensure blocking connectors always close socket + 328205 Improved SelectManager stopping + 328273 Added serializable to default user identity + JETTY-1288 Info statement when atypical classloader set on WebAppContext + JETTY-1289 LRU cache for filter chains jetty-7.2.0.RC0 - 01 October 2010 + 314087 Simplified SelectorManager + 319334 Concurrent, sharable ResourceCache + 319370 WebAppClassLoader.Context + 319444 Two nulls are appended to log statements from ContextHanler$Context + 320073 Reconsile configuration mechanism + 320112 Websocket in aggregate jars + 320264 Removed duplicate mime.property entries + 320457 Added rfc2045 support to B64Code + 321232 BasicAuthenticator ignores bad Authorization header. + 321307 HashSessionManager calls passivation listeners. + 321730 SelectChannelEndPoint prints to System.err + 321735 HttpClient onException called for buffer overflow. + 322448 Added jetty-dir.css for directory listings + 322575 NPE in HotSwapHandler if old handler null + 322683 RewriteHandler thread safety + 323196 org.mortbay properties to org.eclipse + 323435 MovedContextHandler permanent redirection + 323464 IPv6 localhost with no Host header + 324110 Merge async dispatch parameters + 324158 Durable download or Orbit jars + 324260 Jetty-6 continuations handle complete calls + 324359 illegal actions on AsyncContext should not change its state. + 324360 validate input on getResource since loop logic obscures subclass input validation. + 324369 Implement draft-ietf-hybi-thewebsocketprotocol-01 + 324377 Allow dispatch of ServletRequest and ServletResponse + 324379 Change content type after getWriter + 324501 Fire RequestListener.requestDestroyed in last-to-first order. + 324601 Check session expiry on access + 324679 Allow filter to write before static content + 324811 NPE in Server.dump + 324812 restore WebAppContext constructor used by geronimo integration + 325072 include to DefaultServlet of missing file throws FileNotFoundException + 325105 websocket ondisconnect fixed + 325128 websocket send during onConnect + 325468 Clean work webapp dir before unpack + 326612 Handle X-Forwarded-Proto header + JETTY-912 added per exchange timeout api + JETTY-1063 Plugin problems with spaces in classpath resource references + JETTY-1245 Do not use direct buffers with NIO SSL + JETTY-1249 Apply max idle time to all connectors + JETTY-1250 Parallel start of HandlerCollection + JETTY-1256 annotation and jta jars from Orbit + JETTY-1259 NullPointerException in JDBCSessionIdManager when invalidating session + JETTY-1261 errant listener usage in StandardDescriptorProcessor + JETTY-1263 JDBCSessionIdManager table creation fails on Oracle + JETTY-1265 Reason field option in client response + JETTY-1266 Destroy sessions before filters/servlets + JETTY-1268 Form Auth saves POST data + JETTY-1269 Improve log multithreadedness + JETTY-1270 Websocket closed endp protection + JETTY-1271 handled unavailable exception + JETTY-1279 Make jetty-plus.xml enable plus features for all webapps by default + JETTY-1281 Create new session after authentication + JETTY-1283 JSONPojoConvertorFactory can turn off fromJSON + Fix jetty-plus.xml for new configuration names + Added ignore to Logger interface + Improved debug dump jetty-7.1.6.v20100715 + 319519 Warn about duplicate configuration files + 319655 Reset HEAD status + JETTY-1247 synchronize recylcing of SSL NIO buffers + JETTY-1248 fix parsing of bad multiparts + JETTY-1249 Apply max idle time to all connectors + JETTY-1251 Replace then close selector for JVM bugs jetty-8.0.0.M1 - 12 July 2010 + 306350 Ensure jars excluded by ordering are not scanned for annotations + JETTY-1224 Change jetty-8 merge rules for fragment descriptors and annotations + Ensure in web.xml overrides relative in fragments + Ensure empty implies exclusion of all fragments + Ensure servlet-api jar class inheritance hierarchy is scanned jetty-7.1.5.v20100705 + Update ecj to 3.6 Helios release drop + 288194 Add blacklist/whitelist to ProxyServlet and ProxyHandler + 296570 EOFException for HttpExchange when HttpClient.stop called. + 311550 The WebAppProvider should allow setTempDirectory + 316449 Websocket disconnect fix + 316584 Exception on startup if temp path has spaces and extractWAR=false + 316597 Removed null check and fixed name in Resource#hrefEncodeURI + 316970 jetty.sh fails to find JETTY_HOME in standard directories + 316973 jetty.sh claims java installation is invalid + 316976 removed quotes of JAVA_OPTIONS in jetty.sh + 317019 Date HTTP header not sent for HTTP/1.0 requests + 317759 Allow roles and constraints to be added after init + 317906 OPTIONS correctly handles TRACE + 318308 Correct quoting of unicode control characters + 318470 unboxing NPE protection in HttpConnection + 318551 Optional uncheck Printwriter + JETTY-1237 Save local/remote address to be available after close + 317007 Unable to run Jetty OSGi when -Dosgi.compatibility.bootdelegation=false + 316909 CNFE: org.xml.sax.SAXException on org.eclipse.jetty.osgi.boot start with jsp fragment + 317231 Ability to configure jetty with a fragment bundle that contains etc/jetty.xml + 319060 Support web-bundles that are not expanded (bundle is zipped) jetty-6.1.25 - 26 July 2010 + Jetty-6 is now in maintenance mode. + JETTY-1212 Long content lengths + JETTY-1214 Avoid ISE when scavenging invalid session + JETTY-1223 DefaultServlet: NPE when setting relativeResourceBase and resourceBase is not set + JETTY-1226 javax.activation needs to be listed in the system classes + JETTY-1237 Remember local/remote details of endpoint + JETTY-1251 protected against closed selector + COMETD-112 if two threads create the same channel, then create events may occur after subscribe events + 320264 Removed duplicate mime.property entries jetty-7.1.4.v20100610 + 298551 SslSocketConnector does not need keystore stream + 295715 AbstractSessionManager decoupled from Context + 292326 Stop continuations if server is stopped. + 292814 Make QoSFilter and DoSFilter JMX manageable + 293222 Improve request log to handle/show asynchronous latency + 294212 Can not customize session cookie path + 301608 Deregister shutdown hooks + 302350 org.eclipse.jetty.server.NCSARequestLog is missing JavaDoc + 303661 jetty.sh failes if JETTY_HOME is not writeable + 304100 Better document JMX setup in jetty-jmx.xml + 305300 AsyncContext.start dispatches runnable + 314299 Create test harness for JDBCLoginService + 314581 Implement the Sec-Websocket handshake + 315190 CrossOriginFilter avoid headers not understood by WebSocket + 315687 included init script fails to test for JETTY_HOME as empty + 315715 Improved Cookie version handling. Server.setMaxCookieVersion + 315744 Fixed STOP.PORT and STOP.KEY in start.jar + 315748 Removed --fromDaemon from start.jar (replaced with --daemon) + 315925 Improved context xml configuration handling + 315995 Incorrect package name in system classes list + 316119 Fixed maxIdleTime for SocketEndPoint + 316254 Implement @DeclareRoles + 316334 Breaking change on org.eclipse.jetty.client.HttpExchange + 316399 Debug output in MultiPartFilter + 316413 Restarting webapp for packed war fails + 316557 OSGi HttpService failure due to undeployed context handlers + JETTY-547 Delay close after shutdown until request read + JETTY-1231 Support context request log handler jetty-7.1.3.v20100526 + 296567 HttpClient RedirectListener handles new HttpDestination + 297598 JDBCLoginService uses hardcoded credential class + 305898 Websocket handles query string in URI + 307457 Exchanges are left unhandled when connection is lost + 313205 Unable to run test-jdbc-sessions tests + 314177 JSTL support is broken + 314009 jetty.xml configuration file on command line + 314459 support maven3 for builds jetty-7.1.2.v20100523 + 308866 Update test suite to JUnit4 - Module jetty-util + 312948 Recycle SSL crypto buffers + 313196 randomly allocate ports for session test. + 313278 Implement octet ranges in IPAccessHandler + 313336 secure websockets + 314009 updated README.txt + Update links to jetty website and wiki on test webapp jetty-7.1.1.v20100517 + 302344 Make the list of available contexts if root context is not configured optional + 304803 Remove TypeUtil Integer and Long caches + 306226 HttpClient should allow changing the keystore and truststore type + 308857 Update test suite to JUnit4 - Module jetty-jndi + 308856 Update test suite to JUnit4 - Module jetty-jmx + 308860 Update test suite to JUnit4 - Module jetty-rewrite + 308850 Update test suite to JUnit4 - Module jetty-annotations + 308853 Update test suite to JUnit4 - Module jetty-deploy + 308854 Update test suite to JUnit4 - Module jetty-http + 308859 Update test suite to JUnit4 - Module jetty-policy + 308858 Update test suite to JUnit4 - Module jetty-plus + 308863 Update test suite to JUnit4 - Module jetty-servlet + 308855 Update test suite to JUnit4 - Module jetty-io + 308862 Update test suite to JUnit4 - Module jetty-server + 308867 Update test suite to JUnit4 - Module jetty-webapp + 310918 Fixed write blocking for client HttpConnection + 312526 Protect shutdown thread initialization during shutdown jetty-7.1.0 - 05 May 2010 + 306353 fixed cross context dispatch to root context. + 311154 Added deprecated StringBuffer API for backwards compatibility + 311554 Protect shutdown thread from Server#doStop + 312243 Optimized timeout handling jetty-7.1.0.RC1 - 05 May 2010 + 286889 Allow System and Server classes to be set on Server instance and when applied to all webapps + 291448 SessionManager has isCheckingRemoteSessionIdEncoding + 296650 JETTY-1198 reset idle timeout on request body chunks + 297104 HTTP CONNECT does not work correct with SSL destinations + 306782 Close connection when expected 100 continues is not sent + 308848 Update test suite to JUnit4 - Module jetty-ajp + 308861 Update test suite to JUnit4 - Module jetty-security + 308864 Update test suite to JUnit4 - Module jetty-servlets + 308865 Update test suite to JUnit4 - Module jetty-start + 308868 Update test suite to JUnit4 - Module jetty-websocket + 308869 Update test suite to JUnit4 - Module jetty-xml + 309153 Hide extracted WEB-INF/lib when running a non-extracted war + 309369 Added WebSocketLoadTest + 309686 Fixed response buffers usage + 310094 Improved start.jar options handling and configs + 310382 NPE protection when WAR is not a file + 310562 SslSocketConnector fails to start if excludeCipherSuites is set + 310634 Get the localport when opening a server socket. + 310703 Update test suite to JUnit4 - Module tests/test-integration + 310918 Synchronize content exchange + 311154 Use Appendable in preference to StringBuilder/StringBuffer in APIs + 311362 Optional org.eclipse.jetty.util.log.stderr.SOURCE + JETTY-1030 Improve jetty.sh script + JETTY-1142 Replace Set-Cookies with same name jetty-7.1.0.RC0 - 27 April 2010 + 294563 Websocket client connection + 297104 Improve handling of CONNECT method + 306349 ProxyServlet does not work unless deployed at / + 307294 Add AbstractLifeCycle.AbstractLifeCycleListener implementation + 307847 Fixed combining mime type parameters + 307898 Handle large/async websocket messages + 308009 ObjectMBean incorrectly casts getTargetException() to Exception + 308420 convert jetty-plus.xml to use DeploymentManager + 308925 Protect the test webapp from remote access + 309466 Removed synchronization from StdErrLog + 309765 Added JSP module + 310051 _configurationClasses now defaults to null in WebAppContext + 310094 Improved start.jar usage and config files + 310431 Default ErrorHandler as server Bean + 310467 Allow SocketConnector to create generic Connection objects + 310603 Make Logger interface consistent + 310605 Make a clean room implementation of the JSP logger bridge + Add AnnotationConfiguration to jetty-plus.xml + Fix jetty-plus.xml reference to addLifeCycle + JETTY-1200 SSL NIO Endpoint wraps non NIO buffers + JETTY-1202 Use platform default algorithm for SecureRandom + Merged 7.0.2.v20100331 + Add NPE protection to ContainerInitializerConfiguration + Temporarily remove jetty-osgi module to clarify jsp version compatibility + JETTY-1212 handle long content lengths + JETTY-1214 avoid ISE when scavenging invalid session + JETTY-903 Stop both caches jetty-7.0.2.v20100331 - 31 March 2010 + 297552 Don't call Continuation timeouts from acceptor tick + 298236 Additional unit tests for jetty-client + 306783 NPE in StdErrLog when Throwable is null + 306840 Suppress content-length in requests with no content + 306880 Support for UPGRADE in HttpClient + 306884 Suspend with timeout <=0 never expires + 306782 httpbis interpretation of 100 continues. Body never skipped + 307589 updated servlet 3.0 continuations for final API + Take excess logging statements out of startup + Ensure webapps with no WEB-INF don't scan WEB-INF/lib + Allow Configuration array to be set on Server instance for all web apps jetty-6.1.24 - 21 April 2010 + JETTY-903 Stop both caches + JETTY-1198 reset idle timeout on request body chunks + JETTY-1200 SSL NIO Endpoint wraps non NIO buffers + JETTY-1211 SetUID loadlibrary name and debug + 308925 Protect the test webapp from remote access + COMETD-99 ClientImpl logs exceptions in listeners with "debug" level + COMETD-100 ClientImpl logs "null" as clientId + COMETD-107 Reloading the application with reload extension does not fire /meta/connect handlers until long poll timeout expires + Upgraded to cometd 1.1.1 client jetty-6.1.23 - 02 April 2010 + JSON parses NaN as null + Updated JSP to 2.1.v20091210 + COMETD-28 Improved concurrency usage in Bayeux and channel handling + COMETD-46 reset ContentExchange content on resend + COMETD-58 Extension.rcv() return null causes NPE in AbstractBayeux.PublishHandler.publish + COMETD-59 AcknowledgeExtension does not handle null channel in Message + COMETD-62 Delay add listeners until after client construction + 296569 removeLifeCycleListener() has no effect + 292800 ContextDeployer - recursive setting is undone by FilenameFilter + 300178 HttpClients opens too many connections that are immediately closed + 304658 Inconsistent Expires date format in Set-Cookie headers with maxAge=0 + 304698 org.eclipse.jetty.http.HttpFields$DateGenerator.formatCookieDate() uses wrong (?) date format + 306331 Session manager is kept after call to doScope + 306840 suppress content-length in requests without content + Remove references to old content in HttpClient client tests for www.sun.com + JETTY-875 Allow setting of advice field in response to Handshake + JETTY-983 Range handling cleanup + JETTY-1133 Handle multiple URL ; parameters + JETTY-1134 BayeuxClient: Connect msg should be sent as array + JETTY-1149 transient should be volatile in AbstractLifeCycle + JETTY-1153 System property for UrlEncoded charset + JETTY-1155 HttpConnection.close notifies HttpExchange + JETTY-1156 SSL blocking close with JVM Bug busy key fix + JETTY-1157 Don't hold array passed in write(byte[]) + JETTY-1158 NPE in StdErrLog when Throwable is null + JETTY-1161 An Extension that measures round-trip delay for cometd messages. + JETTY-1162 Add support for async/sync message delivery to BayeuxClient + JETTY-1163 AJP13 forces 8859-1 encoding + JETTY-1168 Don't hold sessionIdManager lock when invalidating sessions + JETTY-1170 NPE on client when server-side extension returns null + JETTY-1174 Close rather than finish Gzipstreams to avoid JVM leak + JETTY-1175 NPE in TimesyncExtension + JETTY-1176 NPE in StatisticsExtension if client is null + JETTY-1177 Allow error handler to set cacheControl + JETTY-1178 Make continuation servlet to log the incoming JSON in case of parsing errors + JETTY-1180 Extension methods are wrongly called + JETTY-1182 COMETD-76 do not lock client while sending messages. + JETTY-1183 AcknowledgedMessagesClientExtension does not handle correctly message resend when client long polls again + JETTY-1186 Better document JMX setup in jetty-jmx.xml + JETTY-1188 Null old jobs in QueuedThreadPool + JETTY-1191 Limit size of ChannelId cache + JETTY-1192 Fixed Digested POST and HttpExchange onRetry + JETTY-1193 Exception details are lost in AbstractCometdServlet.getMessages + JETTY-1195 Coalesce buffers in ChannelEndPoint.flush() + JETTY-1196 Enable TCP_NODELAY by default in client connectors + JETTY-1197 SetUID module test fails when using Java 1.6 to build + JETTY-1199 FindBugs cleanups + JETTY-1205 Memory leak in browser-to-client mapping + JETTY-1207 NPE protection in FormAuthenticator + JETTY-1202 Use platfrom default algorithm for SecureRandom jetty-7.0.2.RC0 + JSON parses NaN as null + 290765 Reset input for HttpExchange retry. + 292799 WebAppDeployer - start a started context? + 292800 ContextDeployer - recursive setting is undone by FilenameFilter + 294799 when configuring a webapp, don't look for WEB-INF/jetty6-web.xml + 296569 removeLifeCycleListener() has no effect + 296765 JMX Connector Server and ShutdownThread + 297421 Hide server/system classes from WebAppClassLoader.getResources + 297783 Handle HEAD reponses in HttpClient + 298144 Unit test for jetty-client connecting to a server that uses Basic Auth + 298145 Reorganized test harness to separate the HTTP PUT and HTTP GET test URLs + 298234 Unit test for jetty-client handling different HTTP error codes + 298667 DeploymentManager uses ContextProvider and WebAppProvider + 299455 Enum support in JSONPojoConvertor + 300178 HttpClients opens too many connections that are immediately closed + 300733 Jars from lib/ext are not visible for my web application + 300933 AbstractConnector uses concurrent objects for stats + 301089 Improve statistics available in StatisticsHandler and AbstractConnector + 302018 Improve statistics available in AbstractSessionHandler + 302198 Rename HttpClient authorization classes to Authentication + 302244 invalid configuration boolean conversion in FormAuthenticator + 302246 redirect loop using form authenticator + 302556 CrossOriginFilter does not work correctly when Access-Control-Request-Headers header is not present + 302669 WebInfConfiguration.unpack() unpacks WEB-INF/* from a ResourceCollection, breaking JSP reloading with ResourceCollections + 303526 Added include cyphers + 304307 Handle ;jsessionid in FROM Auth + 304532 Skip some tests on IBM JVMs until resolved + 304658 Inconsistent Expires date format in Set-Cookie headers with maxAge=0 + 304698 org.eclipse.jetty.http.HttpFields$DateGenerator.formatCookieDate() uses wrong (?) date format + 304781 Reset HttpExchange timeout on slow request content. + 304801 SSL connections FULL fix + 306330 Flush filter chain cache after Invoker servlet + 306331 Session manager is kept after call to doScope + JETTY-776 Make new session-tests module to concentrate all reusable session clustering test code + JETTY-910 Allow request listeners to access session + JETTY-983 Range handling cleanup + JETTY-1151 JETTY-1098 allow UTF-8 with 0 carry bits + JETTY-1153 System property for UrlEncoded charset + JETTY-1155 HttpConnection.close notifies HttpExchange + JETTY-1156 SSL blocking close with JVM Bug busy key fix + JETTY-1157 Don't hold array passed in write(byte[]) + JETTY-1163 AJP13 forces 8859-1 encoding + JETTY-1177 Allow error handler to set cacheControl + JETTY-1179 Persistant session tables created on MySQL use wrong datatype + JETTY-1184 shrink thread pool even with frequent small jobs + JETTY-1133 Handle multiple URL ; parameters + JETTY-1174 Close rather than finish Gzipstreams to avoid JVM leak + JETTY-1192 Fixed Digested POST + JETTY-1199 FindBugs cleanups + COMETD-46 reset ContentExchange response content on resend + Added IPAccessHandler + Updated Servlet3Continuation to final 3.0.20100224 + 305997 Coalesce buffers in ChannelEndPoint.flush() + 306028 Enable TCP_NODELAY by default in client connectors jetty-8.0.0.M0 - 28 February 2010 + Updated servlet 3.0 spec 20100224 + Merged 7.0.1.v20091116 + Updated to cometd 1.0.1 jetty-7.0.1.v20091125 - 25 November 2009 + 274251 DefaultServlet supports exact match mode. + 288401 HttpExchange.cancel() Method Unimplemented + 289027 deobfuscate HttpClient SSL passwords + 289265 Test harness for async input + 289959 Improved ContextDeployer configuration + 289960 start.jar assumes command line args are configs + 291019 Fix default DEBUG option; "-D.DEBUG=true" now works + 291340 Race condition in onException() notifications + 291543 make bin/*.sh scripts executable in distribution + 291589 Update jetty-rewrite demo + 292642 Fix errors in embedded Jetty examples + 292825 Continuations ISE rather than ignore bad transitions + 292546 Proactively enforce HttpClient idle timeout + 293222 Improved StatisticsHandler for async + 293506 Unable to use jconsole with Jetty when running with security manager + 293557 Add "jad" mime mapping + 294154 Patched jetty-osgi + 294224 HttpClient timeout setting has no effect when connecting to host + 294345 Support for HTTP/301 + HTTP/302 response codes + 294563 Initial websocket implementation + JETTY-937 More JVM bug work arounds. Insert pause if all else fails + JETTY-983 Send content-length with multipart ranges + JETTY-1114 unsynchronised WebAppClassloader.getResource(String) + JETTY-1121 Merge Multipart query parameters + JETTY-1122 Handle multi-byte utf that causes buffer overflow + JETTY-1125 TransparentProxy incorrectly configured for test webapp + JETTY-1129 Filter control characters out of StdErrLog + JETTY-1135 Handle connection closed before accepted during JVM bug work around + JETTY-1144 fixed multi-byte character overflow + JETTY-1148 Reset partially read request reader. + COMETD-34 Support Baeyux MBean + Fixed XSS issue in CookieDump demo servlet. + Improved start.jar usage text for properties + Promoted Jetty Centralized Logging from Sandbox + Promoted Jetty WebApp Verifier from Sandbox + Refactored continuation test harnessess + Fixed client abort asocciation + CQ-3581 jetty OSGi contribution + Moved centralized logging and verifier back to sandbox + CVE-2009-3555 Prevent SSL renegotiate for SSL vulnerability + 295421 Cannot reset() a newly created HttpExchange: IllegalStateException 0 => 0 + 295562 CrossOriginFilter does not work with default values in Chrome and Safari jetty-7.0.0.v20091005 - 05 October 2009 + 291340 Race condition in onException() notifications jetty-6.1.21 - 22 September 2009 + JETTY-719 Document state machine of jetty http client + JETTY-933 State == HEADER in client + JETTY-936 Improved servlet matching and optimized + JETTY-1038 ChannelId.isParentOf returns the wrong result + JETTY-1061 Catch exceptions from cometd listeners + JETTY-1072 maven plugin handles context path not as documented + JETTY-1080 modified previous fix for windows + JETTY-1084 HEAD command not setting content-type in response under certain circumstances + JETTY-1090 resolve inifinte loop condition for webdav listener + JETTY-1092 MultiPartFilter can be pushed into infinite loop + JETTY-1093 Request.toString throws exception when size exceeds 4k + JETTY-1098 Default form encoding is UTF8 + JETTY-1099 Improve cookie handling in BayeuxClient + JETTY-1100 extend setuid feature to allow setting max open file descriptors + JETTY-1102 Wrong usage of deliver() in private chat messages + JETTY-1108 SSL EOF detection + JETTY-1109 Improper handling of cookies in Terracotta tests + JETTY-1112 Response fails if header exceeds buffer size + JETTY-1113 IllegalStateException when adding servlet filters programmatically + JETTY-1114 Unsynchronize webapp classloader getResource + 282543 HttpClient SSL buffer size fix + 288055 fix jetty-client for failed listener state machine + 288153 reset exchange when resending + 288182 PUT request fails during retry + Fix DefaultServletTest for windows + Update Jetty implementation of com.sun.net.httpserver.* + Include tmp directory sweeper in build + Streamline jetty-jboss build, update sar to QueuedThreadPool jetty-7.0.0.RC6 - 21 September 2009 + Fixed XSS issue in CookieDump demo servlet. + 289958 StatisticsServlet incorrectly adds StatisticsHandler + 289960 start.jar assumes command line args are configs + 290081 Eager consume LF after CR + 290761 HttpExchange isDone handles intercepted events. + JETTY-719 Document state machine of jetty http client + JETTY-780 CNFE during startup of webapp with spring-context >= 2.5.1 + JETTY-936 274251 Improved servlet matching and optimized' + JETTY-1080 modify previous fix to work on windows + JETTY-1084 HEAD command not setting content-type in response under certain circumstances + JETTY-1086 Use UncheckedPrintWriter & cleaned up HttpStatus.Code usage + JETTY-1090 resolve potential infinite loop with webdav listener + JETTY-1092 MultiPartFilter can be pushed into infinite loop + JETTY-1093 Request.toString throws exception when size exceeds 4k + JETTY-1098 Default form encoding is UTF8 + JETTY-1101 Updated servlet3 continuation constructor + JETTY-1105 Custom error pages aren't working + JETTY-1108 SSL EOF detection + JETTY-1112 Response fails if header exceeds buffer size + JETTY-1113 IllegalStateException when adding servlet filters programmatically + 280723 Add non blocking statistics handler + 282543 HttpClient SSL buffer size fix + 283357 org.eclipse.jetty.server.HttpConnectionTest exceptions + 288055 jetty-client fails to resolve failed resolution attempts correctly + 288153 jetty-client resend doesn't reset exchange + 288466 LocalConnector is not thread safe + 288514 AbstractConnector does not handle InterruptedExceptions on shutdown + 288772 Failure to connect does not set status to EXCEPTED + 289146 formalize reload policy functionality + 289156 jetty-client: no longer throw runtime exception for bad authn details + 288182 PUT request fails during retry + 289221 HttpExchange does not timeout when using blocking connector + 289285 org.eclipse.jetty.continuation 7.0.0.RC5 imports the org.mortbay.util.ajax package + 289686 HttpExchange.setStatus() has too coarse synchronization + Tweak DefaultServletTest under windows + Copy VERSION.txt to distro + Remove printlns from jetty-plus jetty-6.1.20 - 27 August 2009 + JETTY-838 Don't log and throw + JETTY-874 Better error on full header. + JETTY-960 Support ldaps + JETTY-1046 maven-jetty-jspc-plugin keepSources takes affect only in packageRoot + JETTY-1057 XSS error page + JETTY-1065 Add RedirectRegexRule to provide match/replace/group redirect support + JETTY-1066 Send 400 error for request URI parse exceptions + JETTY-1068 Avoid busy flush of async SSL + JETTY-1069 Adjust Bayeux Java client backoff algorithm + JETTY-1070 Java Bayeux Client not sending /meta/disconnect on stop + JETTY-1074 JMX thread manipulation + JETTY-1077 HashSSORealm shares Principals between UserRealms + JETTY-1078 Automatic JSON Pojo Conversion + JETTY-1079 ResourceCollection.toString() can throw IllegalStateException + JETTY-1080 Ignore files that would be extracted outside the destination directory when unpacking WARs + JETTY-1081 Handle null content type in GzipFilter + JETTY-1084 Disable GzipFilter for HEAD requests + JETTY-1085 Allow url sessionID if cookie invalid + JETTY-1086 Added UncheckedPrintWriter to avoid ignored EOFs + JETTY-1087 Chunked SSL non blocking input + JETTY-1098 Upgrade jsp to SJSAS-9_1_1-B60F-07_Jan_2009 + 283513 Check endp.isOpen when blocking read + 283818 fixed merge of forward parameters + 285006 Fixed NPE in AbstractConnector during shutdown + 286535 ContentExchange status code + 286911 Clean out cache when recycling HTTP fields + COMETD-7 max latency config for lazy messages + Added getSubscriptions to cometd client + Made unSubscribeAll public on cometd client + Removed clearing of queue in unSubscribeAll for cometd client + Update test-jndi and test-annotation examples for atomikos 3.5.5 + Clarified cometd interval timeout and allow per client intervals + Update Main.main method to call setWar + Added DebugHandler jetty-7.0.0.RC5 - 27 August 2009 + 286911 Clean out cache when recycling HTTP fields + JETTY-838 Don't log and throw + JETTY-874 Better header full warnings + JETTY-960 Support for ldaps + JETTY-1081 Handle null content type in GzipFilter + JETTY-1084 Disable GzipFilter for HEAD requests + JETTY-1085 Allow url sessionID if cookie invalid + JETTY-1086 Added UncheckedPrintWriter to avoid ignored EOFs + JETTY-1087 Chunked SSL non blocking input + 287496 Use start.ini always and added --exec + 287632 FilterContinuations for blocking jetty6 jetty-6.1.19 - 01 July 2009 + JETTY-799 shell script for jetty on cygwin + JETTY-863 Non blocking stats handler + JETTY-937 Further Improvements for sun JVM selector bugs + JETTY-970 BayeuxLoadGenerator latency handling + JETTY-1011 Grizzly uses queued thread pool + JETTY-1028 jetty:run plugin should check for the web.xml from the overlays if not found in src/main/webapp/WEB-INF/ + JETTY-1029 Handle quoted cookie paths + JETTY-1031 Handle large pipeline + JETTY-1033 jetty-plus compiled with jdk1.5 + JETTY-1034 Cookie parsing + JETTY-1037 reimplemented channel doRemove + JETTY-1040 jetty.client.HttpConnection does not handle non IOExceptions + JETTY-1042 Avoid cookie reuse on shared connection + JETTY-1044 add commons-daemon support as contrib/start-daemon module + JETTY-1045 Handle the case where request.PathInfo() should be "/*" + JETTY-1046 maven-jetty-jspc-plugin keepSources takes affect only in packageRoot + JETTY-1047 Cometd client can grow cookie headers + JETTY-1048 Default servlet can handle partially filtered large static content + JETTY-1049 Improved transparent proxy usability + JETTY-1054 Avoid double deploys + JETTY-1055 Cookie quoting + JETTY-1057 Error page stack trace XSS + JETTY-1058 Handle trailing / with aliases on + JETTY-1062 Don't filter cometd message without data jetty-7.0.0.RC4 - 18 August 2009 + 286185 Implement ability for JSON implementation to automatically register convertors + Added discoverable start options + 286535 ContentExchange status code + 285891 SessionAuthentication is serializable + JETTY-1079 ResourceCollection.toString + 279820 Fixed HotSwapHandler + JETTY-1080 Ignore files that would be extracted outside the destination directory when unpacking WARs + JETTY-1057 XSS error page jetty-7.0.0.RC3 - 07 August 2009 + 277403 remove system properties + JETTY-1074 JMX thread manipulation + Improved deferred authentication handling + 285697 extract parameters if dispatch has query + 282447 concurrent destinations in HttpClient + 283172 fix Windows build, broken on directory creation with the DefaultServlet + 283375 additional error-checking on SSL connector passwords to prevent NPE + 283513 Check endp.isOpen when blocking read jetty-7.0.0.RC2 - 29 June 2009 + 283844 Webapp / TLD errors are not clear + 283375 improved extensibility of SSL connectors + 283818 fixed merge of forward parameters + backport jetty-8 annotation parsing to jetty-7 + Disassociate method on IdentityService + 284510 Enhance jetty-start for diagnosis and unit testing + 284475 update jetty.sh for new OPTIONS syntax + Added DebugHandler + Added JavaUtilLog for Jetty logging to java.util.logging framework + 284981 Implement a cross-origin filter + Improved handling of overlays and resourceCollections + 285006 fix AbstractConnector NPE during shutdown. jetty-7.0.0.RC1 - 15 June 2009 + JETTY-1066 283357 400 response for bad URIs + JETTY-1068 Avoid busy flush of async SSL + 283344 Startup on windows is broken jetty-7.0.0.RC0 - 08 June 2009 + JETTY-967 create standalone build for PKCS12Import at codehaus + JETTY-1056 update jetty-ant module for Jetty 7 at codehaus trunk + JETTY-1058 Handle trailing / with aliases + 280843 Buffer pool uses isHeader + 271535 Adding integration tests, and enabling RFC2616 tests + 281287 Handle date headers before 1 Jan 1970 + 282807 Better handling of 100 continues if response committed. jetty-7.0.0.M4 - 01 June 2009 + 281059 NPE in QTP with debug on + JETTY-799 shell script for jetty on cygwin + JETTY-1031 Handle large pipeline + JETTY-1034 Cookie parsing + JETTY-1042 Prevent cookie leak between shared connection + JETTY-1048 Fix for large partially filtered static content + JETTY-1049 Improved transparent proxy usability + JETTY-1054 Avoid double deploys + JETTY-1055 Cookie quoting + JETTY-1057 Error page stack trace XSS jetty-7.0.0.M3 - 20 June 2009 + fixed race with expired async listeners + refactored configuration mechanism + added WebAppContext.setConfigurationDiscovered for servlet 3.0 features + 274251 Allow dispatch to welcome files that are servlets (configurable) + 277403 Cleanup system property usage. + 277798 Denial of Service Filter + Portable continuations for jetty6 and servlet3 + Refactored continuations to only support response wrapping + Added ContinuationThrowable + 276545 Quoted cookie paths + 279725 Support 100 and 102 expectations + Refactored AbstractBuffers to HttpBuffers for performance + Numerous cleanups from static code analysis + 280707 client.HttpConnection does not catch and handle non-IOExceptions + 281470 Handle the case where request.PathInfo() should be "/*" jetty-7.0.0.M2 - 18 May 2009 + JETTY-937 Work around Sun JVM bugs + JETTY-941 Linux chkconfig hint + JETTY-959 CGI servlet doesn't kill the CGI in case the client disconnects + JETTY-980 Fixed ResourceHandler ? handling, and bad URI creation in listings + JETTY-996 Make start-stop-daemon optional + 273767 Update to use geronimo annotations spec 1.1.1 + JETTY-1003 java.lang.IllegalArgumentException: timeout can't be negative + JETTY-1004 CERT VU#402580 Canonical path handling includes ? in path segment + JETTY-1013 MySql Error with JDBCUserRealm + JETTY-1014 Enable start-stop-daemon by default on jetty.sh (START_STOP_DAEMON=1) + JETTY-1015 Reduce BayeuxClient and HttpClient lock contention + JETTY-1020 ZipException in org.mortbay.jetty.webapp.TagLibConfiguration prevents all contexts from being loaded + 275396 Added ScopedHandler to set servlet scope before security handler jetty-6.1.18 - 16 May 2009 + JETTY-937 Improved work around sun JVM selector bugs + JETTY-1004 CERT VU#402580 Canonical path handling includes ? in path segment + JETTY-1008 ContinuationBayeux destroy is called + JETTY-1013 MySql Error with JDBCUserRealm + JETTY-1014 Enable start-stop-daemon by default on jetty.sh (START_STOP_DAEMON=1) + JETTY-1015 Reduce BayeuxClient and HttpClient lock contention + JETTY-1017 HttpDestination has too coarse locking + JETTY-1018 Denial of Service Filter + JETTY-1020 ZipException in org.mortbay.jetty.webapp.TagLibConfiguration prevents all contexts from being loaded + JETTY-1022 Removed several 1.5isms jetty-5.1.15 - 18 May 2009 + JETTY-418 synchronized load class + JETTY-1004 CERT VU402580 Canonical path handling includes ? in path segment + Fixes for CERT438616-CERT237888-CERT21284 jetty-6.1.17 - 30 April 2009 + JETTY-936 Make optional dispatching to welcome files as servlets + JETTY-937 Work around sun JVM selector bugs + JETTY-941 Linux chkconfig hint + JETTY-957 Reduce hardcoded versions + JETTY-980 Security / Directory Listing XSS present + JETTY-982 Make test-jaas-webapp run with jetty:run + JETTY-983 Default Servlet sets accept-ranges for cached/gzipped content + JETTY-988 X-Forwarded-Host has precedence over X-Forwarded-Server + JETTY-989 GzipFilter handles addHeader + JETTY-990 Async HttpClient connect + JETTY-992 URIUtil.encodePath encodes markup characters + JETTY-996 Make start-stop-daemon optional + JETTY-997 Remove jpackage-utils dependency on rpm install + JETTY-985 Allow listeners to implement both interfaces + JETTY-1000 Avoided needless 1.5 dependency + JETTY-1002 cometd-api to 1.0.beta8 + JETTY-1003 java.lang.IllegalArgumentException: timeout can't be negative + JETTY-1004 CERT VU#402580 Canonical path handling includes ? in path segment + JETTY-1006 Resume meta connect on all XD messages jetty-7.0.0.M1 - 22 April 2009 + 271258 FORM Authentication dispatch handling avoids caching + Initial support for LoginService.logout + Removed HTTPConnection specifics from connection dispatching + JETTY-695 Handler dump + Reworked authentication for deferred authentication + Reworked JMX for new layout + JETTY-983 DefaultServlet generates accept-ranges for cached/gzip content + 273011 JETTY-980 JETTY-992 Security / Directory Listing XSS present + 271536 Add support to IO for quietly closing Readers / Writers + 273101 Fix DefaultServletTest XSS test case + 273153 Test for Nested references in DispatchServlet jetty-6.1.16 - 01 April 2009 + JETTY-702 Create "jetty-tasks.xml" for the Ant plugin + JETTY-899 Standardize location for configuration files which go into etc + JETTY-936 Allow dispatch to welcome files that are servlets + JETTY-944 Lazy messages don't prevent long polls waiting + JETTY-946 Redeploys with maven jetty plugin of webapps with overlays don't work + JETTY-947 Exception stops terracotta session scavenger + JETTY-948 ConcurrentModificationException in TerracottaSessionManager scavenger + JETTY-949 Move cometd source to cometd.org project + JETTY-953 SSL keystore file input stream is not being closed directly + JETTY-956 SslSelectChannelConnector - password should be the default value of keyPassword if not specified + JETTY-959 CGI servlet doesn't kill the CGI in case the client disconnects + JETTY-964 Typo in Jetty 6.1.15 Manifest - Bundle-RequiredExcutionEnvironment + JETTY-972 Move cometd code back from cometd.org project (temporarily) + JETTY-973 Deliver same message to a collection of cometd Clients jetty-7.0.0.M0 - 27 March 2009 + JETTY-496 Support inetd/xinetd through use of System.inheritedChannel() + JETTY-540 Merged 3.0 Public Review changes + JETTY-567 Delay in initial TLS Handshake With FireFox 3 beta5 and SslSelectChannelConnector + JETTY-600 Automated tests of WADI integration + upgrade to WADI 2.0 + JETTY-691 System.getProperty() calls ... wrap them in doPrivileged + JETTY-713 Expose additional AbstractConnector methods via MBean + JETTY-731 Completed DeliverListener for cometd + JETTY-748 RandomAccessFileBuffer for hadoop optimization + JETTY-749 Improved ArrayQueue + JETTY-765 ensure stop mojo works for all execution phases + JETTY-774 Improved caching of mime types with charsets + JETTY-775 AbstractSessionTest remove timing related test + JETTY-778 handle granular windows timer in lifecycle test + JETTY-779 Fixed line feed in request log + JETTY-781 Add "mvn jetty:deploy-war" for deploying a pre-assembled war + JETTY-782 Implement interval advice for BayeuxClient + JETTY-783 Update jetty self-signed certificate + JETTY-784 TerracottaSessionManager leaks sessions scavenged in other nodes + JETTY-786 Allow DataSourceUserRealm to create tables + JETTY-787 Handle MSIE7 mixed encoding + JETTY-788 Fix jotm for scoped jndi naming + JETTY-790 WaitingContinuations can change mutex if not pending + JETTY-792 TerracottaSessionManager does not unlock new session with requested id + JETTY-793 Fixed DataCache millisecond rounding + JETTY-794 WADI integration tests fail intermittently. + JETTY-795 NullPointerException in SocketConnector.java + JETTY-801 Bring back 2 arg EnvEntry constructor + JETTY-802 Modify the default error pages to make association with Jetty clearer + JETTY-804 HttpClient timeout does not always work + JETTY-805 Fix jetty-jaas.xml for new UserRealm package + JETTY-806 Timeout related Deadlocks in HTTP Client + JETTY-807 HttpTester to handle charsets + JETTY-808 cometd client demo run.sh + JETTY-809 Need a way to customize WEB-INF/lib file extensions that are added to the classpath + JETTY-811 Allow configuration of system properties for the maven plugin using a file + JETTY-813 Simplify NCSARequestLog.java + JETTY-814 Add org.eclipse.jetty.client.Address.toString() + JETTY-816 Implement reconnect on java bayeux client + JETTY-817 Aborted SSL connections may cause jetty to hang with full cpu + JETTY-818 Support javax.servlet.request.ssl_session_id + JETTY-821 Allow lazy loading of persistent sessions + JETTY-822 Commit when autocommit=true causes error with mysql + JETTY-823 Extend start.config profiles + JETTY-824 Access to inbound byte statistics + JETTY-825 URL decoding of spaces (+) fails for encoding not utf8 + JETTY-830 Add ability to reserve connections on http client + JETTY-831 Add ability to stop java bayeux client + JETTY-832 More UrlDecoded handling in relation to JETTY-825 + JETTY-834 Configure DTD does not allow children + JETTY-837 Response headers set via filter are ignored for static resources + JETTY-840 add default mime types to *.htc and *.pps + JETTY-841 Duplicate messages when sending private message to yourself with cometd chat demo + JETTY-842 NPE in jetty client when no path component + JETTY-843 META-INF/MANIFEST.MF is not present in unpacked webapp + JETTY-844 Replace reflection with direct invocation in Slf4jLog + JETTY-848 Temporary folder not fully cleanup after stop (via Sweeper) + JETTY-854 JNDI scope does not work with applications in a .war + JETTY-859 MultiPartFilter ignores the query string parameters + JETTY-861 switched buffer pools to ThreadLocal implementation + JETTY-862 EncodedHttpURI ignores given encoding in constructor + JETTY-866 jetty-client test case fix + JETTY-869 NCSARequestLog locale config + JETTY-870 NullPointerException in Response when performing redirect to wrong relative URL + JETTY-871 jetty-client expires() NPE race condition fixed + JETTY-876 Added new BlockingArrayQueue and new QueuedThreadPool + JETTY-894 Add android .apk to mime types + JETTY-897 Remove swing dependency in GzipFilter + JETTY-898 Allow jetty debs to start with custom java args provided by users + JETTY-899 Standardize location and build process for configuration files which go into etc + JETTY-890 merge jaspi branch to trunk + JETTY-909 Update useragents cache + JETTY-917 Change for JETTY-811 breaks systemProperties config parameter in maven-jetty-plugin + JETTY-922 Fixed NPE on getRemoteHost when socket closed + JETTY-923 Client supports attributes + JETTY-926 default location for generatedClasses of jspc plugin is incorrect + JETTY-939 NPE in AbstractConfiguration.callPreDestroyCallbacks + JETTY-938 Deadlock in the TerracottaSessionManager + JETTY-946 Redeploys with maven jetty plugin of webapps with overlays don't work + JETTY-950 Fix double-printing of request URI in request log + JETTY-953 SSL keystore file input stream is not being closed directly + JETTY-956 SslSelectChannelConnector - password should be the default value of keyPassword if not specified + moved to org.eclipse packages + simplified HandlerContainer API jetty-6.1.15 - 04 March 2009 + JETTY-931 Fix issue with jetty-rewrite.xml + JETTY-934 fixed stop/start of Bayeux Client + JETTY-938 Deadlock in the TerracottaSessionManager + JETTY-939 NPE in AbstractConfiguration.callPreDestroyCallbacks + JETTY-923 BayeuxClient uses message pools to reduce memory footprint + JETTY-924 Improved BayeuxClient disconnect handling + JETTY-925 Lazy bayeux messages + JETTY-926 default location for generatedClasses of jspc plugin is incorrect jetty-6.1.15 - 02 March 2009 + JETTY-923 BayeuxClient uses message pools to reduce memory footprint + JETTY-924 Improved BayeuxClient disconnect handling + JETTY-925 Lazy bayeux messages + JETTY-926 default location for generatedClasses of jspc plugin is incorrect jetty-6.1.15.rc4 - 19 February 2009 + JETTY-496 Support inetd/xinetd through use of System.inheritedChannel() + JETTY-713 Expose additional AbstractConnector methods via MBean + JETTY-749 Improved ack extension + JETTY-811 Allow configuration of system properties for the maven plugin using a file + JETTY-840 add default mime types to *.htc and *.pps + JETTY-848 Temporary folder not fully cleanup after stop (via Sweeper) + JETTY-872 Handshake handler calls wrong extension callback + JETTY-879 Support extra properties in jQuery comet implementation + JETTY-802 Modify the default error pages to make association with Jetty clearer + JETTY-869 NCSARequestLog locale config + JETTY-870 NullPointerException in Response when performing redirect to wrong relative URL + JETTY-878 Removed printStackTrace from WaitingContinuation + JETTY-882 ChannelBayeuxListener called too many times + JETTY-884 Use hashcode for threadpool ID + JETTY-815 Add comet support to jQuery javascript library + JETTY-887 Split configuration and handshaking in jquery comet + JETTY-888 Fix abort in case of multiple outstanding connections + JETTY-894 Add android .apk to mime types + JETTY-898 Allow jetty debs to start with custom java args provided by users + JETTY-909 Update useragents cache jetty-6.1.15.rc3 - 28 January 2009 + JETTY-691 System.getProperty() calls ... wrap them in doPrivileged + JETTY-844 Replace reflection with direct invocation in Slf4jLog + JETTY-861 switched buffer pools to ThreadLocal implementation + JETTY-866 jetty-client test case fix jetty-6.1.15.rc2 - 23 January 2009 + adjustment to jetty-client assembly packaging + JETTY-567 Delay in initial TLS Handshake With FireFox 3 beta5 and SslSelectChannelConnector jetty-6.1.15.pre0 - 20 January 2009 + JETTY-600 Automated tests of WADI integration + upgrade to WADI 2.0 + JETTY-749 Reliable message delivery + JETTY-794 WADI integration tests fail intermittently. + JETTY-781 Add "mvn jetty:deploy-war" for deploying a pre-assembled war + JETTY-795 NullPointerException in SocketConnector.java + JETTY-798 Jboss session manager incompatible with LifeCycle.Listener + JETTY-801 Bring back 2 arg EnvEntry constructor + JETTY-802 Modify the default error pages to make association with Jetty very clear + JETTY-804 HttpClient timeout does not always work + JETTY-806 Timeout related Deadlocks in HTTP Client + JETTY-807 HttpTester to handle charsets + JETTY-808 cometd client demo run.sh + JETTY-809 Need a way to customize WEB-INF/lib file extensions that are added to the classpath + JETTY-814 Add org.eclipse.jetty.client.Address.toString() + JETTY-816 Implement reconnect on java bayeux client + JETTY-817 Aborted SSL connections may cause jetty to hang with full cpu + JETTY-819 Jetty Plus no more jre 1.4 + JETTY-821 Allow lazy loading of persistent sessions + JETTY-824 Access to inbound byte statistics + JETTY-825 URL decoding of spaces (+) fails for encoding not utf8 + JETTY-827 Externalize servlet api + JETTY-830 Add ability to reserve connections on http client + JETTY-831 Add ability to stop java bayeux client + JETTY-832 More UrlDecoded handling in relation to JETTY-825 + JETTY-833 Update debian and rpm packages for new jsp-2.1-glassfish jars and servlet-api jar + JETTY-834 Configure DTD does not allow children + JETTY-837 Response headers set via filter are ignored for static resources + JETTY-841 Duplicate messages when sending private message to yourself with cometd chat demo + JETTY-842 NPE in jetty client when no path component + JETTY-843 META-INF/MANIFEST.MF is not present in unpacked webapp + JETTY-852 Ensure handshake and connect retried on failure for jquery-cometd + JETTY-854 JNDI scope does not work with applications in a .war + JETTY-855 jetty-client uber assembly support + JETTY-858 ContentExchange provides bytes + JETTY-859 MultiPartFilter ignores the query string parameters + JETTY-862 EncodedHttpURI ignores given encoding in constructor jetty-6.1.14 - 14 November 2008 + JETTY-630 jetty6-plus rpm is missing the jetty6-plus jar + JETTY-748 Reduced flushing of large content + JETTY-765 ensure stop mojo works for all execution phases + JETTY-777 include util5 on the jetty debs + JETTY-778 handle granular windows timer in lifecycle test + JETTY-779 Fixed line feed in request log + JETTY-782 Implement interval advice for BayeuxClient + JETTY-783 Update jetty self-signed certificate + JETTY-784 TerracottaSessionManager leaks sessions scavenged in other nodes + JETTY-787 Handle MSIE7 mixed encoding + JETTY-788 Fix jotm for new scoped jndi + JETTY-790 WaitingContinuations can change mutex if not pending + JETTY-791 Ensure jdk1.4 compatibility for jetty-6 + JETTY-792 TerracottaSessionManager does not unlock new session with requested id + JETTY-793 Fixed DataCache millisecond rounding jetty-6.1.12 - 04 November 2008 + JETTY-731 Completed DeliverListener for cometd + JETTY-772 Increased default threadpool size to 250 + JETTY-774 Cached text/json content type + JETTY-775 fix port of openspaces to jetty-6 jetty-7.0.0.pre5 - 30 October 2008 + JETTY-766 Fix npe + JETTY-767 Fixed SSL Client no progress handshake bug + JETTY-768 Remove EnvEntry overloaded constructors + JETTY-769 jquery example error + JETTY-771 Ensure NamingEntryUtil is jdk1.4 compliant + JETTY-772 Increased default threadpool size to 250 jetty-6.1.12.rc5 - 30 October 2008 + JETTY-703 maxStopTimeMs added to QueuedThreadPool + JETTY-762 improved QueuedThreadPool idle death handling + JETTY-763 Fixed AJP13 constructor + JETTY-766 Ensure SystemProperties set early on jetty-maven-plugin + JETTY-767 Fixed SSL Client no progress handshake bug + JETTY-768 Remove EnvEntry overloaded constructors + JETTY-771 Ensure NamingEntryUtil jdk1.4 compliant jetty-7.0.0.pre4 - 28 October 2008 + JETTY-241 Support for web application overlays in rapid application development (jetty:run) + JETTY-319 improved passing of exception when webapp unavailable + JETTY-331 SecureRandom hangs on systems with low entropy (connectors slow to start) + JETTY-591 No server classes for jetty-web.xml + JETTY-604 AbstractSession.setSessionURL + JETTY-670 $JETTY_HOME/bin/jetty.sh not worked in Solaris, because of /usr/bin/which has no error-code + JETTY-676 ResourceHandler doesn't support HTTP HEAD requests + JETTY-677 GWT serialization issue + JETTY-680 Can't configure the ResourceCollection with maven + JETTY-681 JETTY-692 MultiPartFilter is slow for file uploads + JETTY-682 Added listeners and queue methods to cometd + JETTY-686 LifeCycle.Listener + JETTY-687 Issue with servlet-mapping in dynamic servlet invoker + JETTY-688 Cookie causes NumberFormatException + JETTY-689 processing of non-servlet related annotations + JETTY-690 Updated XBean dependencies to XBean version 3.4.3 and Spring 2.0.5. + JETTY-696 jetty.sh restart not working + JETTY-698 org.eclipse.resource.JarResource.extract does not close JarInputStream jin + JETTY-699 Optimized cometd sending of 1 message to many many clients + JETTY-700 unit test for unread request data + JETTY-703 maxStopTimeMs added to QueuedThreadPool + JETTY-708 allow 3 scopes for jndi resources: jvm, server or webapp + JETTY-709 Jetty plugin's WebAppConfig configured properties gets overridden by AbstractJettyRunMojo even when already set + JETTY-710 Worked around poor implementation of File.toURL() + JETTY-711 DataSourceUserRealm implementation + JETTY-712 HttpClient does not handle request complete after response complete + JETTY-715 AJP Key size as Integer + JETTY-716 Fixed NPE on empty cometd message + JETTY-718 during ssl unwrap, return true if some bytes were read, even if underflow + JETTY-720 fix HttpExchange.waitForStatus + JETTY-721 Support wildcard in VirtualHosts configuration + JETTY-723 jetty.sh does not check if TMP already is set + JETTY-724 better handle EBCDIC default JVM encoding + JETTY-728 Improve Terracotta integration and performances + JETTY-730 Set SAX parse features to defaults + JETTY-731 DeliverListener for cometd + JETTY-732 Case Sensitive Basic Authentication Response Header Implementations + JETTY-733 Expose ssl connectors with xbean + JETTY-735 Wrong default jndi name on DataSourceUserRealm + JETTY-736 Client Specific cometd advice + JETTY-737 refactored jetty.jar into jetty, xml, security, ssl, webapp and deploy jars + JETTY-738 If jetty.sh finds a pid file is does not check to see if a process with that pid is still running + JETTY-739 Race in QueuedThreadPool + JETTY-741 HttpClient connects slowly due to reverse address lookup by InetAddress.getHostName() + JETTY-742 Private messages in cometd chat demo + JETTY-747 Handle HttpClient exceptions better + JETTY-755 Optimized HttpParser and buffers for few busy connections + JETTY-757 Unhide JAAS classes + JETTY-758 Update JSP to glassfish tag SJSAS-9_1_1-B51-18_Sept_2008 + JETTY-759 Fixed JSON small negative real numbers + JETTY-760 Handle wildcard VirtualHost and normalize hostname in ContextHandlerCollection + JETTY-762 improved QueuedThreadPool idle death handling + JETTY-763 Fixed AJP13 constructor + JETTY-766 Ensure SystemProperties set early on jetty-maven-plugin jetty-6.1.12.rc4 - 21 October 2008 + JETTY-319 improved passing of exception when webapp unavailable + JETTY-729 Backport Terracotta integration to Jetty6.1 branch + JETTY-744 Backport of JETTY-741: HttpClient connects slowly due to reverse address lookup by InetAddress.getHostName() + JETTY-747 Handle exceptions better in HttpClient + JETTY-755 Optimized HttpParser and buffers for few busy connections + JETTY-758 Update JSP 2.1 to glassfish tag SJSAS-9_1_1-B51-18_Sept_2008 + JETTY-759 Fixed JSON small negative real numbers + JETTY-760 Handle wildcard VirtualHost and normalize hostname in ContextHandlerCollection jetty-6.1.12.rc3 - 10 October 2008 + JETTY-241 Support for web application overlays in rapid application development (jetty:run) + JETTY-686 LifeCycle.Listener + JETTY-715 AJP key size + JETTY-716 NPE for empty cometd message + JETTY-718 during ssl unwrap, return true if some bytes were read, even if underflow + JETTY-720 fix HttpExchange.waitForStatus + JETTY-721 Support wildcard in VirtualHosts configuration + JETTY-722 jndi related threadlocal not cleared after deploying webapp + JETTY-723 jetty.sh does not check if TMP already is set + JETTY-725 port JETTY-708 (jndi scoping) to jetty-6 + JETTY-730 set SAX parser features to defaults + JETTY-731 DeliverListener for cometd + JETTY-732 Case Sensitive Basic Authentication Response Header Implementations + JETTY-736 Client Specific cometd advice + JETTY-738 If jetty.sh finds a pid file is does not check to see if a process with that pid is still running + JETTY-739 Race in QueuedThreadPool + JETTY-742 Private messages in cometd chat demo jetty-6.1.12rc2 - 12 September 2008 + JETTY-282 Support manually-triggered reloading + JETTY-331 SecureRandom hangs on systems with low entropy (connectors slow to startup) + JETTY-591 No server classes for jetty-web.xml + JETTY-670 $JETTY_HOME/bin/jetty.sh not worked in Solaris, because of /usr/bin/which has no error-code + JETTY-671 Configure DTD does not allow children + JETTY-672 Utf8StringBuffer doesn't properly handle null characters (char with byte value 0) + JETTY-676 ResourceHandler doesn't support HTTP HEAD requests + JETTY-677 GWT serialization issue + JETTY-680 Can't configure the ResourceCollection with maven + JETTY-681 JETTY-692 MultiPartFilter is slow for file uploads + JETTY-682 Added listeners and queue methods to cometd + JETTY-683 ResourceCollection works for jsp files but does not work for static resources under DefaultServlet + JETTY-687 Issue with servlet-mapping in dynamic servlet invoker + JETTY-688 Cookie causes NumberFormatException + JETTY-696 ./jetty.sh restart not working + JETTY-698 org.eclipse.resource.JarResource.extract does not close JarInputStream jin + JETTY-699 Optimize cometd sending of 1 message to many many clients + JETTY-709 Jetty plugin's WebAppConfig configured properties gets overridden by AbstractJettyRunMojo even when already set + JETTY-710 Worked around poor implementation of File.toURL() + JETTY-712 HttpClient does not handle request complete after response complete jetty-7.0.0pre3 - 06 August 2008 + Upgrade jsp 2.1 to SJSAS-9_1_02-B04-11_Apr_2008 + JETTY-30 Externalize servlet-api to own project + JETTY-182 Support setting explicit system classpath for jasper Jsr199JavaCompiler + JETTY-319 Get unavailable exception and added startWithUnavailable option + JETTY-381 JETTY-622 Multiple Web Application Source Directory + JETTY-442 Accessors for mimeType on ResourceHandler + JETTY-502 forward of an include should hide include attributes + JETTY-562 RewriteHandler support for virtual hosts + JETTY-563 JETTY-482 OpenRemoteServiceServlet for GWT1.5M2+ + JETTY-564 Consider optionally importing org.apache.jasper.servlet + JETTY-571 SelectChannelConnector throws Exception on close on Windows + JETTY-608 Suspend/Resume/Complete request listeners + JETTY-621 Improved LazyList javadoc + JETTY-626 Null protect reading the dtd resource from classloader + JETTY-628 Rewrite rule for rewriting scheme + JETTY-629 Don't hold timeout lock during expiry call. + JETTY-632 OSGi tags for Jetty client + JETTY-633 Default form encoding 8859_1 rather than utf-8 + JETTY-635 Correctly merge request parameters when doing forward + JETTY-636 Separate lifeycle of jsp build + JETTY-637 empty date headers throw IllegalArgumentException + JETTY-641 JDBC Realm purge cache problem + JETTY-642 NPE in LdapLoginModule + JETTY-644 LdapLoginModule uses proper filters when searching + JETTY-645 Do not provide jetty-util to the webapps + JETTY-646 Should set Cache-Control header when sending errors to avoid caching + JETTY-647 suspended POSTs with binary data do too many resumes + JETTY-650 Parse "*" URI for HTTP OPTIONS request + JETTY-651 Release resources during destroy + JETTY-653 Upgrade jta api specs to more recent version + JETTY-654 Allow Cometd Bayeux object to be JMX manageable + JETTY-655 Support parsing application/x-www-form-urlencoded parameters via http PUT + JETTY-656 HttpClient defaults to async mode + JETTY-659 ContentExchange and missing headers in HttpClient + JETTY-663 AbstractDatabaseLoginModule handle not found UserInfo and userName + JETTY-665 Support merging class directories + JETTY-666 scanTargetPatterns override the values already being set by scanTarget + JETTY-667 HttpClient handles chunked content + JETTY-669 Http methods other than GET and POST should not have error page content + JETTY-671 Configure DTD does not allow children + JETTY-672 Utf8StringBuffer doesn't properly handle null characters (char with byte value 0) + JETTY-675 ServletContext.getRealPath("") returns null instead of returning the root dir of the webapp jetty-6.1.12rc1 - 01 August 2008 + Upgrade jsp 2.1 to SJSAS-9_1_02-B04-11_Apr_2008 + JETTY-319 Get unavailable exception and added startWithUnavailable option + JETTY-381 JETTY-622 Multiple Web Application Source Directory + JETTY-442 Accessors for mimeType on ResourceHandler + JETTY-502 forward of an include should hide include attributes + JETTY-562 RewriteHandler support for virtual hosts + JETTY-563 GWT OpenRemoteServiceServlet GWT1.5M2+ + JETTY-564 Consider optionally importing org.apache.jasper.servlet + JETTY-571 SelectChannelConnector throws Exception on close on Windows + JETTY-596 Proxy authorization support in HttpClient + JETTY-599 handle buffers consistently handle invalid index for poke + JETTY-603 Handle IPv6 in HttpURI + JETTY-605 Added optional threadpool to BayeuxService + JETTY-606 better writeTo impl for BIO + JETTY-607 Add GigaSpaces session clustering + JETTY-610 jetty.class.path not being interpreted + JETTY-613 website module now generates site-component for jetty-site + JETTY-614 scanner allocated hashmap on every scan + JETTY-623 ServletContext.getServerInfo() non compliant + JETTY-626 Null protect reading the dtd resource from classloader + JETTY-628 Rewrite rule for rewriting scheme + JETTY-629 Don't hold timeout lock during expiry call. + JETTY-632 OSGi tags for Jetty client + JETTY-633 Default form encoding 8859_1 rather than utf-8 + JETTY-635 Correctly merge request parameters when doing forward + JETTY-637 empty date headers throw IllegalArgumentException + JETTY-641 JDBC Realm purge cache problem + JETTY-642 NPE in LdapLoginModule + JETTY-644 LdapLoginModule uses proper filters when searching + JETTY-646 Should set Cache-Control header when sending errors to avoid caching + JETTY-647 suspended POSTs with binary data do too many resumes + JETTY-650 Parse "*" URI for HTTP OPTIONS request + JETTY-651 Release resources during destroy + JETTY-654 Allow Cometd Bayeux object to be JMX manageable + JETTY-655 Support parsing application/x-www-form-urlencoded parameters via http PUT + JETTY-656 HttpClient defaults to async mode + JETTY-657 Backport jetty-7 sslengine + JETTY-658 backport latest HttpClient from jetty-7 to jetty-6 + JETTY-659 ContentExchange and missing headers in HttpClient + JETTY-660 Backported QoSFilter + JETTY-663 AbstractDatabaseLoginModule handle not found UserInfo and userName + JETTY-665 Support merging class directories + JETTY-666 scanTargetPatterns override the values already being set by scanTarget + JETTY-667 HttpClient handles chunked content + JETTY-669 Http methods other than GET and POST should not have error page content jetty-7.0.0pre2 - 30 June 2008 + JETTY-336 413 error for header buffer full + JETTY-425 race in stopping SelectManager + JETTY-568 Avoid freeing DirectBuffers. New locking NIO ResourceCache. + JETTY-569 Stats for suspending requests + JETTY-576 servlet dtds and xsds not being loaded locally + JETTY-572 Unique cometd client ID + JETTY-578 OSGI Bundle-RequiredExcutionEnvironment set to J2SE-1.5 + JETTY-579 OSGI resolved management and servlet.resources import error + JETTY-580 Fixed SSL shutdown + JETTY-581 ContextPath constructor + JETTY-582 final ISO_8859_1 + JETTY-584 handle null contextPath + JETTY-587 persist sessions to database + JETTY-588 handle Retry in ServletException + JETTY-589 Added Statistics Servlet + JETTY-590 Digest auth domain for root context + JETTY-592 expired timeout callback without synchronization + JETTY-595 SessionHandler only deals with base request session + JETTY-596 proxy support in HttpClient + JETTY-598 Added more reliable cometd message flush option + JETTY-599 handle buffers consistently handle invalid index for poke + JETTY-603 Handle IPv6 in HttpURI + JETTY-605 Added optional threadpool to BayeuxService + JETTY-606 better writeTo impl for BIO + JETTY-607 Add GigaSpaces session clustering + JETTY-609 jetty-client improvements for http conversations + JETTY-610 jetty.class.path not being interpreted + JETTY-611 make general purpose jar scanning mechanism + JETTY-612 scan for web.xml fragments + JETTY-613 various distribution related changes + JETTY-614 scanner allocates hashmap on every iteration + JETTY-615 Replaced CDDL servlet.jar with Apache-2.0 licensed version + JETTY-623 ServletContext.getServerInfo() non compliant jetty-6.1.11 - 06 June 2008 + JETTY-336 413 error for full header buffer + JETTY-425 race in stopping SelectManager + JETTY-580 Fixed SSL shutdown + JETTY-581 ContextPath constructor + JETTY-582 final ISO_8859_1 + JETTY-584 handle null contextPath + JETTY-588 handle Retry in ServletException + JETTY-590 Digest auth domain for root context + JETTY-592 expired timeout callback without synchronization + JETTY-595 SessionHandler only deals with base request session + JETTY-596 Proxy support in HttpClient + JETTY-598 Added more reliable cometd message flush option jetty-6.1.10 - 20 May 2008 + Use QueuedThreadPool as default + JETTY-440 allow file name patterns for jsp compilation for jspc plugin + JETTY-529 CNFE when deserializing Array from session resolved + JETTY-537 JSON handles Locales + JETTY-547 Shutdown SocketEndpoint output before close + JETTY-550 Reading 0 bytes corrupts ServletInputStream + JETTY-551 Upgraded to Wadi 2.0-M10 + JETTY-556 Encode all URI fragments + JETTY-557 Allow ServletContext.setAttribute before start + JETTY-558 optional handling of X-Forwarded-For/Host/Server + JETTY-566 allow for non-blocking behavior in jetty maven plugin + JETTY-572 unique cometd client ID + JETTY-579 osgi fixes with management and servlet resources jetty-7.0.0pre1 - 03 May 2008 + Allow annotations example to be built regularly, copy to contexts-available + Make annotations example consistent with servlet 3.0 + Refactor JNDI impl to simplify + Improved suspend examples + address osgi bundling issue relating to build resources + JETTY-529 CNFE when deserializing Array from session resolved + JETTY-558 optional handling of X-Forwarded-For/Host/Server + JETTY-559 ignore unsupported shutdownOutput + JETTY-566 allow for non-blocking behavior in jetty maven plugin + JETTY-440 allow file name patterns for jsp compilation for jspc plugin jetty-7.0.0pre0 - 21 April 2008 + Jetty-6.1.8 Changes + Refactor of Continuation towards servlet 3.0 proposal + JETTY-282 Support manually-triggered reloading by maven plugin + QueuedThreadPool default + RetryRequest exception now extends ThreadDeath + Added option to dispatch to suspended requests. + Delay 100 continues until getInputStream + HttpClient supports pipelined request + BayeuxClient use a single connection for polling + Make javax.servlet.jsp optional osgi import for jetty module + Ensure Jotm tx mgr can be found in jetty-env.xml + Renamed modules management and naming to jmx and jndi. + JETTY-341 100-Continues sent only after getInputStream called. + JETTY-386 backout fix and replaced with ContextHandler.setCompactPath(boolean) + JETTY-399 update OpenRemoteServiceServlet to gwt 1.4 + JETTY-467 allow URL rewriting to be disabled. + JETTY-468 unique holder names for addServletWithMapping + JETTY-471 LDAP JAAS Realm + JETTY-474 Fixed case sensitivity issue with HttpFields + JETTY-475 AJP connector in RPMs + JETTY-486 Improved jetty.sh script + JETTY-487 Handle empty chunked request + JETTY-494 Client side session replication + JETTY-519 HttpClient does not recycle closed connection. + JETTY-522 Add build profile for macos for setuid + JETTY-523 Default servlet uses ServletContext.getResource + JETTY-524 Don't synchronize session event listener calls + JETTY-525 Fixed decoding for long strings + JETTY-526 Fixed MMBean fields on JMX MBeans + JETTY-528 Factor our cookie parsing to CookieCutter + JETTY-530 Improved JMX MBeanContainer lifecycle + JETTY-531 Optional expires on MovedContextHandler + JETTY-532 MBean properties for QueuedThreadPool + JETTY-535 Fixed Bayeux server side client memory leak + JETTY-537 JSON handles Locales + JETTY-538 test harness fix for windows + JETTY-540 Servlet-3.0 & java5 support (work in progress) + JETTY-543 Atomic batch get and put of files. + JETTY-545 Rewrite handler + JETTY-546 Webapp runner. All in one jar to run a webapps + JETTY-547 Shutdown SocketEndpoint output before close + JETTY-550 Reading 0 bytes corrupts ServletInputStream + JETTY-551 Wadi 2.0-M10 + JETTY-553 Fixed customize override + JETTY-556 Encode all URI fragments + JETTY-557 Allow ServletContext.setAttribute before start + JETTY-560 Allow decoupling of jndi names in web.xml jetty-6.1.9 - 26 March 2008 + Make javax.servlet.jsp optional osgi import for jetty module + Ensure Jotm tx mgr can be found in jetty-env.xml + JETTY-399 update OpenRemoteServiceServlet to gwt 1.4 + JETTY-471 LDAP JAAS Realm + JETTY-475 AJP connector in RPMs + JETTY-482 update to JETTY-399 + JETTY-519 HttpClient does not recycle closed connection. + JETTY-522 Add build profile for macos for setuid + JETTY-525 Fixed decoding for long strings + JETTY-526 Fixed MMBean fields on JMX MBeans + JETTY-532 MBean properties for QueuedThreadPool + JETTY-535 Fixed Bayeux server side client memory leak + JETTY-538 test harness fix for windows + JETTY-541 Cometd per client timeouts jetty-6.1.8 - 28 February 2008 + Added QueuedThreadPool + Optimized QuotedStringTokenizer.quote() + further Optimizations and improvements of Cometd + Optimizations and improvements of Cometd, more pooled objects + Improved Cometd timeout handling + Added BayeuxService + Cookie support in BayeuxClient + Improved Bayeux API + add removeHandler(Handler) method to HandlerContainer interface + Added JSON.Convertor and non static JSON instances + Long cache for JSON + Fixed JSON negative numbers + JSON unquotes / + Add "mvn jetty:stop" + allow sessions to be periodically persisted to disk + grizzly fixed for posts + Remove duplicate commons-logging jars and include sslengine in jboss sar + Allow code ranges on ErrorPageErrorHandler + AJP handles bad mod_jk methods + JETTY-350 log ssl errors on SslSocketConnector + JETTY-417 JETTY_LOGS environment variable not queried by jetty.sh + JETTY-433 ContextDeployer constructor fails unnecessarily when using a security manager if jetty.home not set + JETTY-434 ContextDeployer scanning of sub-directories should be optional + JETTY-481 Handle empty Bayeux response + JETTY-489 Improve doco on the jetty.port property for plugin + JETTY-490 Fixed JSONEnumConvertor + JETTY-491 opendocument mime types + JETTY-492 Null pointer in HashSSORealm + JETTY-493 JSON handles BigDecimals + JETTY-498 Improved cookie parsing + JETTY-507 Fixed encoding from JETTY-388 and test case + JETTY-508 Extensible cometd handlers + JETTY-509 Fixed JSONP transport for changing callback names + JETTY-511 jetty.sh mishandled JETTY_HOME when launched from a relative path + JETTY-512 add slf4j as optional to manifest + JETTY-513 Terracotta session replication does not work when the initial page on each server does not set any attributes + JETTY-515 Timer is missing scavenging Task in HashSessionManager jetty-6.1.7 - 22 December 2007 + Added BayeuxService + Added JSON.Convertor and non static JSON instances + Add "mvn jetty:stop" + allow sessions to be periodically persisted to disk + Cookie support in BayeuxClient + grizzly fixed for posts + jetty-6.1 branch created from 6.1.6 and r593 of jetty-contrib trunk + Optimizations and improvements of Cometd, more pooled objects + Update java5 patch + JETTY-386 CERT-553235 backout fix and replaced with ContextHandler.setCompactPath(boolean) + JETTY-467 allow URL rewriting to be disabled. + JETTY-468 unique holder names for addServletWithMapping + JETTY-474 Fixed case sensitivity issue with HttpFields + JETTY-486 Improved jetty.sh script + JETTY-487 Handle empty chunked request jetty-6.1.6 - 18 November 2007 + rudimentary debian packaging + updated grizzly connector to 1.6.1 + JETTY-455 Optional cometd id + JETTY-459 Unable to deploy from Eclipse into the root context + JETTY-461 fixed cometd unknown channel + JETTY-464 typo in ErrorHandler + JETTY-465 System.exit() in constructor exception for MultiPartOutputStream jetty-6.1.6rc1 - 05 November 2007 + Upgrade jsp 2.1 to SJSAS-9_1-B58G-FCS-08_Sept_2007 + Housekeeping on poms + CERT VU#38616 handle single quotes in cookie names. + Improved JSON parsing from Readers + Moved some impl classes from jsp-api-2.1 to jsp-2.1 + Added configuration file for capturing stderr and stdout + Updated for dojo 1.0(rc) cometd + Give bayeux timer name + Give Terracotta session scavenger a name + Jetty Eclipse Plugin 1.0.1: force copy of context file on redeploy + JETTY-388 Handle utf-16 and other multibyte non-utf-8 form content. + JETTY-409 String params that denote files changed to File + JETTY-438 handle trailing . in vhosts + JETTY-439 Fixed 100 continues clash with Connection:close + JETTY-451 Concurrent modification of session during invalidate + JETTY-443 windows bug causes Acceptor thread to die + JETTY-445 removed test code + JETTY-448 added setReuseAddress on AbstractConnector + JETTY-450 Bad request for response sent to server + JETTY-452 CERT VU#237888 Dump Servlet - prevent cross site scripting + JETTY-453 updated Wadi to 2.0-M7 + JETTY-454 handle exceptions with themselves as root cause + JETTY-456 allow null keystore for osX + JETTY-457 AJP certificate chains jetty-6.1.6rc0 - 03 October 2007 + Added jetty.lib system property to start.config + AJP13 Fix on chunked post + Fix cached header optimization for extra characters + SetUID option to support setgid + Make mx4j used only if runtime uses jdk<1.5 + Moved Grizzly to contrib + Give deployment file Scanner threads a unique name + Fix Host header for async client + Fix typo in async client onResponsetHeader method name + Tweak OSGi manifests to remove unneeded imports + Allow scan interval to be set after Scanner started + Add jetty.host system property + Allow properties files on the XmlConfiguration command line. + Prevent infinite loop on stopping with temp dir + Ensure session is completed only when leaving context. + Update terracotta to 2.4.1 and exclude ssl classes + Update jasper2.1 to tag SJSAS-9_1-B58C-FCS-22_Aug_2007 + Removal of unneeded dependencies from management, maven-plugin, naming & plus poms + Adding setUsername,setGroupname to setuid and mavenizing native build + UTF-8 for bayeux client + CVE-2007-5615 Added protection for response splitting with bad headers. + Cached user agents strings in the /org/mortbay/jetty/useragents resource + Make default time format for RequestLog match NCSA default + Use terracotta repo for build; make jetty a terracotta module + Fix patch for java5 to include cometd module + Added ConcatServlet to combine javascript and css + Add ability to persist sessions with HashSessionManager + Avoid FULL exception in window between blockForOutput and remote close + Added JPackage RPM support + Added JSON.Convertable + Updated README, test index.html file and jetty-plus.xml file + JETTY-259 SystemRoot set for windows CGI + JETTY-311 avoid json keywords + JETTY-376 allow anything but CRLF in reason string + JETTY-398 Allow same WADI Dispatcher to be used across multiple web-app contexts + JETTY-400 consume CGI stderr + JETTY-402 keep HashUserRealm in sync with file + JETTY-403 Allow long content length for range requests + JETTY-404 WebAppDeployer sometimes deploys duplicate webapp + JETTY-405 Default date formate for reqest log + JETTY-407 AJP handles unknown content length + JETTY-413 Make rolloveroutputstream timer daemon + JETTY-422 Allow values to be null in config files + JETTY-423 Ensure javax.servlet.forward parameters are latched on first forward + JETTY-425 Handle duplicate stop calls better + JETTY-430 improved cometd logging + JETTY-431 HttpClient soTimeout jetty-6.1.5 - 19 July 2007 + Upgrade to Jasper 2.1 tag SJSAS-9_1-B50G-BETA3-27_June_2007 + Fixed GzipFilter for dispatchers + Fixed reset of reason + JETTY-392 updated LikeJettyXml example jetty-6.1.5rc0 - 15 July 0200 + update terracotta session clustering to terracotta 2.4 + SetUID option to only open connectors before setUID. + Protect SslSelectChannelConnector from exceptions during close + Improved Request log configuration options + Added GzipFilter and UserAgentFilter + make OSGi manifests for jetty jars + update terracotta configs for tc 2.4 stable1 + remove call to open connectors in jetty.xml + update links on website + make jetty plus example webapps use ContextDeployer + Dispatch SslEngine expiry (non atomic) + Make SLF4JLog impl public, add mbean descriptors + SPR-3682 - dont hide forward attr in include. + Upgrade to Jasper 2.1 tag SJSAS-9_1-B50G-BETA3-27_June_2007 + JETTY-253 Improved graceful shutdown + JETTY-373 Stop all dependent lifecycles + JETTY-374 HttpTesters handles large requests/responses + JETTY-375 IllegalStateException when committed. + JETTY-376 allow spaces in reason string + JETTY-377 allow sessions to be wrapped with AbstractSesssionManager.SessionIf + JETTY-378 handle JVMs with non ISO/UTF default encodings + JETTY-380 handle pipelines of more than 4 requests! + JETTY-385 EncodeURL for new sessions from dispatch + JETTY-386 Allow // in file resources jetty-6.1.4 - 15 June 2007 + fixed early open() call in NIO connectors + JETTY-370 ensure maxIdleTime<=0 means connections never expire + JETTY-371 Fixed chunked HEAD response + JETTY-372 make test for cookie caching more rigorous jetty-6.1.4rc1 - 10 June 2007 + Work around IBM JVM socket close issue + moved documentation for jetty and jspc maven plugins to wiki + async client improvements + fixed handling of large streamed files + Fixed synchronization conflict SslSelectChannel and SelectChannel + Optional static content cache + JETTY-310 better exception when no filter file for cometd servlet + JETTY-323 handle htaccess without a user realm + JETTY-346 add wildcard support to extra scan targets for maven plugin + JETTY-355 extensible SslSelectChannelConnector + JETTY-357 cleaned up ssl buffering + JETTY-360 allow connectors, userRealms to be added from a for maven plugin + JETTY-361 prevent url encoding of dir listings for non-link text + JETTY-362 More object locks + JETTY-365 make needClientAuth work on SslSelectChannelConnector + JETTY-366 JETTY-368 Improved bayeux disconnect jetty-6.1.4rc0 - 01 June 2007 + Reorganized import of contrib modules + Unified JMX configuration + Updated slf4j version to 1.3.1 + Updated junit to 3.8.2 + Allow XmlConfiguration properties to be configured + Add (commented out) jspc precompile to test-webapp + Add slf4j-api for upgraded version + Change scope of fields for Session + Add ability to run cometd webapps to maven plugin + Delay ssl handshake until after dispatch in sslSocketConnector + Set so_timeout during ssl handshake as an option on SslSocketConnector + Optional send Date header. Server.setSendDateHeader(boolean) + update etc/jetty-ssl.xml with new handshake timeout setting + fixed JSP close handling + improved date header handling + fixed waiting continuation reset + JETTY-257 fixed comet cross domain + JETTY-309 fix applied to sslEngine + JETTY-317 rollback inclusion of cometd jar for maven plugin + JETTY-318 Prevent meta channels being created + JETTY-330 Allow dependencies with scope provided for jspc plugin + JETTY-335 SslEngine overflow fix + JETTY-337 deprecated get/setCipherSuites and added get/setExcludeCipherSuites + JETTY-338 protect isMoreInBuffer from destroy + JETTY-339 MultiPartFiler deletes temp files on IOException + JETTY-340 FormAuthentication works with null response + JETTY-344 gready fill in ByteArrayBuffer.readFrom + JETTY-345 fixed lost content with blocked NIO. + JETTY-347 Fixed type util init + JETTY-352 Object locks jetty-6.1.3 - 04 May 2007 + Handle CRLF for content in header optimization + JETTY-309 don't clear writable status until dispatch + JETTY-315 suppressed warning + JETTY-322 AJP13 cping and keep alive jetty-6.1.2 - 01 May 2007 + Improved unavailabile handling + sendError resets output state + Fixed session invalidation error in WadiSessionManager + Updated Wadi to version 2.0-M3 + Added static member definition in WadiSessionManager + JETTY-322 fix ajp cpong response and close handling + JETTY-324 fix ant plugin + JETTY-328 updated jboss jetty-6.1.2rc5 - 24 April 2007 + set default keystore for SslSocketConnector + removed some compile warnings + Allow jsp-file to be / or /* + JETTY-305 delayed connection destroy + JETTY-309 handle close in multivalue connection fields. + JETTY-314 fix for possible NPE in Request.isRequestedSessionIdValid jetty-6.1.2rc4 - 19 April 2007 + JETTY-294 Fixed authentication reset + JETTY-299 handle win32 paths for object naming + JETTY-300 removed synchronized on dispatch + JETTY-302 correctly parse quoted content encodings + JETTY-303 fixed dual reset of generator + JETTY-304 Fixed authentication reset jetty-6.1.2rc3 - 16 April 2007 + Improved performance and exclusions for TLD scanning + MBean properties assume writeable unless marked RO + refactor of SessionManager and SessionIdManager for clustering + Improvements to allow simple setting of Cache-Control headers + AJP redirects https requests correctly + Fixed writes of unencoded char arrays. + JETTY-283 Parse 206 and 304 responses in client + JETTY-285 enable jndi for mvn jetty:run-war and jetty:run-exploded + JETTY-289 fixed javax.net.ssl.SSLException on binary file upload + JETTY-292 Fixed error page handler error pages + JETTY-293 fixed NPE on fast init + JETTY-294 Response.reset() resets headers as well as content + JETTY-295 Optional support of authenticated welcome files + JETTY-296 Close direct content inputstreams + JETTY-297 Recreate tmp dir on stop/start + JETTY-298 Names in JMX ObjectNames for context, servlets and filters jetty-6.1.2rc2 - 27 March 2007 + Enable the SharedStoreContextualiser for the WadiSessionManager(Database store for clustering) + AJP13 CPING request and CPONG response implemented + AJP13 Shutdown Request from peer implemented + AJP13 remoteUser, contextPath, servletPath requests implemented + Change some JNDI logging to debug level instead of info + Update jasper to glassfish tag SJSAS-9_1-B39-RC-14_Mar_2007 + Optimized multi threaded init on startup servlets + Removed unneeded specialized TagLibConfiguration class from maven plugin + Refactor Scanner to increase code reuse with maven/ant plugins + Added RestFilter for PUT and DELETE from Aleksi Kallio + Make annotations work for maven plugin + JETTY-125 maven plugin: ensure test dependencies on classpath for + JETTY-246 path encode cookies rather than quote + JETTY-254 prevent close of jar entry by bad JVMs + JETTY-256 fixed isResumed and work around JVM bug + JETTY-258 duplicate log message in ServletHandler + JETTY-260 Close connector before stop + JETTY-262 Allow acceptor thread priority to be adjusted + JETTY-263 Added implementation for authorizationType Packets + JETTY-265 Only quote cookie values if needed + JETTY-266 Fix deadlock with shutdown + JETTY-271 ResourceHandler uses resource for MimeType mapping + JETTY-272 Activate and Passivate events for sessions + JETTY-274 Improve flushing at end of request for blocking + JETTY-276 Partial fix for reset/close race + JETTY-277 Improved ContextHandlerCollection + JETTY-278 Session invalidation delay until no requests + JETTY-280 Fixed deadlock with two flushing threads + JETTY-284 Fixed stop connector race + JETTY-286 isIntegral and isConfidential methods overridden in SslSelectChannelConnector jetty-6.1.2rc1 - 08 March 2007 + TagLibConfiguration uses resource input stream + Improved handling of early close in AJP + add ajp connector jar to jetty-jboss sar + Improved Context setters for wadi support + fix Dump servlet to handle primitive array types + handle comma separated values for the Connection: header + Added option to allow null pathInfo within context + BoundedThreadPool queues rather than blocks excess jobs. + Support null pathInfo option for webservices deployed to jetty/jboss + Workaround to call SecurityAssocation.clear() for jboss webservices calls to ejbs + Ensure jetty/jboss uses servlet-spec classloading order + call preDestroy() after servlet/filter destroy() + Fix constructor for Constraint to detect wildcard role + Added support for lowResourcesIdleTime to SelectChannelConnector + JETTY-157 make CGI handle binary data + JETTY-175 JDBCUserRealm use getInt instead of getObject + JETTY-188 Use timer for session scavaging + JETTY-235 default realm name + JETTY-242 fix race condition with scavenging sessions when stopping + JETTY-243 FULL + JETTY-244 Fixed UTF-8 buffer overflow + JETTY-245 Client API improvements + JETTY-246 spaces in cookies + JETTY-248 setContentLength after content written + JETTY-250 protect attribute enumerations from modification + JETTY-252 Fixed stats handling of close connection + JETTY-254 prevent close of jar file by bad JVMs jetty-6.1.2rc0 - 15 February 2007 + JETTY-223 Fix disassociate of UserPrincipal on dispatches + JETTY-226 Fixed SSLEngine close issue + JETTY-232 Fixed use of override web.xml + JETTY-236 Buffer leak + JETTY-237 AJPParser Buffer Data Handling + JETTY-238 prevent form truncation + Patches from sybase for ClientCertAuthenticator + Coma separated cookies + Cometd timeout clients jetty-6.1.2pre1 - 05 February 2007 + JETTY-224 run build up to process-test before invoking jetty:run + Added error handling for incorrect keystore/truststore password in SslSelectChannelConnector + fixed bug with virtual host handling in ContextHandlerCollection + added win32service to standard build + refactored cometd to be continuation independent + allow ResourceHandler to use resource base from an enclosing ContextHandler jetty-6.1.2pre0 - 01 February 2007 + Fixed 1.4 method in jetty plus + Fixed generation of errors during jsp compilation for jsp-2.1 + Added cometd jsonp transport from aabeling + Added terracotta cluster support for cometd + JETTY-213 request.isUserInRole(String) fixed + JETTY-215 exclude more transitive dependencies from tomcat jars for jsp-2.0 + JETTY-216 handle AJP packet fragmentation + JETTY-218 handle AJP ssl key size and integer + JETTY-219 fixed trailing encoded chars in cookies + JETTY-220 fixed AJP content + JETTY-222 fix problem parsing faces-config.xml + add support for Annotations in servlet, filter and listener sources + improved writer buffering + moved JSON parser to util to support reuse + handle virtual hosts in ContextHandlerCollection + enable SslSelectChannelConnector to modify the SslEngine's client authentication settings jetty-6.1.1 - 15 January 2007 jetty-6.1.1rc1 - 12 January 2007 + Use timers for Rollover logs and scanner + JETTY-210 Build jsp-api-2.0 for java 1.4 jetty-6.1.1rc0 - 10 January 2007 + Fixed unpacking WAR + extras/win32service download only if no JavaServiceWrapper exist + MultiPartFilter deleteFiles option + CGI servlet fails without exception + JETTY-209 Added ServletTester.createSocketConnector + JETTY-210 Build servlet-api-2.5 for java 1.4 + JETTY-211 fixed jboss build + ensure response headers on AjaxFilter messsages turn off caching + start webapps on deployment with jboss, use isDistributed() method from WebAppContext + simplified chat demo jetty-6.1.0 - 09 January 2007 + Fixed unpacking WAR jetty-6.1.0 - 05 January 2007 + Improved config of java5 threadpool + Protect context deployer from Errors + Added WebAppContext.setCopyWebDir to avoid JVM jar caching issues. + GERONIMO-2677 refactor of session id handling for clustering + ServletTester sets content length + Added extras/win32service + JETTY-206 fixed AJP getServerPort and getRemotePort jetty-6.1.0rc3 - 02 January 2007 + JETTY-195 fixed ajp ssl_cert handling + JETTY-197 fixed getRemoteHost + JETTY-203 initialize ServletHandler if no Context instance + JETTY-204 setuid fix + setLocale does not use default content type + Use standard releases of servlet and jsp APIs. + implement resource injection and lifecycle callbacks declared in web.xml + extras/servlet-tester jetty-6.1.0rc2 - 20 December 2006 + AJP13Parser, throw IllegalStateException on unimplemented AJP13 Requests + ContextHandlerCollection is noop with no handlers + ensure servlets initialized if only using ServletHandler + fixed Jetty-197 AJP13 getRemoteHost() + Refactored AbstractSessionManager for ehcache + ensure classpath passed to jspc contains file paths not urls + JETTY-194 doubles slashes are significant in URIs + JETTY-167 cometd refactor + remove code to remove SecurityHandler if no constraints present + JETTY-201 make run-as work for both web container and ejb container in jboss + ensure com.sun.el.Messages.properties included in jsp-2.1 jar jetty-6.1.0rc1 - 14 December 2006 + simplified idle timeout handling + JETTY-193 MailSessionReference without authentication + JETTY-199 newClassPathResource + ensure unique name for ServletHolder instances + added cache session manager(pre-alpha) jetty-6.1.0rc0 - 08 December 2006 + JETTY-181 Allow injection of a java:comp Context + JETTY-182 Optionally set JSP classpath initparameter + Dispatcher does not protect javax.servlet attributes + DefaultHandler links virtual hosts. + Fixed cachesize on invalidate + Optimization of writers + ServletHandler allows non REQUEST exceptions to propogate + TCK fixes from Sybase: + Handle request content encodings + forward query attribute fix + session attribute listener + Servlet role ref + flush if content-length written + 403 for BASIC authorization failure + null for unknown named dispatches + JETTY-184 cometd connect non blocking + Support for RFC2518 102-processing response + JETTY-123 fix improved + Added org.mortbay.thread.concurrent.ThreadPool + Added extras/gwt + Fixed idle timeout + JETTY-189 ProxyConnection + Added spring ejb3 demo example + update jasper to glassfish SJSAS-9_1-B27-EA-07_Dec_2006 + JETTY-185 tmp filename generation jetty-6.1.0pre3 - 22 November 2006 + fixed NIO endpoint flush. Avoid duplicate sends + CVE-2006-6969 Upgraded session ID generation to use SecureRandom + updated glassfish jasper to tag SJSAS-9_1-B25-EA-08_Nov_2006 + Support TLS_DHE_RSA_WITH_AES_256_CBC_SHA + JETTY-180 XBean support for context deploy + JETTY-154 Cookies are double quotes only + Expose isResumed on Continuations + Refactored AJP generator jetty-6.0.2 - 22 November 2006 + Moved all modules updates from 6.1pre2 to 6.0 + Added concept of bufferred endpoint + Added conversion Object -> ObjectName for the result of method calls made on MBeans + Added DataFilter configuration to cometd + added examples/test-jaas-webapp + Added extraClassPath to WebAppContext + Added hierarchical destroy of mbeans + Added ID constructor to AbstractSessionManager.Session + added isStopped() in LifeCycle and AbstractLifeCycle + Added override descriptor for deployment of RO webapps + add replacement in jetty xml config files + alternate optimizations of writer (use -Dbuffer.writers=true) + Allow session cookie to be refreshed + Apply queryEncoding to getQueryString + CGI example in test webapp + change examples/test-jndi-webapp so it can be regularly built + Default soLinger is -1 (disabled) + ensure "" returned for ServletContext.getContextPath() for root context + ensure sessions nulled out on request recycle; ensure session null after invalidate + ensure setContextPath() works when invoked from jetty-web.xml + fixed NIO endpoint flush. Avoid duplicate sends + Fixed NPE in bio.SocketEndPoint.getRemoteAddr() + Fixed resource cache flushing + Fixed tld parsing for maven plugin + HttpGenerator can generate requests + Improved *-mbean.properties files and specialized some MBean + JETTY-118 ignore extra content after close. + JETTY-119 cleanedup Security optimizatoin + JETTY-123 handle windows UNC paths + JETTY-126 handle content > Integer.MAX_VALUE + JETTY-129 ServletContextListeners called after servlets are initialized + JETTY-151 Idle timeout only applies to blocking operations + JETTY-154 Cookies are double quotes only + JETTY-171 Fixed filter mapping + JETTY-172 use getName() instead of toString + JETTY-173 restore servletpath after dispatch + Major refactor of SelectChannel EndPoint for client selector + make .tag files work in packed wars + Plugin shutdown context before stopping it. + Refactored session lifecycle and additional tests + release resource lookup in Default servlet + (re)make JAAS classes available to webapp classloader + Reverted UnixCrypt to use coersions (that effected results) + Session IDs can change worker ID + Simplified ResourceCache and Default servlet + SocketConnector closes all connections in doStop + Upgraded session ID generation to use SecureRandom + updated glassfish jasper to tag SJSAS-9_1-B25-EA-08_Nov_2006 + Support TLS_DHE_RSA_WITH_AES_256_CBC_SHA jetty-5.1.14 - 09 August 2007 + patched with correct version + JETTY-155 force close with content length. + JETTY-369 failed state in Container jetty-5.1.13 + Sourceforge 1648335: problem setting version for AJP13 jetty-5.1.12 - 22 November 2006 + Added support for TLS_DHE_RSA_WITH_AES_256_CBC_SHA + Upgraded session ID generation to use SecureRandom + Quote single quotes in cookies + AJP protected against bad requests from mod_jk + JETTY-154 Cookies ignore single quotes jetty-4.2.27 - 22 November 2006 + Upgraded session ID generation to use SecureRandom + AJP protected against bad requests from mod_jk jetty-6.1.0pre2 - 20 November 2006 + Added extraClassPath to WebAppContext + Fixed resource cache flushing + Clean up jboss module licensing jetty-6.1.0pre1 - 19 November 2006 + Use ContextDeployer as main deployer in jetty.xml + Added extras/jboss + Major refactor of SelectChannel EndPoint for client selector + Fixed NPE in bio.SocketEndPoint.getRemoteAddr() + Reverted UnixCrypt to use coersions (that effected results) + JETTY-151 Idle timeout only applies to blocking operations + alternate optimizations of writer (use -Dbuffer.writers=true) + JETTY-171 Fixed filter mapping + JETTY-172 use getName() instead of toString + JETTY-173 restore servletpath after dispatch + release resource lookup in Default servlet + Simplified ResourceCache and Default servlet + Added override descriptor for deployment of RO webapps + Added hierarchical destroy of mbeans jetty-6.1.0pre0 - 21 October 2006 + add replacement in jetty xml config files + make .tag files work in packed wars + add hot deployment capability + ensure setContextPath() works when invoked from jetty-web.xml + ensure sessions nulled out on request recycle; ensure session null after invalidate + ensure "" returned for ServletContext.getContextPath() for root context + Fixed tld parsing for maven plugin + Improved *-mbean.properties files and specialized some MBean + Added conversion Object -> ObjectName for the result of method calls made on MBeans + JETTY-129 ServletContextListeners called after servlets are initialized + change examples/test-jndi-webapp so it can be regularly built + added isStopped() in LifeCycle and AbstractLifeCycle + fixed isUserInRole checking for JAASUserRealm + fixed ClassCastException in JAASUserRealm.setRoleClassNames(String[]) + add a maven-jetty-jspc-plugin to do jspc precompilation + added examples/test-jaas-webapp + (re)make JAAS classes available to webapp classloader + CGI example in test webapp + Plugin shutdown context before stopping it. + Added concept of bufferred endpoint + Factored ErrorPageErrorHandler out of WebAppContext + Refactored ErrorHandler to avoid statics + Transforming classloader does not transform resources. + SocketConnector closes all connections in doStop + Improved charset handling in URLs + minor optimization of bytes to UTF8 strings + JETTY-112 ContextHandler checks if started + JETTY-113 support optional query char encoding on requests + JETTY-114 removed utf8 characters from code + JETTY-115 Fixed addHeader + added cometd chat demo + JETTY-119 cleanedup Security optimizatoin + Refactored session lifecycle and additional tests + JETTY-121 init not called on externally constructed servlets + JETTY-124 always initialize filter caches + JETTY-126 handle content > Integer.MAX_VALUE + JETTY-123 handle windows UNC paths + JETYY-120 SelectChannelConnector closes all connections on stop + Added ID constructor to AbstractSessionManager.Session + Allow session cookie to be refreshed + Added DataFilter configuration to cometd + Added extras/setuid to support start as root + Apply queryEncoding to getQueryString + JETTY-118 ignore extra content after close. + HttpGenerator can generate requests + Ported HtAccessHandler + Start of a client API + Session IDs can change worker ID + Default soLinger is -1 (disabled) + AJP Connector jetty-5.1.11 - 08 October 2006 + fixed ByteBufferOutputStream capacity calculation + Fixed AJP handling of certificate length (1494939) + Fixed AJP chunk header (1507377) + Fixed order of destruction event calls + Fix to HttpOutputStream from M.Traverso + Default servlet only uses setContentLength on wrapped responses jetty-4.2.26 - 08 October 2006 + Backport of AJP fixes jetty-6.0.1 - 24 September 2006 + fixed isUserInRole checking for JAASUserRealm + fixed ClassCastException in JAASUserRealm.setRoleClassNames(String[]) + Improved charset handling in URLs + Factored ErrorPageErrorHandler out of WebAppContext + Refactored ErrorHandler to avoid statics + JETTY-112 ContextHandler checks if started + JETTY-114 removed utf8 characters from code + JETTY-115 Fixed addHeader + JETTY-121 init not called on externally constructed servlets + minor optimization of bytes to UTF8 strings + JETTY-113 support optional query char encoding on requests + JETTY-124 always initialize filter caches + JETYY-120 SelectChannelConnector closes all connections on stop jetty-6.0.0 - 10 September 2006 + SocketConnector closes all connections in doStop + Conveniance builder methods for listeners and filters + Transforming classloader does not transform resources. + Plugin shutdown context before stopping it. jetty-6.0.0rc4 - 05 September 2006 + bind jetty-env.xml entries to java:comp/env + JETTY-107 Poor cast in SessionDump demo. + Set charset on error pages jetty-6.0.0rc3 - 01 September 2006 + pulled 6.0.0 branch + JETTY-103 + Move MailSessionReference to org.mortbay.naming.factories + Less verbose handling of BadResources from bad URLs + Avoid double error handling of Bad requests + don't warn for content length on head requests + JETTY-104 (raised glassfish ISSUE-1044) hide JSP forced path attribute + JETTY-68 Complete request after sendRedirect + Transferred the sslengine patch from the patches directory to extras jetty-6.0.0rc2 - 25 August 2006 + use mvn -Dslf4j=false jetty:run to disable use of slf4j logging with jdk1.4/jsp2.0 + added org.apache.commons.logging package to system classes that can't be overridden by a webapp classloader + mvn -Djetty.port=x jetty:run uses port number given for the default connector + Fixed NPE when no resource cache + Refactored WebXmlConfiguration to allow custom web.xml resource + Moved more utility packagtes to the util jar + Direct buffer useage is optional + Destroy HttpConnection to improve buffer pooling + Timestamp in StdErrLog jetty-6.0.0rc1 - 16 August 2006 + Support for binding References and Referenceables and javax.mail.Sessions in JNDI + Added TransformingWebAppClassLoader for spring 2.0 byte code modification support + JETTY-90 + Fixed FD leak for bad TCP acks. JETTY-63 + JETTY-87 + Change path mapping so that a path spec of /foo/* does not match /foo.bar : JETTY-88 + add config param to jetty plugin + JETTY-85 JETTY-86 (TrustManager and SecureRandom are now configurable; better handling of null/default values) + parse jsp-property-group in web.xml for additional JSP servlet mappings + protected setContentType from being set during include + JETTY-91 + added modules/spring with XmlBeanFactory configuration + removed support for lowResources from SelectChannelConnector + added start of cometd implementation (JSON only) + added start of grizzly connector + removed org.mortbay. from context system classes configuration + -DSTOP.PORT must be specified. + moved optional modules to extras + fixed bug that caused Response.setStatus to ignore the provided message + refactored resource cache + Allow direct filling of buffers for uncached static content. + Added simple ResourceHandler and FileServer example jetty-6.0.0rc0 - 07 July 2006 + change prefix from "jetty6" to just "jetty" for plugin: eg is now mvn jetty:run + allow or in for plugin + simplified jetty.xml with new constructor injections + added setters and getters on SessionManager API for session related config: cookie name, url parameter name, domain, max age and path. + add ability to have a lib/ext dir from which to recursively add all jars and zips to the classpath + patch to allow Jetty to use JSP2.1 from Glassfish instead of Jasper from Tomcat + fixed classesDirectory param for maven plugin to be configurable + ensure explicitly set tmp directory called "work" is not deleted on exit + ensure war is only unpacked if war is newer than "work" directory + change name of generated tmp directory to be "Jetty_"+host+"_"+port+"_"+contextpath+"_"+virtualhost + Cleaned up idle expiry. + Ssl algorithm taken from system property + Added 8 random letters&digits to Jetty-generated tmp work dir name to ensure uniqueness + Simplify runtime resolution of JSP library for plugin + Ensure mvn clean cleans the build + Do not wrap EofException with EofException + reverse order for destroy event listeners + added StatisticsHandler and statistics on Connector. + Simplified Servlet Context API + Added maximum limit to filter chain cache. + refactor HttpChannelEndPoint in preparation for SslEngine + ContextHandlerCollection addContext and setContextClass + Discard excess bytes in header buffer if connection is closing + Updated javax code from http://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk/java/javax@417727 + Threadpool does not need to be a LifeCycle + support graceful shutdown + Added WebAppContextClassLoader.newInstance to better support exensible loaders. + immutable getParameterMap() + support for SingleThreadModel + changed ServletContext.getResourcePaths() to not return paths containing double slashes + fixed HttpGenerator convertion of non UTF-8: JETTY-82 + added html module from jetty 5 - but deprecated until maintainer found jetty-6.0.0beta17 - 01 June 2006 + Added config to disable file memory mapped buffers for windows + Added Request.isHandled() + Refactored Synchronization of SelectChannelConnector + Recovered repository from Codehaus crash + ContextHandler.setConnectors replace setHosts + Connector lowResourceMaxIdleTime implemented. + Default servlet checks for aliases resources + Added clover reports and enough tests to get >50% coverage + Fixed IE SSL issue. + Implemented runAs on servlets + Flush will flush all bytes rather than just some. + Protected WEB-INF and META-INF + don't reset headers during forward + BoundedThreadPool.doStop waits for threads to complete jetty-6.0.0beta16 - 12 May 2006 + remove a couple of System.err.printlns + replace backwards compativle API in UrlEncoded jetty-6.0.0beta15 - 11 May 2006 + Added Server attribute org.mortbay.jetty.Request.maxFormContentSize + Renamed NotFoundHandler to DefaultHandler + Added automatic scan of all WEB-INF/jetty-*.xml files for plugin + Added parameter to allow other locations to scan for plugin + Major refactor to simplify Server and handler hierarchy + setSendServerVersion method added to Server to control sending of Server: http header + removed SelectBlockingChannelConnector (unmaintained) + Improved HttpException + Moved more resources to resources + Added ThrottlingFilter and fixed race in Continuations + Added taglib resources to 2.1 jsp api jar + Reset of timer task clears expiry + improved MBeanContainer object removal + ContextHandler.setContextPath can be called after start. + Fixed handling of params after forward + Added --version to start.jar + Added embedded examples + Simplified DefaultServlet static content buffering + readded BoundedThreadPool shrinking (and then fixed resulting deadlock) + improved MBean names + improved support for java5 jconsole + Session scavenger threads from threadpool + Thread names include URI if debug set + don't accept partial authority in request line. + enforce 204 and 304 have no content jetty-6.0.0beta14 - 09 April 2006 + ignore dirs and files that don't exist in plugin scanner + added support for stopping jetty using "java -jar start.jar --stop" + added configurability for webdefault.xml in maven plugin + adding InvokerServlet + added ProxyServlet + stop JDBCUserRealm coercing all credentials to String + Change tmp dir of plugin to work to be in line with jetty convention + Modify plugin to select JSP impl at runtime + Use start.config to select which JSP impl at runtime based on jdk version + Added JSP 2.1 APIs from apache + Added Jasper 2.1 as jesper (jasper without JCL) + Started readding logging to jesper using jdk logging + fixed priority of port from url over host header + implemented request.isUserInRole + securityHandler removed if not used. + moved test webapps to examples directory + improved contentType handling and test harness + fixed forward bug (treated as include) + fixed HttpField iterator + added jetty-util.jar module + added reset to Continuation jetty-6.0.0beta12 - 16 March 2006 + Fixed maven plugin JNDI for redeploys + Fixed tld discovery for plugin (search dependencies) + Fixed JettyPlus for root contexts + Fixed error handling in error page + Added JSP2.0 demos to test webapp + Upgraded jasper to 5.5.15 + Added provider support to SslListener + Log ERROR for runtimeExceptions jetty-6.0.0beta11 - 14 March 2006 + added JAAS + added webapp-specific JNDI entries + added missing Configurations for maven plugin + fixed FORM authentication + moved dtd and xsd to standard javax location + added patch to use joda-time + refactored session ID management + refactored configuration files and start() + fixed ; decoding in URIs + Added HttpURI and improved UTF-8 parsing. + refactored writers and improved UTF-8 generation. jetty-6.0.0beta10 - 25 February 2006 + Added support for java:comp/env + Added support for pluggable transaction manager + Forward masks include attributes and vice versa + Fixed default servlet handling of includes + Additional accessors for request logging + added getLocalPort() to connector + Fixed content-type for range requests + Fix for sf1435795 30sec delay from c taylor + Fix for myfaces and include with close + Fix sf1431936 don't chunk the chunk + Fix http://jira.codehaus.org/browse/JETTY-6. hi byte reader + Updates javax to MR2 release jetty-6.0.0beta9 - 09 February 2006 + PathMap for direct context mapping. + Refactored chat demo and upgraded prototype.js + Continuation cleanup + Fixed unraw decoding of query string + Fixed dispatch of wrapped requests. + Fixed double flush of short content. + Added request log. + Added CGI servlet. + Force a tempdir to be set. + Force jasper scratch dir. + fixed setLocale bug sf1426940 + Added TLD tag listener handling. jetty-6.0.0beta8 - 24 January 2006 + fixed dispatch of new session problem. sf:1407090 + reinstated rfc2616 test harness + Handle pipeline requests without hangs + Removed queue from thread pool. + improved caching of content types + fixed bug in overloaded write method on HttpConnection (reported against Tapestry4.0) + hid org.apache.commons.logging and org.slf4j packages from webapp + maven-jetty6-plugin stopped transitive inclusion of log4j and commons-logging from commons-el for jasper + patch to remove spurious ; in HttpFields + improve buffer return mechanism. + conveniance addHandler removeHandler methods + maven-jetty6-plugin: ensure compile is done before invoking jetty + maven-jetty6-plugin: support all types of artifact dependencies jetty-6.0.0Beta7 + Fixed infinite loop with chunk handling + Faster header name lookup + removed singleton Container + reduced info verbosity + null dispatch attributes not in names + maven-jetty6-plugin added tmpDirectory property + maven-jetty6-plugin stopped throwing an error if there is no target/classes directory jetty-6.0.0Beta6 + Fixed issue with blocking reads + Fixed issue with unknown headers + optimizations jetty-6.0.0Beta5 + Moved to SVN + Fixed writer char[] creations + Added management module for mbeans jetty-6.0.0Beta4 + System property support in plugin + CVE-2006-2758 Fixed JSP visibility security issue. + Improved jetty-web.xml access to org.mortbay classes. + Jasper 5.5.12 jetty-6.0.0Beta3 + Fixed error in block read + Named dispatch. + Fixed classloader issue with server classes jetty-6.0.0Beta2 + merged util jar back into jetty jar + Simpler continuation API + loosely coupled with JSP servlet + loosely coupled with SLF4J + Improved reuse of HttpField values and cookies. + Improved buffer return jetty-6.0.0Beta1 + Servlet 2.5 API + SSL connector + maven2 plugin + shutdown hook + refactored start/stop + Implemented all listeners + Error pages + Virtual hosts + Multiple select sets jetty-6.0.0Beta0 + Maven 2 build + Dispatcher parameters + UTF-8 encoding for URLs + Fixed blocking read jetty-6.0.0APLPA3 + Added demo for Continuations + Jasper and associated libraries. jetty-6.0.0ALPHA2 + Continuations - way cool way to suspend a request and retry later. + Dispatchers + Security jetty-6.0.0ALPHA1 + Filters + web.xml handling jetty-6.0.0ALPHA0 + Totally rearchitected and rebuilt, so 10 years of cruft could be removed! + Improved "dependancy injection" and "inversion of control" design of components + Improved "interceptor" design of handlers + Smart split buffer design allows large buffers to only be allocated to active connections. The resulting memory savings allow very large buffers to be used, which increases the chance of efficient asynchronous flushing and of avoiding chunking. + Optional use of NIO Buffering so that efficient direct buffers and memory mapped files can be used. + Optional use of NIO non-blocking scheduling so that threads are not allocated per connection. + Optional use of NIO gather writes, so that for example a HTTP header and a memory mapped + file may be sent as sent is a single operation. + Missing Security + Missing Request Dispatchers + Missing web.xml based configuration + Missing war support jetty-5.1.11RC0 - 05 April 2006 + stop JDBCUserRealm forcing all credentials to be String + force close with shutdownOutput for win32 + NPE protection if desirable client certificates + Added provider support to SslListener + logging improvements for servlet and runtime exceptions + Fixed AJP handling of ;jsessionid. + improved contentType param handling jetty-5.1.10 - 05 January 2006 + Fixed path aliasing with // on windows. + Fix for AJP13 with multiple headers + Fix for AJP13 with encoded path + Remove null dispatch attributes from getAttributeNames + Put POST content default back to iso_8859_1. GET is UTF-8 still jetty-4.2.25 - 04 January 2006 + Fixed aliasing of // for win32 jetty-5.1.9 - 07 December 2005 + Fixed wantClientAuth(false) overriding netClientAuth(true) jetty-6.0.0betaX + See http://jetty.mortbay.org/jetty6 for 6.0 releases jetty-5.1.8 - 07 December 2005 + Fixed space in URL issued created in 5.1.6 jetty-5.1.7 - 07 December 2005 jetty-5.1.7rc0 - 06 December 2005 + improved server stats + char encoding for MultiPartRequest + fixed merging of POST params in dispatch query string. + protect from NPE in dispatcher getValues + Updated to 2.6.2 xerces + JSP file servlet mappings copy JspServlet init params. + Prefix servlet context logs with org.mortbay.jetty.context + better support for URI character encodings + use commons logging jar instead of api jar. jetty-5.1.6 - 18 November 2005 + CVE-2006-2758 Fixed JSP visibility security issue. + Improved jetty-web.xml access to org.mortbay classes. jetty-5.1.5 - 10 November 2005 + Improved shutdown hook + Improved URL Decoding + Improved mapping of JSP files. jetty-5.1.5rc2 - 07 October 2005 + Reverted dispatcher params to RI rather than spec behaviour. + ProxyHandler can handle chained proxies + unsynchronized ContextLoader + ReFixed merge of Dispatcher params + public ServerMBean constructor + UTF-8 encoding for URLs + Response.setLocale will set locale even if getWriter called. jetty-5.1.5rc1 - 23 August 2005 + upgraded to commons logging 1.0.4 + Release commons logging factories when stopping context. + Fixed illegal state with chunks and 100 continue - Tony Seebregts + Fixed PKCS12Import input string method + Fixed merge of Dispatcher parameters + Encoded full path in ResourceHandler directory listing + handle extra params after charset in header + Fixed 100-continues with chunking and early commit jetty-5.1.5rc0 - 16 August 2005 + Fixed component remove memory leak for stop/start cycles + Facade over commons LogFactory so that discovery may be avoided. + Applied ciphersuite patch from tonyj + Authenticators use servlet sendError + CGI sets SCRIPT_FILENAME + HttpTunnel timeout + NPE protection for double stop in ThreadedServer + Expect continues only sent if input is read. jetty-5.1.4 - 05 June 2005 + Fixed FTP close issue. + setup MX4J with JDK1.5 in start.config + set classloader during webapp doStop + NPE protection in ThreadedServer + ModelMBean handles null signatures + Change JAAS impl to be more flexible on finding roles jetty-5.1.4rc0 - 19 April 2005 + ServletHttpContext correctly calls super.doStop. + HttpServer delegates component handling to Container. + Allow ServletHandler in normal HttpContext again. + Stop start.jar putting current directory on classpath. + More protection from null classloaders. + Turn off web.xml validation for JBoss. jetty-5.1.3 - 07 April 2005 + Some minor code janitorial services jetty-4.2.24 - 07 April 2005 jetty-5.1.3rc4 - 31 March 2005 + Moved servlet request wrapping to enterContextScope for geronimo security + refixed / mapping for filters + Allow XmlConfiguration to start with no object. + updated to mx4j 3.0.1 + rework InitialContextFactory to use static 'default' namespace + make java:comp/env immutable for webapps as per J2EE spec jetty-5.1.3rc3 - 20 March 2005 + removed accidental enablement of DEBUG for JettyPlus jndi in log4j.properties + fixed "No getter or setter found" mbean errors jetty-5.1.3rc2 - 16 March 2005 + Updated JSR154Filter for ERROR dispatch + Fixed context to _context refactory error jetty-5.1.3rc1 - 13 March 2005 + Fixed typo in context-param handling. + update to demo site look and feel. + Fixed principal naming in FormAuthenticator + JettyPlus updated to JOTM 2.0.5, XAPool 1.4.2 jetty-4.2.24rc1 + Fixed principal naming in FormAuthenticator jetty-5.1.3rc0 - 08 March 2005 + Flush filter chain caches on servlet/filter change + Fixed rollover filename format bug + Fixed JSR154 error dispatch with explicit pass of type. + Allow system and server classes to be configured for context loader. + IOException if EOF read during chunk. + Fixed HTAccess crypt salt handling. + Added simple xpath support to XmlParser + Added TagLibConfiguration to search for listeners in TLDs. + Added SslListener for 1.4 JSSE API. + Fixed moderate load preventing ThreadPool shrinking. + Added logCookie and logLatency support to NCSARequestLog + Added new JAAS callback to allow extra login form fields in authentication jetty-4.2.24rc0 - 08 March 2005 + Back ported Jetty 5 ThreadedServer and ThreadPool + Added logCookie and logLatency support to NCSARequestLog jetty-5.1.2 - 18 January 2005 + Added id and ref support to XmlConfiguration + Cleaned up AbstractSessionManager synchronization. + Fixed potential concurrent login problem with JAAS + Apply patch #1103953 jetty-4.2.23 - 16 January 2005 + Cleaned up AbstractSessionManager synchronization. + Fixed potential concurrent login problem with JAAS jetty-5.1.2pre0 - 22 December 2004 + Fixed case of Cookie parameters + Support Secure and HttpOnly in session cookies + Modified useRequestedID handling to only use IDs from other contexts + Added global invalidation to AbstractSessionManager + UnavailableException handling from handle + Fixed suffix filters jetty-4.2.23RC0 - 17 December 2004 + LineInput handles readers with small internal buffer + Added LogStream to capture stderr and stdout to logging + Support Secure and HttpOnly in session cookies + Build unsealed jars jetty-5.1.1 - 01 December 2004 jetty-5.1.1RC1 + Some minor findbugs code cleanups + Made more WebApplicationHandle configuration methods public. + Fixed ordering of filters with multiple interleaved mappings. + Allow double // within URIs + Applied patch for MD5 hashed credentials for MD5 jetty-5.1.1RC0 - 17 November 2004 + fix for adding recognized EventListeners + fix commons logging imports to IbmJsseListener + added new contributed shell start/stop script + excluded ErrorPageHandler from standard build in extra/jdk1.2 build jetty-5.1.0 - 14 November 2004 jetty-5.1.RC1 - 24 October 2004 + Allow JSSE listener to be just confidential or just integral. + Fixed NPE for null contenttype + improved clean targets + when committed setHeader is a noop rather than IllegalStateException + Partially flush writers on every write so content length can be detected. + Build unsealed jars + default / mapping does not apply to Filters + many minor cleanups suggested from figbug utility + Allow multiple accepting threads jetty-5.1.RC0 - 11 October 2004 + Fixed many minor issues from J2EE 1.4 TCK testing See sf.net bugs 1031520 - 1032205 + Refactored, simplified and optimized HttpOutputStream + LineInput handles readers with small internal buffer + Added LogStream to capture stderr and stdout to logging + Added filter chain cache + Added JSR77 servlet statistic support + Refactored webapp context configurations + Added LifeCycle events and generic container. + Upgraded to ant-1.6 for jasper + Fixed HTAccessHandler + JBoss 4.0.0 support jetty-5.0.0 - 10 September 2004 jetty-5.0.RC4 - 05 September 2004 + Fixed configuration of URL alias checking + JettyJBoss: Use realm-name from web.xml if present, otherwise use security-domain from jboss-web.xml jetty-5.0.RC3 - 28 August 2004 + DIGEST auth handles qop, stale and maxNonceAge. + Less verbose warning for non validating xml parser. + fixed jaas logout for jetty-jboss + fixed deployment of ejb-link elements in web.xml with jboss + Update to jasper 5.0.27 + Added parameters for acceptQueueSize and lowResources level. + Changed default URI encoding to UTF-8 + Fixes to work with java 1.5 + JettyPlus upgrade to XAPool 1.3.3. and HSQLDB 1.7.2 + JettyPlus addition of pluggable DataSources + Always say close for HTTP/1.0 non keep alive. jetty-4.2.22 + fixed jaas logout for jetty-jboss integration + fixed deployment of ejb-link elements in web.xml for jboss + Added parameters for acceptQueueSize and lowResources level. jetty-5.0.RC2 - 02 July 2004 + Fixed DIGEST challenge delimiters + HTAccess calls UnixCrypt correctly + integrated jetty-jboss with jboss-3.2.4 + Error dispatchers are always GET requests. + OPTIONS works for all URLs on default servlet + add JMX support for JettyPlus + add listing of java:comp/env for webapp with JMX + make choice of override of JNDI ENC entries: config.xml or web.xml + Default servlet may use only pathInfo for resource + Fixed session leak in j2ee + Fixed no-role security constraint combination. + Fix to use runas roles during servlet init and destroy + Fixed JAAS logout + HttpContext sendError for authentication errors jetty-4.2.21 - 02 July 2004 + integrated jetty-jboss with jboss-3.2.4 + add JMX support for JettyPlus + add listing of java:comp/env for webapp with JMX + make choice of override of JNDI ENC entries: config.xml or web.xml + Fixed JAAS logout jetty-5.0.RC1 - 24 May 2004 + Changed to apache 2.0 license + added extra/etc/start-plus.config to set up main.class for jettyplus + maxFormContentLength may be unlimited with <0 value + Fixed HTTP tunnel timeout setting. + Improved handling of exception from servlet init. + FORM auth redirects to context on a re-auth + Handle multiple virutal hosts from JBoss 3.2.4RC2 jetty-4.2.20 - 22 May 2004 + maxFormContentLength may be unlimited with <0 value + Fixed HTTP tunnel timeout setting. + Improved handling of exception from servlet init. + FORM auth redirects to context on a re-auth jetty-5.0.0RC0 - 07 April 2004 + Updated JettyPlus to JOTM 1.4.3 (carol-1.5.2, xapool-1.3.1) + ServletContext attributes wrap HttpContext attributes. + Factored out XML based config from WebApplicationContext + Improved RequestLog performance + Fixed j2se 1.3 problem with HttpFields + Default servlet respectes servlet path + Fixed setCharacterEncoding for parameters. + Fixed DOS problem + Worked around bad jboss URL handler in XMLParser + Forced close of connections over stop/start + ProxiedFor field support added to NCSARequestLog + Fixed Default servlet for non empty servlet paths + Updated mx4j to V2 + Updated jasper to 5.0.19 + Changed dist naming convention to lowercase jetty-4.2.20RC0 - 07 April 2004 + Worked around bad jboss URL handler in XMLParser + Forced close of connections over stop/start + HttpFields protected headers + ProxiedFor field support added to NCSARequestLog + Fixed Default servlet for non empty servlet paths + Changed dist naming convention to lowercase jetty-4.2.19 - 19 March 2004 + Fixed DOS attack problem jetty-5.0.beta2 - 12 February 2004 + Added skeleton JMX MBean for jetty plus + Fixed HEAD with empty chunk bug. + Fixed jetty.home/work handling + Fixed setDate thread safety + Fixed SessionManager init + Improved low thread handling + FileResource better handles non sun JVM + Monitor closes socket before exit + Updated to Japser 5.0.16 + RequestDispatcher uses request encoding for query params + Fixed busy loop in threadpool run + Reorganized ServletHolder init + Added log4j context repository to jettyplus + NPE guard for no-listener junit deployment + Added experimental NIO listeners again. + fixed filter dispatch configuration. + fixed lazy authentication with FORMs jetty-4.2.18 - 01 March 2004 + Added log4j context repository to jettyplus + NPE guard for no-listener junit deployment + Improved log performance + Fixed j2se 1.3 problem with HttpFields + Suppress some more IOExceptions + Default servlet respectes servlet path jetty-4.2.17 - 01 February 2004 + Fixed busy loop in threadpool run + Reorganized ServletHolder init jetty-4.2.16 - 30 January 2004 + Fixed setDate multi-cpu race + Improved low thread handling + FileResource better handles non sun JVM + Fixed HttpTunnel for JDK 1.2 + Monitor closes socket before exit + RequestDispatcher uses request encoding for query params + Update jasper to 4.1.29 jetty-5.0.beta1 - 24 December 2003 + SecurityConstraints not reset by stop() on custom context + Fixed UnixCrypt handling in HTAccessHandler + Added patch for JBoss realm single sign on + Reorganized FAQ + Env variables for CGI + Removed support for old JBoss clustering jetty-4.2.15 - 24 December 2003 + SecurityConstraints not reset by stop() on custom context + Fixed UnixCrypt handling in HTAccessHandler + Added patch for JBoss realm single sign on + Environment variables for CGI + Removed support for old JBoss clustering jetty-5.0.beta0 - 22 November 2003 + Removed support for HTTP trailers + PathMap uses own Map.Entry impl for IBM JVMs + Use ${jetty.home}/work or WEB-INF/work for temp directories if present + Protect ThreadPool.run() from interrupted exceptions + Added org.mortbay.http.ErrorHandler for error pages. + Fixed init race in HttpFields cache + Allow per listener handlers + Added MsieSslHandler to handle browsers that don't grok persistent SSL (msie 5) + Respect content length when decoding form content. + JBoss integration uses writer rather than stream for XML config handling + Expire pages that contain set-cookie as per RFC2109 recommendation + Updated jasper to 5.0.14beta + Removed the CMR/CMP distributed session implementation jetty-4.2.15rc0 - 22 November 2003 + PathMap uses own Map.Entry impl for IBM JVMs + Race in HttpFields cache + Use ${jetty.home}/work or WEB-INF/work for temp directories if present + Protect ThreadPool.run() from interrupted exceptions + Added org.mortbay.http.ErrorHandler for error pages. + JsseListener checks UserAgent for browsers that can't grok persistent SSL (msie5) + Removed the CMR/CMP distributed session implementation jetty-4.2.14 - 04 November 2003 + respect content length when decoding form content. + JBoss integration uses writer rather than stream for XML config handling + Fixed NPE in SSO + Expire pages that contain set-cookie as per RFC2109 recommendation jetty-5.0.alpha3 - 19 October 2003 + Reworked Dispatcher to better support cross context sessions. + Use File.toURI().toURL() when jdk 1.2 alternative is available. + Priority added to ThreadPool + replaced win32 service with http://wrapper.tanukisoftware.org + FileClassPath derived from walk of classloader hierarchy. + Implemented security constraint combinations + Set TransactionManager on JettyPlus datasources and pools + Fixed null pointer if no sevices configured for JettyPlus + Updated jasper and examples to 5.0.12 + Lazy authentication if no auth constraint. + Restore servlet handler after dispatch + Allow customization of HttpConnections + Failed requests excluded from duration stats jetty-4.2.14RC1 - 19 October 2003 + Reworked Dispatcher to better support cross context sessions. + Added UserRealm.logout and arrange for form auth + Allow customization of HttpConnections + Failed requests excluded from jetty-4.2.14RC0 - 07 October 2003 + Correctly setup context classloader in cross context dispatch. + Put a semi busy loop into proxy tunnels for IE problems + Fixed handling of error pages for IO and Servlet exceptions + updated extra/j2ee to jboss 3.2.1+ + Use File.toURI().toURL() when jdk 1.2 alternative is available. + cookie timestamps are in GMT + Priority on ThreadedServer + replaced win32 service with http://wrapper.tanukisoftware.org + Build fileclasspath from a walk of the classloaders + Set TransactionManager on JettyPlus datasources and pools + Fixed null pointer if no sevices configured for JettyPlus + Fixed comments with embedded double dashes on jettyplus.xml file jetty-5.0.alpha2 - 19 September 2003 + Use commons logging. + Use log4j if extra is present. + Improved JMX start. + Update jakarta examples + Correctly setup context classloader in cross context dispatch. + Turn off validation without non-xerces errors + minor doco updates. + moved mailing lists to sourceforge. + Put a semi busy loop into proxy tunnels for IE problems + MultipartRequest supports multi value headers. + XML entity resolution uses URLs not Resources + Implemented ServletRequestListeners as optional filter. + Moved error page mechanism to be webapp only. + Fixed error page handling of IO and Servlet exceptions. jetty-5.0.alpha1 - 12 August 2003 + Switched to mx4j + Improve combinations of Security Constraints + Implemented locale encoding mapping. + Synced with 4.2.12 + Updated to Jasper 5.0.7 + Server javadoc from war jetty-5.0.alpha0 - 16 July 2003 + Compiled against 2.4 servlet spec. + Implemented remote/local addr/port methods + Updated authentication so that a normal Principal is used. + updated to jasper 5.0.3 + Implemented setCharaterEncoding + Implemented filter-mapping element + Implemented Dispatcher forward attributes. jetty-4.2.12 - 12 August 2003 + Restore max inactive interval for session manager + Removed protection of org.mortbay.http attributes + Fixed parameter ordering for a forward request. + Fixed up HTAccessHandler + Improved error messages from ProxyHandler + Added missing S to some OPTIONS strings + Added open method to threaded server. + FORMAuthenticator does 403 with empty error page. + Fixed MIME types for chemicals + Padding for IE in RootNotFoundHandler jetty-4.2.11 - 12 July 2003 + Fixed race in servlet initialization code. + Cookie params all in lower case. + Simplified AJP13 connection handling. + Prevent AJP13 from reordering query. + Support separate Monitor class for start + Branched for Jetty 5 development. jetty-4.2.10 - 07 July 2003 + Updates to JettyPlus documentation + Updates to Jetty tutorial for start.jar, jmx etc jetty-4.2.10pre2 - 04 July 2003 + Improvement to JettyPlus config of datasources and connection pools + Addition of mail service for JettyPlus + Move to Service-based architecture for JettyPlus features + Re-implementation of JNDI + Many improvements in JettyPlus java:comp handling + Allow multiple security-role-ref elements per servlet. + Handle Proxy-Connection better + Cleaned up alias handling. + Confidential redirection includes query + handle multiple security role references + Fixed cookie handling for old cookies and safari + Restricted ports in ProxyHandler. + URI always encodes % + Session statistics + XmlConfiguration can get/set fields. jetty-4.2.10pre1 - 02 June 2003 + Fixed JSP code visibility problem introduced in Jetty-4.2.10pre0 + Added stop.jar + Added SSO implementation for FORM authentication. + WebApplicationContext does not reassign defaults descriptor value. + Fixed AJP13 protocol so that request/response header enums are correct. + Fixed form auth success redirect after retry, introduced in 4.2.9rc1 + Trace support is now optional (in AbstractHttpHandler). + Deprecated forced chunking. + Form authentication remembers URL over 403 + ProxyHandler has improved test for request content + Removed support of org.mortbay.http.User role. + Fixed problem with shared session for inter context dispatching. jetty-4.2.10pre0 - 05 May 2003 + Moved Log4JLogSink into JettyPlus + Added ability to override jetty startup class by using -Djetty.server on runline + Incorporate JettyPlus jotm etc into build. + Massive reorg of the CVS tree. + Incorporate jetty extra and plus into build + Integrate with JAAS + Apply the append flag of RolloverFileOutputStream constructor. + RolloverFileOutputStream manages Rollover thread. + New look and feel for www site. + Fixed table refs in JDBCUserRealm. + Allow params in form auth URLs + Updated to jasper jars from tomcat 4.1.24 + Allow query params in error page URL. + ProxyHandler checks black and white lists for Connect. + Merge multivalued parameters in dispatcher. + Fixed CRLF bug in MultiPartRequest + Warn if max form content size is reached. + getAuthType returns CLIENT_CERT instead of CLIENT-CERT. + getAuthType maps the HttpServletRequest final strings. + FORM Authentication is serializable for session distribution. jetty-4.2.9 - 19 March 2003 + Conditional headers check after /dir to /dir/ redirection. jetty-4.2.9rc2 - 16 March 2003 + Fixed build.xml for source release + Made rfc2068 PUT/POST Continues support optional. + Defaults descriptor has context classloader set. + Allow dispatch to j_security_check + Added X-Forwarded-For header in ProxyHandler + Updated included jmx jars jetty-4.2.9rc1 - 06 March 2003 + Work around URLClassloader not handling leading / + Dump servlet can load resources for testing now. + Added trust manager support to SunJsseListener. + Added support for client certs to AJP13. + Cleaned up includes + Removed checking for single valued headers. + Optional 2.4 behaviour for sessionDestroyed notification. + Stop proxy url from doing user interaction. + Turn request log buffering off by default. + Reduced default context cache sizes (Total 1MB file 100KB). + ProxyHandler has black and white host list. + Added requestlog to HttpContext. + Allow delegated creation of WebApplication derivations. + Check Data contraints before Auth constraints jetty-4.2.8_01 - 18 February 2003 + Patched first release of 4.2.8 with correct version number + Fixed CGI servlet to handle multiple headers. + Added a SetResponseHeadersHandler, can set P3P headers etc. + ProxyHandler can handle multiple cookies. + Fixed AdminServlet to handle changed getServletPath better. + Default servlet can have own resourceBase. + Rolled back SocketChannelListener to 4.2.5 version + Added option to resolve remote hostnames. Defaults to off. + Added MBeans for Servlets and Filters + Moved ProxyHandler to the src1.4 tree jetty-4.2.7 - 04 February 2003 + Upgraded to JSSE 1.0.3_01 to fix security problem. + Fixed proxy tunnel for non persistent connections. + Relative sendRedirect handles trailing / correctly. + Changed PathMap to conform to / getServletPath handling. jetty-4.2.6 - 24 January 2003 + Improved synchronization on AbstractSessionManager. + Allow AJP13 buffers to be resized. + Fixed LineInput problem with expanded buffers. + ClientCertAuthentication updates request. + Fixed rel sendRedirects for root context. + Added HttpContext.setHosts to restrict context by real interface. + Added MBeans for session managers + Improved SocketChannelListener contributed. + Added version to HttpServerMBean. jetty-4.2.5 - 14 January 2003 + Fixed pathParam bug for ;jsessionid + Don't process conditional headers and ranges for includes + Added Log4jSink in the contrib directory. + Fixed requestedSessionId null bug. jetty-4.2.4 - 04 January 2003 + Fixed stop/start handling of servlet context + Reuse empty LogSink slots. + HTAccessHandler checks realm as well as htpassword. + Clear context listeners after stop. + Clear context attributes after stop. + Use requestedSessionId as default session ID. + Added MBeans for handlers + Upgraded jasper to 4.1.18 jetty-4.2.4rc0 - 12 December 2002 + Simplified ThreadedServer + Use ThreadLocals for ByteArrayPool to avoid synchronization. + Use Version to reset HttpFields + Cheap clear for HttpFields + Fixed setBufferSize NPE. + Cleaned up some unused listener throws. + Handle chunked form data. + Allow empty host header. + Avoid optional 100 continues. + Limit form content size. + Handle = in param values. + Added HttpContext.flushCache + Configurable root context. + RootNotFoundHandler to help when no context found. + Update jasper to 4.1.16beta + Fixed dir listing from jars. + Dir listings in UTF8 + Character encoding handling for GET requests. + Removed container transfer encoding handling. + Improved setBufferSize handling + Code logs objects rather than strings. + Better access to session manager. + Fixed isSecure and getScheme for SSL over AJP13 + Improved ProxyHandler to the point is works well for non SSL. + Implemented RFC2817 CONNECT in ProxyHandler + Added gzip content encoding support to Default and ResourceHandler jetty-4.2.3 - 02 December 2002 + Removed aggressive threadpool shrinkage to avoid deadlock on SMP machines. + Fixed some typos + Added links to Jetty Powered page + Clean up of ThreadedServer.stop() + Updated bat scripts + Added PKCS12Import class to import PKCS12 key directly + removed old HttpContext.setDirAllowed() + added main() to org.mortbay.http.Version + Check form authentication config for leading / + Cleaner servlet stop to avoid extra synchronization on handle + org.mortbay.http.HttpContext.FileClassPathAttribute jetty-4.2.2 - 20 November 2002 + Fixed sendRedirect for non http URLS + Fixed URI query recycling for persistent connections + Fixed handling of empty headers + Added EOFException to reduce log verbosity on closed connections. + Avoided bad buffer status after closed connection. jetty-4.2.1 - 18 November 2002 + Fixed bad optimization in UrlEncoding + Re-enabled UrlEncoding test harnesses jetty-4.2.0 - 16 November 2002 + Fixed AJP13 buffer size. + Fixed remove listener bug. + Fixed include of Invoker servlet. + Restrict 304 responses to seconds time resolution. + Use IE date formatting for speed. + Removed jasper source and just include jars from 4.1.12 + Worked around JVM1.3 bug for JSPs + Lowercase jsessionid for URLs only. + Made NCSARequestLog easier to extend. + Added definitions for RFC2518 WebDav response codes. + Removed remaining non portable getBytes() calls + Added upload demo to dump servlet. + Many more optimizations. jetty-4.1.4 - 16 November 2002 + Fixed ContextLoader parent delegation bug + Fixed remove SocketListener bug. + Fixed Invoker servlet for RD.include + Use IE date formatting for last-modified efficiency + Last modified handling uses second resolution. + Made NCSARequestLog simpler to extend. jetty-4.2.0rc1 - 02 November 2002 + Support default mime mapping defined by * + Recycling of HttpFields class. + Renamed Filter application methods. + Fixed firstWrite after commit. + Fixed ContextLoader parent delegation bug. + Fixed problem setting the size of chunked buffers. + Removed unused Servlet and Servlet-Engine headers. + Fixed servletpath on invoker for named servlets. + Fixed directory resource bug in JarFileResource. + Improved handling of 2 byte encoded characters within forms. jetty-4.2.0rc0 - 24 October 2002 + Greg's birthday release! + Added embedded iso8859 writer to HttpOutputStream. + Removed duplicate classes from jar + Fixed RolloverFileOutputStream without date. + Fixed SessionManager initialization + Added authenticator to admin.xml + Fixed Session timeout NPE. jetty-4.1.3 - 24 October 2002 + Fixed RolloverFileOutputStream without date. + Fixed SessionManager initialization + Added authenticator to admin.xml + Fixed Session timeout NPE. jetty-4.0.6 - 24 October 2002 + Clear interrupted status in ThreadPool + Fixed forward query string handling + fixed forward attribute handling for jsp-file servlets + Fixed setCharacterEncoding to work with getReader + Fixed handling of relative sendRedirect after forward. + Fixed virtual hosts temp directories. jetty-4.2.0beta0 - 13 October 2002 + New ThreadPool implementation. + New Buffering implementation. + New AJP13 implementation. + Removed Dispatcher dependancy on ServletHttpContext + getNamedDispatcher(null) returns containers default servlet. + unquote charset in content type + Stop/Start filters in declaration order. + Use "standard" names for default,jsp & invoker servlets. + Fixed caching of directories to avoid shared buffers. + Fixed bad log dir detection + Fix Session invalidation bug + Build without jmx + 404 instead of 403 for WEB-INF requests + FORM authentication sets 403 error page + Allow %3B encoded ; in URLs + Allow anonymous realm + Update jasper to 4.1.12 tag jetty-4.1.2 - 13 October 2002 + Some AJP13 optimizations. + getNamedDispatcher(null) returns containers default servlet. + unquote charset in content type + Stop/Start filters in declaration order. + Use "standard" names for default,jsp & invoker servlets. + Fixed caching of directories to avoid shared buffers. + Fixed bad log dir detection + Fix Session invalidation bug + Build without jmx + 404 instead of 403 for WEB-INF requests + FORM authentication sets 403 error page + Allow %3B encoded ; in URLs + Allow anonymous realm + Update jasper to 4.1.12 tag jetty-4.1.1 - 30 September 2002 + Fixed client scripting vulnerability with jasper2. + Merged LimitedNCSARequestLog into NCSARequestLog + Fixed space in resource name handling for jdk1.4 + Moved launcher/src to src/org/mortbay/start + Fixed infinite recursion in JDBCUserRealm + Avoid setting sotimeout for optimization. + String comparison of If-Modified-Since headers. + Touch files when expanding jars + Deprecated maxReadTime. + Cache directory listings. jetty-4.1.0 - 22 September 2002 + Fixed CGI+windows security hole. + Fixed AJP13 handling of mod_jk loadbalancing. + Stop servlets in opposite order to start. + NCSARequest log buffered default + WEB-INF/classes before WEB-INF/lib + Sorted directory listings. + Handle unremovable tempdir. + Context Initparams to control session cookie domain, path and age. + ClientCertAuthenticator protected from null subjectDN + Added LimitedNCSARequestLog + Use javac -target 1.2 for normal classes jetty-4.1.0RC6 - 14 September 2002 + Don't URL encode FileURLS. + Improved HashUserRealm doco + FormAuthenticator uses normal redirections now. + Encode URLs of Authentication redirections. + Added logon.jsp for no cookie form authentication. + Extended Session API to pass request for jvmRoute handling + Fixed problem with AJP 304 responses. + Improved look and feel of demo + Cleaned up old debug. + Added redirect to welcome file option. jetty-4.1.0RC5 - 08 September 2002 + AJP13Listener caught up with HttpConnection changes. + Added commandPrefix init param to CGI + More cleanup in ThreadPool for idle death. + Improved errors for misconfigured realms. + Implemented security-role-ref for isUserInRole. jetty-4.1.0RC4 - 30 August 2002 + Included IbmJsseListener in the contrib directory. + Updated jasper2 to 4.1.10 tag. + Reverted to 302 for all redirections as all clients do not understand 303 + Created statsLock sync objects to avoid deadlock when stopping. jetty-4.1.0RC3 - 28 August 2002 + Fixed security problem for suffix matching with trailing "/" + addWebApplications encodes paths to allow for spaces in file names. + Improved handling of PUT,DELETE & MOVE. + Improved handling of path encoding in Resources for bad JVMs + Added buffering to request log + Created and integrated the Jetty Launcher + Made Resource canonicalize it's base path for directories + Allow WebApplicationHandler to be used with other handlers. + Added defaults descriptor to addWebApplications. + Allow FORM auth pages to be within security constraint. jetty-4.1.0RC2 - 20 August 2002 + Conveninace setClassLoaderJava2Compliant method. + Clear interrupted status in ThreadPool + Fixed HttpFields cache overflow + Improved ByteArrayPool to handle multiple sizes. + Added HttpListener.bufferReserve + Use system line separator for log files. + Updated to Jasper2 (4_1_9 tag) + Build ant, src and zip versions with the release jetty-4.1.0RC1 - 11 August 2002 + Fixed forward query string handling + Fixed setCharacterEncoding to work with getReader + Fixed getContext to use canonical contextPathSpec + Improved the return codes for PUT + Made HttpServer serializable + Updated international URI doco + Updated jasper to CVS snapshot 200208011920 + Fixed forward to jsp-file servlet + Fixed handling of relative sendRedirect after forward. jetty-4.1.0RC0 - 31 July 2002 + Fixed getRealPath for packed war files. + Changed URI default charset back to ISO_8859_1 + Restructured Password into Password and Credentials + Added DigestAuthenticator + Added link to a Jetty page in Korean. + Added ExpiryHandler which can set a default Expires header. jetty-4.0.5 - 31 July 2002 + Fixed getRealPath for packed war files. + Reversed order of ServletContextListener.contextDestroyed calls + Fixed getRequestURI for RD.forward to return new URI. jetty-4.1.B1 - 19 July 2002 + Updated mini.http.jar target + CGI Servlet, pass all HTTP headers through. + CGI Servlet, catch and report program invocation failure status. + CGI Servlet, fixed suffix mapping problem. + CGI Servlet, set working directory for exec + Support HTTP/0.9 requests again + Reversed order of ServletContextListener.contextDestroyed calls + Moved dynamic servlet handling to Invoker servlet. + Moved webapp resource handling to Default servlet. + Sessions create attribute map lazily. + Added PUT,DELETE,MOVE support to webapps. + Added 2.4 Filter dispatching support. jetty-3.1.9 - 15 July 2002 + Allow doHead requests to be forwarded. + Fixed race in ThreadPool for minThreads <= CPUs jetty-4.1.B0 - 13 July 2002 + Added work around of JDK1.4 bug with NIO listener + Moved 3rd party jars to $JETTY_HOME/ext + Fixed ThreadPool bug when minThreads <= CPUs + close rather than disable stream after forward + Allow filter init to access servlet context methods. + Keep notFoundContext out of context mapping lists. + mod_jk FAQ + Fixed close problem with load balancer. + Stopped RD.includes closing response. + RD.forward changes getRequestURI. + NCSARequestLog can log to stderr jetty-4.1.D2 - 24 June 2002 + Support trusted external authenticators. + Moved jmx classes from JettyExtra to here. + Set contextloader during webapplicationcontext.start + Added AJP13 listener for apache integration. + Fixed ChunkableOutputStream close propagation + Better recycling of HttpRequests. + Protect session.getAttributeNames from concurrent modifications. + Allow comma separated cookies and headers + Back out Don't chunk 30x empty responses. + Conditional header tested against welcome file not directory. + Improved ThreadedServer stopping on bad networks + Use ThreadLocals to avoid unwrapping in Dispatcher. jetty-4.0.4 - 23 June 2002 + Back out change: Don't chunk 30x empty responses. + Conditional header tested against welcome file not directory. + Improved ThreadedServer stopping on bad networks jetty-4.0.3 - 20 June 2002 + WebapplicationContext.start sets context loader + Fixed close propagation of on-chunked output streams + Force security disassociation. + Better recycling of HttpRequests. + Protect session.getAttributeNames from concurrent modifications. + Allow session manager to be initialized when set. + Fixed japanese locale + Allow comma separated cookies and headers jetty-4.1.D1 - 08 June 2002 + Recycle servlet requests and responses + Added simple buffer pool. + Reworked output buffering to keep constant sized buffers. + Don't chunk 30x empty responses. + Fixed "" contextPaths in Dispatcher. + Removed race for the starting of session scavaging + Fixed /foo/../bar// bug in canonical path. + Merged ResourceBase and SecurityBase into HttpContext jetty-4.0.2 - 06 June 2002 + Fixed web.dtd references. + Fixed handler/context start order. + Added OptimizeIt plug + Fixed /foo/../bar// bug in canonical path. + Don't chunk 30x empty responses. + Fixed "" contextPaths in Dispatcher. + Removed race for the starting of session scavaging jetty-3.1.8 - 06 June 2002 + Made SecurityConstraint.addRole() require authentication. + Fixed singled threaded dynamic servlets + Fixed no slash context redirection. + Fixed /foo/../bar// bug in canonical path. jetty-4.1.D0 - 05 June 2002 + The 4.1 Series started looking for even more performance within the 2.3 specification. + Removed the HttpMessage facade mechanism + BRAND NEW WebApplicationHandler & WebApplicationContext + Added TypeUtil to reduce Integer creation. + General clean up of the API for for MBean getters/setters. + Experimental CLIENT-CERT Authenticator + Restructured ResourceHandler into ResourceBase + Fixed web.dtd references. + Fixed handler/context start order. + Added OptimizeIt plug. jetty-4.0.1 - 22 May 2002 + Fixed contextclassloader on ServletContextEvents. + Support graceful stopping of context and server. + Fixed "null" return from getRealPath + OutputStreamLogSink config improvements + Updated jasper to 16 May snapshot jetty-4.0.1RC2 - 14 May 2002 + Better error for jre1.3 with 1.4 classes + Cleaned up RD query string regeneration. + 3DES Keylength was being reported as 0. Now reports 168 bits. + Implemented the run-as servlet tag. + Added confidential and integral redirections to HttpListener + Fixed ServletResponse.reset() to resetBuffer. jetty-4.0.1RC1 - 29 April 2002 + Improved flushing of chunked responses + Better handling if no realm configured. + Expand ByteBuffer full limit with capacity. + Fixed double filtering of welcome files. + Fixed FORM authentication auth of login page bug. + Fixed setTempDirectory creation bug + Avoid flushes during RequestDispatcher.includes jetty-4.0.1RC0 - 18 April 2002 + Updated Jasper to CVS snapshot from Apr 18 18:50:59 BST 2002 + Pass pathParams via welcome file forward for jsessionid + Extended facade interfaces to HttpResponse.sendError + Moved basic auth handling to HttpRequest + AbstractSessionManager sets contextClassLoader for scavanging + Set thread context classloader for webapp load-on-startup inits + Added extract arg to addWebApplications + Fixed delayed response bug: Stopped HttpConnection consuming input from timedout connection. + DTD allows static "Get" and "Set" methods to be invoked. jetty-4.0.0 - 22 March 2002 + Updated tutorial configure version + Added IPAddressHandler for IP restrictions + Updated contributors. + Minor documentation updates. + Jetty.sh cygwin support jetty-4.0.RC3 - 20 March 2002 + Fixed ZZZ offset format to +/-HHMM + Updated history + JDBCUserRealm instantiates JDBC driver + ContextInitialized notified before load-on-startup servlets. + Suppress WriterOutputStream warning. + Changed html attribute order for mozilla quirk. jetty-4.0.RC2 - 12 March 2002 + Fixed security constraint problem with // + Fixed version for String XmlConfigurations + Fixed empty referrer in NCSA log. + Dont try to extract directories + Added experimental nio SocketChannelListener + Added skeleton load balancer + Fixed column name in JDBCUserRealm + Remove last of the Class.forName calls. + Removed redundant sessionID check. + Security FAQ + Disabled the Password EXEC mechanism by default jetty-3.1.7 - 12 March 2002 + Fixed security problem with constraints being bypassed with // in URLs jetty-4.0.RC1 - 06 March 2002 + Added ContentEncodingHandler for compression. + Fixed filter vs forward bug. + Improved efficiency of quality list handling + Simplified filter API to chunkable streams + XmlParser is validating by default. use o.m.x.XmlParser.NotValidating property to change. + contextDestroyed event sent before destruction. + Minor changes to make HttpServer work on J2ME CVM + Warn if jdk 1.4 classes used on JVM <1.4 + WebApplication will use ContextLoader even without WEB-INF directory. + FileResource depends less on FilePermissions. + Call response.flushBuffer after service to flush wrappers. + Empty suffix for temp directory. + Contributors list as an image to prevent SPAM! + Fixed recursive DEBUG loop in Logging. + Updated jetty.sh to always respect arguments. jetty-3.1.6 - 28 February 2002 + Implemented 2.3 clarifications to security constraint semantics PLEASE REVIEW YOUR SECURITY CONSTRAINTS (see README). + Empty suffix for temp directory. + Fixed HttpFields remove bug + Set Listeners default scheme + LineInput can handle any sized marks + HttpResponse.sendError makes a better attempt at finding an error page. + Dispatcher.forward dispatches directly to ServletHolder to avoid premature exception handling. jetty-4.0.B2 - 25 February 2002 + Minor Jasper updates + Improve handling of unknown URL protocols. + Improved default jetty.xml + Adjust servlet facades for welcome redirection + User / mapping rather than /* for servlet requests to static content + Accept jetty-web.xml or web-jetty.xml in WEB-INF + Added optional JDK 1.4 src tree + o.m.u.Frame uses JDK1.4 stack frame handling + Added LoggerLogSink to direct Jetty Logs to JDK1.4 Log. + Start ServletHandler as part of the FilterHandler start. + Simplified addWebApplication + Added String constructor to XmlConfiguration. + Added org.mortbay.http.JDBCUserRealm + Init classloader for JspServlet + Slightly more agressive eating unused input from non persistent connection. jetty-4.0.B1 - 13 February 2002 + WriterOutputStream so JSPs can include static resources. + Suppress error only for IOExceptions not derivitives. + HttpConnection always eats unused bodies + Merged HttpMessage and Message + LineInput waits for LF after CF if seen CRLF before. + Added setClassLoader and moved getFileClassPath to HttpContext + Updated examples webapp from tomcat + getRequestURI returns encoded path + Servlet request destined for static content returns paths as default servlet jetty-4.0.B0 - 04 February 2002 + Implemented 2.3 security constraint semantics PLEASE REVIEW YOUR SECURITY CONSTRAINTS (see README). + Stop and remove NotFound context for HttpServer + HttpContext destroy + Release process builds JettyExtra + Welcome files may be relative + Fixed HttpFields remove bug + Added Array element to XMLConfiguration + Allow listener schemes to be set. + Added index links to tutorial + Renamed getHttpServers and added setAnonymous + Updated crimson to 1.1.3 + Added hack for compat tests in watchdog for old tomcat stuff + Added AbstractSessionManager + Support Random Session IDs in HashSessionManager. + Common handling of TRACE + Updated tutorial and FAQ + Reduce object count and add hash width to StringMap + Factor out RolloverFileOutputStream from OutputStreamLogSink + Remove request logSink and replace with RequestLog using RolloverFileOutputStream + Handle special characters in resource file names better. + Welcome file dispatch sets requestURI. + Removed triggers from Code. jetty-4.0.D4 - 14 January 2002 + Prevent output after forward + Handle ServletRequestWrappers for Generic Servlets + Improved handling of UnavailableException + Extract WAR files to standard temp directory + URI uses UTF8 for % encodings. + Added BlueRibbon campaign. + RequestDispatcher uses cached resources for include + Improved HttpResponsse.sendError error page matching. + Fixed noaccess auth demo. + FORM auth caches UserPrincipal + Added isAuthenticated to UserPrincipal jetty-4.0.D3 - 31 December 2001 + Fixed cached filter wrapping. + Fixed getLocale again + Patch jasper to 20011229101000 + Removed limits on mark in LineInput. + Corrected name to HTTP_REFERER in CGI Servlet. + Fixed UrlEncoding for % + combination. + Generalized temp file handling + Fixed ContextLoader lib handling. + DateCache handles misses better. + HttpFields uses DateCache more. + Moved admin port to 8081 to avoid JBuilder + Made Frame members private and fixed test harness + cookies with maxAge==0 expire on 1 jan 1970 + setCookie always has equals jetty-3.1.5 - 11 December 2001 + setCookie always has equals for cookie value + cookies with maxage==0 expired 1 jan 1970 + Fixed formatting of redirectURLs for NS4.08 + Fixed ChunableInputStream.resetStream bug. + Ignore IO errors when trying to persist connections. + Allow POSTs to static resources. + stopJob/killStop in ThreadPool to improve stopping ThreadedServer on some platforms. + Branched at Jetty_3_1 jetty-4.0.D2 - 02 December 2001 + Removed most of the old doco, which needs to be rewritten and added again. + Restructured for demo and test hierarchies + Fixed formatting of redirect URLs. + Removed ForwardHandler. + Removed Demo.java (until updated). + Made the root context a webapplication. + Moved demo docroot/servlets to demo directory + added addWebApplications auto discovery + Disabled last forwarding by setPath() + Removed Request set methods (will be replaced) + New event model to decouple from beans container. + Better handling of charset in form encoding. + Allow POSTs to static resources. + Fixed ChunableInputStream.resetStream bug. + Ignore IO errors when trying to persist connections. + stopJob/killStop in ThreadPool to improve stopping ThreadedServer on some platforms. jetty-4.0.D1 - 14 November 2001 + Fixed ServletHandler with no servlets + Fixed bug with request dispatcher parameters + New ContextLoader implementation. + New Dispatcher implementation + Added Context and Session Event Handling + Added FilterHolder + Added FilterHandler + Changed HandlerContext to HttpContext + Simplified ServletHandler + Removed destroy methods + Simplified MultiMap jetty-4.0.D0 - 06 November 2001 + Branched from Jetty_3_1 == Jetty_3_1_4 + 2.3 Servlet API + 1.2 JSP API + Jasper from tomcat4 + Start SessionManager abstraction. + Added examples webapp from tomcat4 + Branched at Jetty_3_1 jetty-3.1.4 - 06 November 2001 + Added RequestLogFormat to allow extensible request logs. + Support the ZZZ timezone offset format in DateCache + HTAccessHandler made stricter on misconfiguration + Generate session unbind events on a context.stop() + Default PathMap separator changed to ":," + PathMap now ignores paths after ; or ? characters. + Remove old stuff from contrib that had been moved to extra + getRealPath accepts \ URI separator on platforms using \ file separator. jetty-3.1.3 - 26 October 2001 + Fix security problem with trailing special characters. Trailing %00 enabled JSP source to be viewed or other servlets to be bypassed. + Fixed several problems with external role authentication. Role authentication in JBoss was not working correctly and there were possible object leaks. The fix required an API change to UserPrinciple and UserRealm. + Allow a per context UserRealm instance. + Upgraded JSSE to 1.0.2 + Improved FORM auth handling of role failure. + Improved Jasper debug output. + Improved ThreadedServer timeout defaults + Fixed binary files in CVS + Fixed Virtual hosts to case insensitive. + PathMap spec separator changed from ',' to ':'. May be set with org.mortbay.http.PathMap.separators system property. + Correct dispatch to error pages with javax attributes set. jetty-3.1.2 - 13 October 2001 + Fixed double entry on PathMap.getMatches + Fixed servlet handling of non session url params. + Fixed attr handling in XmlParser.toString + Fixed request log date formatting + Fixed NotFoundHandler handling of unknown methods + Fixed FORM Authentication username. + Fixed authentication role handling in FORM auth. + FORM authentication passes query params. + Added short delay to shutdown hook for JVM bug. + Added ServletHandler.sessionCount() + Added run target to ant + Changed 304 responses for Opera browser. + Changed JSESSIONID to jsessionid + Log OK state after thread low warnings. + Changed unsatisfiable range warnings to debug. + Further improvements in handling of shutdown. jetty-3.1.1 - 27 September 2001 + Fixed jar manifest format - patched 28 Sep 2001 + Removed JDK 1.3 dependancy + Fixed ServletRequest.getLocale(). + Removed incorrect warning for WEB-INF/lib jar files. + Handle requestdispatcher during init. + Use lowercase tags in html package to be XHTML-like. + Correctly ignore auth-constraint descriptions. + Reduced verbosity of bad URL errors from IIS virus attacks jetty-3.1.0 - 21 September 2001 + Added long overdue Tutorial documentation. + Improved some other documentation. + Fix ResourceHandler cache invalidate. + Fix ServletResponse.setLocale() + Fix reuse of Resource + Fix Jetty.bat for spaces. + Fix .. handling in URI + Fix REFFERER in CGI + Fix FORM authentication on exact patterns + Fix flush on stop bug in logs. + Fix param reading on CGI servlet + New simplified jetty.bat + Improved closing of listeners. + Optimized List creation + Removed win32 service.exe + Added HandlerContext.registerHost jetty-3.1.rc9 - 02 September 2001 + Added bin/orgPackage.sh script to change package names. + Changed to org.mortbay domain names. + Form auth login and error pages relative to context path. + Fixed handling of rel form authentication URLs + Added support for Nonblocking listener. + Added lowResourcePersistTimeMs for more graceful degradation when we run out of threads. + Patched Jasper to 3.2.3. + Added handlerContext.setClassPaths + Fixed bug with non cookie sessions. + Format cookies in HttpFields. jetty-3.1.rc8 - 22 August 2001 + Support WEB-INF/web-jetty.xml configuration extension for webapps + Allow per context log files. + Updated sponsors page + Added HttpServer statistics + Don't add notfound context. + Many major and minor optimizations: + ISO8859 conversion + Buffer allocation + URI pathAdd + StringMap + URI canonicalPath + OutputStreamLogSink replaces WriterLogSink + Separation of URL params in HttpHandler API. + Fixed handling of default mime types + Allow contextpaths without leading / + Removed race from dynamic servlet initialization. jetty-3.1.rc7 - 09 August 2001 + Fix bug in sendRedirect for HTTP/1.1 + Added doco for Linux port redirection. + Don't persist connections if low on threads. + Added shutdown hooks to Jetty.Server to trap Ctl-C + Fixed bug with session ID generation. + Added FORM authentication. + Remove old context path specs + Added UML diagrams to Jetty architecture documentation. + Use Enumerations to reduce conversions for servlet API. + Optimized HttpField handling to reduce object creatiyon. + ServletRequest SSL attributes in line with 2.2 and 2.3 specs. + Dump Servlet displays cert chains + Fixed redirect handling by the CGI Servlet. + Fixed request.getPort for redirections from 80 + Added utility methods to ServletHandler for wrapping req/res pairs. + Added method handling to HTAccessHandler. + ServletResponse.sendRedirect puts URLs into absolute format. jetty-3.1.rc6 - 10 July 2001 + Avoid script vulnerability in error pages. + Close persistent HTTP/1.0 connections on missing Content-Length + Use exec for jetty.sh run + Improved SSL debugging information. + KeyPairTool can now load cert chains. + KeyPairTool is more robust to provider setup. + Fixed bug in B64Code. Optimised B64Code. + Added Client authentication to the JsseListener + Fixed a problem with Netscape and the acrobat plugin. + Improved debug output for IOExceptions. + Updated to JSSE-1.0.2, giving full strength crypto. + Win32 Service uses Jetty.Server instead of HttpServer. + Added getResource to HandleContext. + WebApps initialize resourceBase before start. + Fixed XmlParser to handle xerces1.3 OK + Added Get element to the XmlConfiguration class. + Added Static calls to the XmlConfiguration class. + Added debug and logging config example to demo.xml + Moved mime types and encodings to property bundles. + RequestDispatch.forward() uses normal HandlerContext.handle() path if possible. + Cleaned up destroy handling of listeners and contexts. + Removed getConfiguration from LifeCycleThread to avoid JMX clash. + Cleaned up Win32 Service server creation. + Moved gimp image files to Jetty3Extra jetty-3.1.rc5 - 01 May 2001 + Added build target for mini.jetty.jar - see README. + Major restructing of packages to separate servlet dependancies. c.m.XML - moved XML dependant classes from c.m.Util c.m.HTTP - No servlet or XML dependant classes: c.m.Jetty.Servlet - moved from c.m.HTTP.Handler.Servlet c.m.Servlet - received some servlet dependant classes from HTTP. + Added UnixCrypt support to c.m.U.Password + Added HTaccessHandler to authenitcate against apache .htaccess files. + Added query param handling to ForwardHandler + Added ServletHandler().setUsingCookies(). + Optimized canonical path calculations. + Warn and close connections if content-length is incorrectly set. + Request log contains bytes actually returned. + Fixed handling of empty responses at header commit. + Fixed ResourceHandler handling of ;JSESSIONID + Fixed forwarding to null pathInfo requests. + Fixed handling of multiple cookies. + Fixed EOF handling in MultiPartRequest. + Fixed sync of ThreadPool idleSet. + Fixed jetty.bat classpath problems. jetty-3.0.6 - 26 April 2001 + Fixed handling of empty responses at header commit. + Fixed ResourceHandler handling of ;JSESSIONID + Fixed forwarding to null pathInfo requests. + Fixed EOF handlding in MultiPartRequest. + Fixed sync of ThreadPool idleSet. + Load-on-startup the JspServlet so that precompiled servlets work. jetty-3.1.rc4 - 14 April 2001 + Include full versions of JAXP and Crimson + Added idle thread getter to ThreadPool. + Load-on-startup the JspServlet so that precompiled servlets work. + Removed stray debug println from the Frame class. jetty-3.0.5 - 14 April 2001 + Branched from 3.1 trunk to fix major errors + Fixed LineInput bug EOF + Improved flush ordering for forwarded requests. + Turned off range handling by default until bugs resolved + Don't chunk if content length is known. + fixed getLocales handling of quality params + Created better random session ID + Resource handler strips URL params like JSESSION. + Fixed session invalidation unbind notification to conform with spec + Load-on-startup the JspServlet so that precompiled servlets work. jetty-3.1.rc3 - 09 April 2001 + Implemented multi-part ranges so that acrobat is happy. + Simplified multipart response class. + Improved flush ordering for forwarded requests. + Improved ThreadPool stop handling + Frame handles more JIT stacks. + Cleaned up handling of exceptions thrown by servlets. + Handle zero length POSTs + Start session scavenger if needed. + Added ContentHandler Observer to XmlParser. + Allow webapp XmlParser to be observed for ejb-ref tags etc. + Created better random session ID jetty-3.1.rc2 - 30 March 2001 + Lifecycle.start() may throw Exception + Added MultiException to throw multiple nested exceptions. + Improved logging of nested exceptions. + Only one instance of default MIME map. + Use reference JAXP1.1 for XML parsing.y + Version 1.1 of configuration dtd supports New objects. + Improved handling of Primitive classes in XmlConfig + Renamed getConnection to getHttpConnection + fixed getLocales handling of quality params + fixed getParameter(name) handling for multiple values. + added options to turn off ranges and chunking to support acrobat requests. jetty-3.1.rc1 - 18 March 2001 + Moved JMX and SASL handling to Jetty3Extra release + Fixed problem with ServletContext.getContext(uri) + Added Jetty documentation pages from JettyWiki + Cleaned up build.xml script + Minimal handling of Servlet.log before initialization. + Various SSL cleanups + Resource handler strips URL params like JSESSION. jetty-3.1.rc0 - 23 February 2001 + Added JMX management framework. + Use Thread context classloader as default context loader parent. + Fixed init order for unnamed servlets. + Fixed session invalidation unbind notification to conform with spec + Improved handling of primitives in utilities. + Socket made available via HttpConnection. + Improved InetAddrPort and ThreadedServer to reduce DNS lookups. + Dynamic servlets may be restricted to Context classloader. + Reoganized packages to allowed sealed Jars + Changed getter and setter methods that did not conform to beans API. jetty-3.0.4 - 23 February 2001 + Fixed LineInput bug with split CRLF. jetty-3.0.3 - 03 February 2001 + Fixed pipelined request buffer bug. + Handle empty form content without exception. + Allow Log to be disabled before initialization. + Included new Jetty Logo + Implemented web.xml servlet mapping to a JSP + Fixed handling of directories without trailing / jetty-3.0.2 - 13 January 2001 + Replaced ResourceHandler FIFO cache with LRU cache. + Greatly improved buffering in ChunkableOutputStream + Padded error bodies for IE bug. + Improved HTML.Block efficiency + Improved jetty.bat + Improved jetty.sh + Handle unknown status reasons in HttpResponse + Ignore included response updates rather than IllegalStateException + Removed classloading stats which were causing circular class loading problems. + Allow '+' in path portion of a URL. + Try ISO8859_1 encoding if can't find ISO-8859-1 + Restructured demo site pages. + Context specific security permissions. + Added etc/jetty.policy as example policy file. jetty-3.0.1 - 20 December 2000 + Fixed value unbind notification for session invalidation. + Removed double null check possibility from ServletHolder jetty-3.0.0 - 17 December 2000 + Improved jetty.sh logging + Improved dtd resolution in XML parser. + Fixed taglib parsing + Fixed rel path handling in default configurations. + Optional extract war files. + Fixed WriterLogSink init bug + Use inner class to avoid double null check sync problems + Fixed rollover bug in WriterLogSink jetty-3.0.0.rc8 - 13 December 2000 + Optional alias checking added to FileResource. Turned on by default on all platforms without the "/" file separator. + Mapped *.jsp,*.jsP,*.jSp,*.jSP,*.Jsp,*.JsP,*.JSp,*.JSP + Tidied handling of ".", ".." and "//" in resource paths + Protected META-INF as well as WEB-INF in web applications. + Jetty.Server catches init exceptions per server + getSecurityHandler creates handler at position 0. + SysV unix init script + Improved exit admin handling + Change PathMap handling of /* to give precedence over suffix mapping. + Forward to welcome pages rather than redirect. + Removed special characters from source. + Default log options changed if in debug mode. + Removed some unused variables. + Added ForwardHandler + Removed security constraint on demo admin server. + Patched jasper to tomcat 3.2.1 jetty-3.0.0.rc7 - 02 December 2000 + Fixed security problem with lowercase WEB-INF uris on windows. + Extended security constraints (see README and WebApp Demo). + Set thread context classloader during handler start/stop calls. + Don't set MIME-Version in response. + Allow dynamic servlets to be served from / + Handle multiple inits of same servlet class. + Auto add a NotFoundHandler if needed. + Added NotFoundServlet + Added range handling to ResourceHandler. + CGI servlet handles not found better. + WEB-INF protected by NotFoundServlet rather than security constraint. + PUT, MOVE disabled in WebApplication unless defaults file is passed. + Conditionals apply to puts, dels and moves in ResourceHandler. + URIs accept all characters < 0xff. + Set the AcceptRanges header. + Depreciated RollOverLogSink and moved functionality to an improved WriterLogSink. + Changed log options to less verbose defaults. + ThreadedServer.forceStop() now makes a connection to itself to handle non-premptive close. + Double null lock checks use ThreadPool.__nullLockChecks. + Split Debug servlet out of Admin Servlet. + Added Com.mortbay.HTTP.Handler.Servlet.Context.LogSink attribute to Servlet Context. If set, it is used in preference to the system log. jetty-3.0.0.rc6 - 20 November 2000 + RequestDispatcher.forward() only resets buffer, not headers. + Added ServletWriter that can be disabled. + Resource gets systemresources from it's own classloader. + don't include classes in release. + Allow load-on-startup with no content. + Fixed RollOverFileLogSink bug with extra log files. + Improved Log defaults + Don't start HttpServer log sink on add. + Admin servlet uses unique links for IE. + Added Win32 service support + Reduced risk of double null check sync problem. + Don't set connection:close for normal HTTP/1.0 responses. + RequestDispatcher new queries params replace old. + Servlet init order may be negative. + Corrected a few of the many spelling mistakes. + Javadoc improvements. + Webapps serve dynamics servlets by default. + Warn for missing WEB-INF or web.xml + Sessions try version 1 cookies in set-cookie2 header. + Session cookies are given context path + Put extra server and servlet info in header. + Version details in header can be suppressed with System property java.com.mortbay.HTTP.Version.paranoid + Prevent reloading dynamic servlets at different paths. + Implemented resource aliases in HandlerContext - used by Servlet Context + Map tablib configuration to resource aliases. + Implemented customizable error pages. + Simple stats in ContextLoader. + Allow HttpMessage state to be manipulated. + Allow multiple set cookies. jetty-3.0.0.rc5 - 12 November 2000 + Default writer encoding set by mime type if not explicitly set. + Relax webapp rules, accept no web.xml or no WEB-INF + Pass flush through ServletOut + Avoid jprobe race warnings in DateCache + Allow null cookie values + Servlet exceptions cause 503 unavailable rather than 500 server error + RequestDispatcher can dispatch static resources. + Merged DynamicHandler into ServletHandler. + Added debug form to Admin servlet. + Implemented servlet load ordering. + Moved JSP classpath hack to ServletHolder + Removed Makefile build system. + Many javadoc cleanups. jetty-2.4.9 - 12 November 2000 + HttpListener ignore InterruptedIOExceptions + HttpListener default max idle time = 20s + HtmlFilter handles non default encodings + Writing HttpRequests encodes path + HttpRequest.write uses ISO8859_1 encoding. jetty-3.0.0.rc4 - 06 November 2000 + Provide default JettyIndex.properties + Fixed mis-synchronization in ThreadPool.stop() + Fixed mime type mapping bug introduced in RC3 + Ignore more IOExceptions (still visible with debug). jetty-3.0.0.rc3 - 05 November 2000 + Changed ThreadPool.stop for IBM 1.3 JVM + Added bin/jetty.sh run script. + upgraded build.xml to ant v1.2 + Set MaxReadTimeMs in all examples + Further clean up of the connection close actions + Moved unused classes from com.mortbay.Util to com.mortbay.Tools in new distribution package. + Handle mime suffixes containing dots. + Added gz tgz tar.gz .z mime mappings. + Fixed default mimemap initialization bug + Optimized persistent connections by recycling objects + Added HandlerContext.setHttpServerAccess for trusted contexts. + Set the thread context class loader in HandlerContext.handle + Prevent servlet setAttribute calls to protected context attributes. + Removed redundant context attributes. + Implemented mime mapping in webapplications. + Strip ./ from relative resources. + Added context class path dynamic servlet demo jetty-3.0.0.rc2 - 29 October 2000 + Replaced ISO-8859-1 literals with StringUtil static + Pass file based classpath to JspServlet (see README). + Prevented multiple init of ServletHolder + ErlEncoding treats params without values as empty rather than null. + Accept public DTD for XmlConfiguration (old style still supported). + Cleaned up non persistent connection close. + Accept HTTP/1. as HTTP/1.0 (for netscape bug). + Fixed thread name problem in ThreadPool jetty-3.0.0.rc1 - 22 October 2000 + Added simple admin servlet. + Added CGI to demo + Added HashUserRealm and cleaned up security constraints + Added Multipart request and response classes from Jetty2 + Moved and simplified ServletLoader to ContextLoader. + Initialize JSP with classloader. + All attributes in javax. java. and com.mortbay. name spaces to be set. + Partial handling of 0.9 requests. + removed Thread.destroy() calls. + Cleaned up exception handling. jetty-2.4.8 - 23 October 2000 + Fixed bug with 304 replies with bodies. + Improved win32 make files. + Fixed closing socket problem jetty-3.0.B05 - 18 October 2000 + Improved null returns to get almost clean watchdog test. + Cleaned up response committing and flushing + Handler RFC2109 cookies (like any browser handles them!) + Added default webapp servlet mapping /servlet/name/* + Improved path spec interpretation by looking at 2.3 spec + Implemented security-role-ref for servlets + Protected servletConfig from downcast security problems + Made test harnesses work with ant. + improved ant documentation. + Removed most deprecation warnings + Fixed JarFileResource to handle jar files without directories. + Implemented war file support + Java2 style classloading + Improved default log format for clarity. + Separated context attributes and initParams. jetty-3.0.B04 - 12 October 2000 + Restricted context mapping to simple model for servlets. + Fixed problem with session ID in paths + Added modified version of JasperB3.2 for JSP + Moved FileBase to docroot + Merged and renamed third party jars. + Do not try multiple servlets for a request. + Implemented Context.getContext(uri) + Added webdefault.xml for web applications. + Redirect to index files, so index.jsp works. + Filthy hack to teach jasper JspServer Jetty classpath jetty-3.0.B03 - 09 October 2000 + Expanded import package.*; lines + Expanded leading tabs to spaces + Improved Context to Handler contract. + Parse but not handler startup ordering in web applications. + Send request log via a LogSink + Added append mode in RolloverFileLogSink + Made LogSink a Lifecycle interface + Improved handler toString + Redirect context only paths. + Pass object to LogSink + Implemented request dispatching. + Redo dynamic servlets handling + Improved Log rollover. + Simplified path translation and real path calculation. + Catch stop and destroy exceptions in HttpServer.stop() + Handle ignorable spaces in XmlConfiguration + Handle ignorable spaces in WebApplication + Warn about explicit sets of WebApplication + Remove 411 checks as IE breaks this rule after redirect. + Removed last remnants JDK 1.1 support + Added release script jetty-2.4.7 - 06 October 2000 + Allow Objects to be passed to LogSink + Set content length on errors for keep alive. + Added encode methods to URI + Improved win32 build + fixes to SSL doco + Support key and keystore passwords + Various improvements to ServletDispatch, PropertyTree and associated classes. jetty-3.0.B02 - 24 August 2000 + Fixed LineInput bug with SSL giving CR pause LF. + Fixed HTTP/1.0 input close bug + Fixed bug in TestRFC2616 + Improved ThreadedServer stop and destroy + Use resources in WebApplication + Added CGI servlet jetty-3.0.B01 - 21 August 2000 + SSL implemented with JsseListener + Partial implementation of webapp securitycontraints + Implemented more webapp configuration + Switched to the aelfred XML parser from microstar, which is only partially validating, but small and lightweight jetty-2.4.6 - 16 August 2000 + Turn Linger off before closing sockets, to allow restart. + JsseListener & SunJsseListener added and documented + com.mortbay.Util.KeyPairTool added to handle openSSL SSL keys. + Minor changes to compile with jikes. + Added passive mode methods to FTP jetty-3.0.A99 - 10 August 2000 + Implemented jetty.xml configuration + Added Xmlconfiguration utility + ServletLoader simplied and uses ResourcePath + Replaced FileHandler with ResourceHandler + Use SAX XML parsing instead of DOM for space saving. + Removed FileBase. Now use ResourceBase instead + Added Resource abstraction + Make it compile cleanly with jikes. + Re-added commented out imports for JDK-1.1 compile jetty-3.0.A98 - 20 July 2000 + Implemented Jetty demos and Site as Web Application. + Implemented WebApplicationContext + Switched to JDK1.2 only + ServletRequest.getServerPort() returns 80 rather than 0 + Fixed constructor to RolloverFileLogSink + Improved synchronization on LogSink + Allow HttpRequest.toString() handles bad requests. jetty-3.0.A97 - 13 July 2000 + Tempory request log implementation + Less verbose debug + Better tuned SocketListener parameters + Started RequestDispatcher implementation. + Added WML mappings + Fixed makefiles for BSD ls + Fixed persistent commits with no content (eg redirect+keep-alive). + Implemented servlet isSecure(). + Implemented servlet getLocale(s). + Formatted version in server info string. + Protect setContentLength from a late set in default servlet HEAD handling. + Added error handling to LifeCycleThread + implemented removeAttribute on requests jetty-2.4.5 - 09 July 2000 + Don't mark a session invalid until after values unbound. + Formatted version in server info. + Added HtmlExpireFilter and removed response cache revention from HtmlFilter. + Fixed transaction handling in JDBC wrappers jetty-3.0.A96 - 27 June 2000 + Fixed bug with HTTP/1.1 Head reqests to servlets. + Supressed un-needed chunking EOF indicators. jetty-3.0.A95 - 24 June 2000 + Fixed getServletPath for default "/" + Handle spaces in file names in FileHandler. jetty-3.0.A94 - 19 June 2000 + Implemented Sessions. + PathMap exact matches can terminate with ; or # for URL sessions and targets. + Added HandlerContext to allow grouping of handlers into units with the same file, resource and class configurations. + Cleaned up commit() and added complete() to HttpResponse + Updated license to clarify that commercial usage IS OK! jetty-3.0.A93 - 14 June 2000 + Major rethink! Moved to 2.2 servlet API + Lots of changes and probably unstable jetty-3.0.A92 - 07 June 2000 + Added HTML classes to jar + Fixed redirection bug in FileHandler jetty-2.4.4 - 03 June 2000 + Many debug call optimizations + Added RolloverFileLogSink + Improved LogSink configuration + Support System.property expansions in PropertyTrees. + Added uk.org.gosnell.Servlets.CgiServlet to contrib + HttpRequest.setRequestPath does not null pathInfo. + BasicAuthHandler uses getResourcePath so it can be used behind request dispatching + Added HTML.Composite.replace + FileHandler implements IfModifiedSince on index files. + Added build-win32.mak jetty-3.0.A91 - 03 June 2000 + Improved LogSink mechanism + Implemented realPath and getResource methods for servlets. + Abstracted ServletHandler + Simplified HttpServer configuration methods and arguments + Simplified class loading + Added HTML classes from Jetty2 jetty-3.0.A9 - 07 May 2000 + Improvided finally handling of output end game. + Fixed double chunking bug in SocketListener. + File handler checks modified headers on directory indexes. + ServletLoader tries unix then platform separator for zip separator. jetty-3.0.A8 - 04 May 2000 + Servlet2_1 class loading re-acrchitected. See README. + Moved Sevlet2_1 handler to com.mortbay.Servlet2_1 + addCookie takes an int maxAge rather than a expires date. + Added LogSink extensible log architecture. + Code.ignore only outputs when debug is verbose. + Added Tenlet class for reverse telnet. jetty-2.4.3 - 04 May 2000 + Pass Cookies with 0 max age to browser. + Allow CRLF in UrlEncoded jetty-2.4.2 - 23 April 2000 + Added LogSink and FileLogSink classes to allow extensible Log handling. + Handle nested RequestDispatcher includes. + Modified GNUJSP to prevent close in nested requests. + Added GNUJSP to JettyServer.prp file. jetty-3.0.A7 - 15 April 2000 + Include java 1.2 source hierarchy + removed excess ';' from source + fixed flush problem with chunked output for IE5 + Added InetGateway to help debug IE5 problems + added removeValue method to MultiMap jetty-2.4.1 - 09 April 2000 + Removed debug println from ServletHolder. + Set encoding before exception in FileHandler. + Fixed bug in HtmlFilter for tags split between writes. jetty-3.0.A6 - 09 April 2000 + Integrated skeleton 2.1 Servlet container + Improved portability of Frame and Debug. + Dates forced to use US locale + Removed Converter utilities and InetGateway. + added bin/useJava2Collections to convert to JDK1.2 jetty-2.4.0 - 24 March 2000 + Upgraded to gnujsp 1.0.0 + Added per servlet resourceBase configuration. + Absolute URIs are returned by getRequestURI (if sent by browser). + Improved parsing of stack trace in debug mode. + Implemented full handling of cookie max age. + Moved SetUID native code to contrib hierarchy + Form parameters only decoded for POSTs + RequestDispatcher handles URI parameters + Fixed bug with RequestDispatcher.include() + Fixed caste problem in UrlEncoded + Fixed null pointer in ThreadedServer with stopAll + Added VirtualHostHandler for virtual host handling + Added doc directory with a small start jetty-2.3.5 - 25 January 2000 + Fixed nasty bug with HTTP/1.1 redirects. + ProxyHandler sends content for POSTs etc. + Force locale of date formats to US. + Fixed expires bug in Cookies + Added configuration option to turn off Keep-Alive in HTTP/1.0 + Allow configured servlets to be auto reloaded. + Allow properties to be configured for dynamic servlets. + Added contrib/com/kiwiconsulting/jetty JSSE SSL adaptor to release. jetty-2.3.4 - 18 January 2000 + include from linux rather than genunix for native builds + Fixed IllegalStateException handling in DefaultExceptionHandler + MethodTag.invoke() is now public. + Improved HtmlFilter.activate header modifications. + Cookie map keyed on domain as well as name and path. + DictionaryConverter handles null values. + URI decodes applies URL decoding to the path. + Servlet properties allow objects to be stored. + Fixed interaction with resourcePaths and proxy demo. jetty-3.0.A5 - 19 October 1999 + Use ISO8859_1 instead of UTF8 for headers etc. + Use char array in UrlEncoded.decode + Do our own URL string encoding with 8859-1 + Replaced LF wait in LineInput with state boolean. jetty-2.3.3 - 19 October 1999 + Replaced UTF8 encoding with ISO-8859-1 for headers. + Use UrlEncoded for form parameters. + Do our own URL encoding with ISO-8859-1 + HTTP.HTML.EmbedUrl uses contents encoding. jetty-2.3.2 - 17 October 1999 + Fixed getReader bug with HttpRequest. + Updated UrlEncoded with Jetty3 version. jetty-3.0.A4 - 16 October 1999 + Request attributes + Basic Authentication Handler. + Added LF wait after CR to LineInput. + UTF8 in UrlDecoded.decodeString. jetty-2.3.1 - 14 October 1999 + Force UTF8 for FTP commands + Force UTF8 for HTML + Changed demo servlets to use writers in preference to outputstreams + NullHandler/Server default name.name.PROPERTIES to load prefix/name.name.properties + Use UTF8 in HTTP headers + Added Oracle DB adapter + Added assert with no message to Code + ThreadedServer calls setSoTimeout(_maxThreadIdleMs) on accepted sockets. Idle reads will timeout. + Prevented thread churn on idle server. + HTTP/1.0 Keep-Alive (about time!). + Fixed GNUJSP 1.0 resource bug. jetty-3.0.A3 - 14 October 1999 + Added LifeCycle interface to Utils implemented by ThreadPool, ThreadedServer, HttpListener & HttpHandler + StartAll, stopAll and destroyAll methods added to HttpServer. + MaxReadTimeMs added to ThreadedServer. + Added service method to HttpConnection for specialization. jetty-3.0.A2 - 13 October 1999 + UTF8 handling on raw output stream. + Reduced flushing on writing response. + Fixed LineInput problem with repeated CRs + Cleaned up Util TestHarness. + Prevent entity content for responses 100-199,203,304 + Added cookie support and demo. + HTTP/1.0 Keep-alive (about time!) + Virtual Hosts. + NotFound Handler + OPTION * Handling. + TRACE handling. + HEAD handling. jetty-3.0.A1 - 12 October 1999 + LineInput uses own buffering and uses character encodings. + Added MultiMap for common handling of multiple valued parameters. + Added parameters to HttpRequest + Quick port of FileHandler + Setup demo pages. + Added PathMap implementing mapping as defined in the 2.2 API specification (ie. /exact, /prefix/*, *.extention & default ). + Added HttpHandler interface with start/stop/destroy lifecycle + Updated HttpListener is start/stop/destroy lifecycle. + Implemented simple extension architecture in HttpServer. jetty-3.0.A0 - 09 October 1999 + Started fresh repository in CVS + Moved com.mortbay.Base classes to com.mortbay.Util + Cleanup of UrlEncoded, using 1.2 Collections. + Cleanup of URI, using 1.2 Collections. + Extended URI to handle absolute URLs + Cleanup of LineInput, using 1.2 Collections. + Moved HttpInput/OutputStream to ChunkableInput/OutputStream. + Cleaned up chunking code to use LineInput and reduce buffering. + Added support for transfer and content encoding filters. + Added support for servlet 2.2 outbut buffer control. + Generalized notification of outputStream events. + Split HttpHeader into HttpFields and HttpMessage. + HttpMessage supports chunked trailers. + HttpMessage supports message states. + Added generalized HTTP Connection. + Cleanup of HttpRequest and decoupled from Servlet API + Cleanup and abstraction of ThreadPool. + ThreadedServer based on ThreadPool. + Cleanup of HttpResponse and decoupled from Servlet API + Created RFC2616 test harness. + gzip and deflate request transfer encodings + TE field coding and trailer handler + HttpExceptions now produce error pages with specific detail of the exception. jetty-2.3.0 - 05 October 1999 + Added SetUID class with native Unix call to set the effective User ID. + FTP closes files after put/get. + FTP uses InetAddress of command socket for data socket. jetty-2.3.0A - 22 September 1999 + Added GNUJSP 1.0 for the JSP 1.0 API. + Use javax.servlet classes from JWSDK1.0 + Added "Powered by Jetty" button. + ServerContext available to HtmlFilters via context param + Made session IDs less predictable and removed race. + Added BuildJetty.java file. + Expanded tabs to spaces in source. jetty-2.2.8 - 15 September 1999 + Fixed bug in Element.attribute with empty string values. + Made translation of getRequestURI() optional. + Removed recursion from TranslationHandler + Added disableLog() to turn off logging. + Allow default table attributes to be overriden. + Improved quoting in HTML element values jetty-2.2.7 - 09 September 1999 + Reverted semantics of getRequestURI() to return untranslated URI. + Added GzipFilter for content encoding. + Added default row, head and cell elements to Table. + FileHandler passes POST request through if the file does not exist. jetty-2.2.6 - 05 September 1999 + New implementation of ThreadPool, avoids a thread leak problem. + Fixed Cookie max age order of magnitude bug. + Cookies always available from getCookies. + Cookies parameter renamed to CookiesAsParameters + HttpRequest.getSession() always returns a session as per the latest API spec. + Added destroy() method on all HttpHandlers. + ServletHandler.destroy destroys all servlets. + FileHandler does not server files ending in '/' + Ignore duplicate single valued headers, rather than reply with bad request, as IE4 breaks the rules. + Allow the handling of getPathTranslated to be configured in ServletHandler. + Removed JRUN options from ServletHandler configuration. + Added ServletRunnerHandler to the contrib directories. + Updated HTML package to better support CSS: + cssClass, cssID and style methods added to element. + SPAN added to Block + media added to Style + class StyleLink added. jetty-2.2.5 - 19 August 1999 + Fixed bug with closing connections in ThreadedServer + Made start and stop non final in ThreadedServer + Better default handling of ServletExceptions + Always close connection after a bad request. + Set Expires header in HtmlFilter. + Don't override the cookie as parameter option. + Limited growth in MultiPartResponse boundary. + Improved error messages from Jetty.Server. + Close loaded class files so Win32 can overwrite them before GC (what a silly file system!). jetty-2.2.4 - 02 August 1999 + ThreadedServer can use subclasses of Thread. + Better help on Jetty.Server + HttpRequests may be passed to HttpFilter constructors. + HtmlFilter blanks IfModifiedSince headers on construction + Fixed bugs in HtmlFilter parser and added TestHarness. + Improved cfg RCS script. jetty-2.2.3 - 27 July 1999 + Fixed parser bug in HtmlFilter + Made setInitialize public in ServletHolder + Improved performance of com.mortbay.HTML.Heading + Added stop call to HttpServer, used by Exit Servlet. + Simplified JDBC connection handling so that it works with Java1.2 - albeit less efficiently. + FileHandler defaults to allowing directory access. + JDBC tests modified to use cloudscape as DB. jetty-2.2.2 - 22 July 1999 + Fixed bug in HtmlFilter that prevented single char buffers from being written. + Implemented getResourceAsStream in FileJarServletLoader + Fixed bug with CLASSPATH in FileJarServletLoader after attempt to load from a jar. + Fixed bug in com.mortbay.Util.IO with thread routines. + Moved more test harnesses out of classes. + File handler passes through not allowed options for non existant files. + NotFoundHandler can repond with SC_METHOD_NOT_ALLOWED. + Improved com.mortbay.Base.Log handling of different JVMs + Minor fixes to README jetty-2.2.1 - 18 July 1999 + Comma separate header fields. + Protect against duplicate single valued headers. + Less verbose debug in PropertyTree + Ignore IOException in ThreadedServer.run() when closing. + Limit maximum line length in HttpInputStream. + Response with SC_BAD_REQUEST rather than close in more circumstances + Handle continuation lines in HttpHeader. + HtmlFilter resets last-modified and content-length headers. + Implemented com.mortbay.Util.IO as a ThreadPool + Decoupled ExceptionHandler configuration from Handler stacks. Old config style will produce warning and Default behavior. See new config file format for changes. + Added TerseExceptionHandler + Added optional resourceBase property to HttpConfiguration. This is used as a URL prefix in the getResource API and was suggested by the JSERV and Tomcat implementors. jetty-2.2.0 - 01 July 1999 + Improved feature description page. + Added Protekt SSL HttpListener + Moved GNUJSP and Protekt listener to a contrib hierarchy. + ThreadedServer.stop() closes socket before interrupting threads. + Exit servlet improved (a little). + Fixed some of the javadoc formatting. jetty-2.2.Beta4 - 29 June 1999 + FileHandler flushes files from cache in DELETE method. + ThreadedServer.stop() now waits until all threads are stopped. + Options "allowDir" added to FileHandler. + Added getGlobalProperty to Jetty.Server and used this to configure default page type. + Updated README.txt + Restructured com.mortbay.Jetty.Server for better clarity and documentation. + Added comments to configuration files. + Made ServerSocket and accept call generic in ThreadedServer for SSL listeners. + Altered meaning of * in PropertyTree to assist in abbreviated configuration files. + Added JettyMinimalDemo.prp as an example of an abbreviated configuration. + Expanded Mime.prp file + Added property handling to ServletHandler to read JRUN servlet configuration files. jetty-2.2.Beta3 - 22 June 1999 + Re-implemented ThreadedServer to improve and balance performance. + Added file cache to FileHandler + Implemented efficient version of ServletContext.getResourceAsStream() that does not open a new socket connection (as does getResource()). + LookAndFeelServlet uses getResourceAsStream to get the file to wrap. This allows it to benefit from any caching done and to wrap arbitrary content (not just files). + Restructure demo so that LookAndFeel content comes from simple handler stack. + Fixed file and socket leaks in Include and Embed tags. + Ran dos2unix on all text files + Applied contributed patch of spelling and typo corrections + Added alternate constructors to HTML.Include for InputStream. + Server.shutdown() clears configuration so that server may be restarted in same virtual machine. + Improved Block.write. + Fixed bug in HttpResponse flush. jetty-2.2.Beta2 - 12 June 1999 + Added all write methods to HttpOutputStream$SwitchOutputStream + Added com.mortbay.Jetty.Server.shutdown() for gentler shutdown of server. Called from Exit servlet + HttpRequest.getParameterNames() no longer alters the order returned by getQueryString(). + Handle path info of a dynamic loaded servlets and correctly set the servlet path. + Standardized date format in persistent cookies. jetty-2.2.Beta1 - 07 June 1999 + Defined abstract ServletLoader, derivations of which can be specified in HttpConfiguration properties. + Implemented all HttpServer attribute methods by mapping to the HttpConfiguration properties. Dynamic reconfiguration is NOT supported by these methods (but we are thinking about it). + Close files after use to avoid "file leak" under heavy load. + Fixed missing copyright messages from some contributions + Fixed incorrect version numbers in a few places. + Improved ThreadPool synchronization and added minThreads. + Allow configuration of MinListenerThreads, MaxListenerThreads, MaxListenerThreadIdleMs + HtmlFilter optimized for being called by a buffered writer. + Don't warn about IOExceptions unless Debug is on. + Limit the job queue only grow to the max number of threads. + Included GNUJSP 0.9.9 + Optional use of DateCache in log file format + Fixed cache in FileJarServletLoader + Destroy requests and responses to help garbage collector. + Restructure ThreadedServer to reduce object creation. jetty-2.2.Beta0 - 31 May 1999 + Servlet loader handles jar files with different files separator. + ThreadedServer gently shuts down. + Handle malformed % characters in URLs. + Included and improved version of ThreadPool for significant performance improvement under high load. + HttpRequest.getCookies returns empty array rather than null for no cookies. + Added HttpResponse.requestHandled() method to avoid bug with servlet doHead method. + Added Page.rewind() method to allow a page to be written multiple times + Added "Initialize" attribute to servlet configuration to allow servlet to be initialized when loaded. + LogHandler changed to support only a single outfile and optional append. + Included contributed com.mortbay.Jetty.StressTester class + Token effort to keep test files out of the jar + Removed support for STF jetty-2.2.Alpha1 - 07 May 1999 + ServletHolder can auto reload servlets + Dynamic servlets can have autoReload configured + Wait for requests to complete before reloading. + Call destroy on old servlets when reloading. + Made capitalization of config file more consistent(ish) + Fixed bug in SessionDump jetty-2.2.Alpha0 - 06 May 1999 + Improved PropertyTree implementation + Old Jetty.Server class renamed to Jetty.Server21 + New Server class using PropertyTree for configuration + HttpHandlers given setProperties method to configure via Properties. + HttpListener class can be configured + Mime suffix mapping can be configured. + Removed historic API from sessions + Improved SessionDump servlet + Fixed date overflow in Cookies + HttpResponse.sendError avoids IllegalStateException + Added ServletLoader implementation if ClassLoader. + Dynamic loading of servlets. + Added reload method to ServletHolder, but no way to call it yet. + Changed options for FileServer + Implemented ServletServer + Removed SimpleServletServer jetty-2.1.7 - 22 April 1999 + Fixed showstopper bug with getReader and getWriter in requests and responses. + HttpFilter uses package interface to get HttpOutputStream jetty-2.1.6 - 21 April 1999 + Reduced initial size of most hashtables to reduce default memory overheads. + Throw IllegalStateException as required from gets of input/output/reader/writer in requests/responses. + New simpler version of PropertyTree + Updated PropertyTreeEditor + Return EOF from HttpInputStream that has a content length. + Added additional date formats for HttpHeader.getDateHeader jetty-2.1.5 - 15 April 1999 + Session URL encoding fixed for relative URLs. + Reduced session memory overhead of sessions + Form parameters protected against multiple decodes when redirected. + Added setType methods to com.mortbay.FTP.Ftp + Fixed bugs with invalid sessions + Page factory requires response for session encoding + Moved SessionHandler to front of stacks + HtmlFilter now expands to the URL encoded session if required. + Instrumented most of the demo to support URL session encoding. + Implemented HttpRequest.getReader() + Servlet log has been diverted to com.mortbay.Base.Log.event() Thus debug does not need to be turned on to see servlet logs. + Fixed alignment bug in TableForm + Removed RFCs from package + Fixed bug in ServletDispatch for null pathInfo jetty-2.1.4 - 26 March 1999 + Fixed problem compiling PathMap under some JDKs. + Reduced HTML dependence in HTTP package to allow minimal configuration + Tightened license agreement so that binary distributions are required to include the license file. + HttpRequest attributes implemented. + Session max idle time implemented. + pathInfo returns null for zero length pathInfo (as per spec). Sorry if this breaks your servlets - it is a pain! + fixed bug in getRealPath + getPathTranslated now call getRealPath with pathInfo (as per spec). jetty-2.1.3 - 19 March 1999 + Added support for suffixes to PathMap + Included GNUJSP implementation of Java Server Pages + Use Java2 javadoc jetty-2.1.2 - 09 March 1999 + JSDK 2.1.1 + API documentation for JSDK 2.1.1 + Cascading style sheet HTML element added. + Fixed trailing / bug in FileHandler (again!). + Converted most servlets to HttpServlets using do Methods. jetty-2.1.1 - 05 March 1999 + Reduced number of calls to getRemoteHost for optimization + Faster version of HttpInputStream.readLine(). + com.mortbay.Base.DateCache class added and used to speed date handling. + Handle '.' in configured paths (temp fix until PropertyTrees) + Fast char buffer handling in HttpInputStream + Faster version of HttpHeader.read() + Faster version of HttpRequest + Size all StringBuffers jetty-2.1.0 - 22 February 1999 + Session URL Encoding + PropertyTrees (see new Demo page) + ServletDispatch (see new Demo page) + image/jpg -> image/jpeg + Deprecated com.mortbay.Util.STF + getServlet methods return null. jetty-2.1.B1 - 13 February 1999 + Fixed bug with if-modified-since in FileHandler + Added video/quicktime to default MIME types. + Fixed bug with MultipartRequest. + Updated DefaultExceptionHandler. + Updated InetAddrPort. + Updated URI. + Implemented Handler translations and getRealPath. + Improved handling of File.separator in FileHandler. + Implemented RequestDispatcher (NOT Tested!). + Implemented getResource and getResourceAsStream (NOT Tested!). + Replace package com.mortbay.Util.Gateway with class com.mortbay.Util.InetGateway jetty-2.1.B0 - 30 January 1999 + Uses JSDK2.1 API, but not all methods implemented. + Added support for PUT, MOVE, DELETE in FileHandler + FileHandler now sets content length. + Added plug gateway classes com.mortbay.Util.Gateway + Fixed command line bug with SimpleServletConfig + Minor changes to support MS J++ and its non standard language extensions - MMMmmm should have left it unchanged! jetty-2.0.5 - 15 December 1998 + Temp fix to getCharacterEncoding + added getHeaderNoParams jetty-2.0.4 - 10 December 1998 + Use real release of JSDK2.0 (rather than beta). + Portability issues solved for Apple's + Improved error code returns + Removed MORTBAY_HOME support from Makefiles + Improved default Makefile behaviour + Implement getCharacterEncoding jetty-2.0.3 - 13 November 1998 + Limit threads in ThreadedServer and low priority listener option greatly improve performance under worse case loads. + Fix bug with index files for Jetty.Server. Previously servers configured with com.mortbay.Jetty.Server would not handle index.html files. Need to make this configurable in the prp file. + Fixed errors in README file: com.mortbay.Jetty.Server was called com.mortbay.HTTP.Server jetty-2.0.2 - 01 November 1998 + Use JETTY_HOME rather than MORTBAY_HOME for build environment + Add thread pool to threaded server for significant performance improvement. + Buffer files during configuration + Buffer HTTP Response headers. jetty-2.0.1 - 27 October 1998 + Released under an Open Source license. jetty-2.0.0 - 25 October 1998 + Removed exceptional case from FileHandler redirect. + Removed Chat demo (too many netscape dependencies). + Fixed Code.formatObject handling of null objects. + Added multipart/form-data demo. jetty-2.0.Beta3 - 29 September 1998 + Send 301 for directories without trailing / in FileHandler + Ignore exception from HttpListener + Properly implemented multiple listening addresses + Added com.mortbay.Jetty.Server (see README.Jetty) + Demo converted to an instance of com.mortbay.Jetty.Server + Fixed Log Handler again. + Added com.mortbay.HTTP.MultiPartRequest to handle file uploads jetty-2.0Beta2 - 01 July 1998 + Fixed Log Handler for HTTP/1.1 + Slight improvement in READMEEs jetty-2.0Beta1 - 01 June 1998 + Improved performance of Code.debug() calls, significantly in the case of non matching debug patterns. + Fixed bug with calls to service during initialization of servlet + Provided addSection on com.mortbay.HTML.Page + Provided reset on com.mortbay.HTML.Composite. + Proxy demo in different server instance + Handle full URLs in HTTP requests (to some extent) + Improved performance with special asciiToLowerCase + Warn if MSIE used for multi part MIME. jetty-2.0Alpha2 - 01 May 1998 + JDK1.2 javax.servlet API + Added date format to Log + Added timezone to Log + Handle params in getIntHeader and getDateHeader + Removed HttpRequest.getByteContent + Use javax.servlet.http.HttpUtils.parsePostData + Use javax.servlet.http.Cookie + Use javax.servlet.http.HttpSession + Handle Single Threaded servlets with servlet pool jetty-1.3.5 - 01 May 1998 + Fixed socket inet bug in FTP + Debug triggers added to com.mortbay.Base.Code + Added date format to Log + Correct handling of multiple parameters jetty-2.0Alpha1 - 08 April 1998 + Fixed forward bug with no port number + Removed HttpRequestHeader class + Debug triggers added to com.mortbay.Base.Code + Handle HTTP/1.1 Host: header + Correct formatting of Date HTTP headers + HttpTests test harness + Add HTTP/1.1 Date: header + Handle file requests with If-Modified-Since: or If-Unmodified-Since: + Handle HEAD properly + Send Connection: close + Requires Host: header for 1.1 requests + Sends chunked data for 1.1 responses of unknown length. + handle extra spaces in HTTP headers + Really fixed handling of multiple parameters + accept chunked data + Send 100 Continue for HTTP/1.1 requests (concerned about push???) + persistent connections jetty-1.3.4 - 15 March 1998 + Fixed handling of multiple parameters in query and form content. "?A=1%2C2&A=C%2CD" now returns two values ("1,2" & "C,D") rather than 4. + ServletHandler now takes an optional file base directory name which is used to set the translated path for pathInfo in servlet requests. + Dump servlet enhanced to exercise these changes. jetty-1.3.3 + Fixed TableForm.addButtonArea bug. + TableForm.extendRow() uses existing cell + Closed exception window in HttpListener.java jetty-1.3.2 + Fixed proxy bug with no port number + Added per Table cell composite factories jetty-1.3.1 + Minor fixes in SmtpMail + ForwardHandler only forwards as http/1.0 (from Tobias.Miller) + Improved parsing of stack traces + Better handling of InvocationTargetException in debug + Minor release adjustments for Tracker jetty-1.3.0 + Added DbAdaptor to JDBC wrappers + Beta release of Tracker jetty-1.2.0 + Reintroduced STF + Fixed install bug for nested classes + Better Debug configuration + DebugServlet + Alternate look and feel for Jetty jetty-1.1.1 + Improved documentation jetty-1.1 + Improved connection caching in java.mortbay.JDBC + Moved HttpCode to com.mortbay.Util jetty-1.0.1 + Bug fixes jetty-1.0 + First release in com.mortbay package structure + Included Util, JDBC, HTML, HTTP, Jetty jetty8-8.1.3/eclipse-jetty-templates.xml000066400000000000000000000005761174773561500203010ustar00rootroot00000000000000 jetty8-8.1.3/example-async-rest/000077500000000000000000000000001174773561500165135ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/000077500000000000000000000000001174773561500213555ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/pom.xml000066400000000000000000000016711174773561500226770ustar00rootroot00000000000000 org.eclipse.jetty example-async-rest 8.1.3.v20120416 4.0.0 org.eclipse.jetty.example-async-rest example-async-rest-jar jar Example Async Rest :: Jar org.eclipse.jetty jetty-client ${project.version} org.eclipse.jetty.orbit javax.servlet provided jetty8-8.1.3/example-async-rest/async-rest-jar/src/000077500000000000000000000000001174773561500221445ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/000077500000000000000000000000001174773561500230705ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/java/000077500000000000000000000000001174773561500240115ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/java/org/000077500000000000000000000000001174773561500246005ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/java/org/eclipse/000077500000000000000000000000001174773561500262245ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500273635ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/000077500000000000000000000000001174773561500310165ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/000077500000000000000000000000001174773561500330315ustar00rootroot00000000000000AbstractRestServlet.java000066400000000000000000000077471174773561500376020ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest//======================================================================== //Copyright 2004-2008 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 //Unless required by applicable law or agreed to in writing, software //distributed under the License is distributed on an "AS IS" BASIS, //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //See the License for the specific language governing permissions and //limitations under the License. //======================================================================== package org.eclipse.jetty.example.asyncrest; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.URLEncoder; import java.util.Map; import java.util.Queue; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Abstract Servlet implementation class AsyncRESTServlet. * Enquires ebay REST service for auctions by key word. * May be configured with init parameters:
*
appid
The eBay application ID to use
*
* Each request examines the following request parameters:
*
items
The keyword to search for
*
*/ public class AbstractRestServlet extends HttpServlet { protected final static String __DEFAULT_APPID = "Webtide81-adf4-4f0a-ad58-d91e41bbe85"; protected final static String STYLE = ""; protected final static String ITEMS_PARAM = "items"; protected final static String APPID_PARAM = "appid"; protected String _appid; public void init(ServletConfig servletConfig) throws ServletException { if (servletConfig.getInitParameter(APPID_PARAM) == null) _appid = __DEFAULT_APPID; else _appid = servletConfig.getInitParameter(APPID_PARAM); } protected String restURL(String item) { try { return ("http://open.api.ebay.com/shopping?MaxEntries=3&appid=" + _appid + "&version=573&siteid=0&callname=FindItems&responseencoding=JSON&QueryKeywords=" + URLEncoder.encode(item,"UTF-8")); } catch(Exception e) { throw new RuntimeException(e); } } protected String generateThumbs(Queue> results) { StringBuilder thumbs = new StringBuilder(); for (Map m : results) { if (!m.containsKey("GalleryURL")) continue; thumbs.append(""); thumbs.append(""); thumbs.append(" "); } return thumbs.toString(); } protected String ms(long nano) { BigDecimal dec = new BigDecimal(nano); return dec.divide(new BigDecimal(1000000L)).setScale(1,RoundingMode.UP).toString(); } protected int width(long nano) { int w=(int)((nano+999999L)/5000000L); if (w==0) w=2; return w; } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } AsyncRestServlet.java000066400000000000000000000170751174773561500371070ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest//======================================================================== //Copyright 2004-2008 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 //Unless required by applicable law or agreed to in writing, software //distributed under the License is distributed on an "AS IS" BASIS, //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //See the License for the specific language governing permissions and //limitations under the License. //======================================================================== package org.eclipse.jetty.example.asyncrest; import java.io.IOException; import java.io.PrintWriter; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.AsyncContext; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.ContentExchange; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.util.ajax.JSON; /** * Servlet implementation class AsyncRESTServlet. * Enquires ebay REST service for auctions by key word. * May be configured with init parameters:
*
appid
The eBay application ID to use
*
* Each request examines the following request parameters:
*
items
The keyword to search for
*
*/ public class AsyncRestServlet extends AbstractRestServlet { final static String RESULTS_ATTR = "org.eclipse.jetty.demo.client"; final static String DURATION_ATTR = "org.eclipse.jetty.demo.duration"; final static String START_ATTR = "org.eclispe.jetty.demo.start"; HttpClient _client; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); _client = new HttpClient(); _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); try { _client.start(); } catch (Exception e) { throw new ServletException(e); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Long start=System.nanoTime(); // Do we have results yet? Queue> results = (Queue>) request.getAttribute(RESULTS_ATTR); // If no results, this must be the first dispatch, so send the REST request(s) if (results==null) { // define results data structures final Queue> resultsQueue = new ConcurrentLinkedQueue>(); request.setAttribute(RESULTS_ATTR, results=resultsQueue); // suspend the request // This is done before scheduling async handling to avoid race of // dispatch before startAsync! final AsyncContext async = request.startAsync(); async.setTimeout(30000); // extract keywords to search for String[] keywords=request.getParameter(ITEMS_PARAM).split(","); final AtomicInteger outstanding=new AtomicInteger(keywords.length); // Send request each keyword for (final String item:keywords) { _client.send( new AsyncRestRequest(item) { void onAuctionFound(Map auction) { resultsQueue.add(auction); } void onComplete() { if (outstanding.decrementAndGet()<=0) async.dispatch(); } }); } // save timing info and return request.setAttribute(START_ATTR, start); request.setAttribute(DURATION_ATTR, new Long(System.nanoTime() - start)); return; } // We have results! // Generate the response String thumbs = generateThumbs(results); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println(""); out.println(STYLE); out.println(""); long initial = (Long) request.getAttribute(DURATION_ATTR); long start0 = (Long) request.getAttribute(START_ATTR); long now = System.nanoTime(); long total=now-start0; long generate=now-start; long thread=initial+generate; out.print("Asynchronous: "+request.getParameter(ITEMS_PARAM)+"
"); out.print("Total Time: "+ms(total)+"ms
"); out.print("Thread held (red): "+ms(thread)+"ms (" + ms(initial) + " initial + " + ms(generate) + " generate )
"); out.print("Async wait (green): "+ms(total-thread)+"ms
"); out.println(""+ ""+ ""); out.println("
"); out.println(thumbs); out.println("
"); out.println(""); out.close(); } private abstract class AsyncRestRequest extends ContentExchange { AsyncRestRequest(final String item) { // send the exchange setMethod("GET"); setURL(restURL(item)); } abstract void onAuctionFound(Map details); abstract void onComplete(); protected void onResponseComplete() throws IOException { // extract auctions from the results Map query = (Map) JSON.parse(this.getResponseContent()); Object[] auctions = (Object[]) query.get("Item"); if (auctions != null) { for (Object o : auctions) onAuctionFound((Map)o); } onComplete(); } /* ------------------------------------------------------------ */ protected void onConnectionFailed(Throwable ex) { getServletContext().log("onConnectionFailed: ",ex); onComplete(); } /* ------------------------------------------------------------ */ protected void onException(Throwable ex) { getServletContext().log("onConnectionFailed: ",ex); onComplete(); } /* ------------------------------------------------------------ */ protected void onExpire() { getServletContext().log("onConnectionFailed: expired"); onComplete(); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } SerialRestServlet.java000066400000000000000000000070301174773561500372370ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest//======================================================================== //Copyright 2004-2008 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 //Unless required by applicable law or agreed to in writing, software //distributed under the License is distributed on an "AS IS" BASIS, //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //See the License for the specific language governing permissions and //limitations under the License. //======================================================================== package org.eclipse.jetty.example.asyncrest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.LinkedList; import java.util.Map; import java.util.Queue; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.util.ajax.JSON; /** * Servlet implementation class SerialRestServlet */ public class SerialRestServlet extends AbstractRestServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long start = System.nanoTime(); String[] keywords=request.getParameter(ITEMS_PARAM).split(","); Queue> results = new LinkedList>(); // make all requests serially for (String itemName : keywords) { URL url = new URL(restURL(itemName)); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setRequestMethod("GET"); Map query = (Map)JSON.parse(new BufferedReader(new InputStreamReader(connection.getInputStream()))); Object[] auctions = (Object[]) query.get("Item"); if (auctions != null) { for (Object o : auctions) results.add((Map) o); } } // Generate the response String thumbs=generateThumbs(results); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println(""); out.println(STYLE); out.println(""); long now = System.nanoTime(); long total=now-start; out.print("Blocking: "+request.getParameter(ITEMS_PARAM)+"
"); out.print("Total Time: "+ms(total)+"ms
"); out.print("Thread held (red): "+ms(total)+"ms
"); out.println(""); out.println("
"); out.println(thumbs); out.println("
"); out.println(""); out.close(); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/resources/000077500000000000000000000000001174773561500251025ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/resources/META-INF/000077500000000000000000000000001174773561500262425ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/000077500000000000000000000000001174773561500302545ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest.html000066400000000000000000000015311174773561500331550ustar00rootroot00000000000000

Blocking vs Asynchronous REST

This demo calls the EBay WS API both synchronously and asynchronously, to obtain items matching each of the keywords passed on the query string. The time the request thread is head is displayed for both.

jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest/000077500000000000000000000000001174773561500322675ustar00rootroot00000000000000green.png000066400000000000000000000002461174773561500340200ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrestPNG  IHDRKm)sRGB pHYs  tIME1)sX+ztEXtCommentCreated with GIMPWIDATcdπ010 % BIENDB`red.png000066400000000000000000000002441174773561500334700ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrestPNG  IHDRKm)sRGB pHYs  tIME1?1;$tEXtCommentCreated with GIMPWIDATcπ01 ) AֆIENDB`jetty8-8.1.3/example-async-rest/async-rest-jar/src/main/resources/META-INF/web-fragment.xml000066400000000000000000000013501174773561500313410ustar00rootroot00000000000000 SerialRestServlet SerialRestServlet org.eclipse.jetty.example.asyncrest.SerialRestServlet SerialRestServlet /testSerial AsyncRestServlet AsyncRestServlet org.eclipse.jetty.example.asyncrest.AsyncRestServlet true AsyncRestServlet /testAsync jetty8-8.1.3/example-async-rest/async-rest-webapp/000077500000000000000000000000001174773561500220575ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/pom.xml000066400000000000000000000023311174773561500233730ustar00rootroot00000000000000 org.eclipse.jetty example-async-rest 8.1.3.v20120416 4.0.0 org.eclipse.jetty.example-async-rest example-async-rest-webapp war Example Async Rest :: Webapp async-rest org.eclipse.jetty.example-async-rest example-async-rest-jar ${project.version} org.eclipse.jetty jetty-webapp ${project.version} test org.eclipse.jetty.orbit javax.servlet provided jetty8-8.1.3/example-async-rest/async-rest-webapp/src/000077500000000000000000000000001174773561500226465ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/main/000077500000000000000000000000001174773561500235725ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/main/webapp/000077500000000000000000000000001174773561500250505ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/main/webapp/META-INF/000077500000000000000000000000001174773561500262105ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/main/webapp/META-INF/MANIFEST.MF000066400000000000000000000000471174773561500276430ustar00rootroot00000000000000Manifest-Version: 1.0 Class-Path: jetty8-8.1.3/example-async-rest/async-rest-webapp/src/main/webapp/WEB-INF/000077500000000000000000000000001174773561500260775ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/main/webapp/WEB-INF/web.xml000066400000000000000000000005131174773561500273750ustar00rootroot00000000000000 Async REST Webservice Example jetty8-8.1.3/example-async-rest/async-rest-webapp/src/main/webapp/index.html000066400000000000000000000015311174773561500270450ustar00rootroot00000000000000

Blocking vs Asynchronous REST

This demo calls the EBay WS API both synchronously and asynchronously, to obtain items matching each of the keywords passed on the query string. The time the request thread is head is displayed for both.

jetty8-8.1.3/example-async-rest/async-rest-webapp/src/test/000077500000000000000000000000001174773561500236255ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/test/java/000077500000000000000000000000001174773561500245465ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/test/java/org/000077500000000000000000000000001174773561500253355ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/test/java/org/eclipse/000077500000000000000000000000001174773561500267615ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500301205ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/test/java/org/eclipse/jetty/example/000077500000000000000000000000001174773561500315535ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/test/java/org/eclipse/jetty/example/asyncrest/000077500000000000000000000000001174773561500335665ustar00rootroot00000000000000DemoServer.java000066400000000000000000000016521174773561500364310ustar00rootroot00000000000000jetty8-8.1.3/example-async-rest/async-rest-webapp/src/test/java/org/eclipse/jetty/example/asyncrestpackage org.eclipse.jetty.example.asyncrest; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.webapp.WebAppContext; public class DemoServer { public static void main(String[] args) throws Exception { String jetty_home = System.getProperty("jetty.home","."); Server server = new Server(); Connector connector=new SelectChannelConnector(); connector.setPort(Integer.getInteger("jetty.port",8080).intValue()); server.setConnectors(new Connector[]{connector}); WebAppContext webapp = new WebAppContext(); webapp.setContextPath("/"); webapp.setWar(jetty_home+"/target/example-async-rest-webapp-8.0.0.M0-SNAPSHOT"); server.setHandler(webapp); server.start(); server.join(); } } jetty8-8.1.3/example-async-rest/pom.xml000066400000000000000000000012061174773561500200270ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 org.eclipse.jetty example-async-rest pom Example Async Rest async-rest-jar async-rest-webapp jetty8-8.1.3/example-jetty-embedded/000077500000000000000000000000001174773561500173115ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/pom.xml000066400000000000000000000045341174773561500206340ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 example-jetty-embedded Example :: Jetty Embedded Jetty Embedded Examples org.eclipse.jetty jetty-webapp ${project.version} org.eclipse.jetty jetty-security ${project.version} org.eclipse.jetty jetty-servlets ${project.version} org.eclipse.jetty jetty-rewrite ${project.version} org.eclipse.jetty jetty-deploy ${project.version} org.eclipse.jetty jetty-jmx ${project.version} org.eclipse.jetty jetty-ajp ${project.version} org.eclipse.jetty.toolchain jetty-test-helper test org.eclipse.jetty jetty-websocket ${project.version} junit junit test org.eclipse.jetty test-jetty-servlet ${project.version} test jetty8-8.1.3/example-jetty-embedded/prodDb.properties000066400000000000000000000006431174773561500226440ustar00rootroot00000000000000#HSQL Database Engine 1.8.0.10 #Mon Nov 08 13:35:35 EST 2010 hsqldb.script_format=0 runtime.gc_interval=0 sql.enforce_strict_size=false hsqldb.cache_size_scale=8 readonly=false hsqldb.nio_data_file=true hsqldb.cache_scale=14 version=1.8.0 hsqldb.default_table_type=memory hsqldb.cache_file_scale=1 hsqldb.log_size=200 modified=no hsqldb.cache_version=1.7.0 hsqldb.original_version=1.8.0 hsqldb.compatible_version=1.8.0 jetty8-8.1.3/example-jetty-embedded/prodDb.script000066400000000000000000000001451174773561500217510ustar00rootroot00000000000000CREATE SCHEMA PUBLIC AUTHORIZATION DBA CREATE USER SA PASSWORD "" GRANT DBA TO SA SET WRITE_DELAY 10 jetty8-8.1.3/example-jetty-embedded/src/000077500000000000000000000000001174773561500201005ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/main/000077500000000000000000000000001174773561500210245ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/main/java/000077500000000000000000000000001174773561500217455ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/main/java/org/000077500000000000000000000000001174773561500225345ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/000077500000000000000000000000001174773561500241605ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500253175ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/000077500000000000000000000000001174773561500270505ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/DumpServlet.java000066400000000000000000000035161174773561500321720ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class DumpServlet extends HttpServlet { public DumpServlet() { } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("

DumpServlet

");
        response.getWriter().println("requestURI=" + request.getRequestURI());
        response.getWriter().println("contextPath=" + request.getContextPath());
        response.getWriter().println("servletPath=" + request.getServletPath());
        response.getWriter().println("pathInfo=" + request.getPathInfo());
        response.getWriter().println("session=" + request.getSession(true).getId());
        response.getWriter().println("
"); } }jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServer.java000066400000000000000000000044031174773561500317620ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ /** Simple Jetty FileServer. * This is a simple example of Jetty configured as a FileServer. * * File server Usage - java org.eclipse.jetty.server.example.FileServer [ port [ * docroot ]] * * @see FileServerXml for the equivalent example done in XML configuration. * @author gregw * */ public class FileServer { private static final Logger LOG = Log.getLogger(FileServer.class); public static void main(String[] args) throws Exception { Server server = new Server(args.length == 0?8080:Integer.parseInt(args[0])); ResourceHandler resource_handler = new ResourceHandler(); resource_handler.setDirectoriesListed(true); resource_handler.setWelcomeFiles(new String[]{ "index.html" }); resource_handler.setResourceBase(args.length == 2?args[1]:"."); LOG.info("serving " + resource_handler.getBaseResource()); HandlerList handlers = new HandlerList(); handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() }); server.setHandler(handlers); server.start(); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServerXml.java000066400000000000000000000017251174773561500324470ustar00rootroot00000000000000package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.xml.XmlConfiguration; /* ------------------------------------------------------------ */ /** A Jetty FileServer. * This server is identical to {@link FileServer}, except that it * is configured via an {@link XmlConfiguration} config file that * does the identical work. *

* See fileserver.xml */ public class FileServerXml { public static void main(String[] args) throws Exception { Resource fileserver_xml = Resource.newSystemResource("fileserver.xml"); XmlConfiguration configuration = new XmlConfiguration(fileserver_xml.getInputStream()); Server server = (Server)configuration.configure(); server.start(); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/HelloHandler.java000066400000000000000000000036341174773561500322620ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; public class HelloHandler extends AbstractHandler { final String _greeting; final String _body; public HelloHandler() { _greeting="Hello World"; _body=null; } public HelloHandler(String greeting) { _greeting=greeting; _body=null; } public HelloHandler(String greeting,String body) { _greeting=greeting; _body=body; } public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html;charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK); baseRequest.setHandled(true); response.getWriter().println("

"+_greeting+"

"); if (_body!=null) response.getWriter().println(_body); } }jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/HelloServlet.java000066400000000000000000000030101174773561500323150ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class HelloServlet extends HttpServlet { String greeting = "Hello"; public HelloServlet() { } public HelloServlet(String hi) { greeting = hi; } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("

" + greeting + " from HelloServlet

"); } }jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java000066400000000000000000000153071174773561500323060ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import java.lang.management.ManagementFactory; import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.deploy.providers.ContextProvider; import org.eclipse.jetty.deploy.providers.WebAppProvider; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.NCSARequestLog; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.RequestLogHandler; import org.eclipse.jetty.server.handler.StatisticsHandler; import org.eclipse.jetty.server.nio.BlockingChannelConnector; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.server.ssl.SslSocketConnector; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; public class LikeJettyXml { public static void main(String[] args) throws Exception { String jetty_home = System.getProperty("jetty.home","../jetty-distribution/target/distribution"); System.setProperty("jetty.home",jetty_home); Server server = new Server(); server.setDumpAfterStart(true); server.setDumpBeforeStop(true); // Setup JMX MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer()); mbContainer.start(); server.getContainer().addEventListener(mbContainer); server.addBean(mbContainer,true); mbContainer.addBean(new Log()); // Setup Threadpool QueuedThreadPool threadPool = new QueuedThreadPool(); threadPool.setMaxThreads(500); server.setThreadPool(threadPool); // Setup Connectors SelectChannelConnector connector = new SelectChannelConnector(); connector.setPort(8080); connector.setMaxIdleTime(30000); connector.setConfidentialPort(8443); connector.setStatsOn(false); server.setConnectors(new Connector[] { connector }); BlockingChannelConnector bConnector = new BlockingChannelConnector(); bConnector.setPort(8888); bConnector.setMaxIdleTime(30000); bConnector.setConfidentialPort(8443); bConnector.setAcceptors(1); server.addConnector(bConnector); SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector(); ssl_connector.setPort(8443); SslContextFactory cf = ssl_connector.getSslContextFactory(); cf.setKeyStorePath(jetty_home + "/etc/keystore"); cf.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); cf.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); cf.setTrustStore(jetty_home + "/etc/keystore"); cf.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); cf.setExcludeCipherSuites( new String[] { "SSL_RSA_WITH_DES_CBC_SHA", "SSL_DHE_RSA_WITH_DES_CBC_SHA", "SSL_DHE_DSS_WITH_DES_CBC_SHA", "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" }); ssl_connector.setStatsOn(false); server.addConnector(ssl_connector); ssl_connector.open(); SslSocketConnector ssl2_connector = new SslSocketConnector(cf); ssl2_connector.setPort(8444); ssl2_connector.setStatsOn(false); server.addConnector(ssl2_connector); ssl2_connector.open(); /* Ajp13SocketConnector ajp = new Ajp13SocketConnector(); ajp.setPort(8009); server.addConnector(ajp); */ HandlerCollection handlers = new HandlerCollection(); ContextHandlerCollection contexts = new ContextHandlerCollection(); RequestLogHandler requestLogHandler = new RequestLogHandler(); handlers.setHandlers(new Handler[] { contexts, new DefaultHandler(), requestLogHandler }); StatisticsHandler stats = new StatisticsHandler(); stats.setHandler(handlers); server.setHandler(stats); // Setup deployers DeploymentManager deployer = new DeploymentManager(); deployer.setContexts(contexts); server.addBean(deployer); ContextProvider context_provider = new ContextProvider(); context_provider.setMonitoredDirName(jetty_home + "/contexts"); context_provider.setScanInterval(2); deployer.addAppProvider(context_provider); WebAppProvider webapp_provider = new WebAppProvider(); webapp_provider.setMonitoredDirName(jetty_home + "/webapps"); webapp_provider.setParentLoaderPriority(false); webapp_provider.setExtractWars(true); webapp_provider.setScanInterval(2); webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml"); webapp_provider.setContextXmlDir(jetty_home + "/contexts"); deployer.addAppProvider(webapp_provider); HashLoginService login = new HashLoginService(); login.setName("Test Realm"); login.setConfig(jetty_home + "/etc/realm.properties"); server.addBean(login); NCSARequestLog requestLog = new NCSARequestLog(jetty_home + "/logs/jetty-yyyy_mm_dd.log"); requestLog.setExtended(false); requestLogHandler.setRequestLog(requestLog); server.setStopAtShutdown(true); server.setSendServerVersion(true); server.start(); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java000066400000000000000000000047731174773561500326700ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; /* ------------------------------------------------------------ */ /** * A Jetty server with multiple connectors. * */ public class ManyConnectors { public static void main(String[] args) throws Exception { Server server = new Server(); SelectChannelConnector connector0 = new SelectChannelConnector(); connector0.setPort(8080); connector0.setMaxIdleTime(30000); connector0.setRequestHeaderSize(8192); SelectChannelConnector connector1 = new SelectChannelConnector(); connector1.setHost("127.0.0.1"); connector1.setPort(8888); connector1.setThreadPool(new QueuedThreadPool(20)); connector1.setName("admin"); SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector(); String jetty_home = System.getProperty("jetty.home","../jetty-distribution/target/distribution"); System.setProperty("jetty.home",jetty_home); ssl_connector.setPort(8443); SslContextFactory cf = ssl_connector.getSslContextFactory(); cf.setKeyStorePath(jetty_home + "/etc/keystore"); cf.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); cf.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); server.setConnectors(new Connector[] { connector0, connector1, ssl_connector }); server.setHandler(new HelloHandler()); server.start(); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyContexts.java000066400000000000000000000055051174773561500323540ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.nio.SelectChannelConnector; /* ------------------------------------------------------------ */ /** * A {@link ContextHandlerCollection} handler may be used to direct a request to * a specific Context. The URI path prefix and optional virtual host is used to * select the context. * */ public class ManyContexts { public final static String BODY= "root context
"+ "normal context
"+ "virtual context
"; public static void main(String[] args) throws Exception { Server server = new Server(); Connector connector = new SelectChannelConnector(); connector.setPort(8080); server.setConnectors(new Connector[] { connector }); ContextHandler context0 = new ContextHandler(); context0.setContextPath("/"); Handler handler0 = new HelloHandler("Root Context",BODY); context0.setHandler(handler0); ContextHandler context1 = new ContextHandler(); context1.setContextPath("/context"); Handler handler1 = new HelloHandler("A Context",BODY); context1.setHandler(handler1); ContextHandler context2 = new ContextHandler(); context2.setContextPath("/context"); context2.setVirtualHosts(new String[] { "127.0.0.2" }); Handler handler2 = new HelloHandler("A Virtual Context",BODY); context2.setHandler(handler2); ContextHandlerCollection contexts = new ContextHandlerCollection(); contexts.setHandlers(new Handler[] { context0, context1, context2 }); server.setHandler(contexts); server.start(); System.err.println(server.dump()); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyHandlers.java000066400000000000000000000113011174773561500322740ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import java.io.File; import java.io.IOException; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.NCSARequestLog; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.server.handler.HandlerWrapper; import org.eclipse.jetty.server.handler.RequestLogHandler; import org.eclipse.jetty.util.ajax.JSON; /* ------------------------------------------------------------ */ /** * Frequently many handlers are combined together to handle different aspects of * a request. A handler may: *
    *
  • handle the request and completely generate the response *
  • partially handle the request, but defer response generation to another * handler. *
  • select another handler to pass the request to. *
  • use business logic to decide to do one of the above. *
* * Multiple handlers may be combined with: *
    *
  • {@link HandlerWrapper} which will nest one handler inside another. In * this example, the HelloHandler is nested inside a HandlerWrapper that sets * the greeting as a request attribute. *
  • {@link HandlerList} which will call a collection of handlers until the * request is marked as handled. In this example, a list is used to combine the * param handler (which only handles the request if there are parameters) and * the wrapper handler. Frequently handler lists are terminated with the * {@link DefaultHandler}, which will generate a suitable 404 response if the * request has not been handled. *
  • {@link HandlerCollection} which will call each handler regardless if the * request has been handled or not. Typically this is used to always pass a * request to the logging handler. *
*/ public class ManyHandlers { public static void main(String[] args) throws Exception { Server server = new Server(8080); // create the handlers Handler param = new ParamHandler(); HandlerWrapper wrapper = new HandlerWrapper() { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { request.setAttribute("welcome","Hello"); super.handle(target,baseRequest,request,response); } }; Handler hello = new HelloHandler(); Handler dft = new DefaultHandler(); RequestLogHandler log = new RequestLogHandler(); // configure logs log.setRequestLog(new NCSARequestLog(File.createTempFile("demo","log").getAbsolutePath())); // create the handler collections HandlerCollection handlers = new HandlerCollection(); HandlerList list = new HandlerList(); // link them all together wrapper.setHandler(hello); list.setHandlers(new Handler[] { param, wrapper, dft }); handlers.setHandlers(new Handler[] { list, log }); server.setHandler(handlers); server.start(); server.join(); } public static class ParamHandler extends AbstractHandler { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { Map params = request.getParameterMap(); if (params.size() > 0) { response.setContentType("text/plain"); response.getWriter().println(JSON.toString(params)); ((Request)request).setHandled(true); } } } } ManyServletContexts.java000066400000000000000000000045521174773561500336430ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import java.lang.management.ManagementFactory; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.log.Log; public class ManyServletContexts { public static void main(String[] args) throws Exception { Server server = new Server(8080); // Setup JMX MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer()); mbContainer.start(); server.getContainer().addEventListener(mbContainer); server.addBean(mbContainer,true); ContextHandlerCollection contexts = new ContextHandlerCollection(); server.setHandler(contexts); ServletContextHandler root = new ServletContextHandler(contexts,"/",ServletContextHandler.SESSIONS); root.addServlet(new ServletHolder(new HelloServlet("Hello")),"/"); root.addServlet(new ServletHolder(new HelloServlet("Ciao")),"/it/*"); root.addServlet(new ServletHolder(new HelloServlet("Bonjoir")),"/fr/*"); ServletContextHandler other = new ServletContextHandler(contexts,"/other",ServletContextHandler.SESSIONS); other.addServlet(DefaultServlet.class.getCanonicalName(),"/"); other.addServlet(new ServletHolder(new HelloServlet("YO!")),"*.yo"); server.start(); System.err.println(server.dump()); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/MinimalServlets.java000066400000000000000000000041261174773561500330340ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.bio.SocketConnector; import org.eclipse.jetty.servlet.ServletHandler; public class MinimalServlets { public static void main(String[] args) throws Exception { Server server = new Server(); Connector connector = new SocketConnector(); connector.setPort(8080); server.setConnectors(new Connector[] { connector }); ServletHandler handler = new ServletHandler(); server.setHandler(handler); handler.addServletWithMapping("org.eclipse.jetty.embedded.MinimalServlets$HelloServlet","/"); server.start(); server.join(); } public static class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("

Hello SimpleServlet

"); } } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/OneContext.java000066400000000000000000000032161174773561500320030ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; /* ------------------------------------------------------------ */ /** * A {@link ContextHandler} provides a common environment for multiple Handlers, * such as: URI context path, class loader, static resource base. * * Typically a ContextHandler is used only when multiple contexts are likely. */ public class OneContext { public static void main(String[] args) throws Exception { Server server = new Server(8080); ContextHandler context = new ContextHandler(); context.setContextPath("/"); context.setResourceBase("."); context.setClassLoader(Thread.currentThread().getContextClassLoader()); server.setHandler(context); context.setHandler(new HelloHandler()); server.start(); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/OneHandler.java000066400000000000000000000020551174773561500317340ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Server; public class OneHandler { public static void main(String[] args) throws Exception { Server server = new Server(8080); server.setHandler(new HelloHandler()); server.start(); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/OneServletContext.java000066400000000000000000000035201174773561500333460ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; public class OneServletContext { public static void main(String[] args) throws Exception { Server server = new Server(8080); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); server.setHandler(context); // Server content from tmp ServletHolder holder = context.addServlet(org.eclipse.jetty.servlet.DefaultServlet.class,"/tmp/*"); holder.setInitParameter("resourceBase","/tmp"); holder.setInitParameter("pathInfoOnly","true"); // Serve some hello world servlets context.addServlet(new ServletHolder(new HelloServlet()),"/*"); context.addServlet(new ServletHolder(new HelloServlet("Buongiorno Mondo")),"/it/*"); context.addServlet(new ServletHolder(new HelloServlet("Bonjour le Monde")),"/fr/*"); server.start(); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java000066400000000000000000000046331174773561500315410ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.webapp.WebAppContext; public class OneWebApp { public static void main(String[] args) throws Exception { Server server = new Server(); Connector connector = new SelectChannelConnector(); connector.setPort(Integer.getInteger("jetty.port",8080).intValue()); server.setConnectors(new Connector[] { connector }); //If you're running this from inside Eclipse, then Server.getVersion will not provide //the correct number as there is no manifest. Use the command line instead to provide the path to the //test webapp String war = args.length > 0?args[0]: "../test-jetty-webapp/target/test-jetty-webapp-"+Server.getVersion(); String path = args.length > 1?args[1]:"/"; System.err.println(war + " " + path); WebAppContext webapp = new WebAppContext(); webapp.setContextPath(path); webapp.setWar(war); //If the webapp contains security constraints, you will need to configure a LoginService if (war.contains("test-jetty-webapp")) { org.eclipse.jetty.security.HashLoginService loginService = new org.eclipse.jetty.security.HashLoginService(); loginService.setName("Test Realm"); loginService.setConfig("src/test/resources/realm.properties"); webapp.getSecurityHandler().setLoginService(loginService); } server.setHandler(webapp); server.start(); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ProxyServer.java000066400000000000000000000043771174773561500322360ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.ConnectHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlets.ProxyServlet; public class ProxyServer { public static void main(String[] args) throws Exception { Server server = new Server(); SelectChannelConnector connector = new SelectChannelConnector(); connector.setPort(8888); server.addConnector(connector); HandlerCollection handlers = new HandlerCollection(); server.setHandler(handlers); // Setup proxy servlet ServletContextHandler context = new ServletContextHandler(handlers, "/", ServletContextHandler.SESSIONS); ServletHolder proxyServlet = new ServletHolder(ProxyServlet.class); proxyServlet.setInitParameter("whiteList", "google.com, www.eclipse.org, localhost"); proxyServlet.setInitParameter("blackList", "google.com/calendar/*, www.eclipse.org/committers/"); context.addServlet(proxyServlet, "/*"); // Setup proxy handler to handle CONNECT methods ConnectHandler proxy = new ConnectHandler(); proxy.setWhite(new String[]{"mail.google.com"}); proxy.addWhite("www.google.com"); handlers.addHandler(proxy); server.start(); } } SecuredHelloHandler.java000066400000000000000000000047261174773561500335210ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.security.Constraint; public class SecuredHelloHandler { public static void main(String[] args) throws Exception { Server server = new Server(8080); LoginService loginService = new HashLoginService("MyRealm","src/test/resources/realm.properties"); server.addBean(loginService); ConstraintSecurityHandler security = new ConstraintSecurityHandler(); server.setHandler(security); Constraint constraint = new Constraint(); constraint.setName("auth"); constraint.setAuthenticate( true ); constraint.setRoles(new String[]{"user", "admin"}); ConstraintMapping mapping = new ConstraintMapping(); mapping.setPathSpec( "/*" ); mapping.setConstraint( constraint ); Set knownRoles = new HashSet(); knownRoles.add("user"); knownRoles.add("admin"); security.setConstraintMappings(Collections.singletonList(mapping), knownRoles); security.setAuthenticator(new BasicAuthenticator()); security.setLoginService(loginService); security.setStrict(false); HelloHandler hh = new HelloHandler(); security.setHandler(hh); server.start(); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/SimplestServer.java000066400000000000000000000021601174773561500327010ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Server; /* ------------------------------------------------------------ */ /** The simplest possible Jetty server. */ public class SimplestServer { public static void main(String[] args) throws Exception { Server server = new Server(8080); server.start(); server.join(); } } jetty8-8.1.3/example-jetty-embedded/src/main/resources/000077500000000000000000000000001174773561500230365ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/main/resources/fileserver.xml000066400000000000000000000022071174773561500257270ustar00rootroot00000000000000 8080 true index.html . jetty8-8.1.3/example-jetty-embedded/src/test/000077500000000000000000000000001174773561500210575ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/test/java/000077500000000000000000000000001174773561500220005ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/test/java/org/000077500000000000000000000000001174773561500225675ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/test/java/org/eclipse/000077500000000000000000000000001174773561500242135ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500253525ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/test/java/org/eclipse/jetty/embedded/000077500000000000000000000000001174773561500271035ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/test/java/org/eclipse/jetty/embedded/GzipHandlerTest.java000066400000000000000000000116501174773561500330200ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.embedded; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.zip.GZIPInputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.LocalConnector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.GzipHandler; import org.eclipse.jetty.testing.HttpTester; import org.eclipse.jetty.util.IO; import org.junit.After; import org.junit.Before; import org.junit.Test; public class GzipHandlerTest { private static String __content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+ "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+ "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+ "Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+ "at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+ "velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+ "Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+ "eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+ "sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+ "consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+ "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+ "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque."; private Server _server; private LocalConnector _connector; @Before public void init() throws Exception { _server = new Server(); _connector = new LocalConnector(); _server.addConnector(_connector); Handler testHandler = new AbstractHandler() { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { PrintWriter writer = response.getWriter(); writer.write(__content); writer.close(); baseRequest.setHandled(true); } }; GzipHandler gzipHandler = new GzipHandler(); gzipHandler.setHandler(testHandler); _server.setHandler(gzipHandler); _server.start(); } @After public void destroy() throws Exception { _server.stop(); _server.join(); } @Test public void testGzipHandler() throws Exception { // generated and parsed test HttpTester request = new HttpTester(); HttpTester response = new HttpTester(); request.setMethod("GET"); request.setVersion("HTTP/1.0"); request.setHeader("Host","tester"); request.setHeader("accept-encoding","gzip"); request.setURI("/"); ByteArrayBuffer reqsBuff = new ByteArrayBuffer(request.generate().getBytes()); ByteArrayBuffer respBuff = _connector.getResponses(reqsBuff, false); response.parse(respBuff.asArray()); assertTrue(response.getMethod()==null); assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase("gzip")); assertEquals(HttpServletResponse.SC_OK,response.getStatus()); InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes())); ByteArrayOutputStream testOut = new ByteArrayOutputStream(); IO.copy(testIn,testOut); assertEquals(__content, testOut.toString("UTF8")); } } jetty8-8.1.3/example-jetty-embedded/src/test/resources/000077500000000000000000000000001174773561500230715ustar00rootroot00000000000000jetty8-8.1.3/example-jetty-embedded/src/test/resources/realm.properties000066400000000000000000000014361174773561500263130ustar00rootroot00000000000000# # This file defines users passwords and roles for a HashUserRealm # # The format is # : [, ...] # # Passwords may be clear text, obfuscated or checksummed. The class # org.eclipse.util.Password should be used to generate obfuscated # passwords or password checksums # # If DIGEST Authentication is used, the password must be in a recoverable # format, either plain text or OBF:. # # if using digest authentication, do not MD5-hash the password jetty: jetty,user admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin,user other: OBF:1xmk1w261u9r1w1c1xmq,user plain: plain,user user: password,user # This entry is for digest auth. The credential is a MD5 hash of username:realmname:password digest: MD5:6e120743ad67abfbc385bc2bb754e297,user jetty8-8.1.3/icon.jpg000066400000000000000000000043621174773561500144310ustar00rootroot00000000000000JFIFHHC   C    @@ 8 !1"2ABQeq#Ra$6bcrs< !"12ABQaqr#RbCc ?DQDEDQDE`./Q ^u%Ŧs +PiH%J8R:Rm"w·6j mt%)H'`+).ֶ 4oaLߚ#Ԧ6dڲK^[:l6Z[eJRIP' ÝiiU6T߆1K Ҥ-^@4uQHnLSyX*&y^p}A4bűQC` C5LYWL1\d7,Sl,OjN4_Uidqx|:llG_Y\zqsK˚y ~52O=6𢿛69jް vwrG-Fi_kOYG?u? K-CYV uS~!f+@ 1!qkϣ$穵 >:xB7~iWǵ߭M}*Ò\K)D+XY$6ar~+4s@xs$N"1SEM/B!G*H} lrGN%o-9. %ij}9NUsSV--zmlRõB,6s?UWO(R+.ϵܬCK6)6ggx(3- C8C.]깎;}D<)ȝȟ:^*ےNnWyC-8)m%dHJֺVҘ>6.`ʹxX$iX8 *y e_Lh %7 ,ɓ4dsϵKCn3(mP !s)9kfÄ#_hۛrSH jJO+pamlM%w}ic1DKe rDo]#h9A ʢ,.:;b+;3=W'ҙ ZDd7mEe >'asɎR ڟ%.6-oҨҼR:&hcf~f썅FҎq{lB{1E 8j/9Iߜ~TSum1o'rsߧ˽3qYK-$% QBo]$K"YЊE˘um!#9mITJlxPO}2~֖Drx#sL(d,GS'idYg֏+$:-a [=j"zԩEDQDEDQjetty8-8.1.3/jetty-aggregate/000077500000000000000000000000001174773561500160555ustar00rootroot00000000000000jetty8-8.1.3/jetty-aggregate/jetty-all-server/000077500000000000000000000000001174773561500212665ustar00rootroot00000000000000jetty8-8.1.3/jetty-aggregate/jetty-all-server/pom.xml000066400000000000000000000227661174773561500226200ustar00rootroot00000000000000 org.eclipse.jetty.aggregate jetty-aggregate-project 8.1.3.v20120416 4.0.0 jetty-all-server Jetty :: Aggregate :: All Server ${project.groupId}.${project.artifactId} ${project.build.directory}/sources org.apache.maven.plugins maven-dependency-plugin unpack-dependencies unpack-dependencies **/MANIFEST.MF,javax/** javax javax,org.eclipse.jetty.orbit ${project.build.directory}/classes false true unpack-source generate-sources unpack-dependencies sources **/* META-INF/** org.eclipse.jetty javax javax,org.eclipse.jetty.orbit ${project.build.directory}/sources true true maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.apache.felix maven-bundle-plugin true bundle-manifest process-classes manifest !org.eclipse.jetty*, javax.annotation;version="1.0.0";resolution:=optional, javax.servlet;version="2.6.0", javax.servlet.annotation;version="2.6.0", javax.servlet.descriptor;version="2.6.0", javax.servlet.http;version="2.6.0", javax.mail;version="1.4.0";resolution:=optional, javax.mail.event;version="1.4.0";resolution:=optional, javax.mail.internet;version="1.4.0";resolution:=optional, javax.mail.search;version="1.4.0";resolution:=optional, javax.mail.util;version="1.4.0";resolution:=optional, javax.transaction;version="1.1.0";resolution:=optional, javax.transaction.xa;version="1.1.0";resolution:=optional, org.slf4j;resolution:=optional, org.slf4j.spi;resolution:=optional, org.slf4j.helpers;resolution:=optional, org.xml.sax, org.xml.sax.helpers, javax.security.cert, javax.xml.parsers, javax.net.ssl, !org.mortbay.*, org.objectweb.asm;version="3.1.0";resolution:=optional, org.objectweb.asm.commons;version="3.1.0";resolution:=optional, javax.security.auth.message*;resolution:=optional, * org.eclipse.jetty*;version="${parsedVersion.osgiVersion}" <_nouses>true J2SE-1.5 org.eclipse.jetty jetty-deploy ${project.version} provided org.eclipse.jetty jetty-websocket ${project.version} provided org.eclipse.jetty.orbit javax.servlet compile org.eclipse.jetty jetty-jmx ${project.version} provided org.eclipse.jetty jetty-plus ${project.version} provided org.eclipse.jetty jetty-ajp ${project.version} provided org.eclipse.jetty jetty-annotations ${project.version} provided org.eclipse.jetty jetty-jaspi ${project.version} provided org.eclipse.jetty jetty-jndi ${project.version} provided org.eclipse.jetty jetty-rewrite ${project.version} provided org.eclipse.jetty jetty-servlets ${project.version} provided org.eclipse.jetty jetty-nested ${project.version} provided org.eclipse.jetty.orbit javax.security.auth.message compile org.eclipse.jetty.orbit javax.mail.glassfish compile org.eclipse.jetty.orbit javax.activation compile org.eclipse.jetty.orbit javax.annotation compile jetty8-8.1.3/jetty-aggregate/jetty-all/000077500000000000000000000000001174773561500177625ustar00rootroot00000000000000jetty8-8.1.3/jetty-aggregate/jetty-all/pom.xml000066400000000000000000000143401174773561500213010ustar00rootroot00000000000000 org.eclipse.jetty.aggregate jetty-aggregate-project 8.1.3.v20120416 4.0.0 jetty-all Jetty :: Aggregate :: All core Jetty ${project.build.directory}/sources org.apache.maven.plugins maven-dependency-plugin unpack-dependencies unpack-dependencies **/MANIFEST.MF,javax/** javax javax,org.eclipse.jetty.orbit ${project.build.directory}/classes false true unpack-source generate-sources unpack-dependencies sources **/* META-INF/**,**/Servlet3Continuation*,**/Jetty6Continuation* org.eclipse.jetty javax javax,org.eclipse.jetty.orbit ${project.build.directory}/sources true true org.apache.maven.plugins maven-jar-plugin package package jar development http://eclipse.org/jetty ${user.name} org.eclipse.jetty http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt Jetty org.apache.maven.plugins maven-javadoc-plugin javadoc-jar compile jar org.eclipse.jetty jetty-client ${project.version} provided org.eclipse.jetty jetty-deploy ${project.version} provided org.eclipse.jetty jetty-websocket ${project.version} provided org.eclipse.jetty.orbit javax.servlet compile org.eclipse.jetty jetty-jmx ${project.version} provided org.eclipse.jetty jetty-plus ${project.version} provided org.eclipse.jetty jetty-ajp ${project.version} provided org.eclipse.jetty jetty-annotations ${project.version} provided org.eclipse.jetty jetty-jaspi ${project.version} provided org.eclipse.jetty jetty-jndi ${project.version} provided org.eclipse.jetty jetty-rewrite ${project.version} provided org.eclipse.jetty jetty-servlets ${project.version} provided org.eclipse.jetty jetty-nested ${project.version} provided org.slf4j slf4j-api provided true jetty8-8.1.3/jetty-aggregate/jetty-client/000077500000000000000000000000001174773561500204705ustar00rootroot00000000000000jetty8-8.1.3/jetty-aggregate/jetty-client/pom.xml000066400000000000000000000062551174773561500220150ustar00rootroot00000000000000 org.eclipse.jetty.aggregate jetty-aggregate-project 8.1.3.v20120416 4.0.0 jetty-client Jetty :: Aggregate :: HTTP Client ${project.build.directory}/sources org.apache.maven.plugins maven-dependency-plugin unpack-dependencies unpack-dependencies META-INF/**,org/eclipse/** **/MANIFEST.MF ${project.build.directory}/classes false true unpack-source generate-sources unpack-dependencies sources **/* META-INF/** org.eclipse.jetty ${project.build.directory}/sources true true org.apache.maven.plugins maven-jar-plugin package package jar development http://eclipse.org/jetty ${user.name} org.eclipse.jetty http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt Jetty HTTP Client org.eclipse.jetty jetty-client ${project.version} provided jetty8-8.1.3/jetty-aggregate/jetty-plus/000077500000000000000000000000001174773561500201755ustar00rootroot00000000000000jetty8-8.1.3/jetty-aggregate/jetty-plus/pom.xml000066400000000000000000000066251174773561500215230ustar00rootroot00000000000000 org.eclipse.jetty.aggregate jetty-aggregate-project 8.1.3.v20120416 4.0.0 jetty-plus Jetty :: Aggregate :: Plus Server ${project.build.directory}/sources org.apache.maven.plugins maven-dependency-plugin unpack-dependencies unpack-dependencies **/MANIFEST.MF,javax/** javax javax,org.eclipse.jetty.orbit ${project.build.directory}/classes false true unpack-source generate-sources unpack-dependencies sources **/* META-INF/** org.eclipse.jetty javax javax,org.eclipse.jetty.orbit ${project.build.directory}/sources true true org.apache.maven.plugins maven-jar-plugin package package jar development http://eclipse.org/jetty ${user.name} org.eclipse.jetty http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt Jetty HTTP Server org.eclipse.jetty jetty-plus ${project.version} provided jetty8-8.1.3/jetty-aggregate/jetty-server/000077500000000000000000000000001174773561500205205ustar00rootroot00000000000000jetty8-8.1.3/jetty-aggregate/jetty-server/pom.xml000066400000000000000000000071401174773561500220370ustar00rootroot00000000000000 org.eclipse.jetty.aggregate jetty-aggregate-project 8.1.3.v20120416 4.0.0 jetty-server Jetty :: Aggregate :: HTTP Server ${project.build.directory}/sources org.apache.maven.plugins maven-dependency-plugin unpack-dependencies unpack-dependencies **/MANIFEST.MF,javax/** javax javax,org.eclipse.jetty.orbit ${project.build.directory}/classes false true unpack-source generate-sources unpack-dependencies sources **/* META-INF/** org.eclipse.jetty javax javax,org.eclipse.jetty.orbit ${project.build.directory}/sources true true org.apache.maven.plugins maven-jar-plugin package package jar development http://eclipse.org/jetty ${user.name} org.eclipse.jetty http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt Jetty HTTP Server org.eclipse.jetty jetty-server ${project.version} provided org.eclipse.jetty jetty-websocket ${project.version} provided jetty8-8.1.3/jetty-aggregate/jetty-servlet/000077500000000000000000000000001174773561500206765ustar00rootroot00000000000000jetty8-8.1.3/jetty-aggregate/jetty-servlet/pom.xml000066400000000000000000000071341174773561500222200ustar00rootroot00000000000000 org.eclipse.jetty.aggregate jetty-aggregate-project 8.1.3.v20120416 4.0.0 jetty-servlet Jetty :: Aggregate :: Servlet Server ${project.build.directory}/sources org.apache.maven.plugins maven-dependency-plugin unpack-dependencies unpack-dependencies **/MANIFEST.MF,javax/** javax javax,org.eclipse.jetty.orbit ${project.build.directory}/classes false true unpack-source generate-sources unpack-dependencies sources **/* META-INF/** org.eclipse.jetty javax javax,org.eclipse.jetty.orbit ${project.build.directory}/sources true true org.apache.maven.plugins maven-jar-plugin package package jar development http://eclipse.org/jetty ${user.name} org.eclipse.jetty http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt Jetty HTTP Server org.eclipse.jetty jetty-servlet ${project.version} provided org.eclipse.jetty jetty-websocket ${project.version} provided jetty8-8.1.3/jetty-aggregate/jetty-webapp/000077500000000000000000000000001174773561500204705ustar00rootroot00000000000000jetty8-8.1.3/jetty-aggregate/jetty-webapp/pom.xml000066400000000000000000000075131174773561500220130ustar00rootroot00000000000000 org.eclipse.jetty.aggregate jetty-aggregate-project 8.1.3.v20120416 4.0.0 jetty-webapp Jetty :: Aggregate :: WebApp Server ${project.build.directory}/sources org.apache.maven.plugins maven-dependency-plugin unpack-dependencies unpack-dependencies META-INF/**,org/eclipse/**,org/apache/jasper/compiler/** **/MANIFEST.MF,javax/** javax javax,org.eclipse.jetty.orbit ${project.build.directory}/classes false true unpack-source generate-sources unpack-dependencies sources **/* META-INF/** org.eclipse.jetty javax javax,org.eclipse.jetty.orbit ${project.build.directory}/sources true true org.apache.maven.plugins maven-jar-plugin package package jar development http://eclipse.org/jetty ${user.name} org.eclipse.jetty http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt Jetty HTTP Server org.eclipse.jetty jetty-webapp ${project.version} provided org.eclipse.jetty.orbit javax.servlet org.eclipse.jetty.orbit javax.servlet compile jetty8-8.1.3/jetty-aggregate/jetty-websocket/000077500000000000000000000000001174773561500212005ustar00rootroot00000000000000jetty8-8.1.3/jetty-aggregate/jetty-websocket/pom.xml000066400000000000000000000066501174773561500225240ustar00rootroot00000000000000 org.eclipse.jetty.aggregate jetty-aggregate-project 8.1.3.v20120416 4.0.0 jetty-websocket Jetty :: Aggregate :: Websocket ${project.build.directory}/sources org.apache.maven.plugins maven-dependency-plugin unpack-dependencies unpack-dependencies **/MANIFEST.MF,javax/**,about.html javax javax,org.eclipse.jetty.orbit ${project.build.directory}/classes false true unpack-source generate-sources unpack-dependencies sources **/* META-INF/** org.eclipse.jetty javax javax,org.eclipse.jetty.orbit ${project.build.directory}/sources true true org.apache.maven.plugins maven-jar-plugin package package jar development http://eclipse.org/jetty ${user.name} org.eclipse.jetty http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt Jetty HTTP Server org.eclipse.jetty jetty-websocket ${project.version} provided jetty8-8.1.3/jetty-aggregate/pom.xml000066400000000000000000000027371174773561500174030ustar00rootroot00000000000000 4.0.0 org.eclipse.jetty jetty-project 8.1.3.v20120416 org.eclipse.jetty.aggregate jetty-aggregate-project Jetty :: Aggregate Project pom org.apache.maven.plugins maven-pmd-plugin true org.codehaus.mojo findbugs-maven-plugin true jetty-server jetty-client jetty-servlet jetty-webapp jetty-websocket jetty-plus jetty-all-server jetty-all jetty8-8.1.3/jetty-ajp/000077500000000000000000000000001174773561500147015ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/pom.xml000066400000000000000000000050371174773561500162230ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 jetty-ajp Jetty :: AJP ${project.groupId}.ajp org.apache.felix maven-bundle-plugin true manifest javax.servlet.*;version="2.6.0",* org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.apache.maven.plugins maven-assembly-plugin package single config org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.ajp.* org.eclipse.jetty jetty-server ${project.version} junit junit test jetty8-8.1.3/jetty-ajp/src/000077500000000000000000000000001174773561500154705ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/main/000077500000000000000000000000001174773561500164145ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/main/config/000077500000000000000000000000001174773561500176615ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/main/config/etc/000077500000000000000000000000001174773561500204345ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/main/config/etc/jetty-ajp.xml000066400000000000000000000011241174773561500230630ustar00rootroot00000000000000 8009 jetty8-8.1.3/jetty-ajp/src/main/java/000077500000000000000000000000001174773561500173355ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/main/java/org/000077500000000000000000000000001174773561500201245ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/000077500000000000000000000000001174773561500215505ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500227075ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/000077500000000000000000000000001174773561500234615ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13Connection.java000066400000000000000000000176221174773561500272320ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Collection; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpException; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.BlockingHttpConnection; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * Connection implementation of the Ajp13 protocol.

XXX Refactor to remove * duplication of HttpConnection * */ public class Ajp13Connection extends BlockingHttpConnection { private static final Logger LOG = Log.getLogger(Ajp13Connection.class); public Ajp13Connection(Connector connector, EndPoint endPoint, Server server) { super(connector, endPoint, server, new Ajp13Parser(connector.getRequestBuffers(), endPoint), new Ajp13Generator(connector.getResponseBuffers(), endPoint), new Ajp13Request() ); ((Ajp13Parser)_parser).setEventHandler(new RequestHandler()); ((Ajp13Parser)_parser).setGenerator((Ajp13Generator)_generator); ((Ajp13Request)_request).setConnection(this); } @Override public boolean isConfidential(Request request) { return ((Ajp13Request) request).isSslSecure(); } @Override public boolean isIntegral(Request request) { return ((Ajp13Request) request).isSslSecure(); } @Override public ServletInputStream getInputStream() { if (_in == null) _in = new Ajp13Parser.Input((Ajp13Parser) _parser, _connector.getMaxIdleTime()); return _in; } private class RequestHandler implements Ajp13Parser.EventHandler { public void startForwardRequest() throws IOException { _uri.clear(); ((Ajp13Request) _request).setSslSecure(false); _request.setTimeStamp(System.currentTimeMillis()); _request.setUri(_uri); } public void parsedAuthorizationType(Buffer authType) throws IOException { //TODO JASPI this doesn't appear to make sense yet... how does ajp auth fit into jetty auth? // _request.setAuthType(authType.toString()); } public void parsedRemoteUser(Buffer remoteUser) throws IOException { ((Ajp13Request)_request).setRemoteUser(remoteUser.toString()); } public void parsedServletPath(Buffer servletPath) throws IOException { _request.setServletPath(servletPath.toString()); } public void parsedContextPath(Buffer context) throws IOException { _request.setContextPath(context.toString()); } public void parsedSslCert(Buffer sslCert) throws IOException { try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); ByteArrayInputStream bis = new ByteArrayInputStream(sslCert.toString().getBytes()); Collection certCollection = cf.generateCertificates(bis); X509Certificate[] certificates = new X509Certificate[certCollection.size()]; int i=0; for (Object aCertCollection : certCollection) { certificates[i++] = (X509Certificate) aCertCollection; } _request.setAttribute("javax.servlet.request.X509Certificate", certificates); } catch (Exception e) { LOG.warn(e.toString()); LOG.ignore(e); if (sslCert!=null) _request.setAttribute("javax.servlet.request.X509Certificate", sslCert.toString()); } } public void parsedSslCipher(Buffer sslCipher) throws IOException { _request.setAttribute("javax.servlet.request.cipher_suite", sslCipher.toString()); } public void parsedSslSession(Buffer sslSession) throws IOException { _request.setAttribute("javax.servlet.request.ssl_session", sslSession.toString()); } public void parsedSslKeySize(int keySize) throws IOException { _request.setAttribute("javax.servlet.request.key_size", new Integer(keySize)); } public void parsedMethod(Buffer method) throws IOException { if (method == null) throw new HttpException(HttpServletResponse.SC_BAD_REQUEST); _request.setMethod(method.toString()); } public void parsedUri(Buffer uri) throws IOException { _uri.parse(uri.toString()); } public void parsedProtocol(Buffer protocol) throws IOException { if (protocol != null && protocol.length()>0) { _request.setProtocol(protocol.toString()); } } public void parsedRemoteAddr(Buffer addr) throws IOException { if (addr != null && addr.length()>0) { _request.setRemoteAddr(addr.toString()); } } public void parsedRemoteHost(Buffer name) throws IOException { if (name != null && name.length()>0) { _request.setRemoteHost(name.toString()); } } public void parsedServerName(Buffer name) throws IOException { if (name != null && name.length()>0) { _request.setServerName(name.toString()); } } public void parsedServerPort(int port) throws IOException { _request.setServerPort(port); } public void parsedSslSecure(boolean secure) throws IOException { ((Ajp13Request) _request).setSslSecure(secure); } public void parsedQueryString(Buffer value) throws IOException { String u = _uri + "?" + value; _uri.parse(u); } public void parsedHeader(Buffer name, Buffer value) throws IOException { _requestFields.add(name, value); } public void parsedRequestAttribute(String key, Buffer value) throws IOException { if (value==null) _request.removeAttribute(key); else _request.setAttribute(key,value.toString()); } public void parsedRequestAttribute(String key, int value) throws IOException { _request.setAttribute(key, Integer.toString(value)); } public void headerComplete() throws IOException { handleRequest(); } public void messageComplete(long contextLength) throws IOException { } public void content(Buffer ref) throws IOException { } } } jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13Generator.java000066400000000000000000000565771174773561500270750ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.HashMap; import org.eclipse.jetty.http.AbstractGenerator; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpTokens; import org.eclipse.jetty.http.HttpVersions; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * * */ public class Ajp13Generator extends AbstractGenerator { private static final Logger LOG = Log.getLogger(Ajp13Generator.class); private static HashMap __headerHash = new HashMap(); static { byte[] xA001 = { (byte)0xA0, (byte)0x01 }; byte[] xA002 = { (byte)0xA0, (byte)0x02 }; byte[] xA003 = { (byte)0xA0, (byte)0x03 }; byte[] xA004 = { (byte)0xA0, (byte)0x04 }; byte[] xA005 = { (byte)0xA0, (byte)0x05 }; byte[] xA006 = { (byte)0xA0, (byte)0x06 }; byte[] xA007 = { (byte)0xA0, (byte)0x07 }; byte[] xA008 = { (byte)0xA0, (byte)0x08 }; byte[] xA009 = { (byte)0xA0, (byte)0x09 }; byte[] xA00A = { (byte)0xA0, (byte)0x0A }; byte[] xA00B = { (byte)0xA0, (byte)0x0B }; __headerHash.put("Content-Type",xA001); __headerHash.put("Content-Language",xA002); __headerHash.put("Content-Length",xA003); __headerHash.put("Date",xA004); __headerHash.put("Last-Modified",xA005); __headerHash.put("Location",xA006); __headerHash.put("Set-Cookie",xA007); __headerHash.put("Set-Cookie2",xA008); __headerHash.put("Servlet-Engine",xA009); __headerHash.put("Status",xA00A); __headerHash.put("WWW-Authenticate",xA00B); } // A, B ajp response header // 0, 1 ajp int 1 packet length // 9 CPONG response Code private static final byte[] AJP13_CPONG_RESPONSE = { 'A', 'B', 0, 1, 9 }; private static final byte[] AJP13_END_RESPONSE = { 'A', 'B', 0, 2, 5, 1 }; // AB ajp respose // 0, 3 int = 3 packets in length // 6, send signal to get more data // 31, -7 byte values for int 8185 = (8 * 1024) - 7 MAX_DATA private static final byte[] AJP13_MORE_CONTENT = { 'A', 'B', 0, 3, 6, 31, -7 }; private static String SERVER = "Server: Jetty(7.x.x)"; public static void setServerVersion(String version) { SERVER = "Jetty(" + version + ")"; } /* ------------------------------------------------------------ */ private boolean _expectMore = false; private boolean _needMore = false; private boolean _needEOC = false; private boolean _bufferPrepared = false; /* ------------------------------------------------------------ */ public Ajp13Generator(Buffers buffers, EndPoint io) { super(buffers,io); } /* ------------------------------------------------------------ */ @Override public boolean isRequest() { return false; } /* ------------------------------------------------------------ */ @Override public boolean isResponse() { return true; } /* ------------------------------------------------------------ */ @Override public void reset() { super.reset(); _needEOC = false; _needMore = false; _expectMore = false; _bufferPrepared = false; _last = false; _state = STATE_HEADER; _status = 0; _version = HttpVersions.HTTP_1_1_ORDINAL; _reason = null; _method = null; _uri = null; _contentWritten = 0; _contentLength = HttpTokens.UNKNOWN_CONTENT; _last = false; _head = false; _noContent = false; _persistent = true; _header = null; // Buffer for HTTP header (and maybe small _content) _buffer = null; // Buffer for copy of passed _content _content = null; // Buffer passed to addContent } /* ------------------------------------------------------------ */ @Override public int getContentBufferSize() { try { initContent(); } catch (IOException e) { throw new RuntimeException(e); } return super.getContentBufferSize() - 7; } /* ------------------------------------------------------------ */ @Override public void increaseContentBufferSize(int contentBufferSize) { // Not supported with AJP } /* ------------------------------------------------------------ */ /** * Add content. * * @param content * @param last * @throws IllegalArgumentException * if content is {@link Buffer#isImmutable immutable}. * @throws IllegalStateException * If the request is not expecting any more content, or if the buffers are full and cannot be flushed. * @throws IOException * if there is a problem flushing the buffers. */ public void addContent(Buffer content, boolean last) throws IOException { if (_noContent) { content.clear(); return; } if (content.isImmutable()) throw new IllegalArgumentException("immutable"); if (_last || _state == STATE_END) { LOG.debug("Ignoring extra content {}",content); content.clear(); return; } _last = last; if (!_endp.isOpen()) { _state = STATE_END; return; } // Handle any unfinished business? if (_content != null && _content.length() > 0) { flushBuffer(); if (_content != null && _content.length() > 0) throw new IllegalStateException("FULL"); } _content = content; _contentWritten += content.length(); // Handle the _content if (_head) { content.clear(); _content = null; } else { // Yes - so we better check we have a buffer initContent(); // Copy _content to buffer; int len = 0; len = _buffer.put(_content); // make sure there is space for a trailing null if (len > 0 && _buffer.space() == 0) { len--; _buffer.setPutIndex(_buffer.putIndex() - 1); } _content.skip(len); if (_content.length() == 0) _content = null; } } /* ------------------------------------------------------------ */ /** * Add content. * * @param b * byte * @return true if the buffers are full * @throws IOException */ public boolean addContent(byte b) throws IOException { if (_noContent) return false; if (_last || _state == STATE_END) throw new IllegalStateException("Closed"); if (!_endp.isOpen()) { _state = STATE_END; return false; } // Handle any unfinished business? if (_content != null && _content.length() > 0) { flushBuffer(); if (_content != null && _content.length() > 0) throw new IllegalStateException("FULL"); } _contentWritten++; // Handle the _content if (_head) return false; // we better check we have a buffer initContent(); // Copy _content to buffer; _buffer.put(b); return _buffer.space() <= 1; } /* ------------------------------------------------------------ */ /** * Prepare buffer for unchecked writes. Prepare the generator buffer to receive unchecked writes * * @return the available space in the buffer. * @throws IOException */ @Override public int prepareUncheckedAddContent() throws IOException { if (_noContent) return -1; if (_last || _state == STATE_END) throw new IllegalStateException("Closed"); if (!_endp.isOpen()) { _state = STATE_END; return -1; } // Handle any unfinished business? Buffer content = _content; if (content != null && content.length() > 0) { flushBuffer(); if (content != null && content.length() > 0) throw new IllegalStateException("FULL"); } // we better check we have a buffer initContent(); _contentWritten -= _buffer.length(); // Handle the _content if (_head) return Integer.MAX_VALUE; return _buffer.space() - 1; } /* ------------------------------------------------------------ */ @Override public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException { if (_state != STATE_HEADER) return; if (_last && !allContentAdded) throw new IllegalStateException("last?"); _last = _last | allContentAdded; boolean has_server = false; if (_persistent == null) _persistent = (_version > HttpVersions.HTTP_1_0_ORDINAL); // get a header buffer if (_header == null) _header = _buffers.getHeader(); Buffer tmpbuf = _buffer; _buffer = _header; try { // start the header _buffer.put((byte)'A'); _buffer.put((byte)'B'); addInt(0); _buffer.put((byte)0x4); addInt(_status); if (_reason == null) _reason = HttpGenerator.getReasonBuffer(_status); if (_reason == null) _reason = new ByteArrayBuffer(Integer.toString(_status)); addBuffer(_reason); if (_status == 100 || _status == 204 || _status == 304) { _noContent = true; _content = null; } // allocate 2 bytes for number of headers int field_index = _buffer.putIndex(); addInt(0); int num_fields = 0; if (fields != null) { // Add headers int s = fields.size(); for (int f = 0; f < s; f++) { HttpFields.Field field = fields.getField(f); if (field == null) continue; num_fields++; byte[] codes = (byte[])__headerHash.get(field.getName()); if (codes != null) { _buffer.put(codes); } else { addString(field.getName()); } addString(field.getValue()); } } if (!has_server && _status > 100 && getSendServerVersion()) { num_fields++; addString("Server"); addString(SERVER); } // TODO Add content length if last content known. // insert the number of headers int tmp = _buffer.putIndex(); _buffer.setPutIndex(field_index); addInt(num_fields); _buffer.setPutIndex(tmp); // get the payload size ( - 4 bytes for the ajp header) // excluding the // ajp header int payloadSize = _buffer.length() - 4; // insert the total packet size on 2nd and 3rd byte that // was previously // allocated addInt(2,payloadSize); } finally { _buffer = tmpbuf; } _state = STATE_CONTENT; } /* ------------------------------------------------------------ */ /** * Complete the message. * * @throws IOException */ @Override public void complete() throws IOException { if (_state == STATE_END) return; super.complete(); if (_state < STATE_FLUSHING) { _state = STATE_FLUSHING; _needEOC = true; } flushBuffer(); } /* ------------------------------------------------------------ */ @Override public int flushBuffer() throws IOException { try { if (_state == STATE_HEADER && !_expectMore) throw new IllegalStateException("State==HEADER"); prepareBuffers(); if (_endp == null) { // TODO - probably still needed! // if (_rneedMore && _buffe != null) // { // if(!_hasSentEOC) // _buffer.put(AJP13_MORE_CONTENT); // } if (!_expectMore && _needEOC && _buffer != null) { _buffer.put(AJP13_END_RESPONSE); } _needEOC = false; return 0; } // Keep flushing while there is something to flush // (except break below) int total = 0; long last_len = -1; Flushing: while (true) { int len = -1; int to_flush = ((_header != null && _header.length() > 0)?4:0) | ((_buffer != null && _buffer.length() > 0)?2:0); switch (to_flush) { case 7: throw new IllegalStateException(); // should // never // happen! case 6: len = _endp.flush(_header,_buffer,null); break; case 5: throw new IllegalStateException(); // should // never // happen! case 4: len = _endp.flush(_header); break; case 3: throw new IllegalStateException(); // should // never // happen! case 2: len = _endp.flush(_buffer); break; case 1: throw new IllegalStateException(); // should // never // happen! case 0: { // Nothing more we can write now. if (_header != null) _header.clear(); _bufferPrepared = false; if (_buffer != null) { _buffer.clear(); // reserve some space for the // header _buffer.setPutIndex(7); _buffer.setGetIndex(7); // Special case handling for // small left over buffer from // an addContent that caused a // buffer flush. if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING) { _buffer.put(_content); _content.clear(); _content = null; break Flushing; } } // Are we completely finished for now? if (!_expectMore && !_needEOC && (_content == null || _content.length() == 0)) { if (_state == STATE_FLUSHING) _state = STATE_END; // if (_state == STATE_END) // { // _endp.close(); // } // break Flushing; } // Try to prepare more to write. prepareBuffers(); } } // If we failed to flush anything twice in a row // break if (len <= 0) { if (last_len <= 0) break Flushing; break; } last_len = len; total += len; } return total; } catch (IOException e) { LOG.ignore(e); throw (e instanceof EofException)?e:new EofException(e); } } /* ------------------------------------------------------------ */ private void prepareBuffers() { if (!_bufferPrepared) { // Refill buffer if possible if (_content != null && _content.length() > 0 && _buffer != null && _buffer.space() > 0) { int len = _buffer.put(_content); // Make sure there is space for a trailing null if (len > 0 && _buffer.space() == 0) { len--; _buffer.setPutIndex(_buffer.putIndex() - 1); } _content.skip(len); if (_content.length() == 0) _content = null; if (_buffer.length() == 0) { _content = null; } } // add header if needed if (_buffer != null) { int payloadSize = _buffer.length(); // 4 bytes for the ajp header // 1 byte for response type // 2 bytes for the response size // 1 byte because we count from zero?? if (payloadSize > 0) { _bufferPrepared = true; _buffer.put((byte)0); int put = _buffer.putIndex(); _buffer.setGetIndex(0); _buffer.setPutIndex(0); _buffer.put((byte)'A'); _buffer.put((byte)'B'); addInt(payloadSize + 4); _buffer.put((byte)3); addInt(payloadSize); _buffer.setPutIndex(put); } } if (_needMore) { if (_header == null) { _header = _buffers.getHeader(); } if (_buffer == null && _header != null && _header.space() >= AJP13_MORE_CONTENT.length) { _header.put(AJP13_MORE_CONTENT); _needMore = false; } else if (_buffer != null && _buffer.space() >= AJP13_MORE_CONTENT.length) { // send closing packet if all contents // are added _buffer.put(AJP13_MORE_CONTENT); _needMore = false; _bufferPrepared = true; } } if (!_expectMore && _needEOC) { if (_buffer == null && _header.space() >= AJP13_END_RESPONSE.length) { _header.put(AJP13_END_RESPONSE); _needEOC = false; } else if (_buffer != null && _buffer.space() >= AJP13_END_RESPONSE.length) { // send closing packet if all contents // are added _buffer.put(AJP13_END_RESPONSE); _needEOC = false; _bufferPrepared = true; } } } } /* ------------------------------------------------------------ */ @Override public boolean isComplete() { return !_expectMore && _state == STATE_END; } /* ------------------------------------------------------------ */ private void initContent() throws IOException { if (_buffer == null) { _buffer = _buffers.getBuffer(); _buffer.setPutIndex(7); _buffer.setGetIndex(7); } } /* ------------------------------------------------------------ */ private void addInt(int i) { _buffer.put((byte)((i >> 8) & 0xFF)); _buffer.put((byte)(i & 0xFF)); } /* ------------------------------------------------------------ */ private void addInt(int startIndex, int i) { _buffer.poke(startIndex,(byte)((i >> 8) & 0xFF)); _buffer.poke((startIndex + 1),(byte)(i & 0xFF)); } /* ------------------------------------------------------------ */ private void addString(String str) throws UnsupportedEncodingException { if (str == null) { addInt(0xFFFF); return; } // TODO - need to use a writer to convert, to avoid this hacky // conversion and temp buffer byte[] b = str.getBytes(StringUtil.__ISO_8859_1); addInt(b.length); _buffer.put(b); _buffer.put((byte)0); } /* ------------------------------------------------------------ */ private void addBuffer(Buffer b) { if (b == null) { addInt(0xFFFF); return; } addInt(b.length()); _buffer.put(b); _buffer.put((byte)0); } /* ------------------------------------------------------------ */ public void getBodyChunk() throws IOException { ByteArrayBuffer bf = new ByteArrayBuffer(AJP13_MORE_CONTENT); _endp.flush(bf); } /* ------------------------------------------------------------ */ public void gotBody() { _needMore = false; _expectMore = false; } /* ------------------------------------------------------------ */ public void sendCPong() throws IOException { Buffer buff = _buffers.getBuffer(); buff.put(AJP13_CPONG_RESPONSE); // flushing cpong response do { _endp.flush(buff); } while (buff.length() > 0); _buffers.returnBuffer(buff); reset(); } } jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13Packet.java000066400000000000000000000046451174773561500263430ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import org.eclipse.jetty.io.BufferCache; /** * */ public class Ajp13Packet { public final static int MAX_PACKET_SIZE=(8*1024); public final static int HDR_SIZE=4; // Used in writing response... public final static int DATA_HDR_SIZE=7; public final static int MAX_DATA_SIZE=MAX_PACKET_SIZE-DATA_HDR_SIZE; public final static String // Server -> Container FORWARD_REQUEST="FORWARD REQUEST", SHUTDOWN="SHUTDOWN", PING_REQUEST="PING REQUEST", // Obsolete CPING_REQUEST="CPING REQUEST", // Server <- Container SEND_BODY_CHUNK="SEND BODY CHUNK", SEND_HEADERS="SEND HEADERS", END_RESPONSE="END RESPONSE", GET_BODY_CHUNK="GET BODY CHUNK", CPONG_REPLY="CPONG REPLY"; public final static int FORWARD_REQUEST_ORDINAL=2, SHUTDOWN_ORDINAL=7, PING_REQUEST_ORDINAL=8, // Obsolete CPING_REQUEST_ORDINAL=10, SEND_BODY_CHUNK_ORDINAL=3, SEND_HEADERS_ORDINAL=4, END_RESPONSE_ORDINAL=5, GET_BODY_CHUNK_ORDINAL=6, CPONG_REPLY_ORDINAL=9; public final static BufferCache CACHE=new BufferCache(); static { CACHE.add(FORWARD_REQUEST,FORWARD_REQUEST_ORDINAL); CACHE.add(SHUTDOWN,SHUTDOWN_ORDINAL); CACHE.add(PING_REQUEST,PING_REQUEST_ORDINAL); // Obsolete CACHE.add(CPING_REQUEST,CPING_REQUEST_ORDINAL); CACHE.add(SEND_BODY_CHUNK,SEND_BODY_CHUNK_ORDINAL); CACHE.add(SEND_HEADERS,SEND_HEADERS_ORDINAL); CACHE.add(END_RESPONSE,END_RESPONSE_ORDINAL); CACHE.add(GET_BODY_CHUNK,GET_BODY_CHUNK_ORDINAL); CACHE.add(CPONG_REPLY,CPONG_REPLY_ORDINAL); } } jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13PacketMethods.java000066400000000000000000000075171174773561500276700ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache; /** * */ public class Ajp13PacketMethods { // TODO - this can probably be replaced by HttpMethods or at least an // extension of it. // It is probably most efficient if "GET" ends up as the same instance public final static String OPTIONS="OPTIONS", GET="GET", HEAD="HEAD", POST="POST", PUT="PUT", DELETE="DELETE", TRACE="TRACE", PROPFIND="PROPFIND", PROPPATCH="PROPPATCH", MKCOL="MKCOL", COPY="COPY", MOVE="MOVE", LOCK="LOCK", UNLOCK="UNLOCK", ACL="ACL", REPORT="REPORT", VERSION_CONTROL="VERSION-CONTROL", CHECKIN="CHECKIN", CHECKOUT="CHECKOUT", UNCHCKOUT="UNCHECKOUT", SEARCH="SEARCH", MKWORKSPACE="MKWORKSPACE", UPDATE="UPDATE", LABEL="LABEL", MERGE="MERGE", BASELINE_CONTROL="BASELINE-CONTROL", MKACTIVITY="MKACTIVITY"; public final static int OPTIONS_ORDINAL=1, GET_ORDINAL=2, HEAD_ORDINAL=3, POST__ORDINAL=4, PUT_ORDINAL=5, DELETE_ORDINAL=6, TRACE_ORDINAL=7, PROPFIND_ORDINAL=8, PROPPATCH_ORDINAL=9, MKCOL_ORDINAL=10, COPY_ORDINAL=11, MOVE_ORDINAL=12, LOCK_ORDINAL=13, UNLOCK_ORDINAL=14, ACL_ORDINAL=15, REPORT_ORDINAL=16, VERSION_CONTROL_ORDINAL=17, CHECKIN_ORDINAL=18, CHECKOUT_ORDINAL=19, UNCHCKOUT_ORDINAL=20, SEARCH_ORDINAL=21, MKWORKSPACE_ORDINAL=22, UPDATE_ORDINAL=23, LABEL_ORDINAL=24, MERGE_ORDINAL=25, BASELINE_CONTROL_ORDINAL=26, MKACTIVITY_ORDINAL=27; public final static BufferCache CACHE=new BufferCache(); public final static Buffer OPTIONS_BUFFER=CACHE.add(OPTIONS,OPTIONS_ORDINAL), GET_BUFFER=CACHE.add(GET,GET_ORDINAL), HEAD_BUFFER=CACHE.add(HEAD, HEAD_ORDINAL), POST__BUFFER=CACHE.add(POST,POST__ORDINAL), PUT_BUFFER=CACHE.add(PUT,PUT_ORDINAL), DELETE_BUFFER=CACHE.add(DELETE,DELETE_ORDINAL), TRACE_BUFFER=CACHE.add(TRACE,TRACE_ORDINAL), PROPFIND_BUFFER=CACHE.add(PROPFIND,PROPFIND_ORDINAL), PROPPATCH_BUFFER=CACHE.add(PROPPATCH, PROPPATCH_ORDINAL), MKCOL_BUFFER=CACHE.add(MKCOL,MKCOL_ORDINAL), COPY_BUFFER=CACHE.add(COPY,COPY_ORDINAL), MOVE_BUFFER=CACHE.add(MOVE,MOVE_ORDINAL), LOCK_BUFFER=CACHE.add(LOCK,LOCK_ORDINAL), UNLOCK_BUFFER=CACHE.add(UNLOCK,UNLOCK_ORDINAL), ACL_BUFFER=CACHE.add(ACL,ACL_ORDINAL), REPORT_BUFFER=CACHE.add(REPORT,REPORT_ORDINAL), VERSION_CONTROL_BUFFER=CACHE.add(VERSION_CONTROL,VERSION_CONTROL_ORDINAL), CHECKIN_BUFFER=CACHE.add(CHECKIN,CHECKIN_ORDINAL), CHECKOUT_BUFFER=CACHE.add(CHECKOUT,CHECKOUT_ORDINAL), UNCHCKOUT_BUFFER=CACHE.add(UNCHCKOUT,UNCHCKOUT_ORDINAL), SEARCH_BUFFER=CACHE.add(SEARCH,SEARCH_ORDINAL), MKWORKSPACE_BUFFER=CACHE.add(MKWORKSPACE,MKWORKSPACE_ORDINAL), UPDATE_BUFFER=CACHE.add(UPDATE,UPDATE_ORDINAL), LABEL_BUFFER=CACHE.add(LABEL,LABEL_ORDINAL), MERGE_BUFFER=CACHE.add(MERGE,MERGE_ORDINAL), BASELINE_CONTROL_BUFFER=CACHE.add(BASELINE_CONTROL,BASELINE_CONTROL_ORDINAL), MKACTIVITY_BUFFER=CACHE.add(MKACTIVITY,MKACTIVITY_ORDINAL); } jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13Parser.java000066400000000000000000000743051174773561500263700ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import java.io.IOException; import java.io.InterruptedIOException; import javax.servlet.ServletInputStream; import org.eclipse.jetty.http.HttpTokens; import org.eclipse.jetty.http.Parser; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferUtil; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.View; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * */ public class Ajp13Parser implements Parser { private static final Logger LOG = Log.getLogger(Ajp13Parser.class); private final static int STATE_START = -1; private final static int STATE_END = 0; private final static int STATE_AJP13CHUNK_START = 1; private final static int STATE_AJP13CHUNK = 2; private int _state = STATE_START; private long _contentLength; private long _contentPosition; private int _chunkLength; private int _chunkPosition; private int _headers; private Buffers _buffers; private EndPoint _endp; private Buffer _buffer; private Buffer _header; // Buffer for header data (and small _content) private Buffer _body; // Buffer for large content private View _contentView = new View(); private EventHandler _handler; private Ajp13Generator _generator; private View _tok0; // Saved token: header name, request method or response version private View _tok1; // Saved token: header value, request URI orresponse code protected int _length; protected int _packetLength; /* ------------------------------------------------------------------------------- */ public Ajp13Parser(Buffers buffers, EndPoint endPoint) { _buffers = buffers; _endp = endPoint; } /* ------------------------------------------------------------------------------- */ public void setEventHandler(EventHandler handler) { _handler=handler; } /* ------------------------------------------------------------------------------- */ public void setGenerator(Ajp13Generator generator) { _generator=generator; } /* ------------------------------------------------------------------------------- */ public long getContentLength() { return _contentLength; } /* ------------------------------------------------------------------------------- */ public int getState() { return _state; } /* ------------------------------------------------------------------------------- */ public boolean inContentState() { return _state > 0; } /* ------------------------------------------------------------------------------- */ public boolean inHeaderState() { return _state < 0; } /* ------------------------------------------------------------------------------- */ public boolean isIdle() { return _state == STATE_START; } /* ------------------------------------------------------------------------------- */ public boolean isComplete() { return _state == STATE_END; } /* ------------------------------------------------------------------------------- */ public boolean isMoreInBuffer() { if (_header != null && _header.hasContent() || _body != null && _body.hasContent()) return true; return false; } /* ------------------------------------------------------------------------------- */ public boolean isState(int state) { return _state == state; } /* ------------------------------------------------------------------------------- */ public void parse() throws IOException { if (_state == STATE_END) reset(); if (_state != STATE_START) throw new IllegalStateException("!START"); // continue parsing while (!isComplete()) { parseNext(); } } /* ------------------------------------------------------------------------------- */ public boolean parseAvailable() throws IOException { boolean progress=parseNext()>0; // continue parsing while (!isComplete() && _buffer!=null && _buffer.length()>0) { progress |= parseNext()>0; } return progress; } /* ------------------------------------------------------------------------------- */ private int fill() throws IOException { int filled = -1; if (_body != null && _buffer != _body) { // mod_jk implementations may have some partial data from header // check if there are partial contents in the header // copy it to the body if there are any if(_header.length() > 0) { // copy the patial data from the header to the body _body.put(_header); } _buffer = _body; if (_buffer.length()>0) { filled = _buffer.length(); return filled; } } if (_buffer.markIndex() == 0 && _buffer.putIndex() == _buffer.capacity()) throw new IOException("FULL"); if (_endp != null && filled <= 0) { // Compress buffer if handling _content buffer // TODO check this is not moving data too much if (_buffer == _body) _buffer.compact(); if (_buffer.space() == 0) throw new IOException("FULL"); try { filled = _endp.fill(_buffer); } catch (IOException e) { // This is normal in AJP since the socket closes on timeout only LOG.debug(e); reset(); throw (e instanceof EofException) ? e : new EofException(e); } } if (filled < 0) { if (_state > STATE_END) { _state = STATE_END; _handler.messageComplete(_contentPosition); return filled; } reset(); throw new EofException(); } return filled; } volatile int _seq=0; /* ------------------------------------------------------------------------------- */ public int parseNext() throws IOException { int total_filled = 0; if (_buffer == null) { if (_header == null) _header = _buffers.getHeader(); _buffer = _header; _tok0 = new View(_header); _tok1 = new View(_header); _tok0.setPutIndex(_tok0.getIndex()); _tok1.setPutIndex(_tok1.getIndex()); } if (_state == STATE_END) throw new IllegalStateException("STATE_END"); if (_state > STATE_END && _contentPosition == _contentLength) { _state = STATE_END; _handler.messageComplete(_contentPosition); return 1; } if (_state < 0) { // have we seen a packet? if (_packetLength<=0) { if (_buffer.length()<4) { if (total_filled<0) total_filled=0; total_filled+=fill(); if (_buffer.length()<4) return total_filled; } _contentLength = HttpTokens.UNKNOWN_CONTENT; int _magic = Ajp13RequestPacket.getInt(_buffer); if (_magic != Ajp13RequestHeaders.MAGIC) throw new IOException("Bad AJP13 rcv packet: " + "0x" + Integer.toHexString(_magic) + " expected " + "0x" + Integer.toHexString(Ajp13RequestHeaders.MAGIC) + " " + this); _packetLength = Ajp13RequestPacket.getInt(_buffer); if (_packetLength > Ajp13Packet.MAX_PACKET_SIZE) throw new IOException("AJP13 packet (" + _packetLength + "bytes) too large for buffer"); } if (_buffer.length() < _packetLength) { if (total_filled<0) total_filled=0; total_filled+=fill(); if (_buffer.length() < _packetLength) return total_filled; } // Parse Header Buffer bufHeaderName = null; Buffer bufHeaderValue = null; int attr_type = 0; byte packetType = Ajp13RequestPacket.getByte(_buffer); switch (packetType) { case Ajp13Packet.FORWARD_REQUEST_ORDINAL: _handler.startForwardRequest(); break; case Ajp13Packet.CPING_REQUEST_ORDINAL: (_generator).sendCPong(); if(_header != null) { _buffers.returnBuffer(_header); _header = null; } if(_body != null) { _buffers.returnBuffer(_body); _body = null; } _buffer= null; reset(); return -1; case Ajp13Packet.SHUTDOWN_ORDINAL: shutdownRequest(); return -1; default: // XXX Throw an Exception here?? Close // connection! LOG.warn("AJP13 message type ({PING}: "+packetType+" ) not supported/recognized as an AJP request"); throw new IllegalStateException("PING is not implemented"); } _handler.parsedMethod(Ajp13RequestPacket.getMethod(_buffer)); _handler.parsedProtocol(Ajp13RequestPacket.getString(_buffer, _tok0)); _handler.parsedUri(Ajp13RequestPacket.getString(_buffer, _tok1)); _handler.parsedRemoteAddr(Ajp13RequestPacket.getString(_buffer, _tok1)); _handler.parsedRemoteHost(Ajp13RequestPacket.getString(_buffer, _tok1)); _handler.parsedServerName(Ajp13RequestPacket.getString(_buffer, _tok1)); _handler.parsedServerPort(Ajp13RequestPacket.getInt(_buffer)); _handler.parsedSslSecure(Ajp13RequestPacket.getBool(_buffer)); _headers = Ajp13RequestPacket.getInt(_buffer); for (int h=0;h<_headers;h++) { bufHeaderName = Ajp13RequestPacket.getHeaderName(_buffer, _tok0); bufHeaderValue = Ajp13RequestPacket.getString(_buffer, _tok1); if (bufHeaderName != null && bufHeaderName.toString().equals(Ajp13RequestHeaders.CONTENT_LENGTH)) { _contentLength = BufferUtil.toLong(bufHeaderValue); if (_contentLength == 0) _contentLength = HttpTokens.NO_CONTENT; } _handler.parsedHeader(bufHeaderName, bufHeaderValue); } attr_type = Ajp13RequestPacket.getByte(_buffer) & 0xff; while (attr_type != 0xFF) { switch (attr_type) { // XXX How does this plug into the web // containers // authentication? case Ajp13RequestHeaders.REMOTE_USER_ATTR: _handler.parsedRemoteUser(Ajp13RequestPacket.getString(_buffer, _tok1)); break; case Ajp13RequestHeaders.AUTH_TYPE_ATTR: //XXX JASPI how does this make sense? _handler.parsedAuthorizationType(Ajp13RequestPacket.getString(_buffer, _tok1)); break; case Ajp13RequestHeaders.QUERY_STRING_ATTR: _handler.parsedQueryString(Ajp13RequestPacket.getString(_buffer, _tok1)); break; case Ajp13RequestHeaders.JVM_ROUTE_ATTR: // moved to Eclipse naming usage // used in org.eclipse.jetty.servlet.HashSessionIdManager _handler.parsedRequestAttribute("org.eclipse.jetty.ajp.JVMRoute", Ajp13RequestPacket.getString(_buffer, _tok1)); break; case Ajp13RequestHeaders.SSL_CERT_ATTR: _handler.parsedSslCert(Ajp13RequestPacket.getString(_buffer, _tok1)); break; case Ajp13RequestHeaders.SSL_CIPHER_ATTR: _handler.parsedSslCipher(Ajp13RequestPacket.getString(_buffer, _tok1)); // SslSocketConnector.customize() break; case Ajp13RequestHeaders.SSL_SESSION_ATTR: _handler.parsedSslSession(Ajp13RequestPacket.getString(_buffer, _tok1)); break; case Ajp13RequestHeaders.REQUEST_ATTR: _handler.parsedRequestAttribute(Ajp13RequestPacket.getString(_buffer, _tok0).toString(), Ajp13RequestPacket.getString(_buffer, _tok1)); break; // New Jk API? // Check if experimental or can they // assumed to be // supported case Ajp13RequestHeaders.SSL_KEYSIZE_ATTR: // This has been implemented in AJP13 as either a string or a integer. // Servlet specs say javax.servlet.request.key_size must be an Integer // Does it look like a string containing digits? int length = Ajp13RequestPacket.getInt(_buffer); if (length>0 && length<16) { // this must be a string length rather than a key length _buffer.skip(-2); _handler.parsedSslKeySize(Integer.parseInt(Ajp13RequestPacket.getString(_buffer, _tok1).toString())); } else _handler.parsedSslKeySize(length); break; // Used to lock down jk requests with a // secreate // key. case Ajp13RequestHeaders.SECRET_ATTR: // XXX Investigate safest way to // deal with // this... // should this tie into shutdown // packet? break; case Ajp13RequestHeaders.STORED_METHOD_ATTR: // XXX Confirm this should // really overide // previously parsed method? // _handler.parsedMethod(Ajp13PacketMethods.CACHE.get(Ajp13RequestPacket.getString())); break; case Ajp13RequestHeaders.CONTEXT_ATTR: _handler.parsedContextPath(Ajp13RequestPacket.getString(_buffer, _tok1)); break; case Ajp13RequestHeaders.SERVLET_PATH_ATTR: _handler.parsedServletPath(Ajp13RequestPacket.getString(_buffer, _tok1)); break; default: LOG.warn("Unsupported Ajp13 Request Attribute {}", new Integer(attr_type)); break; } attr_type = Ajp13RequestPacket.getByte(_buffer) & 0xff; } _contentPosition = 0; switch ((int) _contentLength) { case HttpTokens.NO_CONTENT: _state = STATE_END; _handler.headerComplete(); _handler.messageComplete(_contentPosition); break; case HttpTokens.UNKNOWN_CONTENT: _generator.getBodyChunk(); if (_buffers != null && _body == null && _buffer == _header && _header.length() <= 0) { _body = _buffers.getBuffer(); _body.clear(); } _state = STATE_AJP13CHUNK_START; _handler.headerComplete(); // May recurse here! return total_filled; default: if (_buffers != null && _body == null && _buffer == _header && _contentLength > (_header.capacity() - _header.getIndex())) { _body = _buffers.getBuffer(); _body.clear(); } _state = STATE_AJP13CHUNK_START; _handler.headerComplete(); // May recurse here! return total_filled; } } Buffer chunk; while (_state>STATE_END) { switch (_state) { case STATE_AJP13CHUNK_START: if (_buffer.length()<6) { if (total_filled<0) total_filled=0; total_filled+=fill(); if (_buffer.length()<6) return total_filled; } int _magic=Ajp13RequestPacket.getInt(_buffer); if (_magic!=Ajp13RequestHeaders.MAGIC) { throw new IOException("Bad AJP13 rcv packet: "+"0x"+Integer.toHexString(_magic)+" expected "+"0x" +Integer.toHexString(Ajp13RequestHeaders.MAGIC)+" "+this); } _chunkPosition=0; _chunkLength=Ajp13RequestPacket.getInt(_buffer)-2; Ajp13RequestPacket.getInt(_buffer); if (_chunkLength==0) { _state=STATE_END; _generator.gotBody(); _handler.messageComplete(_contentPosition); return total_filled; } _state=STATE_AJP13CHUNK; break; case STATE_AJP13CHUNK: if (_buffer.length()<_chunkLength) { if (total_filled<0) total_filled=0; total_filled+=fill(); if (_buffer.length()<_chunkLength) return total_filled; } int remaining=_chunkLength-_chunkPosition; if (remaining==0) { _state=STATE_AJP13CHUNK_START; if (_contentPosition<_contentLength) { _generator.getBodyChunk(); } else { _generator.gotBody(); } return total_filled; } if (_buffer.length()_body.length()) take=_body.length(); _body.peek(_body.getIndex(),take); _body.skip(_header.put(_body.peek(_body.getIndex(),take))); } if (_header!=null) _header.setMarkIndex(-1); if (_body!=null) _body.setMarkIndex(-1); _buffer=_header; } /* ------------------------------------------------------------------------------- */ public void returnBuffers() { if (_body!=null && !_body.hasContent() && _body.markIndex()==-1) { if (_buffer==_body) _buffer=_header; if (_buffers!=null) _buffers.returnBuffer(_body); _body=null; } if (_header!=null && !_header.hasContent() && _header.markIndex()==-1) { if (_buffer==_header) _buffer=null; _buffers.returnBuffer(_header); _header=null; } } /* ------------------------------------------------------------------------------- */ Buffer getHeaderBuffer() { return _buffer; } private void shutdownRequest() { _state = STATE_END; if(!Ajp13SocketConnector.__allowShutdown) { LOG.warn("AJP13: Shutdown Request is Denied, allowShutdown is set to false!!!"); return; } if(Ajp13SocketConnector.__secretWord != null) { LOG.warn("AJP13: Validating Secret Word"); try { String secretWord = Ajp13RequestPacket.getString(_buffer, _tok1).toString(); if(!Ajp13SocketConnector.__secretWord.equals(secretWord)) { LOG.warn("AJP13: Shutdown Request Denied, Invalid Sercret word!!!"); throw new IllegalStateException("AJP13: Secret Word is Invalid: Peer has requested shutdown but, Secret Word did not match"); } } catch (Exception e) { LOG.warn("AJP13: Secret Word is Required!!!"); LOG.debug(e); throw new IllegalStateException("AJP13: Secret Word is Required: Peer has requested shutdown but, has not provided a Secret Word"); } LOG.warn("AJP13: Shutdown Request is Denied, allowShutdown is set to false!!!"); return; } LOG.warn("AJP13: Peer Has Requested for Shutdown!!!"); LOG.warn("AJP13: Jetty 6 is shutting down !!!"); System.exit(0); } /* ------------------------------------------------------------------------------- */ public interface EventHandler { // public void shutdownRequest() throws IOException; // public void cpingRequest() throws IOException; public void content(Buffer ref) throws IOException; public void headerComplete() throws IOException; public void messageComplete(long contextLength) throws IOException; public void parsedHeader(Buffer name, Buffer value) throws IOException; public void parsedMethod(Buffer method) throws IOException; public void parsedProtocol(Buffer protocol) throws IOException; public void parsedQueryString(Buffer value) throws IOException; public void parsedRemoteAddr(Buffer addr) throws IOException; public void parsedRemoteHost(Buffer host) throws IOException; public void parsedRequestAttribute(String key, Buffer value) throws IOException; public void parsedRequestAttribute(String key, int value) throws IOException; public void parsedServerName(Buffer name) throws IOException; public void parsedServerPort(int port) throws IOException; public void parsedSslSecure(boolean secure) throws IOException; public void parsedUri(Buffer uri) throws IOException; public void startForwardRequest() throws IOException; public void parsedAuthorizationType(Buffer authType) throws IOException; public void parsedRemoteUser(Buffer remoteUser) throws IOException; public void parsedServletPath(Buffer servletPath) throws IOException; public void parsedContextPath(Buffer context) throws IOException; public void parsedSslCert(Buffer sslCert) throws IOException; public void parsedSslCipher(Buffer sslCipher) throws IOException; public void parsedSslSession(Buffer sslSession) throws IOException; public void parsedSslKeySize(int keySize) throws IOException; } /* ------------------------------------------------------------ */ /** * TODO Make this common with HttpParser * */ public static class Input extends ServletInputStream { private Ajp13Parser _parser; private EndPoint _endp; private long _maxIdleTime; private View _content; /* ------------------------------------------------------------ */ public Input(Ajp13Parser parser, long maxIdleTime) { _parser = parser; _endp = parser._endp; _maxIdleTime = maxIdleTime; _content = _parser._contentView; } /* ------------------------------------------------------------ */ @Override public int read() throws IOException { int c = -1; if (blockForContent()) c = 0xff & _content.get(); return c; } /* ------------------------------------------------------------ */ /* * @see java.io.InputStream#read(byte[], int, int) */ @Override public int read(byte[] b, int off, int len) throws IOException { int l = -1; if (blockForContent()) l = _content.get(b, off, len); return l; } /* ------------------------------------------------------------ */ private boolean blockForContent() throws IOException { if (_content.length() > 0) return true; if (_parser.isState(Ajp13Parser.STATE_END) || _parser.isState(Ajp13Parser.STATE_START)) return false; // Handle simple end points. if (_endp == null) _parser.parseNext(); // Handle blocking end points else if (_endp.isBlocking()) { _parser.parseNext(); // parse until some progress is made (or IOException thrown for timeout) while (_content.length() == 0 && !_parser.isState(Ajp13Parser.STATE_END)) { // Try to get more _parser._content _parser.parseNext(); } } else // Handle non-blocking end point { long filled = _parser.parseNext(); boolean blocked = false; // parse until some progress is made (or // IOException thrown for timeout) while (_content.length() == 0 && !_parser.isState(Ajp13Parser.STATE_END)) { // if fill called, but no bytes read, // then block if (filled > 0) blocked = false; else if (filled == 0) { if (blocked) throw new InterruptedIOException("timeout"); blocked = true; _endp.blockReadable(_maxIdleTime); } // Try to get more _parser._content filled = _parser.parseNext(); } } return _content.length() > 0; } } public boolean isPersistent() { return true; } public void setPersistent(boolean persistent) { LOG.warn("AJP13.setPersistent is not IMPLEMENTED!"); } } jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13Request.java000066400000000000000000000066101174773561500265560ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import org.eclipse.jetty.server.AbstractHttpConnection; import org.eclipse.jetty.server.Request; public class Ajp13Request extends Request { protected String _remoteAddr; protected String _remoteHost; protected String _remoteUser; protected boolean _sslSecure; /* ------------------------------------------------------------ */ public Ajp13Request(AbstractHttpConnection connection) { super(connection); } /* ------------------------------------------------------------ */ public Ajp13Request() { } /* ------------------------------------------------------------ */ void setConnection(Ajp13Connection connection) { super.setConnection(connection); } /* ------------------------------------------------------------ */ public void setRemoteUser(String remoteUser) { _remoteUser = remoteUser; } /* ------------------------------------------------------------ */ @Override public String getRemoteUser() { if(_remoteUser != null) return _remoteUser; return super.getRemoteUser(); } /* ------------------------------------------------------------ */ @Override public String getRemoteAddr() { if (_remoteAddr != null) return _remoteAddr; if (_remoteHost != null) return _remoteHost; return super.getRemoteAddr(); } /* ------------------------------------------------------------ */ @Override public void setRemoteAddr(String remoteAddr) { _remoteAddr = remoteAddr; } /* ------------------------------------------------------------ */ @Override public String getRemoteHost() { if (_remoteHost != null) return _remoteHost; if (_remoteAddr != null) return _remoteAddr; return super.getRemoteHost(); } /* ------------------------------------------------------------ */ @Override public void setRemoteHost(String remoteHost) { _remoteHost = remoteHost; } /* ------------------------------------------------------------ */ public boolean isSslSecure() { return _sslSecure; } /* ------------------------------------------------------------ */ public void setSslSecure(boolean sslSecure) { _sslSecure = sslSecure; } /* ------------------------------------------------------------ */ @Override protected void recycle() { super.recycle(); _remoteAddr = null; _remoteHost = null; _remoteUser = null; _sslSecure = false; } } jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13RequestHeaders.java000066400000000000000000000063351174773561500300560ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache; /** * XXX Should this implement the Buffer interface? * * */ public class Ajp13RequestHeaders extends BufferCache { public final static int MAGIC=0x1234; public final static String ACCEPT="accept", ACCEPT_CHARSET="accept-charset", ACCEPT_ENCODING="accept-encoding", ACCEPT_LANGUAGE="accept-language", AUTHORIZATION="authorization", CONNECTION="connection", CONTENT_TYPE="content-type", CONTENT_LENGTH="content-length", COOKIE="cookie", COOKIE2="cookie2", HOST="host", PRAGMA="pragma", REFERER="referer", USER_AGENT="user-agent"; public final static int ACCEPT_ORDINAL=1, ACCEPT_CHARSET_ORDINAL=2, ACCEPT_ENCODING_ORDINAL=3, ACCEPT_LANGUAGE_ORDINAL=4, AUTHORIZATION_ORDINAL=5, CONNECTION_ORDINAL=6, CONTENT_TYPE_ORDINAL=7, CONTENT_LENGTH_ORDINAL=8, COOKIE_ORDINAL=9, COOKIE2_ORDINAL=10, HOST_ORDINAL=11, PRAGMA_ORDINAL=12, REFERER_ORDINAL=13, USER_AGENT_ORDINAL=14; public final static BufferCache CACHE=new BufferCache(); public final static Buffer ACCEPT_BUFFER=CACHE.add(ACCEPT,ACCEPT_ORDINAL), ACCEPT_CHARSET_BUFFER=CACHE.add(ACCEPT_CHARSET,ACCEPT_CHARSET_ORDINAL), ACCEPT_ENCODING_BUFFER=CACHE.add(ACCEPT_ENCODING,ACCEPT_ENCODING_ORDINAL), ACCEPT_LANGUAGE_BUFFER=CACHE .add(ACCEPT_LANGUAGE,ACCEPT_LANGUAGE_ORDINAL), AUTHORIZATION_BUFFER=CACHE.add(AUTHORIZATION,AUTHORIZATION_ORDINAL), CONNECTION_BUFFER=CACHE .add(CONNECTION,CONNECTION_ORDINAL), CONTENT_TYPE_BUFFER=CACHE.add(CONTENT_TYPE,CONTENT_TYPE_ORDINAL), CONTENT_LENGTH_BUFFER=CACHE.add( CONTENT_LENGTH,CONTENT_LENGTH_ORDINAL), COOKIE_BUFFER=CACHE.add(COOKIE,COOKIE_ORDINAL), COOKIE2_BUFFER=CACHE.add(COOKIE2,COOKIE2_ORDINAL), HOST_BUFFER=CACHE.add(HOST,HOST_ORDINAL), PRAGMA_BUFFER=CACHE.add(PRAGMA,PRAGMA_ORDINAL), REFERER_BUFFER=CACHE.add(REFERER,REFERER_ORDINAL), USER_AGENT_BUFFER=CACHE.add(USER_AGENT,USER_AGENT_ORDINAL); public final static byte CONTEXT_ATTR=1, // Legacy SERVLET_PATH_ATTR=2, // Legacy REMOTE_USER_ATTR=3, AUTH_TYPE_ATTR=4, QUERY_STRING_ATTR=5, JVM_ROUTE_ATTR=6, SSL_CERT_ATTR=7, SSL_CIPHER_ATTR=8, SSL_SESSION_ATTR=9, REQUEST_ATTR=10, SSL_KEYSIZE_ATTR=11, SECRET_ATTR=12, STORED_METHOD_ATTR=13; } jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13RequestPacket.java000066400000000000000000000045061174773561500277100ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.View; /** * * * */ public class Ajp13RequestPacket { public static boolean isEmpty(Buffer _buffer) { return _buffer.length()==0; } public static int getInt(Buffer _buffer) { return ((_buffer.get()&0xFF)<<8)|(_buffer.get()&0xFF); } public static Buffer getString(Buffer _buffer, View tok) { int len=((_buffer.peek()&0xFF)<<8)|(_buffer.peek(_buffer.getIndex()+1)&0xFF); if (len==0xffff) { _buffer.skip(2); return null; } int start=_buffer.getIndex(); tok.update(start+2,start+len+2); _buffer.skip(len+3); return tok; } public static byte getByte(Buffer _buffer) { return _buffer.get(); } public static boolean getBool(Buffer _buffer) { return _buffer.get()>0; } public static Buffer getMethod(Buffer _buffer) { return Ajp13PacketMethods.CACHE.get(_buffer.get()); } public static Buffer getHeaderName(Buffer _buffer, View tok) { int len=((_buffer.peek()&0xFF)<<8)|(_buffer.peek(_buffer.getIndex()+1)&0xFF); if ((0xFF00&len)==0xA000) { _buffer.skip(1); return Ajp13RequestHeaders.CACHE.get(_buffer.get()); } int start=_buffer.getIndex(); tok.update(start+2,start+len+2); _buffer.skip(len+3); return tok; } public static Buffer get(Buffer buffer, int length) { return buffer.get(length); } } jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13ResponseHeaders.java000066400000000000000000000047301174773561500302210ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache; /** * */ public class Ajp13ResponseHeaders extends BufferCache { public final static int MAGIC=0xab00; public final static String CONTENT_TYPE="Content-Type", CONTENT_LANGUAGE="Content-Language", CONTENT_LENGTH="Content-Length", DATE="Date", LAST_MODIFIED="Last-Modified", LOCATION="Location", SET_COOKIE="Set-Cookie", SET_COOKIE2="Set-Cookie2", SERVLET_ENGINE="Servlet-Engine", STATUS="Status", WWW_AUTHENTICATE="WWW-Authenticate"; public final static int CONTENT_TYPE_ORDINAL=1, CONTENT_LANGUAGE_ORDINAL=2, CONTENT_LENGTH_ORDINAL=3, DATE_ORDINAL=4, LAST_MODIFIED_ORDINAL=5, LOCATION_ORDINAL=6, SET_COOKIE_ORDINAL=7, SET_COOKIE2_ORDINAL=8, SERVLET_ENGINE_ORDINAL=9, STATUS_ORDINAL=10, WWW_AUTHENTICATE_ORDINAL=11; public final static BufferCache CACHE=new BufferCache(); public final static Buffer CONTENT_TYPE_BUFFER=CACHE.add(CONTENT_TYPE,CONTENT_TYPE_ORDINAL), CONTENT_LANGUAGE_BUFFER=CACHE.add(CONTENT_LANGUAGE, CONTENT_LANGUAGE_ORDINAL), CONTENT_LENGTH_BUFFER=CACHE.add(CONTENT_LENGTH,CONTENT_LENGTH_ORDINAL), DATE_BUFFER=CACHE.add(DATE,DATE_ORDINAL), LAST_MODIFIED_BUFFER=CACHE.add(LAST_MODIFIED,LAST_MODIFIED_ORDINAL), LOCATION_BUFFER=CACHE.add(LOCATION,LOCATION_ORDINAL), SET_COOKIE_BUFFER=CACHE .add(SET_COOKIE,SET_COOKIE_ORDINAL), SET_COOKIE2_BUFFER=CACHE.add(SET_COOKIE2,SET_COOKIE2_ORDINAL), SERVLET_ENGINE_BUFFER=CACHE.add( SERVLET_ENGINE,SERVLET_ENGINE_ORDINAL), STATUS_BUFFER=CACHE.add(STATUS,STATUS_ORDINAL), WWW_AUTHENTICATE_BUFFER=CACHE.add(WWW_AUTHENTICATE, WWW_AUTHENTICATE_ORDINAL); } jetty8-8.1.3/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13SocketConnector.java000066400000000000000000000102671174773561500302340ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import java.io.IOException; import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.bio.SocketConnector; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * * * */ public class Ajp13SocketConnector extends SocketConnector { private static final Logger LOG = Log.getLogger(Ajp13SocketConnector.class); static String __secretWord = null; static boolean __allowShutdown = false; public Ajp13SocketConnector() { super.setRequestHeaderSize(Ajp13Packet.MAX_PACKET_SIZE); super.setResponseHeaderSize(Ajp13Packet.MAX_PACKET_SIZE); super.setRequestBufferSize(Ajp13Packet.MAX_PACKET_SIZE); super.setResponseBufferSize(Ajp13Packet.MAX_PACKET_SIZE); // IN AJP protocol the socket stay open, so // by default the time out is set to 0 seconds super.setMaxIdleTime(0); } @Override protected void doStart() throws Exception { super.doStart(); LOG.info("AJP13 is not a secure protocol. Please protect port {}",Integer.toString(getLocalPort())); } /* ------------------------------------------------------------ */ /* (non-Javadoc) * @see org.eclipse.jetty.server.bio.SocketConnector#customize(org.eclipse.io.EndPoint, org.eclipse.jetty.server.Request) */ @Override public void customize(EndPoint endpoint, Request request) throws IOException { super.customize(endpoint,request); if (request.isSecure()) request.setScheme(HttpSchemes.HTTPS); } /* ------------------------------------------------------------ */ @Override protected Connection newConnection(EndPoint endpoint) { return new Ajp13Connection(this,endpoint,getServer()); } /* ------------------------------------------------------------ */ // Secured on a packet by packet bases not by connection @Override public boolean isConfidential(Request request) { return ((Ajp13Request) request).isSslSecure(); } /* ------------------------------------------------------------ */ // Secured on a packet by packet bases not by connection @Override public boolean isIntegral(Request request) { return ((Ajp13Request) request).isSslSecure(); } /* ------------------------------------------------------------ */ @Deprecated public void setHeaderBufferSize(int headerBufferSize) { LOG.debug(Log.IGNORED); } /* ------------------------------------------------------------ */ @Override public void setRequestBufferSize(int requestBufferSize) { LOG.debug(Log.IGNORED); } /* ------------------------------------------------------------ */ @Override public void setResponseBufferSize(int responseBufferSize) { LOG.debug(Log.IGNORED); } /* ------------------------------------------------------------ */ public void setAllowShutdown(boolean allowShutdown) { LOG.warn("AJP13: Shutdown Request is: " + allowShutdown); __allowShutdown = allowShutdown; } /* ------------------------------------------------------------ */ public void setSecretWord(String secretWord) { LOG.warn("AJP13: Shutdown Request secret word is : " + secretWord); __secretWord = secretWord; } } jetty8-8.1.3/jetty-ajp/src/test/000077500000000000000000000000001174773561500164475ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/test/java/000077500000000000000000000000001174773561500173705ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/test/java/org/000077500000000000000000000000001174773561500201575ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/test/java/org/eclipse/000077500000000000000000000000001174773561500216035ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500227425ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/test/java/org/eclipse/jetty/ajp/000077500000000000000000000000001174773561500235145ustar00rootroot00000000000000jetty8-8.1.3/jetty-ajp/src/test/java/org/eclipse/jetty/ajp/Ajp13ConnectionTest.java000066400000000000000000000417161174773561500301260ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.net.SocketTimeoutException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class Ajp13ConnectionTest { private static final Logger LOG = Log.getLogger(Ajp13ConnectionTest.class); private static Server _server; private static Ajp13SocketConnector _connector; private Socket _client; @BeforeClass public static void startServer() throws Exception { _server=new Server(); _connector=new Ajp13SocketConnector(); _connector.setPort(0); _server.setConnectors(new Connector[] { _connector }); _server.setHandler(new Handler()); _server.start(); } @AfterClass public static void stopServer() throws Exception { _connector.close(); _server.stop(); } @Before public void openSocket() throws Exception { _client=new Socket("localhost",_connector.getLocalPort()); _client.setSoTimeout(500); } @After public void closeSocket() throws Exception { _client.close(); } @Test public void testPacket1() throws Exception { OutputStream os=_client.getOutputStream(); String packet="123401070202000f77696474683d20485454502f312e300000122f636f6e74726f6c2f70726f647563742f2200000e3230382e32372e3230332e31323800ffff000c7777772e756c74612e636f6d000050000005a006000a6b6565702d616c69766500a00b000c7777772e756c74612e636f6d00a00e002b4d6f7a696c6c612f342e302028636f6d70617469626c653b20426f726465724d616e6167657220332e302900a0010043696d6167652f6769662c20696d6167652f782d786269746d61702c20696d6167652f6a7065672c20696d6167652f706a7065672c20696d6167652f706d672c202a2f2a00a008000130000600067570726f64310008000a4145533235362d53484100ff"; os.write(TypeUtil.fromHexString(packet)); os.flush(); readResponse(_client); assertTrue(true); } @Test public void testPacket2() throws Exception { OutputStream os=_client.getOutputStream(); String packet="1234020102020008485454502f312e3100000f2f6363632d7777777777772f61616100000c38382e3838382e38382e383830ffff00116363632e6363636363636363632e636f6d0001bb010009a00b00116363632e6363636363636363632e636f6d00a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004039324643303544413043444141443232303137413743443141453939353132413330443938363838423843433041454643364231363035323543433232353341000b0100ff"; os.write(TypeUtil.fromHexString(packet)); os.flush(); readResponse(_client); assertTrue(true); } @Test public void testPacket3() throws Exception { OutputStream os=_client.getOutputStream(); String packet="1234028f02020008485454502f312e3100000d2f666f726d746573742e6a737000000d3139322e3136382e342e31383000ffff00107777772e777265636b6167652e6f726700005000000aa0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a00200075554462d382c2a00a003000c677a69702c6465666c61746500a004000e656e2d67622c656e3b713d302e3500a006000a6b6565702d616c69766500a00900f95048505345535349443d37626361383232616638333466316465373663633630336366636435313938633b20667041757468436f6f6b69653d433035383430394537393344364245434633324230353234344242303039343230383344443645443533304230454637464137414544413745453231313538333745363033454435364332364446353531383635333335423433374531423637414641343533364345304546323342333642323133374243423932333943363631433131443330393842333938414546334546334146454344423746353842443b204a53455353494f4e49443d7365366331623864663432762e6a657474793300a00b00107777772e777265636b6167652e6f726700000a6b6565702d616c69766500000333303000a00e00654d6f7a696c6c612f352e3020285831313b20553b204c696e7578207838365f36343b20656e2d55533b2072763a312e382e302e3929204765636b6f2f3230303631323035202844656269616e2d312e382e302e392d3129204570697068616e792f322e313400a008000130000600066a657474793300ff"; os.write(TypeUtil.fromHexString(packet)); os.flush(); readResponse(_client); assertTrue(true); } @Test public void testSSLPacketWithIntegerKeySize() throws Exception { OutputStream os=_client.getOutputStream(); String packet="1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b0100ff"; os.write(TypeUtil.fromHexString(packet)); os.flush(); readResponse(_client); assertTrue(true); } @Test public void testSSLPacketWithStringKeySize() throws Exception { OutputStream os=_client.getOutputStream(); String packet="1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b000332353600ff"; os.write(TypeUtil.fromHexString(packet)); os.flush(); readResponse(_client); assertTrue(true); } @Test public void testPacketWithBody() throws Exception { OutputStream os=_client.getOutputStream(); os.write(TypeUtil.fromHexString(getTestHeader())); os.write(TypeUtil.fromHexString(getTestShortBody())); os.write(TypeUtil.fromHexString(getTestTinyBody())); readResponse(_client); assertTrue(true); } @Test public void testPacketWithChunkedBody() throws Exception { OutputStream os=_client.getOutputStream(); String packet="123400ff02040008485454502f312e3100000f2f746573742f64756d702f696e666f0000093132372e302e302e3100ffff00096c6f63616c686f7374000050000007a00e000d4a6176612f312e352e305f313100a00b00096c6f63616c686f737400a0010034746578742f68746d6c2c20696d6167652f6769662c20696d6167652f6a7065672c202a3b20713d2e322c202a2f2a3b20713d2e3200a006000a6b6565702d616c69766500a00700216170706c69636174696f6e2f782d7777772d666f726d2d75726c656e636f6465640000115472616e736665722d456e636f64696e670000076368756e6b656400000c4d61782d466f727761726473000002313000ff"; os.write(TypeUtil.fromHexString(packet)); os.flush(); os.write(TypeUtil.fromHexString("1234007e007c7468656e616d653d746865253230717569636b25323062726f776e253230666f782532306a756d70732532306f766572253230746f2532307468652532306c617a79253230646f67253230544845253230515549434b25323042524f574e253230464f582532304a554d50532532304f564552253230544f25323054")); os.flush(); os.write(TypeUtil.fromHexString("12340042004048452532304c415a59253230444f472532302676616c75656f66323d6162636465666768696a6b6c6d6e6f707172737475767778797a31323334353637383930")); os.flush(); os.write(TypeUtil.fromHexString("123400020000")); os.flush(); readResponse(_client); assertTrue(true); } private String getTestHeader() { StringBuffer header=new StringBuffer(""); header.append("1234026902040008485454502f31"); header.append("2e310000162f61646d696e2f496d6167"); header.append("6555706c6f61642e68746d00000a3130"); header.append("2e34382e31302e3100ffff000a31302e"); header.append("34382e31302e3200005000000da00b00"); header.append("0a31302e34382e31302e3200a00e005a"); header.append("4d6f7a696c6c612f352e30202857696e"); header.append("646f77733b20553b2057696e646f7773"); header.append("204e5420352e313b20656e2d55533b20"); header.append("72763a312e382e312e3129204765636b"); header.append("6f2f3230303631323034204669726566"); header.append("6f782f322e302e302e3100a001006374"); header.append("6578742f786d6c2c6170706c69636174"); header.append("696f6e2f786d6c2c6170706c69636174"); header.append("696f6e2f7868746d6c2b786d6c2c7465"); header.append("78742f68746d6c3b713d302e392c7465"); header.append("78742f706c61696e3b713d302e382c69"); header.append("6d6167652f706e672c2a2f2a3b713d30"); header.append("2e3500a004000e656e2d75732c656e3b"); header.append("713d302e3500a003000c677a69702c64"); header.append("65666c61746500a002001e49534f2d38"); header.append("3835392d312c7574662d383b713d302e"); header.append("372c2a3b713d302e3700000a4b656570"); header.append("2d416c69766500000333303000a00600"); header.append("0a6b6565702d616c69766500a00d003f"); header.append("687474703a2f2f31302e34382e31302e"); header.append("322f61646d696e2f496d61676555706c"); header.append("6f61642e68746d3f6964303d4974656d"); header.append("266964313d32266964323d696d673200"); header.append("a00900174a53455353494f4e49443d75"); header.append("383977733070696168746d00a0070046"); header.append("6d756c7469706172742f666f726d2d64"); header.append("6174613b20626f756e646172793d2d2d"); header.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d"); header.append("2d2d2d2d2d2d2d2d2d39343338333235"); header.append("34323630383700a00800033735390000"); header.append("0c4d61782d466f727761726473000002"); header.append("3130000500176964303d4974656d2669"); header.append("64313d32266964323d696d673200ff"); return header.toString(); } private String getTestShortBody() { StringBuffer body=new StringBuffer(""); body.append("123402f702f52d2d2d2d2d2d2d2d"); body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d"); body.append("2d2d2d2d2d3934333833323534323630"); body.append("38370d0a436f6e74656e742d44697370"); body.append("6f736974696f6e3a20666f726d2d6461"); body.append("74613b206e616d653d227265636f7264"); body.append("4964220d0a0d0a320d0a2d2d2d2d2d2d"); body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d"); body.append("2d2d2d2d2d2d2d393433383332353432"); body.append("363038370d0a436f6e74656e742d4469"); body.append("73706f736974696f6e3a20666f726d2d"); body.append("646174613b206e616d653d226e616d65"); body.append("220d0a0d0a4974656d0d0a2d2d2d2d2d"); body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d"); body.append("2d2d2d2d2d2d2d2d3934333833323534"); body.append("32363038370d0a436f6e74656e742d44"); body.append("6973706f736974696f6e3a20666f726d"); body.append("2d646174613b206e616d653d22746e49"); body.append("6d674964220d0a0d0a696d67320d0a2d"); body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d"); body.append("2d2d2d2d2d2d2d2d2d2d2d2d39343338"); body.append("3332353432363038370d0a436f6e7465"); body.append("6e742d446973706f736974696f6e3a20"); body.append("666f726d2d646174613b206e616d653d"); body.append("227468756d624e61696c496d61676546"); body.append("696c65223b2066696c656e616d653d22"); body.append("6161612e747874220d0a436f6e74656e"); body.append("742d547970653a20746578742f706c61"); body.append("696e0d0a0d0a61616161616161616161"); body.append("61616161616161616161616161616161"); body.append("61616161616161616161616161616161"); body.append("61616161616161616161616161616161"); body.append("0d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d"); body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d39"); body.append("3433383332353432363038370d0a436f"); body.append("6e74656e742d446973706f736974696f"); body.append("6e3a20666f726d2d646174613b206e61"); body.append("6d653d226c61726765496d6167654669"); body.append("6c65223b2066696c656e616d653d2261"); body.append("61612e747874220d0a436f6e74656e74"); body.append("2d547970653a20746578742f706c6169"); body.append("6e0d0a0d0a6161616161616161616161"); body.append("61616161616161616161616161616161"); body.append("61616161616161616161616161616161"); body.append("6161616161616161616161616161610d"); body.append("0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d"); body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d3934"); body.append("33383332353432363038372d2d"); return body.toString(); } private String getTestTinyBody() { StringBuffer body = new StringBuffer(""); body.append("123400042d2d0d0a"); return body.toString(); } // TODO: char array instead of string? private String readResponse(Socket _client) throws IOException { ByteArrayOutputStream bout = new ByteArrayOutputStream(); try { IO.copy(_client.getInputStream(),bout); } catch(SocketTimeoutException e) { LOG.ignore(e); } return bout.toString("utf-8"); } public static class Handler extends AbstractHandler { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/plain"); response.getWriter().println("success"); } } } jetty8-8.1.3/jetty-ajp/src/test/java/org/eclipse/jetty/ajp/TestAjpParser.java000066400000000000000000000731651174773561500271220ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.ajp; import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.IOException; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.SimpleBuffers; import org.eclipse.jetty.util.TypeUtil; import org.junit.Test; public class TestAjpParser { @Test public void testPacket1() throws Exception { String packet = "123401070202000f77696474683d20485454502f312e300000122f636f6e74726f6c2f70726f647563742f2200000e3230382e32372e3230332e31323800ffff000c7777772e756c74612e636f6d000050000005a006000a6b6565702d616c69766500a00b000c7777772e756c74612e636f6d00a00e002b4d6f7a696c6c612f342e302028636f6d70617469626c653b20426f726465724d616e6167657220332e302900a0010043696d6167652f6769662c20696d6167652f782d786269746d61702c20696d6167652f6a7065672c20696d6167652f706a7065672c20696d6167652f706d672c202a2f2a00a008000130000600067570726f64310008000a4145533235362d53484100ff"; byte[] src = TypeUtil.fromHexString(packet); ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE); SimpleBuffers buffers=new SimpleBuffers(buffer,null); EndPoint endp = new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE); Ajp13Parser parser = new Ajp13Parser(buffers,endp); parser.setEventHandler(new EH()); parser.setGenerator(new Ajp13Generator(buffers,endp)); parser.parseAvailable(); assertTrue(true); } @Test public void testPacket2() throws Exception { String packet="1234020102020008485454502f312e3100000f2f6363632d7777777777772f61616100000c38382e3838382e38382e383830ffff00116363632e6363636363636363632e636f6d0001bb010009a00b00116363632e6363636363636363632e636f6d00a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004039324643303544413043444141443232303137413743443141453939353132413330443938363838423843433041454643364231363035323543433232353341000b0100ff"; byte[] src=TypeUtil.fromHexString(packet); ByteArrayBuffer buffer=new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE); SimpleBuffers buffers=new SimpleBuffers(buffer,null); EndPoint endp=new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE); Ajp13Parser parser = new Ajp13Parser(buffers,endp); parser.setEventHandler(new EH()); parser.setGenerator(new Ajp13Generator(buffers,endp)); parser.parse(); assertTrue(true); } @Test public void testPacket3() throws Exception { String packet="1234028f02020008485454502f312e3100000d2f666f726d746573742e6a737000000d3139322e3136382e342e31383000ffff00107777772e777265636b6167652e6f726700005000000aa0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a00200075554462d382c2a00a003000c677a69702c6465666c61746500a004000e656e2d67622c656e3b713d302e3500a006000a6b6565702d616c69766500a00900f95048505345535349443d37626361383232616638333466316465373663633630336366636435313938633b20667041757468436f6f6b69653d433035383430394537393344364245434633324230353234344242303039343230383344443645443533304230454637464137414544413745453231313538333745363033454435364332364446353531383635333335423433374531423637414641343533364345304546323342333642323133374243423932333943363631433131443330393842333938414546334546334146454344423746353842443b204a53455353494f4e49443d7365366331623864663432762e6a657474793300a00b00107777772e777265636b6167652e6f726700000a6b6565702d616c69766500000333303000a00e00654d6f7a696c6c612f352e3020285831313b20553b204c696e7578207838365f36343b20656e2d55533b2072763a312e382e302e3929204765636b6f2f3230303631323035202844656269616e2d312e382e302e392d3129204570697068616e792f322e313400a008000130000600066a657474793300ff"; byte[] src=TypeUtil.fromHexString(packet); ByteArrayBuffer buffer=new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE); SimpleBuffers buffers=new SimpleBuffers(buffer,null); EndPoint endp=new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE); Ajp13Parser parser = new Ajp13Parser(buffers,endp); parser.setEventHandler(new EH()); parser.setGenerator(new Ajp13Generator(buffers,endp)); parser.parse(); assertTrue(true); } @Test public void testSSLPacketWithIntegerKeySize() throws Exception { String packet = "1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b0100ff"; byte[] src = TypeUtil.fromHexString(packet); ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE); SimpleBuffers buffers=new SimpleBuffers(buffer,null); EndPoint endp = new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE); Ajp13Parser parser = new Ajp13Parser(buffers,endp); parser.setEventHandler(new EH()); parser.setGenerator(new Ajp13Generator(buffers,endp)); parser.parseAvailable(); assertTrue(true); } @Test public void testSSLPacketWithStringKeySize() throws Exception { String packet = "1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b000332353600ff"; byte[] src = TypeUtil.fromHexString(packet); ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE); SimpleBuffers buffers=new SimpleBuffers(buffer,null); EndPoint endp = new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE); Ajp13Parser parser = new Ajp13Parser(buffers,endp); parser.setEventHandler(new EH()); parser.setGenerator(new Ajp13Generator(buffers,endp)); parser.parseAvailable(); assertTrue(true); } @Test public void testSSLPacketFragment() throws Exception { String packet = "1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b0100ff"; byte[] src = TypeUtil.fromHexString(packet); for (int f=1;f0); assertEquals(1,parser.getState()); assertEquals(2,count[0]); endp.setIn(new ByteArrayBuffer(TypeUtil.fromHexString("12340042004048452532304c415a59253230444f472532302676616c75656f66323d6162636465666768696a6b6c6d6e6f707172737475767778797a31323334353637383930"))); while (parser.parseNext()>0); assertEquals(1,parser.getState()); assertEquals(3,count[0]); endp.setIn(new ByteArrayBuffer(TypeUtil.fromHexString("123400020000"))); while (parser.getState()!=0 && parser.parseNext()>0); assertEquals(0,parser.getState()); assertEquals(3,count[0]); assertTrue(true); } @Test public void testPacketFragment() throws Exception { String packet = "123401070202000f77696474683d20485454502f312e300000122f636f6e74726f6c2f70726f647563742f2200000e3230382e32372e3230332e31323800ffff000c7777772e756c74612e636f6d000050000005a006000a6b6565702d616c69766500a00b000c7777772e756c74612e636f6d00a00e002b4d6f7a696c6c612f342e302028636f6d70617469626c653b20426f726465724d616e6167657220332e302900a0010043696d6167652f6769662c20696d6167652f782d786269746d61702c20696d6167652f6a7065672c20696d6167652f706a7065672c20696d6167652f706d672c202a2f2a00a008000130000600067570726f64310008000a4145533235362d53484100ff"; byte[] src = TypeUtil.fromHexString(packet); for (int f=1;f org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 jetty-annotations Jetty :: Servlet Annotations Annotation support for deploying servlets in jetty. ${project.groupId}.annotations org.apache.maven.plugins maven-assembly-plugin package single config org.apache.felix maven-bundle-plugin true generate-manifest manifest javax.servlet.*;version="2.6.0",* org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.annotations.* junit junit test org.eclipse.jetty jetty-jndi ${project.version} test org.eclipse.jetty jetty-plus ${project.version} org.eclipse.jetty jetty-webapp ${project.version} org.eclipse.jetty.orbit javax.annotation org.eclipse.jetty.orbit org.objectweb.asm jetty8-8.1.3/jetty-annotations/src/000077500000000000000000000000001174773561500172535ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/000077500000000000000000000000001174773561500201775ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/config/000077500000000000000000000000001174773561500214445ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/config/etc/000077500000000000000000000000001174773561500222175ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/config/etc/jetty-annotations.xml000066400000000000000000000020661174773561500264370ustar00rootroot00000000000000 org.eclipse.jetty.webapp.configuration org.eclipse.jetty.webapp.WebInfConfiguration org.eclipse.jetty.webapp.WebXmlConfiguration org.eclipse.jetty.webapp.MetaInfConfiguration org.eclipse.jetty.webapp.FragmentConfiguration org.eclipse.jetty.annotations.AnnotationConfiguration org.eclipse.jetty.webapp.JettyWebXmlConfiguration jetty8-8.1.3/jetty-annotations/src/main/java/000077500000000000000000000000001174773561500211205ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/000077500000000000000000000000001174773561500217075ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/000077500000000000000000000000001174773561500233335ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500244725ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/000077500000000000000000000000001174773561500270275ustar00rootroot00000000000000AbstractDiscoverableAnnotationHandler.java000066400000000000000000000033701174773561500372350ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.ArrayList; import java.util.List; import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler; import org.eclipse.jetty.annotations.AnnotationParser.Value; import org.eclipse.jetty.webapp.DiscoveredAnnotation; import org.eclipse.jetty.webapp.WebAppContext; /** * DiscoverableAnnotationHandler * * */ public abstract class AbstractDiscoverableAnnotationHandler implements DiscoverableAnnotationHandler { protected WebAppContext _context; protected List _annotations = new ArrayList(); public AbstractDiscoverableAnnotationHandler(WebAppContext context) { _context = context; } public List getAnnotationList () { return _annotations; } public void resetList() { _annotations.clear(); } public void addAnnotation (DiscoveredAnnotation a) { _annotations.add(a); } } AnnotationConfiguration.java000066400000000000000000000451731174773561500344670ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.net.URI; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; import java.util.Set; import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.HandlesTypes; import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler; import org.eclipse.jetty.plus.annotation.ContainerInitializer; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.Configuration; import org.eclipse.jetty.webapp.AbstractConfiguration; import org.eclipse.jetty.webapp.Descriptor; import org.eclipse.jetty.webapp.DiscoveredAnnotation; import org.eclipse.jetty.webapp.FragmentDescriptor; import org.eclipse.jetty.webapp.MetaDataComplete; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebDescriptor; /** * Configuration for Annotations * * */ public class AnnotationConfiguration extends AbstractConfiguration { private static final Logger LOG = Log.getLogger(AnnotationConfiguration.class); public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap"; public static final String CONTAINER_INITIALIZERS = "org.eclipse.jetty.containerInitializers"; public void preConfigure(final WebAppContext context) throws Exception { } @Override public void configure(WebAppContext context) throws Exception { boolean metadataComplete = context.getMetaData().isMetaDataComplete(); context.addDecorator(new AnnotationDecorator(context)); //Even if metadata is complete, we still need to scan for ServletContainerInitializers - if there are any AnnotationParser parser = null; if (!metadataComplete) { //If metadata isn't complete, if this is a servlet 3 webapp or isConfigDiscovered is true, we need to search for annotations if (context.getServletContext().getEffectiveMajorVersion() >= 3 || context.isConfigurationDiscovered()) { parser = createAnnotationParser(); parser.registerAnnotationHandler("javax.servlet.annotation.WebServlet", new WebServletAnnotationHandler(context)); parser.registerAnnotationHandler("javax.servlet.annotation.WebFilter", new WebFilterAnnotationHandler(context)); parser.registerAnnotationHandler("javax.servlet.annotation.WebListener", new WebListenerAnnotationHandler(context)); } } else if (LOG.isDebugEnabled()) LOG.debug("Metadata-complete==true, not processing discoverable servlet annotations for context "+context); //Regardless of metadata, if there are any ServletContainerInitializers with @HandlesTypes, then we need to scan all the //classes so we can call their onStartup() methods correctly List nonExcludedInitializers = getNonExcludedInitializers(context); parser = registerServletContainerInitializerAnnotationHandlers(context, parser, nonExcludedInitializers); if (parser != null) { if (LOG.isDebugEnabled()) LOG.debug("Scanning all classses for annotations: webxmlVersion="+context.getServletContext().getEffectiveMajorVersion()+" configurationDiscovered="+context.isConfigurationDiscovered()); parseContainerPath(context, parser); //email from Rajiv Mordani jsrs 315 7 April 2010 // If there is a then the ordering should be // WEB-INF/classes the order of the declared elements + others. // In case there is no others then it is // WEB-INF/classes + order of the elements. parseWebInfClasses(context, parser); parseWebInfLib (context, parser); } } /** * @return a new AnnotationParser. This method can be overridden to use a different impleemntation of * the AnnotationParser. Note that this is considered internal API. */ protected AnnotationParser createAnnotationParser() { return new AnnotationParser(); } @Override public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception { context.addDecorator(new AnnotationDecorator(context)); } public AnnotationParser registerServletContainerInitializerAnnotationHandlers (WebAppContext context, AnnotationParser parser, List scis) throws Exception { //TODO verify my interpretation of the spec. That is, that metadata-complete has nothing //to do with finding the ServletContainerInitializers, classes designated to be of interest to them, //or even calling them on startup. //Get all ServletContainerInitializers, and check them for HandlesTypes annotations. //For each class in the HandlesTypes value, if it IS an annotation, register a handler //that will record the classes that have that annotation. //If it is NOT an annotation, then we will interrogate the type hierarchy discovered during //parsing later on to find the applicable classes. if (scis == null || scis.isEmpty()) return parser; // nothing to do ServletContainerInitializerListener listener = new ServletContainerInitializerListener(); listener.setWebAppContext(context); context.addEventListener(listener); //may need to add a listener ArrayList initializers = new ArrayList(); context.setAttribute(CONTAINER_INITIALIZERS, initializers); for (ServletContainerInitializer service : scis) { HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class); ContainerInitializer initializer = new ContainerInitializer(); initializer.setTarget(service); initializers.add(initializer); if (annotation != null) { //There is a HandlesTypes annotation on the on the ServletContainerInitializer Class[] classes = annotation.value(); if (classes != null) { initializer.setInterestedTypes(classes); //We need to create a parser if we haven't already if (parser == null) parser = createAnnotationParser(); //If we haven't already done so, we need to register a handler that will //process the whole class hierarchy if (context.getAttribute(CLASS_INHERITANCE_MAP) == null) { ClassInheritanceHandler classHandler = new ClassInheritanceHandler(); context.setAttribute(CLASS_INHERITANCE_MAP, classHandler.getMap()); parser.registerClassHandler(classHandler); } for (Class c: classes) { //The value of one of the HandlesTypes classes is actually an Annotation itself so //register a handler for it if (c.isAnnotation()) { if (LOG.isDebugEnabled()) LOG.debug("Registering annotation handler for "+c.getName()); parser.registerAnnotationHandler(c.getName(), new ContainerInitializerAnnotationHandler(initializer, c)); } } } else if (LOG.isDebugEnabled()) LOG.debug("No classes in HandlesTypes on initializer "+service.getClass()); } else if (LOG.isDebugEnabled()) LOG.debug("No annotation on initializer "+service.getClass()); } //return the parser in case we lazily created it return parser; } /** * Check to see if the ServletContainerIntializer loaded via the ServiceLoader came * from a jar that is excluded by the fragment ordering. See ServletSpec 3.0 p.85. * @param orderedJars * @param service * @return */ public boolean isFromExcludedJar (WebAppContext context, ServletContainerInitializer service) throws Exception { List orderedJars = context.getMetaData().getOrderedWebInfJars(); //If no ordering, nothing is excluded if (context.getMetaData().getOrdering() == null) return false; //there is an ordering, but there are no jars resulting from the ordering, everything excluded if (orderedJars.isEmpty()) return true; String loadingJarName = Thread.currentThread().getContextClassLoader().getResource(service.getClass().getName().replace('.','/')+".class").toString(); int i = loadingJarName.indexOf(".jar"); if (i < 0) return false; //not from a jar therefore not from WEB-INF so not excludable loadingJarName = loadingJarName.substring(0,i+4); loadingJarName = (loadingJarName.startsWith("jar:")?loadingJarName.substring(4):loadingJarName); URI loadingJarURI = Resource.newResource(loadingJarName).getURI(); boolean found = false; Iterator itor = orderedJars.iterator(); while (!found && itor.hasNext()) { Resource r = itor.next(); found = r.getURI().equals(loadingJarURI); } return !found; } public List getNonExcludedInitializers (WebAppContext context) throws Exception { List nonExcludedInitializers = new ArrayList(); //We use the ServiceLoader mechanism to find the ServletContainerInitializer classes to inspect ServiceLoader loadedInitializers = ServiceLoader.load(ServletContainerInitializer.class, context.getClassLoader()); if (loadedInitializers != null) { for (ServletContainerInitializer service : loadedInitializers) { if (!isFromExcludedJar(context, service)) nonExcludedInitializers.add(service); } } return nonExcludedInitializers; } public void parseContainerPath (final WebAppContext context, final AnnotationParser parser) throws Exception { //if no pattern for the container path is defined, then by default scan NOTHING LOG.debug("Scanning container jars"); //clear any previously discovered annotations clearAnnotationList(parser.getAnnotationHandlers()); //Convert from Resource to URI ArrayList containerUris = new ArrayList(); for (Resource r : context.getMetaData().getOrderedContainerJars()) { URI uri = r.getURI(); containerUris.add(uri); } parser.parse (containerUris.toArray(new URI[containerUris.size()]), new ClassNameResolver () { public boolean isExcluded (String name) { if (context.isSystemClass(name)) return false; if (context.isServerClass(name)) return true; return false; } public boolean shouldOverride (String name) { //looking at system classpath if (context.isParentLoaderPriority()) return true; return false; } }); //gather together all annotations discovered List annotations = new ArrayList(); gatherAnnotations(annotations, parser.getAnnotationHandlers()); context.getMetaData().addDiscoveredAnnotations(annotations); } public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser) throws Exception { List frags = context.getMetaData().getFragments(); //email from Rajiv Mordani jsrs 315 7 April 2010 //jars that do not have a web-fragment.xml are still considered fragments //they have to participate in the ordering ArrayList webInfUris = new ArrayList(); List jars = context.getMetaData().getOrderedWebInfJars(); //No ordering just use the jars in any order if (jars == null || jars.isEmpty()) jars = context.getMetaData().getWebInfJars(); for (Resource r : jars) { //clear any previously discovered annotations from handlers clearAnnotationList(parser.getAnnotationHandlers()); URI uri = r.getURI(); FragmentDescriptor f = getFragmentFromJar(r, frags); //if a jar has no web-fragment.xml we scan it (because it is not exluded by the ordering) //or if it has a fragment we scan it if it is not metadata complete if (f == null || !isMetaDataComplete(f)) { parser.parse(uri, new ClassNameResolver() { public boolean isExcluded (String name) { if (context.isSystemClass(name)) return true; if (context.isServerClass(name)) return false; return false; } public boolean shouldOverride (String name) { //looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp? if (context.isParentLoaderPriority()) return false; return true; } }); List annotations = new ArrayList(); gatherAnnotations(annotations, parser.getAnnotationHandlers()); context.getMetaData().addDiscoveredAnnotations(r, annotations); } } } public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser) throws Exception { LOG.debug("Scanning classes in WEB-INF/classes"); if (context.getWebInf() != null) { Resource classesDir = context.getWebInf().addPath("classes/"); if (classesDir.exists()) { clearAnnotationList(parser.getAnnotationHandlers()); parser.parse(classesDir, new ClassNameResolver() { public boolean isExcluded (String name) { if (context.isSystemClass(name)) return true; if (context.isServerClass(name)) return false; return false; } public boolean shouldOverride (String name) { //looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp? if (context.isParentLoaderPriority()) return false; return true; } }); //TODO - where to set the annotations discovered from WEB-INF/classes? List annotations = new ArrayList(); gatherAnnotations(annotations, parser.getAnnotationHandlers()); context.getMetaData().addDiscoveredAnnotations (annotations); } } } public FragmentDescriptor getFragmentFromJar (Resource jar, List frags) throws Exception { //check if the jar has a web-fragment.xml FragmentDescriptor d = null; for (FragmentDescriptor frag: frags) { Resource fragResource = frag.getResource(); //eg jar:file:///a/b/c/foo.jar!/META-INF/web-fragment.xml if (Resource.isContainedIn(fragResource,jar)) { d = frag; break; } } return d; } public boolean isMetaDataComplete (WebDescriptor d) { return (d!=null && d.getMetaDataComplete() == MetaDataComplete.True); } protected void clearAnnotationList (List handlers) { if (handlers == null) return; for (DiscoverableAnnotationHandler h:handlers) { if (h instanceof AbstractDiscoverableAnnotationHandler) ((AbstractDiscoverableAnnotationHandler)h).resetList(); } } protected void gatherAnnotations (List annotations, List handlers) { for (DiscoverableAnnotationHandler h:handlers) { if (h instanceof AbstractDiscoverableAnnotationHandler) annotations.addAll(((AbstractDiscoverableAnnotationHandler)h).getAnnotationList()); } } } jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationDecorator.java000066400000000000000000000126341174773561500336550ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.EventListener; import javax.servlet.Filter; import javax.servlet.Servlet; import javax.servlet.ServletException; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletContextHandler.Decorator; import org.eclipse.jetty.webapp.WebAppContext; /** * WebAppDecoratorWrapper * * */ public class AnnotationDecorator implements Decorator { AnnotationIntrospector _introspector = new AnnotationIntrospector(); /** * @param context */ public AnnotationDecorator(WebAppContext context) { _introspector.registerHandler(new ResourceAnnotationHandler(context)); _introspector.registerHandler(new ResourcesAnnotationHandler(context)); _introspector.registerHandler(new RunAsAnnotationHandler(context)); _introspector.registerHandler(new PostConstructAnnotationHandler(context)); _introspector.registerHandler(new PreDestroyAnnotationHandler(context)); _introspector.registerHandler(new DeclareRolesAnnotationHandler(context)); _introspector.registerHandler(new MultiPartConfigAnnotationHandler(context)); _introspector.registerHandler(new ServletSecurityAnnotationHandler(context)); } /* ------------------------------------------------------------ */ /** * @param filter * @throws ServletException * @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateFilterHolder(org.eclipse.jetty.servlet.FilterHolder) */ public void decorateFilterHolder(FilterHolder filter) throws ServletException { } /* ------------------------------------------------------------ */ /** * @param * @param filter * @return the decorated filter * @throws ServletException * @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateFilterInstance(javax.servlet.Filter) */ public T decorateFilterInstance(T filter) throws ServletException { introspect(filter); return filter; } /* ------------------------------------------------------------ */ /** * @param * @param listener * @return the decorated event listener instance * @throws ServletException * @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateListenerInstance(java.util.EventListener) */ public T decorateListenerInstance(T listener) throws ServletException { introspect(listener); return listener; } /* ------------------------------------------------------------ */ /** * @param servlet * @throws ServletException * @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateServletHolder(org.eclipse.jetty.servlet.ServletHolder) */ public void decorateServletHolder(ServletHolder servlet) throws ServletException { } /* ------------------------------------------------------------ */ /** * @param * @param servlet * @return the decorated servlet instance * @throws ServletException * @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateServletInstance(javax.servlet.Servlet) */ public T decorateServletInstance(T servlet) throws ServletException { introspect(servlet); return servlet; } /* ------------------------------------------------------------ */ /** * @param f * @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#destroyFilterInstance(javax.servlet.Filter) */ public void destroyFilterInstance(Filter f) { } /* ------------------------------------------------------------ */ /** * @param s * @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#destroyServletInstance(javax.servlet.Servlet) */ public void destroyServletInstance(Servlet s) { } /* ------------------------------------------------------------ */ /** * @param f * @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#destroyListenerInstance(java.util.EventListener) */ public void destroyListenerInstance(EventListener f) { } /** * Look for annotations that can be discovered with introspection: *

    *
  • Resource *
  • Resources *
  • PostConstruct *
  • PreDestroy *
  • ServletSecurity? *
* @param o */ protected void introspect (Object o) { _introspector.introspect(o.getClass()); } } AnnotationIntrospector.java000066400000000000000000000060401174773561500343410ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.ArrayList; import java.util.List; import org.eclipse.jetty.util.log.Log; /** * AnnotationIntrospector * * */ public class AnnotationIntrospector { protected List _handlers = new ArrayList(); /** * IntrospectableAnnotationHandler * * Interface for all handlers that wish to introspect a class to find a particular annotation */ public interface IntrospectableAnnotationHandler { public void handle(Class clazz); } /** * AbstractIntrospectableAnnotationHandler * * Base class for handlers that introspect a class to find a particular annotation. * A handler can optionally introspect the parent hierarchy of a class. */ public static abstract class AbstractIntrospectableAnnotationHandler implements IntrospectableAnnotationHandler { private boolean _introspectAncestors; public abstract void doHandle(Class clazz); public AbstractIntrospectableAnnotationHandler(boolean introspectAncestors) { _introspectAncestors = introspectAncestors; } public void handle(Class clazz) { Class c = clazz; //process the whole inheritance hierarchy for the class while (c!=null && (!c.equals(Object.class))) { doHandle(c); if (!_introspectAncestors) break; c = c.getSuperclass(); } } } public void registerHandler (IntrospectableAnnotationHandler handler) { _handlers.add(handler); } public void introspect (Class clazz) { if (_handlers == null) return; if (clazz == null) return; for (IntrospectableAnnotationHandler handler:_handlers) { try { handler.handle(clazz); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } } } jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java000066400000000000000000000531151174773561500331660ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.jar.JarEntry; import org.eclipse.jetty.util.Loader; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.JarScanner; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassReader; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.commons.EmptyVisitor; /** * AnnotationParser * * Use asm to scan classes for annotations. A SAX-style parsing is done, with * a handler being able to be registered to handle each annotation type. */ public class AnnotationParser { private static final Logger LOG = Log.getLogger(AnnotationParser.class); protected List _parsedClassNames = new ArrayList(); protected Map> _annotationHandlers = new HashMap>(); protected List _classHandlers = new ArrayList(); protected List _methodHandlers = new ArrayList(); protected List _fieldHandlers = new ArrayList(); public static String normalize (String name) { if (name==null) return null; if (name.startsWith("L") && name.endsWith(";")) name = name.substring(1, name.length()-1); if (name.endsWith(".class")) name = name.substring(0, name.length()-".class".length()); return name.replace('/', '.'); } public abstract class Value { String _name; public Value (String name) { _name = name; } public String getName() { return _name; } public abstract Object getValue(); } public class SimpleValue extends Value { Object _val; public SimpleValue(String name) { super(name); } public void setValue(Object val) { _val=val; } public Object getValue() { return _val; } public String toString() { return "("+getName()+":"+_val+")"; } } public class ListValue extends Value { List _val; public ListValue (String name) { super(name); _val = new ArrayList(); } public Object getValue() { return _val; } public List getList() { return _val; } public void addValue (Value v) { _val.add(v); } public int size () { return _val.size(); } public String toString() { StringBuffer buff = new StringBuffer(); buff.append("("); buff.append(getName()); buff.append(":"); for (Value n: _val) { buff.append(" "+n.toString()); } buff.append(")"); return buff.toString(); } } public interface DiscoverableAnnotationHandler { public void handleClass (String className, int version, int access, String signature, String superName, String[] interfaces, String annotation, Listvalues); public void handleMethod (String className, String methodName, int access, String desc, String signature,String[] exceptions, String annotation, Listvalues); public void handleField (String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, Listvalues); } public interface ClassHandler { public void handle (String className, int version, int access, String signature, String superName, String[] interfaces); } public interface MethodHandler { public void handle (String className, String methodName, int access, String desc, String signature,String[] exceptions); } public interface FieldHandler { public void handle (String className, String fieldName, int access, String fieldType, String signature, Object value); } public class MyAnnotationVisitor implements AnnotationVisitor { List _annotationValues; String _annotationName; public MyAnnotationVisitor (String annotationName, List values) { _annotationValues = values; _annotationName = annotationName; } public List getAnnotationValues() { return _annotationValues; } /** * Visit a single-valued (name,value) pair for this annotation * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object) */ public void visit(String aname, Object avalue) { SimpleValue v = new SimpleValue(aname); v.setValue(avalue); _annotationValues.add(v); } /** * Visit a (name,value) pair whose value is another Annotation * @see org.objectweb.asm.AnnotationVisitor#visitAnnotation(java.lang.String, java.lang.String) */ public AnnotationVisitor visitAnnotation(String name, String desc) { String s = normalize(desc); ListValue v = new ListValue(s); _annotationValues.add(v); MyAnnotationVisitor visitor = new MyAnnotationVisitor(s, v.getList()); return visitor; } /** * Visit an array valued (name, value) pair for this annotation * @see org.objectweb.asm.AnnotationVisitor#visitArray(java.lang.String) */ public AnnotationVisitor visitArray(String name) { ListValue v = new ListValue(name); _annotationValues.add(v); MyAnnotationVisitor visitor = new MyAnnotationVisitor(null, v.getList()); return visitor; } /** * Visit a enum-valued (name,value) pair for this annotation * @see org.objectweb.asm.AnnotationVisitor#visitEnum(java.lang.String, java.lang.String, java.lang.String) */ public void visitEnum(String name, String desc, String value) { //TODO } public void visitEnd() { } } /** * MyClassVisitor * * ASM visitor for a class. */ public class MyClassVisitor extends EmptyVisitor { String _className; int _access; String _signature; String _superName; String[] _interfaces; int _version; public void visit (int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { _className = normalize(name); _access = access; _signature = signature; _superName = superName; _interfaces = interfaces; _version = version; _parsedClassNames.add(_className); //call all registered ClassHandlers String[] normalizedInterfaces = null; if (interfaces!= null) { normalizedInterfaces = new String[interfaces.length]; int i=0; for (String s : interfaces) normalizedInterfaces[i++] = normalize(s); } for (ClassHandler h : AnnotationParser.this._classHandlers) { h.handle(_className, _version, _access, _signature, normalize(_superName), normalizedInterfaces); } } public AnnotationVisitor visitAnnotation (String desc, boolean visible) { MyAnnotationVisitor visitor = new MyAnnotationVisitor(normalize(desc), new ArrayList()) { public void visitEnd() { super.visitEnd(); //call all AnnotationHandlers with classname, annotation name + values List handlers = AnnotationParser.this._annotationHandlers.get(_annotationName); if (handlers != null) { for (DiscoverableAnnotationHandler h:handlers) { h.handleClass(_className, _version, _access, _signature, _superName, _interfaces, _annotationName, _annotationValues); } } } }; return visitor; } public MethodVisitor visitMethod (final int access, final String name, final String methodDesc, final String signature, final String[] exceptions) { return new EmptyVisitor () { public AnnotationVisitor visitAnnotation(String desc, boolean visible) { MyAnnotationVisitor visitor = new MyAnnotationVisitor (normalize(desc), new ArrayList()) { public void visitEnd() { super.visitEnd(); //call all AnnotationHandlers with classname, method, annotation name + values List handlers = AnnotationParser.this._annotationHandlers.get(_annotationName); if (handlers != null) { for (DiscoverableAnnotationHandler h:handlers) { h.handleMethod(_className, name, access, methodDesc, signature, exceptions, _annotationName, _annotationValues); } } } }; return visitor; } }; } public FieldVisitor visitField (final int access, final String fieldName, final String fieldType, final String signature, final Object value) { return new EmptyVisitor () { public AnnotationVisitor visitAnnotation(String desc, boolean visible) { MyAnnotationVisitor visitor = new MyAnnotationVisitor(normalize(desc), new ArrayList()) { public void visitEnd() { super.visitEnd(); List handlers = AnnotationParser.this._annotationHandlers.get(_annotationName); if (handlers != null) { for (DiscoverableAnnotationHandler h:handlers) { h.handleField(_className, fieldName, access, fieldType, signature, value, _annotationName, _annotationValues); } } } }; return visitor; } }; } } /** * Register a handler that will be called back when the named annotation is * encountered on a class. * * @param annotationName * @param handler */ public void registerAnnotationHandler (String annotationName, DiscoverableAnnotationHandler handler) { List handlers = _annotationHandlers.get(annotationName); if (handlers == null) { handlers = new ArrayList(); _annotationHandlers.put(annotationName, handlers); } handlers.add(handler); } public List getAnnotationHandlers(String annotationName) { List handlers = _annotationHandlers.get(annotationName); if (handlers == null) return Collections.emptyList(); return new ArrayList(); } public List getAnnotationHandlers() { List allHandlers = new ArrayList(); for (List list:_annotationHandlers.values()) allHandlers.addAll(list); return allHandlers; } public void registerClassHandler (ClassHandler handler) { _classHandlers.add(handler); } public boolean isParsed (String className) { return _parsedClassNames.contains(className); } public void parse (String className, ClassNameResolver resolver) throws Exception { if (className == null) return; if (!resolver.isExcluded(className)) { if (!isParsed(className) || resolver.shouldOverride(className)) { className = className.replace('.', '/')+".class"; URL resource = Loader.getResource(this.getClass(), className, false); if (resource!= null) { Resource r = Resource.newResource(resource); scanClass(r.getInputStream()); } } } } public void parse (Class clazz, ClassNameResolver resolver, boolean visitSuperClasses) throws Exception { Class cz = clazz; while (cz != null) { if (!resolver.isExcluded(cz.getName())) { if (!isParsed(cz.getName()) || resolver.shouldOverride(cz.getName())) { String nameAsResource = cz.getName().replace('.', '/')+".class"; URL resource = Loader.getResource(this.getClass(), nameAsResource, false); if (resource!= null) { Resource r = Resource.newResource(resource); scanClass(r.getInputStream()); } } } if (visitSuperClasses) cz = cz.getSuperclass(); else cz = null; } } public void parse (String[] classNames, ClassNameResolver resolver) throws Exception { if (classNames == null) return; parse(Arrays.asList(classNames), resolver); } public void parse (List classNames, ClassNameResolver resolver) throws Exception { for (String s:classNames) { if ((resolver == null) || (!resolver.isExcluded(s) && (!isParsed(s) || resolver.shouldOverride(s)))) { s = s.replace('.', '/')+".class"; URL resource = Loader.getResource(this.getClass(), s, false); if (resource!= null) { Resource r = Resource.newResource(resource); scanClass(r.getInputStream()); } } } } public void parse (Resource dir, ClassNameResolver resolver) throws Exception { if (!dir.isDirectory() || !dir.exists()) return; String[] files=dir.list(); for (int f=0;files!=null && f values) { _initializer.addAnnotatedTypeName(className); } public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, List values) { _initializer.addAnnotatedTypeName(className); } public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation, List values) { _initializer.addAnnotatedTypeName(className); } } DeclareRolesAnnotationHandler.java000066400000000000000000000041611174773561500355120ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import javax.servlet.Servlet; import javax.annotation.security.DeclareRoles; import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.webapp.WebAppContext; /** * DeclaresRolesAnnotationHandler * * */ public class DeclareRolesAnnotationHandler extends AbstractIntrospectableAnnotationHandler { protected WebAppContext _context; /** * @param context */ public DeclareRolesAnnotationHandler(WebAppContext context) { super(false); _context = context; } /** * @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class) */ public void doHandle(Class clazz) { if (!Servlet.class.isAssignableFrom(clazz)) return; //only applicable on javax.servlet.Servlet derivatives DeclareRoles declareRoles = (DeclareRoles) clazz.getAnnotation(DeclareRoles.class); if (declareRoles == null) return; String[] roles = declareRoles.value(); if (roles != null && roles.length > 0) { for (String r:roles) ((ConstraintSecurityHandler)_context.getSecurityHandler()).addRole(r); } } } MultiPartConfigAnnotationHandler.java000066400000000000000000000066271174773561500362260ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import javax.servlet.MultipartConfigElement; import javax.servlet.Servlet; import javax.servlet.annotation.MultipartConfig; import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.webapp.Descriptor; import org.eclipse.jetty.webapp.MetaData; import org.eclipse.jetty.webapp.WebAppContext; /** * MultiPartConfigAnnotationHandler * * */ public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnnotationHandler { protected WebAppContext _context; public MultiPartConfigAnnotationHandler(WebAppContext context) { //TODO verify that MultipartConfig is not inheritable super(false); _context = context; } /** * @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class) */ public void doHandle(Class clazz) { if (!Servlet.class.isAssignableFrom(clazz)) return; MultipartConfig multi = (MultipartConfig) clazz.getAnnotation(MultipartConfig.class); if (multi == null) return; MetaData metaData = _context.getMetaData(); //TODO: The MultipartConfigElement needs to be set on the ServletHolder's Registration. //How to identify the correct Servlet? If the Servlet has no WebServlet annotation on it, does it mean that this MultipartConfig //annotation applies to all declared instances in web.xml/programmatically? //Assuming TRUE for now. ServletHolder holder = getServletHolderForClass(clazz); if (holder != null) { Descriptor d = metaData.getOriginDescriptor(holder.getName()+".servlet.multipart-config"); //if a descriptor has already set the value for multipart config, do not //let the annotation override it if (d == null) { metaData.setOrigin(holder.getName()+".servlet.multipart-config"); holder.getRegistration().setMultipartConfig(new MultipartConfigElement(multi)); } } } private ServletHolder getServletHolderForClass (Class clazz) { ServletHolder holder = null; ServletHolder[] holders = _context.getServletHandler().getServlets(); if (holders != null) { for (ServletHolder h : holders) { if (h.getClassName().equals(clazz.getName())) { holder = h; } } } return holder; } } PostConstructAnnotationHandler.java000066400000000000000000000073551174773561500360100ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import javax.annotation.PostConstruct; import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler; import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection; import org.eclipse.jetty.plus.annotation.PostConstructCallback; import org.eclipse.jetty.webapp.MetaData; import org.eclipse.jetty.webapp.Origin; import org.eclipse.jetty.webapp.WebAppContext; public class PostConstructAnnotationHandler extends AbstractIntrospectableAnnotationHandler { protected WebAppContext _context; public PostConstructAnnotationHandler (WebAppContext wac) { super(true); _context = wac; } public void doHandle(Class clazz) { //Check that the PostConstruct is on a class that we're interested in if (Util.isServletType(clazz)) { Method[] methods = clazz.getDeclaredMethods(); for (int i=0; i values) { LOG.warn ("@RunAs annotation not applicable for fields: "+className+"."+fieldName); } public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation, List values) { LOG.warn("@RunAs annotation ignored on method: "+className+"."+methodName+" "+signature); } private ServletHolder getServletHolderForClass (Class clazz) { ServletHolder holder = null; ServletHolder[] holders = _context.getServletHandler().getServlets(); if (holders != null) { for (ServletHolder h : holders) { if (h.getClassName().equals(clazz.getName())) { holder = h; } } } return holder; } } ServletContainerInitializerListener.java000066400000000000000000000132401174773561500370140ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotationspackage org.eclipse.jetty.annotations; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.eclipse.jetty.annotations.AnnotationConfiguration; import org.eclipse.jetty.plus.annotation.ContainerInitializer; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.webapp.WebAppContext; // ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== /** * ServletContainerInitializerListener * * */ public class ServletContainerInitializerListener implements ServletContextListener { WebAppContext _context = null; public void setWebAppContext (WebAppContext context) { _context = context; } /** * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) */ public void contextInitialized(ServletContextEvent sce) { List initializers = (List)_context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS); MultiMap classMap = (MultiMap)_context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP); if (initializers != null) { for (ContainerInitializer i : initializers) { //We have already found the classes that directly have an annotation that was in the HandlesTypes //annotation of the ServletContainerInitializer. For each of those classes, walk the inheritance //hierarchy to find classes that extend or implement them. if (i.getAnnotatedTypeNames() != null) { Set annotatedClassNames = new HashSet(i.getAnnotatedTypeNames()); for (String name : annotatedClassNames) { //add the class with the annotation i.addApplicableTypeName(name); //add the classes that inherit the annotation if (classMap != null) { List implementsOrExtends = (List)classMap.getValues(name); if (implementsOrExtends != null && !implementsOrExtends.isEmpty()) addInheritedTypes(classMap, i, implementsOrExtends); } } } //Now we need to look at the HandlesTypes classes that were not annotations. We need to //find all classes that extend or implement them. if (i.getInterestedTypes() != null) { for (Class c : i.getInterestedTypes()) { if (!c.isAnnotation()) { //add the classes that implement or extend the class. //TODO but not including the class itself? if (classMap != null) { List implementsOrExtends = (List)classMap.getValues(c.getName()); if (implementsOrExtends != null && !implementsOrExtends.isEmpty()) addInheritedTypes(classMap, i, implementsOrExtends); } } } } //instantiate ServletContainerInitializers, call doStart try { i.callStartup(_context); } catch (Exception e) { //OK, how do I throw an exception such that it really stops the startup sequence? e.printStackTrace(); } } //TODO Email from Jan Luehe 18 August: after all ServletContainerInitializers have been //called, need to check to see if there are any ServletRegistrations remaining //that are "preliminary" and fail the deployment if so. } } void addInheritedTypes (MultiMap classMap, ContainerInitializer initializer, List applicableTypes) { for (String s : applicableTypes) { //add the name of the class that extends or implements initializer.addApplicableTypeName(s); //walk the hierarchy and find all types that extend or implement it List implementsOrExtends = (List)classMap.getValues(s); if (implementsOrExtends != null && !implementsOrExtends.isEmpty()) addInheritedTypes (classMap, initializer, implementsOrExtends); } } /** * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) */ public void contextDestroyed(ServletContextEvent sce) { // TODO Auto-generated method stub } } ServletSecurityAnnotationHandler.java000066400000000000000000000306131174773561500363230ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.ArrayList; import java.util.List; import javax.servlet.annotation.HttpConstraint; import javax.servlet.annotation.HttpMethodConstraint; import javax.servlet.annotation.ServletSecurity; import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic; import javax.servlet.annotation.ServletSecurity.TransportGuarantee; import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler; import org.eclipse.jetty.security.ConstraintAware; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletMapping; import org.eclipse.jetty.util.LazyList; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.webapp.WebAppContext; /** * ServletSecurityAnnotationHandler * * Inspect a class to see if it has an @ServletSecurity annotation on it, * setting up the s. * * A servlet can be defined in: *
    *
  • web.xml *
  • web-fragment.xml *
  • @WebServlet annotation discovered *
  • ServletContext.createServlet *
* * The ServletSecurity annotation for a servlet should only be processed * iff metadata-complete == false. */ public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnnotationHandler { private static final Logger LOG = Log.getLogger(ServletSecurityAnnotationHandler.class); private WebAppContext _context; public ServletSecurityAnnotationHandler(WebAppContext wac) { super(false); _context = wac; } /** * @see org.eclipse.jetty.annotations.AnnotationIntrospector.IntrospectableAnnotationHandler#handle(java.lang.Class) */ public void doHandle(Class clazz) { if (!(_context.getSecurityHandler() instanceof ConstraintAware)) { LOG.warn("SecurityHandler not ConstraintAware, skipping security annotation processing"); return; } ServletSecurity servletSecurity = (ServletSecurity)clazz.getAnnotation(ServletSecurity.class); if (servletSecurity == null) return; //If there are already constraints defined (ie from web.xml or programmatically(?)) that match any //of the url patterns defined for this servlet, then skip the security annotation. List servletMappings = getServletMappings(clazz.getCanonicalName()); List constraintMappings = ((ConstraintAware)_context.getSecurityHandler()).getConstraintMappings(); if (constraintsExist(servletMappings, constraintMappings)) { LOG.warn("Constraints already defined for "+clazz.getName()+", skipping ServletSecurity annotation"); return; } //Make a fresh list constraintMappings = new ArrayList(); //Get the values that form the constraints that will apply unless there are HttpMethodConstraints to augment them HttpConstraint defaults = servletSecurity.value(); //Make a Constraint for the and specified by the HttpConstraint Constraint defaultConstraint = makeConstraint (clazz, defaults.rolesAllowed(), defaults.value(), defaults.transportGuarantee()); constraintMappings.addAll(makeMethodMappings(clazz, defaultConstraint, servletMappings, servletSecurity.httpMethodConstraints())); //set up the security constraints produced by the annotation ConstraintAware securityHandler = (ConstraintAware)_context.getSecurityHandler(); for (ConstraintMapping m:constraintMappings) securityHandler.addConstraintMapping(m); } /** * Make a jetty Constraint object, which represents the and * elements, based on the security annotation. * @param servlet * @param rolesAllowed * @param permitOrDeny * @param transport * @return */ protected Constraint makeConstraint (Class servlet, String[] rolesAllowed, EmptyRoleSemantic permitOrDeny, TransportGuarantee transport) { Constraint constraint = new Constraint(); if (rolesAllowed == null || rolesAllowed.length==0) { if (permitOrDeny.equals(EmptyRoleSemantic.DENY)) { //Equivalent to with no roles constraint.setName(servlet.getName()+"-Deny"); constraint.setAuthenticate(true); } else { //Equivalent to no constraint.setAuthenticate(false); constraint.setName(servlet.getName()+"-Permit"); } } else { //Equivalent to with list of s constraint.setAuthenticate(true); constraint.setRoles(rolesAllowed); constraint.setName(servlet.getName()+"-RolesAllowed"); } //Equivalent to //CONFIDENTIAL constraint.setDataConstraint((transport.equals(TransportGuarantee.CONFIDENTIAL)?Constraint.DC_CONFIDENTIAL:Constraint.DC_NONE)); return constraint; } /** * Make a ConstraintMapping which captures the or elements for a particular url pattern, * and relates it to a Constraint object ( and ). * @param constraint * @param url * @param method * @param omissions * @return */ protected ConstraintMapping makeConstraintMapping (Constraint constraint, String url, String method, String[] omissions) { ConstraintMapping mapping = new ConstraintMapping(); mapping.setConstraint(constraint); mapping.setPathSpec(url); if (method != null) mapping.setMethod(method); if (omissions != null) mapping.setMethodOmissions(omissions); return mapping; } /** * Make the Jetty Constraints and ConstraintMapping objects that correspond to the HttpMethodConstraint * annotations for each url pattern for the servlet. * @param servlet * @param defaultConstraint * @param servletMappings * @param annotations * @return */ protected List makeMethodMappings (Class servlet, Constraint defaultConstraint, List servletMappings, HttpMethodConstraint[] annotations) { List mappings = new ArrayList(); //for each url-pattern existing for the servlet make a ConstraintMapping for the HttpConstraint, and ConstraintMappings for //each HttpMethodConstraint for (ServletMapping sm : servletMappings) { for (String url : sm.getPathSpecs()) { //Make a ConstraintMapping that matches the defaultConstraint ConstraintMapping defaultMapping = makeConstraintMapping(defaultConstraint, url, null, null); //If there are HttpMethodConstraint annotations, make a Constraint and a ConstraintMapping for it if (annotations != null && annotations.length>0) { List omissions = new ArrayList(); //for each HttpMethodConstraint annotation, make a new Constraint and ConstraintMappings for this url for (int i=0; i < annotations.length;i++) { //Make a Constraint that captures the and elements Constraint methodConstraint = makeConstraint(servlet, annotations[i].rolesAllowed(), annotations[i].emptyRoleSemantic(), annotations[i].transportGuarantee()); //Make ConstraintMapping that captures the elements ConstraintMapping methodConstraintMapping = makeConstraintMapping (methodConstraint, url,annotations[i].value(), null); mappings.add(methodConstraintMapping); omissions.add(annotations[i].value()); } defaultMapping.setMethodOmissions(omissions.toArray(new String[0])); } //add the constraint mapping containing the http-method-omissions, if there are any mappings.add(defaultMapping); } } return mappings; } /** * Get the ServletMappings for the servlet's class. * @param className * @return */ protected List getServletMappings(String className) { List results = new ArrayList(); ServletMapping[] mappings = _context.getServletHandler().getServletMappings(); for (ServletMapping mapping : mappings) { //Check the name of the servlet that this mapping applies to, and then find the ServletHolder for it to find it's class ServletHolder holder = _context.getServletHandler().getServlet(mapping.getServletName()); if (holder.getClassName().equals(className)) results.add(mapping); } return results; } /** * Check if there are already elements defined that match the url-patterns for * the servlet. * @param servletMappings * @return */ protected boolean constraintsExist (List servletMappings, List constraintMappings) { boolean exists = false; //Check to see if the path spec on each constraint mapping matches a pathSpec in the servlet mappings. //If it does, then we should ignore the security annotations. for (ServletMapping mapping : servletMappings) { //Get its url mappings String[] pathSpecs = mapping.getPathSpecs(); if (pathSpecs == null) continue; //Check through the constraints to see if there are any whose pathSpecs (url mappings) //match the servlet. If so, then we already have constraints defined for this servlet, //and we will not be processing the annotation (ie web.xml or programmatic override). for (int i=0; constraintMappings != null && i < constraintMappings.size() && !exists; i++) { for (int j=0; j < pathSpecs.length; j++) { if (pathSpecs[j].equals(constraintMappings.get(i).getPathSpec())) { exists = true; break; } } } } return exists; } } jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/Util.java000066400000000000000000000161401174773561500306110ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.lang.reflect.Array; import org.eclipse.jetty.util.Loader; import org.eclipse.jetty.util.TypeUtil; import org.objectweb.asm.Type; /** * Util */ public class Util { private static Class[] __envEntryClassTypes = new Class[] {String.class, Character.class, Integer.class, Boolean.class, Double.class, Byte.class, Short.class, Long.class, Float.class}; private static String[] __envEntryTypes = new String[] { Type.getDescriptor(String.class), Type.getDescriptor(Character.class), Type.getDescriptor(Integer.class), Type.getDescriptor(Boolean.class), Type.getDescriptor(Double.class), Type.getDescriptor(Byte.class), Type.getDescriptor(Short.class), Type.getDescriptor(Long.class), Type.getDescriptor(Float.class)}; /** * Check if the presented method belongs to a class that is one * of the classes with which a servlet container should be concerned. * @param c * @return true if class is a type of one of the following: * ({@link javax.servlet.Servlet}, * {@link javax.servlet.Filter}, * {@link javax.servlet.ServletContextListener}, * {@link javax.servlet.ServletContextAttributeListener}, * {@link javax.servlet.ServletRequestListener}, * {@link javax.servlet.ServletRequestAttributeListener}, * {@link javax.servlet.http.HttpSessionListener}, * {@link javax.servlet.http.HttpSessionAttributeListener}) */ public static boolean isServletType (Class c) { boolean isServlet = false; if (javax.servlet.Servlet.class.isAssignableFrom(c) || javax.servlet.Filter.class.isAssignableFrom(c) || javax.servlet.ServletContextListener.class.isAssignableFrom(c) || javax.servlet.ServletContextAttributeListener.class.isAssignableFrom(c) || javax.servlet.ServletRequestListener.class.isAssignableFrom(c) || javax.servlet.ServletRequestAttributeListener.class.isAssignableFrom(c) || javax.servlet.http.HttpSessionListener.class.isAssignableFrom(c) || javax.servlet.http.HttpSessionAttributeListener.class.isAssignableFrom(c) || javax.servlet.AsyncListener.class.isAssignableFrom(c)) isServlet=true; return isServlet; } public static boolean isEnvEntryType (Class type) { boolean result = false; for (int i=0;i<__envEntryClassTypes.length && !result;i++) { result = (type.equals(__envEntryClassTypes[i])); } return result; } public static boolean isEnvEntryType (String desc) { boolean result = false; for (int i=0;i<__envEntryTypes.length && !result;i++) { result = (desc.equals(__envEntryTypes[i])); } return result; } public static String normalizePattern(String p) { if (p!=null && p.length()>0 && !p.startsWith("/") && !p.startsWith("*")) return "/"+p; return p; } public static Class[] convertTypes (String params) throws Exception { return convertTypes(Type.getArgumentTypes(params)); } public static Class[] convertTypes (Type[] types) throws Exception { if (types==null) return new Class[0]; Class[] classArray = new Class[types.length]; for (int i=0; i 0 && filterAnnotation.urlPatterns().length > 0) { LOG.warn(clazz.getName()+" defines both @WebFilter.value and @WebFilter.urlPatterns"); return; } String name = (filterAnnotation.filterName().equals("")?clazz.getName():filterAnnotation.filterName()); String[] urlPatterns = filterAnnotation.value(); if (urlPatterns.length == 0) urlPatterns = filterAnnotation.urlPatterns(); FilterHolder holder = _context.getServletHandler().getFilter(name); if (holder == null) { //Filter with this name does not already exist, so add it holder = _context.getServletHandler().newFilterHolder(Holder.Source.ANNOTATION); holder.setName(name); holder.setHeldClass(clazz); metaData.setOrigin(name+".filter.filter-class"); holder.setDisplayName(filterAnnotation.displayName()); metaData.setOrigin(name+".filter.display-name"); for (WebInitParam ip: filterAnnotation.initParams()) { holder.setInitParameter(ip.name(), ip.value()); metaData.setOrigin(name+".filter.init-param."+ip.name()); } FilterMapping mapping = new FilterMapping(); mapping.setFilterName(holder.getName()); if (urlPatterns.length > 0) { ArrayList paths = new ArrayList(); for (String s:urlPatterns) { paths.add(Util.normalizePattern(s)); } mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()])); } if (filterAnnotation.servletNames().length > 0) { ArrayList names = new ArrayList(); for (String s : filterAnnotation.servletNames()) { names.add(s); } mapping.setServletNames((String[])names.toArray(new String[names.size()])); } EnumSet dispatcherSet = EnumSet.noneOf(DispatcherType.class); for (DispatcherType d : filterAnnotation.dispatcherTypes()) { dispatcherSet.add(d); } mapping.setDispatcherTypes(dispatcherSet); metaData.setOrigin(name+".filter.mappings"); holder.setAsyncSupported(filterAnnotation.asyncSupported()); metaData.setOrigin(name+".filter.async-supported"); _context.getServletHandler().addFilter(holder); _context.getServletHandler().addFilterMapping(mapping); } else { //A Filter definition for the same name already exists from web.xml //ServletSpec 3.0 p81 if the Filter is already defined and has mappings, //they override the annotation. If it already has DispatcherType set, that //also overrides the annotation. Init-params are additive, but web.xml overrides //init-params of the same name. for (WebInitParam ip: filterAnnotation.initParams()) { //if (holder.getInitParameter(ip.name()) == null) if (metaData.getOrigin(name+".filter.init-param."+ip.name())==Origin.NotSet) { holder.setInitParameter(ip.name(), ip.value()); metaData.setOrigin(name+".filter.init-param."+ip.name()); } } FilterMapping[] mappings = _context.getServletHandler().getFilterMappings(); boolean mappingExists = false; if (mappings != null) { for (FilterMapping m:mappings) { if (m.getFilterName().equals(name)) { mappingExists = true; break; } } } //if a descriptor didn't specify at least one mapping, use the mappings from the annotation and the DispatcherTypes //from the annotation if (!mappingExists) { FilterMapping mapping = new FilterMapping(); mapping.setFilterName(holder.getName()); if (urlPatterns.length > 0) { ArrayList paths = new ArrayList(); for (String s:urlPatterns) { paths.add(Util.normalizePattern(s)); } mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()])); } if (filterAnnotation.servletNames().length > 0) { ArrayList names = new ArrayList(); for (String s : filterAnnotation.servletNames()) { names.add(s); } mapping.setServletNames((String[])names.toArray(new String[names.size()])); } EnumSet dispatcherSet = EnumSet.noneOf(DispatcherType.class); for (DispatcherType d : filterAnnotation.dispatcherTypes()) { dispatcherSet.add(d); } mapping.setDispatcherTypes(dispatcherSet); _context.getServletHandler().addFilterMapping(mapping); metaData.setOrigin(name+".filter.mappings"); } } } } WebFilterAnnotationHandler.java000066400000000000000000000045471174773561500350410ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2009-2010 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.List; import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler; import org.eclipse.jetty.annotations.AnnotationParser.Value; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.webapp.DiscoveredAnnotation; import org.eclipse.jetty.webapp.WebAppContext; /** * WebFilterAnnotationHandler * * */ public class WebFilterAnnotationHandler extends AbstractDiscoverableAnnotationHandler { private static final Logger LOG = Log.getLogger(WebFilterAnnotationHandler.class); public WebFilterAnnotationHandler (WebAppContext context) { super(context); } public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation, List values) { WebFilterAnnotation wfAnnotation = new WebFilterAnnotation(_context, className); addAnnotation(wfAnnotation); } public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, List values) { LOG.warn ("@WebFilter not applicable for fields: "+className+"."+fieldName); } public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation, List values) { LOG.warn ("@WebFilter not applicable for methods: "+className+"."+methodName+" "+signature); } } WebListenerAnnotation.java000066400000000000000000000061111174773561500340700ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextListener; import javax.servlet.ServletRequestAttributeListener; import javax.servlet.ServletRequestListener; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionListener; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.webapp.DiscoveredAnnotation; import org.eclipse.jetty.webapp.MetaData; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.Origin; /** * WebListenerAnnotation * * */ public class WebListenerAnnotation extends DiscoveredAnnotation { private static final Logger LOG = Log.getLogger(WebListenerAnnotation.class); /** * @param context * @param className */ public WebListenerAnnotation(WebAppContext context, String className) { super(context, className); } /** * @see org.eclipse.jetty.annotations.ClassAnnotation#apply() */ public void apply() { // TODO check algorithm against ordering rules for descriptors v annotations Class clazz = getTargetClass(); if (clazz == null) { LOG.warn(_className+" cannot be loaded"); return; } try { if (ServletContextListener.class.isAssignableFrom(clazz) || ServletContextAttributeListener.class.isAssignableFrom(clazz) || ServletRequestListener.class.isAssignableFrom(clazz) || ServletRequestAttributeListener.class.isAssignableFrom(clazz) || HttpSessionListener.class.isAssignableFrom(clazz) || HttpSessionAttributeListener.class.isAssignableFrom(clazz)) { java.util.EventListener listener = (java.util.EventListener)clazz.newInstance(); MetaData metaData = _context.getMetaData(); if (metaData.getOrigin(clazz.getName()+".listener") == Origin.NotSet) _context.addEventListener(listener); } else LOG.warn(clazz.getName()+" does not implement one of the servlet listener interfaces"); } catch (Exception e) { LOG.warn(e); } } } WebListenerAnnotationHandler.java000066400000000000000000000046601174773561500353750ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2009-2010 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.List; import org.eclipse.jetty.annotations.AnnotationParser.Value; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.webapp.WebAppContext; public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotationHandler { private static final Logger LOG = Log.getLogger(WebListenerAnnotationHandler.class); public WebListenerAnnotationHandler (WebAppContext context) { super(context); } /** * @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List) */ public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation, List values) { WebListenerAnnotation wlAnnotation = new WebListenerAnnotation(_context, className); addAnnotation(wlAnnotation); } public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, List values) { LOG.warn ("@WebListener is not applicable to fields: "+className+"."+fieldName); } public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation, List values) { LOG.warn ("@WebListener is not applicable to methods: "+className+"."+methodName+" "+signature); } } jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java000066400000000000000000000152051174773561500340120ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2010 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.ArrayList; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import org.eclipse.jetty.servlet.Holder; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletMapping; import org.eclipse.jetty.util.LazyList; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.webapp.DiscoveredAnnotation; import org.eclipse.jetty.webapp.MetaData; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.Origin; /** * WebServletAnnotation * * */ public class WebServletAnnotation extends DiscoveredAnnotation { private static final Logger LOG = Log.getLogger(WebServletAnnotation.class); public WebServletAnnotation (WebAppContext context, String className) { super(context, className); } /** * @see org.eclipse.jetty.annotations.ClassAnnotation#apply() */ public void apply() { //TODO check this algorithm with new rules for applying descriptors and annotations in order Class clazz = getTargetClass(); if (clazz == null) { LOG.warn(_className+" cannot be loaded"); return; } //Servlet Spec 8.1.1 if (!HttpServlet.class.isAssignableFrom(clazz)) { LOG.warn(clazz.getName()+" is not assignable from javax.servlet.http.HttpServlet"); return; } WebServlet annotation = (WebServlet)clazz.getAnnotation(WebServlet.class); if (annotation.urlPatterns().length > 0 && annotation.value().length > 0) { LOG.warn(clazz.getName()+ " defines both @WebServlet.value and @WebServlet.urlPatterns"); return; } String[] urlPatterns = annotation.value(); if (urlPatterns.length == 0) urlPatterns = annotation.urlPatterns(); if (urlPatterns.length == 0) { LOG.warn(clazz.getName()+ " defines neither @WebServlet.value nor @WebServlet.urlPatterns"); return; } //canonicalize the patterns ArrayList urlPatternList = new ArrayList(); for (String p : urlPatterns) urlPatternList.add(Util.normalizePattern(p)); String servletName = (annotation.name().equals("")?clazz.getName():annotation.name()); MetaData metaData = _context.getMetaData(); //Find out if a of this type already exists with this name ServletHolder[] holders = _context.getServletHandler().getServlets(); boolean isNew = true; ServletHolder holder = null; if (holders != null) { for (ServletHolder h : holders) { if (h.getClassName().equals(clazz.getName()) && h.getName() != null && servletName.equals(h.getName())) { holder = h; isNew = false; break; } } } if (isNew) { //No servlet of this name has already been defined, either by a descriptor //or another annotation (which would be impossible). holder = _context.getServletHandler().newServletHolder(Holder.Source.ANNOTATION); holder.setHeldClass(clazz); metaData.setOrigin(servletName+".servlet.servlet-class"); holder.setName(servletName); holder.setDisplayName(annotation.displayName()); metaData.setOrigin(servletName+".servlet.display-name"); holder.setInitOrder(annotation.loadOnStartup()); metaData.setOrigin(servletName+".servlet.load-on-startup"); holder.setAsyncSupported(annotation.asyncSupported()); metaData.setOrigin(servletName+".servlet.async-supported"); for (WebInitParam ip:annotation.initParams()) { holder.setInitParameter(ip.name(), ip.value()); metaData.setOrigin(servletName+".servlet.init-param."+ip.name()); } _context.getServletHandler().addServlet(holder); ServletMapping mapping = new ServletMapping(); mapping.setServletName(holder.getName()); mapping.setPathSpecs( LazyList.toStringArray(urlPatternList)); _context.getServletHandler().addServletMapping(mapping); metaData.setOrigin(servletName+".servlet.mappings"); } else { //check if the existing servlet has each init-param from the annotation //if not, add it for (WebInitParam ip:annotation.initParams()) { //if (holder.getInitParameter(ip.name()) == null) if (metaData.getOrigin(servletName+".servlet.init-param"+ip.name())==Origin.NotSet) { holder.setInitParameter(ip.name(), ip.value()); metaData.setOrigin(servletName+".servlet.init-param."+ip.name()); } } //check the url-patterns, if there annotation has a new one, add it ServletMapping[] mappings = _context.getServletHandler().getServletMappings(); //ServletSpec 3.0 p81 If a servlet already has url mappings from a //descriptor the annotation is ignored if (mappings == null && metaData.getOriginDescriptor(servletName+".servlet.mappings") != null) { ServletMapping mapping = new ServletMapping(); mapping.setServletName(servletName); mapping.setPathSpecs(LazyList.toStringArray(urlPatternList)); _context.getServletHandler().addServletMapping(mapping); } } } } WebServletAnnotationHandler.java000066400000000000000000000054271174773561500352360ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/main/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.List; import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler; import org.eclipse.jetty.annotations.AnnotationParser.Value; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.webapp.DiscoveredAnnotation; import org.eclipse.jetty.webapp.WebAppContext; /** * WebServletAnnotationHandler * * Process a WebServlet annotation on a class. * */ public class WebServletAnnotationHandler extends AbstractDiscoverableAnnotationHandler { private static final Logger LOG = Log.getLogger(WebServletAnnotationHandler.class); public WebServletAnnotationHandler (WebAppContext context) { super(context); } /** * Handle discovering a WebServlet annotation. * * * @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List) */ public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotationName, List values) { if (!"javax.servlet.annotation.WebServlet".equals(annotationName)) return; WebServletAnnotation annotation = new WebServletAnnotation (_context, className); addAnnotation(annotation); } public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, List values) { LOG.warn ("@WebServlet annotation not supported for fields"); } public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation, List values) { LOG.warn ("@WebServlet annotation not supported for methods"); } } jetty8-8.1.3/jetty-annotations/src/test/000077500000000000000000000000001174773561500202325ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/000077500000000000000000000000001174773561500211535ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/000077500000000000000000000000001174773561500217425ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/000077500000000000000000000000001174773561500233665ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500245255ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/000077500000000000000000000000001174773561500270625ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ClassA.java000066400000000000000000000036521174773561500311010ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; /** * ClassA * * */ @Sample(1) public class ClassA { private Integer e; private Integer f; private Integer g; private Integer h; private Integer j; private Integer k; public static class Foo { } @Sample(7) private Integer m; @Sample(2) public void a (Integer[] x) { System.err.println("ClassA.public"); } @Sample(3) protected void b(Foo[] f) { System.err.println("ClassA.protected"); } @Sample(4) void c(int[] x) { System.err.println("ClassA.package"); } @Sample(5) private void d(int x, String y) { System.err.println("ClassA.private"); } @Sample(6) protected void l() { System.err.println("ClassA.protected method l"); } public Integer getE() { return this.e; } public Integer getF() { return this.f; } public Integer getG() { return this.g; } public Integer getJ() { return this.j; } public void x() { System.err.println("ClassA.x"); } } jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ClassB.java000066400000000000000000000026571174773561500311060ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; /** * ClassB * * */ @Sample(value=50) @Multi({"do", "re", "mi"}) public class ClassB extends ClassA implements InterfaceD { //test override of public scope method @Sample(value=51) @Multi({"fa", "so", "la"}) public void a() { System.err.println("ClassB.public"); } //test override of package scope method @Sample(value=52) void c() { System.err.println("ClassB.package"); } public void l() { System.err.println("Overridden method l has no annotation"); } //test no annotation public void z() { System.err.println("ClassB.z"); } } jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/FilterC.java000066400000000000000000000046511174773561500312630ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.io.IOException; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; import javax.annotation.security.RunAs; import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebFilter(filterName="CFilter", dispatcherTypes={DispatcherType.REQUEST}, urlPatterns = {"/*"}, initParams={@WebInitParam(name="a", value="99")}, asyncSupported=false) @RunAs("admin") public class FilterC implements Filter { @Resource (mappedName="foo") private Double foo; @PreDestroy public void pre () { } @PostConstruct public void post() { } public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)arg0; HttpServletResponse response = (HttpServletResponse)arg1; HttpSession session = request.getSession(true); String val = request.getParameter("action"); if (val!=null) session.setAttribute("action", val); arg2.doFilter(request, response); } public void destroy() { } public void init(FilterConfig arg0) throws ServletException { } } jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/InterfaceD.java000066400000000000000000000015271174773561500317360ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; /** * InterfaceD * * */ public interface InterfaceD { } jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ListenerC.java000066400000000000000000000022061174773561500316150ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class ListenerC implements ServletContextListener { public void contextDestroyed(ServletContextEvent arg0) { } public void contextInitialized(ServletContextEvent arg0) { } } jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Multi.java000066400000000000000000000005461174773561500310240ustar00rootroot00000000000000package org.eclipse.jetty.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) public @interface Multi { String[] value(); } jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Sample.java000066400000000000000000000021221174773561500311430ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) public @interface Sample { int value(); } jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ServletC.java000066400000000000000000000047141174773561500314620ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2010 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.io.IOException; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; import javax.annotation.security.DeclareRoles; import javax.annotation.security.RunAs; import javax.servlet.ServletException; import javax.servlet.annotation.HttpConstraint; import javax.servlet.annotation.HttpMethodConstraint; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.ServletSecurity; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @DeclareRoles({"alice"}) @WebServlet(urlPatterns = { "/foo/*", "/bah/*" }, name="CServlet", initParams={@WebInitParam(name="x", value="y")}, loadOnStartup=2, asyncSupported=false) @MultipartConfig(fileSizeThreshold=1000, maxFileSize=2000, maxRequestSize=3000) @RunAs("admin") @ServletSecurity(value=@HttpConstraint(rolesAllowed={"fred", "bill", "dorothy"}), httpMethodConstraints={@HttpMethodConstraint(value="GET", rolesAllowed={"bob", "carol", "ted"})}) public class ServletC extends HttpServlet { @Resource (mappedName="foo", type=Double.class) private Double foo; @PreDestroy public void pre () { } @PostConstruct public void post() { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.getWriter().println("

Annotated Servlet

"); response.getWriter().println("An annotated Servlet."); } } TestAnnotationConfiguration.java000066400000000000000000000036431174773561500353560ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.List; import junit.framework.TestCase; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.FragmentDescriptor; import org.eclipse.jetty.webapp.WebAppContext; /** * TestAnnotationConfiguration * * */ public class TestAnnotationConfiguration extends TestCase { public void testGetFragmentFromJar () throws Exception { String dir = System.getProperty("basedir", "."); File file = new File(dir); file=new File(file.getCanonicalPath()); URL url=file.toURL(); Resource jar1 = Resource.newResource(url+"file.jar"); AnnotationConfiguration config = new AnnotationConfiguration(); WebAppContext wac = new WebAppContext(); List frags = new ArrayList(); frags.add(new FragmentDescriptor(Resource.newResource("jar:"+url+"file.jar!/fooa.props"))); frags.add(new FragmentDescriptor(Resource.newResource("jar:"+url+"file2.jar!/foob.props"))); assertNotNull(config.getFragmentFromJar(jar1, frags)); } } TestAnnotationInheritance.java000066400000000000000000000216071174773561500350000ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.naming.Context; import javax.naming.InitialContext; import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler; import org.eclipse.jetty.annotations.AnnotationParser.Value; import org.eclipse.jetty.util.MultiMap; import org.junit.After; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** * */ public class TestAnnotationInheritance { List classNames = new ArrayList(); class SampleHandler implements DiscoverableAnnotationHandler { public final List annotatedClassNames = new ArrayList(); public final List annotatedMethods = new ArrayList(); public final List annotatedFields = new ArrayList(); public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation, List values) { annotatedClassNames.add(className); } public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, List values) { annotatedFields.add(className+"."+fieldName); } public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation, List values) { annotatedMethods.add(className+"."+methodName); } } @After public void destroy() throws Exception { classNames.clear(); InitialContext ic = new InitialContext(); Context comp = (Context)ic.lookup("java:comp"); comp.destroySubcontext("env"); } @Test public void testParseClassNames() throws Exception { classNames.add(ClassA.class.getName()); classNames.add(ClassB.class.getName()); SampleHandler handler = new SampleHandler(); AnnotationParser parser = new AnnotationParser(); parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", handler); parser.parse(classNames, new ClassNameResolver () { public boolean isExcluded(String name) { return false; } public boolean shouldOverride(String name) { return false; } }); //check we got 2 class annotations assertEquals(2, handler.annotatedClassNames.size()); //check we got all annotated methods on each class assertEquals (7, handler.annotatedMethods.size()); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.a")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.b")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.c")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.d")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.l")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassB.a")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassB.c")); //check we got all annotated fields on each class assertEquals(1, handler.annotatedFields.size()); assertEquals("org.eclipse.jetty.annotations.ClassA.m", handler.annotatedFields.get(0)); } @Test public void testParseClass() throws Exception { SampleHandler handler = new SampleHandler(); AnnotationParser parser = new AnnotationParser(); parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", handler); parser.parse(ClassB.class, new ClassNameResolver () { public boolean isExcluded(String name) { return false; } public boolean shouldOverride(String name) { return false; } }, true); //check we got 2 class annotations assertEquals(2, handler.annotatedClassNames.size()); //check we got all annotated methods on each class assertEquals (7, handler.annotatedMethods.size()); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.a")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.b")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.c")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.d")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.l")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassB.a")); assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassB.c")); //check we got all annotated fields on each class assertEquals(1, handler.annotatedFields.size()); assertEquals("org.eclipse.jetty.annotations.ClassA.m", handler.annotatedFields.get(0)); } @Test public void testExclusions() throws Exception { AnnotationParser parser = new AnnotationParser(); SampleHandler handler = new SampleHandler(); parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", handler); parser.parse(ClassA.class.getName(), new ClassNameResolver() { public boolean isExcluded(String name) { return true; } public boolean shouldOverride(String name) { return false; } }); assertEquals (0, handler.annotatedClassNames.size()); assertEquals (0, handler.annotatedFields.size()); assertEquals (0, handler.annotatedMethods.size()); handler.annotatedClassNames.clear(); handler.annotatedFields.clear(); handler.annotatedMethods.clear(); parser.parse (ClassA.class.getName(), new ClassNameResolver() { public boolean isExcluded(String name) { return false; } public boolean shouldOverride(String name) { return false; } }); assertEquals (1, handler.annotatedClassNames.size()); } @Test public void testTypeInheritanceHandling() throws Exception { AnnotationParser parser = new AnnotationParser(); ClassInheritanceHandler handler = new ClassInheritanceHandler(); parser.registerClassHandler(handler); class Foo implements InterfaceD { } classNames.clear(); classNames.add(ClassA.class.getName()); classNames.add(ClassB.class.getName()); classNames.add(InterfaceD.class.getName()); classNames.add(Foo.class.getName()); parser.parse(classNames, null); MultiMap map = handler.getMap(); assertNotNull(map); assertFalse(map.isEmpty()); assertEquals(2, map.size()); Map stringArrayMap = map.toStringArrayMap(); assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.ClassA")); assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.InterfaceD")); String[] classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.ClassA"); assertEquals(1, classes.length); assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]); classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.InterfaceD"); assertEquals(2, classes.length); assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]); assertEquals(Foo.class.getName(), classes[1]); } } jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java000066400000000000000000000136611174773561500340630ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.Arrays; import java.util.List; import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler; import org.eclipse.jetty.annotations.AnnotationParser.Value; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class TestAnnotationParser { @Test public void testSampleAnnotation() throws Exception { String[] classNames = new String[]{"org.eclipse.jetty.annotations.ClassA"}; AnnotationParser parser = new AnnotationParser(); class SampleAnnotationHandler implements DiscoverableAnnotationHandler { private List methods = Arrays.asList("a", "b", "c", "d", "l"); public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation, List values) { assertEquals ("org.eclipse.jetty.annotations.ClassA", className); } public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, List values) { assertEquals ("m", fieldName); assertEquals (org.objectweb.asm.Type.OBJECT, org.objectweb.asm.Type.getType(fieldType).getSort()); assertEquals (1, values.size()); Value anv1 = values.get(0); assertEquals ("value", anv1.getName()); assertEquals (7, anv1.getValue()); } public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation, List values) { System.err.println("Sample annotated method : classname="+className+" methodName="+methodName+" access="+access+" desc="+desc+" signature="+signature); org.objectweb.asm.Type retType = org.objectweb.asm.Type.getReturnType(desc); System.err.println("REturn type = "+retType); org.objectweb.asm.Type[] params = org.objectweb.asm.Type.getArgumentTypes(desc); if (params == null) System.err.println("No params"); else System.err.println(params.length+" params"); if (exceptions == null) System.err.println("No exceptions"); else System.err.println(exceptions.length+" exceptions"); assertEquals("org.eclipse.jetty.annotations.ClassA", className); assertTrue(methods.contains(methodName)); assertEquals("org.eclipse.jetty.annotations.Sample", annotation); } } parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", new SampleAnnotationHandler()); long start = System.currentTimeMillis(); parser.parse(classNames, new ClassNameResolver () { public boolean isExcluded(String name) { return false; } public boolean shouldOverride(String name) { return false; } }); long end = System.currentTimeMillis(); System.err.println("Time to parse class: "+((end-start))); } @Test public void testMultiAnnotation() throws Exception { String[] classNames = new String[]{"org.eclipse.jetty.annotations.ClassB"}; AnnotationParser parser = new AnnotationParser(); class MultiAnnotationHandler implements DiscoverableAnnotationHandler { public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation, List values) { assertTrue("org.eclipse.jetty.annotations.ClassB".equals(className)); for (Value anv: values) { System.err.println(anv.toString()); } } public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, List values) { //there should not be any fail(); } public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation, List values) { assertTrue("org.eclipse.jetty.annotations.ClassB".equals(className)); assertTrue("a".equals(methodName)); for (Value anv: values) { System.err.println(anv.toString()); } } } parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Multi", new MultiAnnotationHandler()); parser.parse(classNames, null); } } TestSecurityAnnotationConversions.java000066400000000000000000000363451174773561500366140ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.annotation.ServletSecurity; import javax.servlet.annotation.HttpConstraint; import javax.servlet.annotation.HttpMethodConstraint; import javax.servlet.annotation.ServletSecurity.TransportGuarantee; import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic; import javax.servlet.http.HttpServlet; import org.eclipse.jetty.security.ConstraintAware; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.servlet.Holder; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletMapping; import org.eclipse.jetty.util.LazyList; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.webapp.WebAppContext; import junit.framework.TestCase; public class TestSecurityAnnotationConversions extends TestCase { @ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.DENY)) public static class DenyServlet extends HttpServlet {} @ServletSecurity public static class PermitServlet extends HttpServlet {} @ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.PERMIT, transportGuarantee=TransportGuarantee.CONFIDENTIAL, rolesAllowed={"tom", "dick", "harry"})) public static class RolesServlet extends HttpServlet {} @ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.PERMIT, transportGuarantee=TransportGuarantee.CONFIDENTIAL, rolesAllowed={"tom", "dick", "harry"}), httpMethodConstraints={@HttpMethodConstraint(value="GET")}) public static class Method1Servlet extends HttpServlet {} @ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.PERMIT, transportGuarantee=TransportGuarantee.CONFIDENTIAL, rolesAllowed={"tom", "dick", "harry"}), httpMethodConstraints={@HttpMethodConstraint(value="GET", transportGuarantee=TransportGuarantee.CONFIDENTIAL)}) public static class Method2Servlet extends HttpServlet {} public void setUp() { } public void testDenyAllOnClass () throws Exception { WebAppContext wac = makeWebAppContext(DenyServlet.class.getCanonicalName(), "denyServlet", new String[]{"/foo/*", "*.foo"}); //Assume we found 1 servlet with a @HttpConstraint with value=EmptyRoleSemantic.DENY security annotation ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac); AnnotationIntrospector introspector = new AnnotationIntrospector(); introspector.registerHandler(annotationHandler); //set up the expected outcomes: //1 ConstraintMapping per ServletMapping pathSpec Constraint expectedConstraint = new Constraint(); expectedConstraint.setAuthenticate(true); expectedConstraint.setDataConstraint(Constraint.DC_NONE); ConstraintMapping[] expectedMappings = new ConstraintMapping[2]; expectedMappings[0] = new ConstraintMapping(); expectedMappings[0].setConstraint(expectedConstraint); expectedMappings[0].setPathSpec("/foo/*"); expectedMappings[1] = new ConstraintMapping(); expectedMappings[1].setConstraint(expectedConstraint); expectedMappings[1].setPathSpec("*.foo"); introspector.introspect(DenyServlet.class); compareResults(expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings()); } public void testPermitAll() throws Exception { //Assume we found 1 servlet with a @ServletSecurity security annotation WebAppContext wac = makeWebAppContext(PermitServlet.class.getCanonicalName(), "permitServlet", new String[]{"/foo/*", "*.foo"}); ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac); AnnotationIntrospector introspector = new AnnotationIntrospector(); introspector.registerHandler(annotationHandler); //set up the expected outcomes: //1 ConstraintMapping per ServletMapping pathSpec Constraint expectedConstraint = new Constraint(); expectedConstraint.setAuthenticate(false); expectedConstraint.setDataConstraint(Constraint.DC_NONE); ConstraintMapping[] expectedMappings = new ConstraintMapping[2]; expectedMappings[0] = new ConstraintMapping(); expectedMappings[0].setConstraint(expectedConstraint); expectedMappings[0].setPathSpec("/foo/*"); expectedMappings[1] = new ConstraintMapping(); expectedMappings[1].setConstraint(expectedConstraint); expectedMappings[1].setPathSpec("*.foo"); introspector.introspect(PermitServlet.class); compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings()); } public void testRolesAllowedWithTransportGuarantee () throws Exception { //Assume we found 1 servlet with annotation with roles defined and //and a TransportGuarantee WebAppContext wac = makeWebAppContext(RolesServlet.class.getCanonicalName(), "rolesServlet", new String[]{"/foo/*", "*.foo"}); ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac); AnnotationIntrospector introspector = new AnnotationIntrospector(); introspector.registerHandler(annotationHandler); //set up the expected outcomes:compareResults //1 ConstraintMapping per ServletMapping Constraint expectedConstraint = new Constraint(); expectedConstraint.setAuthenticate(true); expectedConstraint.setRoles(new String[]{"tom", "dick", "harry"}); expectedConstraint.setDataConstraint(Constraint.DC_CONFIDENTIAL); ConstraintMapping[] expectedMappings = new ConstraintMapping[2]; expectedMappings[0] = new ConstraintMapping(); expectedMappings[0].setConstraint(expectedConstraint); expectedMappings[0].setPathSpec("/foo/*"); expectedMappings[1] = new ConstraintMapping(); expectedMappings[1].setConstraint(expectedConstraint); expectedMappings[1].setPathSpec("*.foo"); introspector.introspect(RolesServlet.class); compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings()); } public void testMethodAnnotation () throws Exception { //ServletSecurity annotation with HttpConstraint of TransportGuarantee.CONFIDENTIAL, and a list of rolesAllowed, and //a HttpMethodConstraint for GET method that permits all and has TransportGuarantee.NONE (ie is default) WebAppContext wac = makeWebAppContext(Method1Servlet.class.getCanonicalName(), "method1Servlet", new String[]{"/foo/*", "*.foo"}); //set up the expected outcomes: - a Constraint for the RolesAllowed on the class //with userdata constraint of DC_CONFIDENTIAL //and mappings for each of the pathSpecs Constraint expectedConstraint1 = new Constraint(); expectedConstraint1.setAuthenticate(true); expectedConstraint1.setRoles(new String[]{"tom", "dick", "harry"}); expectedConstraint1.setDataConstraint(Constraint.DC_CONFIDENTIAL); //a Constraint for the PermitAll on the doGet method with a userdata //constraint of DC_CONFIDENTIAL inherited from the class Constraint expectedConstraint2 = new Constraint(); expectedConstraint2.setDataConstraint(Constraint.DC_NONE); ConstraintMapping[] expectedMappings = new ConstraintMapping[4]; expectedMappings[0] = new ConstraintMapping(); expectedMappings[0].setConstraint(expectedConstraint1); expectedMappings[0].setPathSpec("/foo/*"); expectedMappings[0].setMethodOmissions(new String[]{"GET"}); expectedMappings[1] = new ConstraintMapping(); expectedMappings[1].setConstraint(expectedConstraint1); expectedMappings[1].setPathSpec("*.foo"); expectedMappings[1].setMethodOmissions(new String[]{"GET"}); expectedMappings[2] = new ConstraintMapping(); expectedMappings[2].setConstraint(expectedConstraint2); expectedMappings[2].setPathSpec("/foo/*"); expectedMappings[2].setMethod("GET"); expectedMappings[3] = new ConstraintMapping(); expectedMappings[3].setConstraint(expectedConstraint2); expectedMappings[3].setPathSpec("*.foo"); expectedMappings[3].setMethod("GET"); AnnotationIntrospector introspector = new AnnotationIntrospector(); ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac); introspector.registerHandler(annotationHandler); introspector.introspect(Method1Servlet.class); compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings()); } public void testMethodAnnotation2 () throws Exception { //A ServletSecurity annotation that has HttpConstraint of CONFIDENTIAL with defined roles, but a //HttpMethodConstraint for GET that permits all, but also requires CONFIDENTIAL WebAppContext wac = makeWebAppContext(Method2Servlet.class.getCanonicalName(), "method2Servlet", new String[]{"/foo/*", "*.foo"}); AnnotationIntrospector introspector = new AnnotationIntrospector(); ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac); introspector.registerHandler(annotationHandler); //set up the expected outcomes: - a Constraint for the RolesAllowed on the class //with userdata constraint of DC_CONFIDENTIAL //and mappings for each of the pathSpecs Constraint expectedConstraint1 = new Constraint(); expectedConstraint1.setAuthenticate(true); expectedConstraint1.setRoles(new String[]{"tom", "dick", "harry"}); expectedConstraint1.setDataConstraint(Constraint.DC_CONFIDENTIAL); //a Constraint for the Permit on the GET method with a userdata //constraint of DC_CONFIDENTIAL Constraint expectedConstraint2 = new Constraint(); expectedConstraint2.setDataConstraint(Constraint.DC_CONFIDENTIAL); ConstraintMapping[] expectedMappings = new ConstraintMapping[4]; expectedMappings[0] = new ConstraintMapping(); expectedMappings[0].setConstraint(expectedConstraint1); expectedMappings[0].setPathSpec("/foo/*"); expectedMappings[0].setMethodOmissions(new String[]{"GET"}); expectedMappings[1] = new ConstraintMapping(); expectedMappings[1].setConstraint(expectedConstraint1); expectedMappings[1].setPathSpec("*.foo"); expectedMappings[1].setMethodOmissions(new String[]{"GET"}); expectedMappings[2] = new ConstraintMapping(); expectedMappings[2].setConstraint(expectedConstraint2); expectedMappings[2].setPathSpec("/foo/*"); expectedMappings[2].setMethod("GET"); expectedMappings[3] = new ConstraintMapping(); expectedMappings[3].setConstraint(expectedConstraint2); expectedMappings[3].setPathSpec("*.foo"); expectedMappings[3].setMethod("GET"); introspector.introspect(Method2Servlet.class); compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings()); } private void compareResults (ConstraintMapping[] expectedMappings, List actualMappings) { assertNotNull(actualMappings); assertEquals(expectedMappings.length, actualMappings.size()); for (int k=0; k < actualMappings.size(); k++) { ConstraintMapping am = actualMappings.get(k); boolean matched = false; for (int i=0; i< expectedMappings.length && !matched; i++) { ConstraintMapping em = expectedMappings[i]; if (em.getPathSpec().equals(am.getPathSpec())) { if ((em.getMethod()==null && am.getMethod() == null) || em.getMethod() != null && em.getMethod().equals(am.getMethod())) { matched = true; assertEquals(em.getConstraint().getAuthenticate(), am.getConstraint().getAuthenticate()); assertEquals(em.getConstraint().getDataConstraint(), am.getConstraint().getDataConstraint()); if (em.getMethodOmissions() == null) { assertNull(am.getMethodOmissions()); } else { assertTrue(Arrays.equals(am.getMethodOmissions(), em.getMethodOmissions())); } if (em.getConstraint().getRoles() == null) { assertNull(am.getConstraint().getRoles()); } else { assertTrue(Arrays.equals(em.getConstraint().getRoles(), am.getConstraint().getRoles())); } } } } if (!matched) fail("No expected ConstraintMapping matching method:"+am.getMethod()+" pathSpec: "+am.getPathSpec()); } } private WebAppContext makeWebAppContext (String className, String servletName, String[] paths) { WebAppContext wac = new WebAppContext(); ServletHolder[] holders = new ServletHolder[1]; holders[0] = new ServletHolder(); holders[0].setClassName(className); holders[0].setName(servletName); holders[0].setServletHandler(wac.getServletHandler()); wac.getServletHandler().setServlets(holders); wac.setSecurityHandler(new ConstraintSecurityHandler()); ServletMapping[] servletMappings = new ServletMapping[1]; servletMappings[0] = new ServletMapping(); servletMappings[0].setPathSpecs(paths); servletMappings[0].setServletName(servletName); wac.getServletHandler().setServletMappings(servletMappings); return wac; } } TestServletAnnotations.java000066400000000000000000000071201174773561500343500ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletMapping; import org.eclipse.jetty.webapp.WebAppContext; import org.junit.Test; /** * TestServletAnnotations * * */ public class TestServletAnnotations { @Test public void testServletAnnotation() throws Exception { List classes = new ArrayList(); classes.add("org.eclipse.jetty.annotations.ServletC"); AnnotationParser parser = new AnnotationParser(); WebAppContext wac = new WebAppContext(); WebServletAnnotationHandler handler = new WebServletAnnotationHandler(wac); parser.registerAnnotationHandler("javax.servlet.annotation.WebServlet", handler); parser.parse(classes, new ClassNameResolver () { public boolean isExcluded(String name) { return false; } public boolean shouldOverride(String name) { return false; } }); assertEquals(1, handler.getAnnotationList().size()); assertTrue(handler.getAnnotationList().get(0) instanceof WebServletAnnotation); handler.getAnnotationList().get(0).apply(); ServletHolder[] holders = wac.getServletHandler().getServlets(); assertNotNull(holders); assertEquals(1, holders.length); assertEquals("CServlet", holders[0].getName()); ServletMapping[] mappings = wac.getServletHandler().getServletMappings(); assertNotNull(mappings); assertEquals(1, mappings.length); String[] paths = mappings[0].getPathSpecs(); assertNotNull(paths); assertEquals(2, paths.length); assertEquals("y", holders[0].getInitParameter("x")); assertEquals(2,holders[0].getInitOrder()); assertFalse(holders[0].isAsyncSupported()); } public void testDeclareRoles () throws Exception { WebAppContext wac = new WebAppContext(); ConstraintSecurityHandler sh = new ConstraintSecurityHandler(); wac.setSecurityHandler(sh); sh.setRoles(new HashSet(Arrays.asList(new String[]{"humpty", "dumpty"}))); DeclareRolesAnnotationHandler handler = new DeclareRolesAnnotationHandler(wac); handler.doHandle(ServletC.class); assertTrue(sh.getRoles().contains("alice")); assertTrue(sh.getRoles().contains("humpty")); assertTrue(sh.getRoles().contains("dumpty")); } } jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/000077500000000000000000000000001174773561500310745ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/ResourceA.java000066400000000000000000000060621174773561500336330ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations.resources; import java.io.IOException; import javax.annotation.Resource; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * ResourceA * * */ public class ResourceA implements javax.servlet.Servlet { private Integer e; private Integer h; private Integer k; @Resource(name="myf", mappedName="resB") //test giving both a name and mapped name from the environment private Integer f;//test a non inherited field that needs injection @Resource(mappedName="resA") //test the default naming scheme but using a mapped name from the environment private Integer g; @Resource(name="resA") //test using the given name as the name from the environment private Integer j; @Resource(mappedName="resB") //test using the default name on an inherited field protected Integer n; //TODO - if it's inherited, is it supposed to use the classname of the class it is inherited by? @Resource(name="mye", mappedName="resA", type=Integer.class) public void setE(Integer e) { this.e=e; } public Integer getE() { return this.e; } public Integer getF() { return this.f; } public Integer getG() { return this.g; } public Integer getJ() { return this.j; } @Resource(mappedName="resA") public void setH(Integer h) { this.h=h; } @Resource(name="resA") public void setK(Integer k) { this.k=k; } public void x() { System.err.println("ResourceA.x"); } public void destroy() { // TODO Auto-generated method stub } public ServletConfig getServletConfig() { // TODO Auto-generated method stub return null; } public String getServletInfo() { // TODO Auto-generated method stub return null; } public void init(ServletConfig arg0) throws ServletException { // TODO Auto-generated method stub } public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { // TODO Auto-generated method stub } } jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/ResourceB.java000066400000000000000000000025071174773561500336340ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.annotations.resources; import javax.annotation.Resource; import javax.annotation.Resources; /** * ResourceB * * */ @Resources({ @Resource(name="peach", mappedName="resA"), @Resource(name="pear", mappedName="resB") }) public class ResourceB extends ResourceA { @Resource(mappedName="resB") private Integer f;//test no inheritance of private fields @Resource private Integer p = new Integer(8); //test no injection because no value //test no annotation public void z() { System.err.println("ResourceB.z"); } } TestResourceAnnotations.java000066400000000000000000000130121174773561500365220ustar00rootroot00000000000000jetty8-8.1.3/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resourcespackage org.eclipse.jetty.annotations.resources; import java.lang.reflect.Field; import java.util.List; import javax.naming.Context; import javax.naming.InitialContext; import org.eclipse.jetty.annotations.AnnotationIntrospector; import org.eclipse.jetty.annotations.ResourceAnnotationHandler; import org.eclipse.jetty.annotations.ResourcesAnnotationHandler; import org.eclipse.jetty.plus.annotation.Injection; import org.eclipse.jetty.plus.annotation.InjectionCollection; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.webapp.WebAppContext; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; public class TestResourceAnnotations { private Server server; private WebAppContext wac; private InjectionCollection injections; private Context comp; private Context env; private Object objA = 1000; private Object objB = 2000; @Before public void init() throws Exception { server = new Server(); wac = new WebAppContext(); wac.setServer(server); injections = new InjectionCollection(); wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections); InitialContext ic = new InitialContext(); comp = (Context)ic.lookup("java:comp"); env = comp.createSubcontext("env"); } @After public void destroy() throws Exception { comp.destroySubcontext("env"); } @Test public void testResourceAnnotations () throws Exception { new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false); new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false); AnnotationIntrospector parser = new AnnotationIntrospector(); ResourceAnnotationHandler handler = new ResourceAnnotationHandler(wac); parser.registerHandler(handler); parser.introspect(ResourceA.class); parser.introspect(ResourceB.class); //processing classA should give us these jndi name bindings: // java:comp/env/myf // java:comp/env/org.eclipse.jetty.annotations.resources.ResourceA/g // java:comp/env/mye // java:comp/env/org.eclipse.jetty.annotations.resources.ResourceA/h // java:comp/env/resA // java:comp/env/org.eclipse.jetty.annotations.resources.ResourceB/f // java:comp/env/org.eclipse.jetty.annotations.resources.ResourceA/n // assertEquals(objB, env.lookup("myf")); assertEquals(objA, env.lookup("mye")); assertEquals(objA, env.lookup("resA")); assertEquals(objA, env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/g")); assertEquals(objA, env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/h")); assertEquals(objB, env.lookup("org.eclipse.jetty.annotations.resources.ResourceB/f")); assertEquals(objB, env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/n")); //we should have Injections assertNotNull(injections); List resBInjections = injections.getInjections(ResourceB.class.getCanonicalName()); assertNotNull(resBInjections); //only 1 field injection because the other has no Resource mapping assertEquals(1, resBInjections.size()); Injection fi = resBInjections.get(0); assertEquals ("f", fi.getTarget().getName()); //3 method injections on class ResourceA, 4 field injections List resAInjections = injections.getInjections(ResourceA.class.getCanonicalName()); assertNotNull(resAInjections); assertEquals(7, resAInjections.size()); int fieldCount = 0; int methodCount = 0; for (Injection x : resAInjections) { if (x.isField()) fieldCount++; else methodCount++; } assertEquals(4, fieldCount); assertEquals(3, methodCount); //test injection ResourceB binst = new ResourceB(); injections.inject(binst); //check injected values Field f = ResourceB.class.getDeclaredField ("f"); f.setAccessible(true); assertEquals(objB , f.get(binst)); //@Resource(mappedName="resA") //test the default naming scheme but using a mapped name from the environment f = ResourceA.class.getDeclaredField("g"); f.setAccessible(true); assertEquals(objA, f.get(binst)); //@Resource(name="resA") //test using the given name as the name from the environment f = ResourceA.class.getDeclaredField("j"); f.setAccessible(true); assertEquals(objA, f.get(binst)); //@Resource(mappedName="resB") //test using the default name on an inherited field f = ResourceA.class.getDeclaredField("n"); f.setAccessible(true); assertEquals(objB, f.get(binst)); } @Test public void testResourcesAnnotation () throws Exception { new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false); new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false); AnnotationIntrospector introspector = new AnnotationIntrospector(); ResourcesAnnotationHandler handler = new ResourcesAnnotationHandler(wac); introspector.registerHandler(handler); introspector.introspect(ResourceA.class); introspector.introspect(ResourceB.class); assertEquals(objA, env.lookup("peach")); assertEquals(objB, env.lookup("pear")); } } jetty8-8.1.3/jetty-client/000077500000000000000000000000001174773561500154055ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/pom.xml000066400000000000000000000111331174773561500167210ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 jetty-client Jetty :: Asynchronous HTTP Client {$jetty.url} ${project.groupId}.client target/test-policy org.apache.felix maven-bundle-plugin true manifest javax.net.*,* org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.client.* org.apache.maven.plugins maven-dependency-plugin unpack generate-test-resources unpack org.eclipse.jetty.toolchain jetty-test-policy ${jetty-test-policy-version} jar true **/*.keystore,**/*.pem ${jetty.test.policy.loc} org.eclipse.jetty jetty-http ${project.version} org.eclipse.jetty jetty-server ${project.version} test org.eclipse.jetty jetty-security ${project.version} test org.eclipse.jetty jetty-servlet ${project.version} test org.eclipse.jetty jetty-websocket ${project.version} test org.eclipse.jetty.toolchain jetty-test-helper test jetty8-8.1.3/jetty-client/src/000077500000000000000000000000001174773561500161745ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/main/000077500000000000000000000000001174773561500171205ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/main/java/000077500000000000000000000000001174773561500200415ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/main/java/org/000077500000000000000000000000001174773561500206305ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/000077500000000000000000000000001174773561500222545ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500234135ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/000077500000000000000000000000001174773561500246715ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java000066400000000000000000000455151174773561500321710ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.jetty.client.security.Authentication; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeaderValues; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersions; import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.View; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.Timeout; /** * * @version $Revision: 879 $ $Date: 2009-09-11 16:13:28 +0200 (Fri, 11 Sep 2009) $ */ public abstract class AbstractHttpConnection extends AbstractConnection implements Dumpable { private static final Logger LOG = Log.getLogger(AbstractHttpConnection.class); protected HttpDestination _destination; protected HttpGenerator _generator; protected HttpParser _parser; protected boolean _http11 = true; protected int _status; protected Buffer _connectionHeader; protected boolean _reserved; // The current exchange waiting for a response protected volatile HttpExchange _exchange; protected HttpExchange _pipeline; private final Timeout.Task _idleTimeout = new ConnectionIdleTask(); private AtomicBoolean _idle = new AtomicBoolean(false); AbstractHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endp) { super(endp); _generator = new HttpGenerator(requestBuffers,endp); _parser = new HttpParser(responseBuffers,endp,new Handler()); } public void setReserved (boolean reserved) { _reserved = reserved; } public boolean isReserved() { return _reserved; } public HttpDestination getDestination() { return _destination; } public void setDestination(HttpDestination destination) { _destination = destination; } public boolean send(HttpExchange ex) throws IOException { LOG.debug("Send {} on {}",ex,this); synchronized (this) { if (_exchange != null) { if (_pipeline != null) throw new IllegalStateException(this + " PIPELINED!!! _exchange=" + _exchange); _pipeline = ex; return true; } _exchange = ex; _exchange.associate(this); // The call to associate() may have closed the connection, check if it's the case if (!_endp.isOpen()) { _exchange.disassociate(); _exchange = null; return false; } _exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_COMMIT); adjustIdleTimeout(); return true; } } private void adjustIdleTimeout() throws IOException { // Adjusts the idle timeout in case the default or exchange timeout // are greater. This is needed for long polls, where one wants an // aggressive releasing of idle connections (so idle timeout is small) // but still allow long polls to complete normally long timeout = _exchange.getTimeout(); if (timeout <= 0) timeout = _destination.getHttpClient().getTimeout(); long endPointTimeout = _endp.getMaxIdleTime(); if (timeout > 0 && timeout > endPointTimeout) { // Make it larger than the exchange timeout so that there are // no races between the idle timeout and the exchange timeout // when trying to close the endpoint _endp.setMaxIdleTime(2 * (int)timeout); } } public abstract Connection handle() throws IOException; public boolean isIdle() { synchronized (this) { return _exchange == null; } } public boolean isSuspended() { return false; } public void onClose() { } protected void commitRequest() throws IOException { synchronized (this) { _status=0; if (_exchange.getStatus() != HttpExchange.STATUS_WAITING_FOR_COMMIT) throw new IllegalStateException(); _exchange.setStatus(HttpExchange.STATUS_SENDING_REQUEST); _generator.setVersion(_exchange.getVersion()); String method=_exchange.getMethod(); String uri = _exchange.getRequestURI(); if (_destination.isProxied()) { if (!HttpMethods.CONNECT.equals(method) && uri.startsWith("/")) { boolean secure = _destination.isSecure(); String host = _destination.getAddress().getHost(); int port = _destination.getAddress().getPort(); StringBuilder absoluteURI = new StringBuilder(); absoluteURI.append(secure ? HttpSchemes.HTTPS : HttpSchemes.HTTP); absoluteURI.append("://"); absoluteURI.append(host); // Avoid adding default ports if (!(secure && port == 443 || !secure && port == 80)) absoluteURI.append(":").append(port); absoluteURI.append(uri); uri = absoluteURI.toString(); } Authentication auth = _destination.getProxyAuthentication(); if (auth != null) auth.setCredentials(_exchange); } _generator.setRequest(method, uri); _parser.setHeadResponse(HttpMethods.HEAD.equalsIgnoreCase(method)); HttpFields requestHeaders = _exchange.getRequestFields(); if (_exchange.getVersion() >= HttpVersions.HTTP_1_1_ORDINAL) { if (!requestHeaders.containsKey(HttpHeaders.HOST_BUFFER)) requestHeaders.add(HttpHeaders.HOST_BUFFER,_destination.getHostHeader()); } Buffer requestContent = _exchange.getRequestContent(); if (requestContent != null) { requestHeaders.putLongField(HttpHeaders.CONTENT_LENGTH, requestContent.length()); _generator.completeHeader(requestHeaders,false); _generator.addContent(new View(requestContent),true); } else { InputStream requestContentStream = _exchange.getRequestContentSource(); if (requestContentStream != null) { _generator.completeHeader(requestHeaders, false); int available = requestContentStream.available(); if (available > 0) { // TODO deal with any known content length // TODO reuse this buffer! byte[] buf = new byte[available]; int length = requestContentStream.read(buf); _generator.addContent(new ByteArrayBuffer(buf, 0, length), false); } } else { requestHeaders.remove(HttpHeaders.CONTENT_LENGTH); _generator.completeHeader(requestHeaders, true); } } _exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE); } } protected void reset() throws IOException { _connectionHeader = null; _parser.reset(); _generator.reset(); _http11 = true; } private class Handler extends HttpParser.EventHandler { @Override public void startRequest(Buffer method, Buffer url, Buffer version) throws IOException { // System.out.println( method.toString() + "///" + url.toString() + // "///" + version.toString() ); // TODO validate this is acceptable, the = 0) { host = hostAndPort.substring(0, colon); port = Integer.parseInt(hostAndPort.substring(colon + 1)); } else { host = hostAndPort; port = 0; } return new Address(host, port); } public Address(String host, int port) { if (host == null) throw new IllegalArgumentException("Host is null"); this.host = host.trim(); this.port = port; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Address that = (Address)obj; if (!host.equals(that.host)) return false; return port == that.port; } @Override public int hashCode() { int result = host.hashCode(); result = 31 * result + port; return result; } public String getHost() { return host; } public int getPort() { return port; } public InetSocketAddress toSocketAddress() { return new InetSocketAddress(getHost(), getPort()); } @Override public String toString() { return host + ":" + port; } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java000066400000000000000000000240051174773561500314720ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import org.eclipse.jetty.http.AbstractGenerator; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.nio.AsyncConnection; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ /** Asynchronous Client HTTP Connection */ public class AsyncHttpConnection extends AbstractHttpConnection implements AsyncConnection { private static final Logger LOG = Log.getLogger(AsyncHttpConnection.class); private boolean _requestComplete; private Buffer _requestContentChunk; private final AsyncEndPoint _asyncEndp; AsyncHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endp) { super(requestBuffers,responseBuffers,endp); _asyncEndp=(AsyncEndPoint)endp; } protected void reset() throws IOException { _requestComplete = false; super.reset(); } public Connection handle() throws IOException { Connection connection = this; boolean progress=true; try { boolean failed = false; // While we are making progress and have not changed connection while (progress && connection==this) { LOG.debug("while open={} more={} progress={}",_endp.isOpen(),_parser.isMoreInBuffer(),progress); progress=false; HttpExchange exchange=_exchange; LOG.debug("exchange {} on {}",exchange,this); try { // Should we commit the request? if (!_generator.isCommitted() && exchange!=null && exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT) { LOG.debug("commit {}",exchange); progress=true; commitRequest(); } // Generate output if (_generator.isCommitted() && !_generator.isComplete()) { if (_generator.flushBuffer()>0) { LOG.debug("flushed"); progress=true; } // Is there more content to send or should we complete the generator if (_generator.isState(AbstractGenerator.STATE_CONTENT)) { // Look for more content to send. if (_requestContentChunk==null) _requestContentChunk = exchange.getRequestContentChunk(null); if (_requestContentChunk==null) { LOG.debug("complete {}",exchange); progress=true; _generator.complete(); } else if (_generator.isEmpty()) { LOG.debug("addChunk"); progress=true; Buffer chunk=_requestContentChunk; _requestContentChunk=exchange.getRequestContentChunk(null); _generator.addContent(chunk,_requestContentChunk==null); } } } // Signal request completion if (_generator.isComplete() && !_requestComplete) { LOG.debug("requestComplete {}",exchange); progress=true; _requestComplete = true; exchange.getEventListener().onRequestComplete(); } // Read any input that is available if (!_parser.isComplete() && _parser.parseAvailable()) { LOG.debug("parsed {}",exchange); progress=true; } // Flush output _endp.flush(); // Has any IO been done by the endpoint itself since last loop if (_asyncEndp.hasProgressed()) { LOG.debug("hasProgressed {}",exchange); progress=true; } } catch (Throwable e) { LOG.debug("Failure on " + _exchange, e); failed = true; synchronized (this) { if (exchange != null) { // Cancelling the exchange causes an exception as we close the connection, // but we don't report it as it is normal cancelling operation if (exchange.getStatus() != HttpExchange.STATUS_CANCELLING && exchange.getStatus() != HttpExchange.STATUS_CANCELLED && !exchange.isDone()) { if (exchange.setStatus(HttpExchange.STATUS_EXCEPTED)) exchange.getEventListener().onException(e); } } else { if (e instanceof IOException) throw (IOException)e; if (e instanceof Error) throw (Error)e; if (e instanceof RuntimeException) throw (RuntimeException)e; throw new RuntimeException(e); } } } finally { LOG.debug("finally {} on {} progress={} {}",exchange,this,progress,_endp); boolean complete = failed || _generator.isComplete() && _parser.isComplete(); if (complete) { boolean persistent = !failed && _parser.isPersistent() && _generator.isPersistent(); _generator.setPersistent(persistent); reset(); if (persistent) _endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout()); synchronized (this) { exchange=_exchange; _exchange = null; // Cancel the exchange if (exchange!=null) { exchange.cancelTimeout(_destination.getHttpClient()); // TODO should we check the exchange is done? } // handle switched protocols if (_status==HttpStatus.SWITCHING_PROTOCOLS_101) { Connection switched=exchange.onSwitchProtocol(_endp); if (switched!=null) connection=switched; { // switched protocol! _pipeline = null; if (_pipeline!=null) _destination.send(_pipeline); _pipeline = null; connection=switched; } } // handle pipelined requests if (_pipeline!=null) { if (!persistent || connection!=this) _destination.send(_pipeline); else _exchange=_pipeline; _pipeline=null; } if (_exchange==null && !isReserved()) // TODO how do we return switched connections? _destination.returnConnection(this, !persistent); } } } } } finally { _parser.returnBuffers(); _generator.returnBuffers(); LOG.debug("unhandle {} on {}",_exchange,_endp); } return connection; } public void onInputShutdown() throws IOException { if (_generator.isIdle()) _endp.shutdownOutput(); } @Override public boolean send(HttpExchange ex) throws IOException { boolean sent=super.send(ex); if (sent) _asyncEndp.asyncDispatch(); return sent; } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/BlockingHttpConnection.java000066400000000000000000000231551174773561500321520ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import java.io.InterruptedIOException; import org.eclipse.jetty.http.AbstractGenerator; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ /** Blocking HTTP Connection */ public class BlockingHttpConnection extends AbstractHttpConnection { private static final Logger LOG = Log.getLogger(BlockingHttpConnection.class); private boolean _requestComplete; private Buffer _requestContentChunk; BlockingHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endPoint) { super(requestBuffers, responseBuffers, endPoint); } protected void reset() throws IOException { _requestComplete = false; super.reset(); } @Override public Connection handle() throws IOException { Connection connection = this; try { boolean failed = false; // While we are making progress and have not changed connection while (_endp.isOpen() && connection==this) { LOG.debug("open={} more={}",_endp.isOpen(),_parser.isMoreInBuffer()); HttpExchange exchange; synchronized (this) { exchange=_exchange; while (exchange == null) { try { this.wait(); exchange=_exchange; } catch (InterruptedException e) { throw new InterruptedIOException(); } } } LOG.debug("exchange {}",exchange); try { // Should we commit the request? if (!_generator.isCommitted() && exchange!=null && exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT) { LOG.debug("commit"); commitRequest(); } // Generate output while (_generator.isCommitted() && !_generator.isComplete()) { if (_generator.flushBuffer()>0) { LOG.debug("flushed"); } // Is there more content to send or should we complete the generator if (_generator.isState(AbstractGenerator.STATE_CONTENT)) { // Look for more content to send. if (_requestContentChunk==null) _requestContentChunk = exchange.getRequestContentChunk(null); if (_requestContentChunk==null) { LOG.debug("complete"); _generator.complete(); } else if (_generator.isEmpty()) { LOG.debug("addChunk"); Buffer chunk=_requestContentChunk; _requestContentChunk=exchange.getRequestContentChunk(null); _generator.addContent(chunk,_requestContentChunk==null); } } } // Signal request completion if (_generator.isComplete() && !_requestComplete) { LOG.debug("requestComplete"); _requestComplete = true; exchange.getEventListener().onRequestComplete(); } // Read any input that is available if (!_parser.isComplete() && _parser.parseAvailable()) { LOG.debug("parsed"); } // Flush output _endp.flush(); } catch (Throwable e) { LOG.debug("Failure on " + _exchange, e); failed = true; synchronized (this) { if (exchange != null) { // Cancelling the exchange causes an exception as we close the connection, // but we don't report it as it is normal cancelling operation if (exchange.getStatus() != HttpExchange.STATUS_CANCELLING && exchange.getStatus() != HttpExchange.STATUS_CANCELLED && !exchange.isDone()) { if(exchange.setStatus(HttpExchange.STATUS_EXCEPTED)) exchange.getEventListener().onException(e); } } else { if (e instanceof IOException) throw (IOException)e; if (e instanceof Error) throw (Error)e; if (e instanceof RuntimeException) throw (RuntimeException)e; throw new RuntimeException(e); } } } finally { LOG.debug("{} {}",_generator, _parser); LOG.debug("{}",_endp); boolean complete = failed || _generator.isComplete() && _parser.isComplete(); if (complete) { boolean persistent = !failed && _parser.isPersistent() && _generator.isPersistent(); _generator.setPersistent(persistent); reset(); if (persistent) _endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout()); synchronized (this) { exchange=_exchange; _exchange = null; // Cancel the exchange if (exchange!=null) { exchange.cancelTimeout(_destination.getHttpClient()); // TODO should we check the exchange is done? } // handle switched protocols if (_status==HttpStatus.SWITCHING_PROTOCOLS_101) { Connection switched=exchange.onSwitchProtocol(_endp); if (switched!=null) connection=switched; { // switched protocol! _pipeline = null; if (_pipeline!=null) _destination.send(_pipeline); _pipeline = null; connection=switched; } } // handle pipelined requests if (_pipeline!=null) { if (!persistent || connection!=this) _destination.send(_pipeline); else _exchange=_pipeline; _pipeline=null; } if (_exchange==null && !isReserved()) // TODO how do we return switched connections? _destination.returnConnection(this, !persistent); } } } } } finally { _parser.returnBuffers(); _generator.returnBuffers(); } return connection; } @Override public boolean send(HttpExchange ex) throws IOException { boolean sent=super.send(ex); if (sent) { synchronized (this) { notifyAll(); } } return sent; } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/CachedExchange.java000066400000000000000000000045361174773561500303560ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.io.Buffer; /** * An exchange that retains response status and response headers for later use. */ public class CachedExchange extends HttpExchange { private final HttpFields _responseFields; private volatile int _responseStatus; /** * Creates a new CachedExchange. * * @param cacheHeaders true to cache response headers, false to not cache them */ public CachedExchange(boolean cacheHeaders) { _responseFields = cacheHeaders ? new HttpFields() : null; } public synchronized int getResponseStatus() { if (getStatus() < HttpExchange.STATUS_PARSING_HEADERS) throw new IllegalStateException("Response not received yet"); return _responseStatus; } public synchronized HttpFields getResponseFields() { if (getStatus() < HttpExchange.STATUS_PARSING_CONTENT) throw new IllegalStateException("Headers not completely received yet"); return _responseFields; } @Override protected synchronized void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { _responseStatus = status; super.onResponseStatus(version, status, reason); } @Override protected synchronized void onResponseHeader(Buffer name, Buffer value) throws IOException { if (_responseFields != null) { _responseFields.add(name, value.asImmutableBuffer()); } super.onResponseHeader(name, value); } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/ContentExchange.java000066400000000000000000000100171174773561500306100ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferUtil; import org.eclipse.jetty.util.StringUtil; /** * A exchange that retains response content for later use. */ public class ContentExchange extends CachedExchange { private int _bufferSize = 4096; private String _encoding = "utf-8"; private ByteArrayOutputStream _responseContent; private File _fileForUpload; public ContentExchange() { super(false); } public ContentExchange(boolean cacheFields) { super(cacheFields); } public synchronized String getResponseContent() throws UnsupportedEncodingException { if (_responseContent != null) return _responseContent.toString(_encoding); return null; } public synchronized byte[] getResponseContentBytes() { if (_responseContent != null) return _responseContent.toByteArray(); return null; } @Override protected synchronized void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { if (_responseContent!=null) _responseContent.reset(); super.onResponseStatus(version,status,reason); } @Override protected synchronized void onResponseHeader(Buffer name, Buffer value) throws IOException { super.onResponseHeader(name, value); int header = HttpHeaders.CACHE.getOrdinal(name); switch (header) { case HttpHeaders.CONTENT_LENGTH_ORDINAL: _bufferSize = BufferUtil.toInt(value); break; case HttpHeaders.CONTENT_TYPE_ORDINAL: String mime = StringUtil.asciiToLowerCase(value.toString()); int i = mime.indexOf("charset="); if (i > 0) { _encoding = mime.substring(i + 8); i = _encoding.indexOf(';'); if (i > 0) _encoding = _encoding.substring(0, i); } break; } } @Override protected synchronized void onResponseContent(Buffer content) throws IOException { super.onResponseContent(content); if (_responseContent == null) _responseContent = new ByteArrayOutputStream(_bufferSize); content.writeTo(_responseContent); } @Override protected synchronized void onRetry() throws IOException { if (_fileForUpload != null) { setRequestContent(null); setRequestContentSource(getInputStream()); } else super.onRetry(); } private synchronized InputStream getInputStream() throws IOException { return new FileInputStream(_fileForUpload); } public synchronized File getFileForUpload() { return _fileForUpload; } public synchronized void setFileForUpload(File fileForUpload) throws IOException { this._fileForUpload = fileForUpload; setRequestContentSource(getInputStream()); } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java000066400000000000000000000672521174773561500276260ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import java.io.InputStream; import java.net.UnknownHostException; import java.util.Enumeration; import java.util.LinkedList; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.net.ssl.SSLContext; import org.eclipse.jetty.client.security.Authentication; import org.eclipse.jetty.client.security.RealmResolver; import org.eclipse.jetty.client.security.SecurityListener; import org.eclipse.jetty.http.HttpBuffers; import org.eclipse.jetty.http.HttpBuffersImpl; import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.Buffers.Type; import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.AttributesMap; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.ThreadPool; import org.eclipse.jetty.util.thread.Timeout; /** * Http Client. *

* HttpClient is the main active component of the client API implementation. * It is the opposite of the Connectors in standard Jetty, in that it listens * for responses rather than requests. Just like the connectors, there is a * blocking socket version and a non-blocking NIO version (implemented as nested classes * selected by {@link #setConnectorType(int)}). *

* The an instance of {@link HttpExchange} is passed to the {@link #send(HttpExchange)} method * to send a request. The exchange contains both the headers and content (source) of the request * plus the callbacks to handle responses. A HttpClient can have many exchanges outstanding * and they may be queued on the {@link HttpDestination} waiting for a {@link AbstractHttpConnection}, * queued in the {@link AbstractHttpConnection} waiting to be transmitted or pipelined on the actual * TCP/IP connection waiting for a response. *

* The {@link HttpDestination} class is an aggregation of {@link AbstractHttpConnection}s for the * same host, port and protocol. A destination may limit the number of connections * open and they provide a pool of open connections that may be reused. Connections may also * be allocated from a destination, so that multiple request sources are not multiplexed * over the same connection. * * @see HttpExchange * @see HttpDestination */ public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attributes, Dumpable { public static final int CONNECTOR_SOCKET = 0; public static final int CONNECTOR_SELECT_CHANNEL = 2; private int _connectorType = CONNECTOR_SELECT_CHANNEL; private boolean _useDirectBuffers = true; private boolean _connectBlocking = true; private int _maxConnectionsPerAddress = Integer.MAX_VALUE; private int _maxQueueSizePerAddress = Integer.MAX_VALUE; private ConcurrentMap _destinations = new ConcurrentHashMap(); ThreadPool _threadPool; Connector _connector; private long _idleTimeout = 20000; private long _timeout = 320000; private int _connectTimeout = 75000; private Timeout _timeoutQ = new Timeout(); private Timeout _idleTimeoutQ = new Timeout(); private Address _proxy; private Authentication _proxyAuthentication; private Set _noProxy; private int _maxRetries = 3; private int _maxRedirects = 20; private LinkedList _registeredListeners; private final SslContextFactory _sslContextFactory; private RealmResolver _realmResolver; private AttributesMap _attributes=new AttributesMap(); private final HttpBuffersImpl _buffers= new HttpBuffersImpl(); /* ------------------------------------------------------------------------------- */ private void setBufferTypes() { if (_connectorType==CONNECTOR_SOCKET) { _buffers.setRequestBufferType(Type.BYTE_ARRAY); _buffers.setRequestHeaderType(Type.BYTE_ARRAY); _buffers.setResponseBufferType(Type.BYTE_ARRAY); _buffers.setResponseHeaderType(Type.BYTE_ARRAY); } else { _buffers.setRequestBufferType(Type.DIRECT); _buffers.setRequestHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT); _buffers.setResponseBufferType(Type.DIRECT); _buffers.setResponseHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT); } } /* ------------------------------------------------------------------------------- */ public HttpClient() { this(new SslContextFactory()); } /* ------------------------------------------------------------------------------- */ public HttpClient(SslContextFactory sslContextFactory) { _sslContextFactory = sslContextFactory; addBean(_sslContextFactory); addBean(_buffers); } /* ------------------------------------------------------------------------------- */ /** * @return True if connects will be in blocking mode. */ public boolean isConnectBlocking() { return _connectBlocking; } /* ------------------------------------------------------------------------------- */ /** * @param connectBlocking True if connects will be in blocking mode. */ public void setConnectBlocking(boolean connectBlocking) { _connectBlocking = connectBlocking; } /* ------------------------------------------------------------------------------- */ public void send(HttpExchange exchange) throws IOException { boolean ssl = HttpSchemes.HTTPS_BUFFER.equalsIgnoreCase(exchange.getScheme()); exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_CONNECTION); HttpDestination destination = getDestination(exchange.getAddress(), ssl); destination.send(exchange); } /* ------------------------------------------------------------ */ /** * @return the threadpool */ public ThreadPool getThreadPool() { return _threadPool; } /* ------------------------------------------------------------ */ /** Set the ThreadPool. * The threadpool passed is added via {@link #addBean(Object)} so that * it's lifecycle may be managed as a {@link AggregateLifeCycle}. * @param threadPool the threadPool to set */ public void setThreadPool(ThreadPool threadPool) { removeBean(_threadPool); _threadPool = threadPool; addBean(_threadPool); } /* ------------------------------------------------------------ */ /** * @param name * @return Attribute associated with client */ public Object getAttribute(String name) { return _attributes.getAttribute(name); } /* ------------------------------------------------------------ */ /** * @return names of attributes associated with client */ public Enumeration getAttributeNames() { return _attributes.getAttributeNames(); } /* ------------------------------------------------------------ */ /** * @param name */ public void removeAttribute(String name) { _attributes.removeAttribute(name); } /* ------------------------------------------------------------ */ /** * Set an attribute on the HttpClient. * Attributes are not used by the client, but are provided for * so that users of a shared HttpClient may share other structures. * @param name * @param attribute */ public void setAttribute(String name, Object attribute) { _attributes.setAttribute(name,attribute); } /* ------------------------------------------------------------ */ public void clearAttributes() { _attributes.clearAttributes(); } /* ------------------------------------------------------------------------------- */ public HttpDestination getDestination(Address remote, boolean ssl) throws IOException { if (remote == null) throw new UnknownHostException("Remote socket address cannot be null."); HttpDestination destination = _destinations.get(remote); if (destination == null) { destination = new HttpDestination(this, remote, ssl); if (_proxy != null && (_noProxy == null || !_noProxy.contains(remote.getHost()))) { destination.setProxy(_proxy); if (_proxyAuthentication != null) destination.setProxyAuthentication(_proxyAuthentication); } HttpDestination other =_destinations.putIfAbsent(remote, destination); if (other!=null) destination=other; } return destination; } /* ------------------------------------------------------------ */ public void schedule(Timeout.Task task) { _timeoutQ.schedule(task); } /* ------------------------------------------------------------ */ public void schedule(Timeout.Task task, long timeout) { _timeoutQ.schedule(task, timeout - _timeoutQ.getDuration()); } /* ------------------------------------------------------------ */ public void scheduleIdle(Timeout.Task task) { _idleTimeoutQ.schedule(task); } /* ------------------------------------------------------------ */ public void cancel(Timeout.Task task) { task.cancel(); } /* ------------------------------------------------------------ */ /** * Get whether the connector can use direct NIO buffers. */ public boolean getUseDirectBuffers() { return _useDirectBuffers; } /* ------------------------------------------------------------ */ /** Set a RealmResolver for client Authentication. * If a realmResolver is set, then the HttpDestinations created by * this client will instantiate a {@link SecurityListener} so that * BASIC and DIGEST authentication can be performed. * @param resolver */ public void setRealmResolver(RealmResolver resolver) { _realmResolver = resolver; } /* ------------------------------------------------------------ */ /** * returns the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null * * @return the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null */ public RealmResolver getRealmResolver() { return _realmResolver; } /* ------------------------------------------------------------ */ public boolean hasRealms() { return _realmResolver == null ? false : true; } /* ------------------------------------------------------------ */ /** * Registers a listener that can listen to the stream of execution between the client and the * server and influence events. Sequential calls to the method wrapper sequentially wrap the preceding * listener in a delegation model. *

* NOTE: the SecurityListener is a special listener which doesn't need to be added via this * mechanic, if you register security realms then it will automatically be added as the top listener of the * delegation stack. * * @param listenerClass */ public void registerListener(String listenerClass) { if (_registeredListeners == null) { _registeredListeners = new LinkedList(); } _registeredListeners.add(listenerClass); } /* ------------------------------------------------------------ */ public LinkedList getRegisteredListeners() { return _registeredListeners; } /* ------------------------------------------------------------ */ /** * Set to use NIO direct buffers. * * @param direct If True (the default), the connector can use NIO direct * buffers. Some JVMs have memory management issues (bugs) with * direct buffers. */ public void setUseDirectBuffers(boolean direct) { _useDirectBuffers = direct; setBufferTypes(); } /* ------------------------------------------------------------ */ /** * Get the type of connector (socket, blocking or select) in use. */ public int getConnectorType() { return _connectorType; } /* ------------------------------------------------------------ */ public void setConnectorType(int connectorType) { this._connectorType = connectorType; setBufferTypes(); } /* ------------------------------------------------------------ */ public int getMaxConnectionsPerAddress() { return _maxConnectionsPerAddress; } /* ------------------------------------------------------------ */ public void setMaxConnectionsPerAddress(int maxConnectionsPerAddress) { _maxConnectionsPerAddress = maxConnectionsPerAddress; } public int getMaxQueueSizePerAddress() { return _maxQueueSizePerAddress; } public void setMaxQueueSizePerAddress(int maxQueueSizePerAddress) { this._maxQueueSizePerAddress = maxQueueSizePerAddress; } /* ------------------------------------------------------------ */ @Override protected void doStart() throws Exception { setBufferTypes(); _timeoutQ.setDuration(_timeout); _timeoutQ.setNow(); _idleTimeoutQ.setDuration(_idleTimeout); _idleTimeoutQ.setNow(); if (_threadPool==null) { QueuedThreadPool pool = new LocalQueuedThreadPool(); pool.setMaxThreads(16); pool.setDaemon(true); pool.setName("HttpClient"); _threadPool = pool; addBean(_threadPool,true); } _connector=(_connectorType == CONNECTOR_SELECT_CHANNEL)?new SelectConnector(this):new SocketConnector(this); addBean(_connector,true); super.doStart(); _threadPool.dispatch(new Runnable() { public void run() { while (isRunning()) { _timeoutQ.tick(System.currentTimeMillis()); _idleTimeoutQ.tick(_timeoutQ.getNow()); try { Thread.sleep(200); } catch (InterruptedException ignored) { } } } }); } /* ------------------------------------------------------------ */ @Override protected void doStop() throws Exception { for (HttpDestination destination : _destinations.values()) destination.close(); _timeoutQ.cancelAll(); _idleTimeoutQ.cancelAll(); super.doStop(); if (_threadPool instanceof LocalQueuedThreadPool) { removeBean(_threadPool); _threadPool = null; } removeBean(_connector); } /* ------------------------------------------------------------ */ interface Connector extends LifeCycle { public void startConnection(HttpDestination destination) throws IOException; } /* ------------------------------------------------------------ */ /** * if a keystore location has been provided then client will attempt to use it as the keystore, * otherwise we simply ignore certificates and run with a loose ssl context. * * @return the SSL context */ protected SSLContext getSSLContext() { return _sslContextFactory.getSslContext(); } /* ------------------------------------------------------------ */ /** * @return the instance of SslContextFactory associated with the client */ public SslContextFactory getSslContextFactory() { return _sslContextFactory; } /* ------------------------------------------------------------ */ /** * @return the period in milliseconds a {@link AbstractHttpConnection} can be idle for before it is closed. */ public long getIdleTimeout() { return _idleTimeout; } /* ------------------------------------------------------------ */ /** * @param ms the period in milliseconds a {@link AbstractHttpConnection} can be idle for before it is closed. */ public void setIdleTimeout(long ms) { _idleTimeout = ms; } /* ------------------------------------------------------------ */ /** * @return the period in ms that an exchange will wait for a response from the server. * @deprecated use {@link #getTimeout()} instead. */ @Deprecated public int getSoTimeout() { return Long.valueOf(getTimeout()).intValue(); } /* ------------------------------------------------------------ */ /** * @deprecated use {@link #setTimeout(long)} instead. * @param timeout the period in ms that an exchange will wait for a response from the server. */ @Deprecated public void setSoTimeout(int timeout) { setTimeout(timeout); } /* ------------------------------------------------------------ */ /** * @return the period in ms that an exchange will wait for a response from the server. */ public long getTimeout() { return _timeout; } /* ------------------------------------------------------------ */ /** * @param timeout the period in ms that an exchange will wait for a response from the server. */ public void setTimeout(long timeout) { _timeout = timeout; } /* ------------------------------------------------------------ */ /** * @return the period in ms before timing out an attempt to connect */ public int getConnectTimeout() { return _connectTimeout; } /* ------------------------------------------------------------ */ /** * @param connectTimeout the period in ms before timing out an attempt to connect */ public void setConnectTimeout(int connectTimeout) { this._connectTimeout = connectTimeout; } /* ------------------------------------------------------------ */ public Address getProxy() { return _proxy; } /* ------------------------------------------------------------ */ public void setProxy(Address proxy) { this._proxy = proxy; } /* ------------------------------------------------------------ */ public Authentication getProxyAuthentication() { return _proxyAuthentication; } /* ------------------------------------------------------------ */ public void setProxyAuthentication(Authentication authentication) { _proxyAuthentication = authentication; } /* ------------------------------------------------------------ */ public boolean isProxied() { return this._proxy != null; } /* ------------------------------------------------------------ */ public Set getNoProxy() { return _noProxy; } /* ------------------------------------------------------------ */ public void setNoProxy(Set noProxyAddresses) { _noProxy = noProxyAddresses; } /* ------------------------------------------------------------ */ public int maxRetries() { return _maxRetries; } /* ------------------------------------------------------------ */ public void setMaxRetries(int retries) { _maxRetries = retries; } /* ------------------------------------------------------------ */ public int maxRedirects() { return _maxRedirects; } /* ------------------------------------------------------------ */ public void setMaxRedirects(int redirects) { _maxRedirects = redirects; } public int getRequestBufferSize() { return _buffers.getRequestBufferSize(); } public void setRequestBufferSize(int requestBufferSize) { _buffers.setRequestBufferSize(requestBufferSize); } public int getRequestHeaderSize() { return _buffers.getRequestHeaderSize(); } public void setRequestHeaderSize(int requestHeaderSize) { _buffers.setRequestHeaderSize(requestHeaderSize); } public int getResponseBufferSize() { return _buffers.getResponseBufferSize(); } public void setResponseBufferSize(int responseBufferSize) { _buffers.setResponseBufferSize(responseBufferSize); } public int getResponseHeaderSize() { return _buffers.getResponseHeaderSize(); } public void setResponseHeaderSize(int responseHeaderSize) { _buffers.setResponseHeaderSize(responseHeaderSize); } public Type getRequestBufferType() { return _buffers.getRequestBufferType(); } public Type getRequestHeaderType() { return _buffers.getRequestHeaderType(); } public Type getResponseBufferType() { return _buffers.getResponseBufferType(); } public Type getResponseHeaderType() { return _buffers.getResponseHeaderType(); } public void setRequestBuffers(Buffers requestBuffers) { _buffers.setRequestBuffers(requestBuffers); } public void setResponseBuffers(Buffers responseBuffers) { _buffers.setResponseBuffers(responseBuffers); } public Buffers getRequestBuffers() { return _buffers.getRequestBuffers(); } public Buffers getResponseBuffers() { return _buffers.getResponseBuffers(); } public void setMaxBuffers(int maxBuffers) { _buffers.setMaxBuffers(maxBuffers); } public int getMaxBuffers() { return _buffers.getMaxBuffers(); } /* ------------------------------------------------------------ */ @Deprecated public String getTrustStoreLocation() { return _sslContextFactory.getTrustStore(); } /* ------------------------------------------------------------ */ @Deprecated public void setTrustStoreLocation(String trustStoreLocation) { _sslContextFactory.setTrustStore(trustStoreLocation); } /* ------------------------------------------------------------ */ @Deprecated public InputStream getTrustStoreInputStream() { return _sslContextFactory.getTrustStoreInputStream(); } /* ------------------------------------------------------------ */ @Deprecated public void setTrustStoreInputStream(InputStream trustStoreInputStream) { _sslContextFactory.setTrustStoreInputStream(trustStoreInputStream); } /* ------------------------------------------------------------ */ @Deprecated public String getKeyStoreLocation() { return _sslContextFactory.getKeyStorePath(); } /* ------------------------------------------------------------ */ @Deprecated public void setKeyStoreLocation(String keyStoreLocation) { _sslContextFactory.setKeyStorePath(keyStoreLocation); } @Deprecated public InputStream getKeyStoreInputStream() { return _sslContextFactory.getKeyStoreInputStream(); } @Deprecated public void setKeyStoreInputStream(InputStream keyStoreInputStream) { _sslContextFactory.setKeyStoreInputStream(keyStoreInputStream); } /* ------------------------------------------------------------ */ @Deprecated public void setKeyStorePassword(String keyStorePassword) { _sslContextFactory.setKeyStorePassword(keyStorePassword); } /* ------------------------------------------------------------ */ @Deprecated public void setKeyManagerPassword(String keyManagerPassword) { _sslContextFactory.setKeyManagerPassword(keyManagerPassword); } /* ------------------------------------------------------------ */ @Deprecated public void setTrustStorePassword(String trustStorePassword) { _sslContextFactory.setTrustStorePassword(trustStorePassword); } /* ------------------------------------------------------------ */ @Deprecated public String getKeyStoreType() { return _sslContextFactory.getKeyStoreType(); } /* ------------------------------------------------------------ */ @Deprecated public void setKeyStoreType(String keyStoreType) { _sslContextFactory.setKeyStoreType(keyStoreType); } /* ------------------------------------------------------------ */ @Deprecated public String getTrustStoreType() { return _sslContextFactory.getTrustStoreType(); } /* ------------------------------------------------------------ */ @Deprecated public void setTrustStoreType(String trustStoreType) { _sslContextFactory.setTrustStoreType(trustStoreType); } /* ------------------------------------------------------------ */ @Deprecated public String getKeyManagerAlgorithm() { return _sslContextFactory.getSslKeyManagerFactoryAlgorithm(); } /* ------------------------------------------------------------ */ @Deprecated public void setKeyManagerAlgorithm(String keyManagerAlgorithm) { _sslContextFactory.setSslKeyManagerFactoryAlgorithm(keyManagerAlgorithm); } /* ------------------------------------------------------------ */ @Deprecated public String getTrustManagerAlgorithm() { return _sslContextFactory.getTrustManagerFactoryAlgorithm(); } /* ------------------------------------------------------------ */ @Deprecated public void setTrustManagerAlgorithm(String trustManagerAlgorithm) { _sslContextFactory.setTrustManagerFactoryAlgorithm(trustManagerAlgorithm); } /* ------------------------------------------------------------ */ @Deprecated public String getProtocol() { return _sslContextFactory.getProtocol(); } /* ------------------------------------------------------------ */ @Deprecated public void setProtocol(String protocol) { _sslContextFactory.setProtocol(protocol); } /* ------------------------------------------------------------ */ @Deprecated public String getProvider() { return _sslContextFactory.getProvider(); } /* ------------------------------------------------------------ */ @Deprecated public void setProvider(String provider) { _sslContextFactory.setProvider(provider); } /* ------------------------------------------------------------ */ @Deprecated public String getSecureRandomAlgorithm() { return _sslContextFactory.getSecureRandomAlgorithm(); } /* ------------------------------------------------------------ */ @Deprecated public void setSecureRandomAlgorithm(String secureRandomAlgorithm) { _sslContextFactory.setSecureRandomAlgorithm(secureRandomAlgorithm); } private static class LocalQueuedThreadPool extends QueuedThreadPool { } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java000066400000000000000000000531251174773561500306630ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import java.lang.reflect.Constructor; import java.net.ProtocolException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.RejectedExecutionException; import org.eclipse.jetty.client.HttpClient.Connector; import org.eclipse.jetty.client.security.Authentication; import org.eclipse.jetty.client.security.SecurityListener; import org.eclipse.jetty.http.HttpCookie; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.PathMap; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * @version $Revision: 879 $ $Date: 2009-09-11 16:13:28 +0200 (Fri, 11 Sep 2009) $ */ public class HttpDestination implements Dumpable { private static final Logger LOG = Log.getLogger(HttpDestination.class); private final List _queue = new LinkedList(); private final List _connections = new LinkedList(); private final BlockingQueue _newQueue = new ArrayBlockingQueue(10, true); private final List _idle = new ArrayList(); private final HttpClient _client; private final Address _address; private final boolean _ssl; private final ByteArrayBuffer _hostHeader; private volatile int _maxConnections; private volatile int _maxQueueSize; private int _pendingConnections = 0; private int _newConnection = 0; private volatile Address _proxy; private Authentication _proxyAuthentication; private PathMap _authorizations; private List _cookies; HttpDestination(HttpClient client, Address address, boolean ssl) { _client = client; _address = address; _ssl = ssl; _maxConnections = _client.getMaxConnectionsPerAddress(); _maxQueueSize = _client.getMaxQueueSizePerAddress(); String addressString = address.getHost(); if (address.getPort() != (_ssl ? 443 : 80)) addressString += ":" + address.getPort(); _hostHeader = new ByteArrayBuffer(addressString); } public HttpClient getHttpClient() { return _client; } public Address getAddress() { return _address; } public boolean isSecure() { return _ssl; } public Buffer getHostHeader() { return _hostHeader; } public int getMaxConnections() { return _maxConnections; } public void setMaxConnections(int maxConnections) { this._maxConnections = maxConnections; } public int getMaxQueueSize() { return _maxQueueSize; } public void setMaxQueueSize(int maxQueueSize) { this._maxQueueSize = maxQueueSize; } public int getConnections() { synchronized (this) { return _connections.size(); } } public int getIdleConnections() { synchronized (this) { return _idle.size(); } } public void addAuthorization(String pathSpec, Authentication authorization) { synchronized (this) { if (_authorizations == null) _authorizations = new PathMap(); _authorizations.put(pathSpec, authorization); } // TODO query and remove methods } public void addCookie(HttpCookie cookie) { synchronized (this) { if (_cookies == null) _cookies = new ArrayList(); _cookies.add(cookie); } // TODO query, remove and age methods } /** * Get a connection. We either get an idle connection if one is available, or * we make a new connection, if we have not yet reached maxConnections. If we * have reached maxConnections, we wait until the number reduces. * * @param timeout max time prepared to block waiting to be able to get a connection * @return a HttpConnection for this destination * @throws IOException if an I/O error occurs */ private AbstractHttpConnection getConnection(long timeout) throws IOException { AbstractHttpConnection connection = null; while ((connection == null) && (connection = getIdleConnection()) == null && timeout > 0) { boolean startConnection = false; synchronized (this) { int totalConnections = _connections.size() + _pendingConnections; if (totalConnections < _maxConnections) { _newConnection++; startConnection = true; } } if (startConnection) { startNewConnection(); try { Object o = _newQueue.take(); if (o instanceof AbstractHttpConnection) { connection = (AbstractHttpConnection)o; } else throw (IOException)o; } catch (InterruptedException e) { LOG.ignore(e); } } else { try { Thread.currentThread(); Thread.sleep(200); timeout -= 200; } catch (InterruptedException e) { LOG.ignore(e); } } } return connection; } public AbstractHttpConnection reserveConnection(long timeout) throws IOException { AbstractHttpConnection connection = getConnection(timeout); if (connection != null) connection.setReserved(true); return connection; } public AbstractHttpConnection getIdleConnection() throws IOException { AbstractHttpConnection connection = null; while (true) { synchronized (this) { if (connection != null) { _connections.remove(connection); connection.close(); connection = null; } if (_idle.size() > 0) connection = _idle.remove(_idle.size() - 1); } if (connection == null) { return null; } // Check if the connection was idle, // but it expired just a moment ago if (connection.cancelIdleTimeout()) { return connection; } } } protected void startNewConnection() { try { synchronized (this) { _pendingConnections++; } final Connector connector = _client._connector; if (connector != null) connector.startConnection(this); } catch (Exception e) { LOG.debug(e); onConnectionFailed(e); } } public void onConnectionFailed(Throwable throwable) { Throwable connect_failure = null; boolean startConnection = false; synchronized (this) { _pendingConnections--; if (_newConnection > 0) { connect_failure = throwable; _newConnection--; } else if (_queue.size() > 0) { HttpExchange ex = _queue.remove(0); if (ex.setStatus(HttpExchange.STATUS_EXCEPTED)) ex.getEventListener().onConnectionFailed(throwable); // Since an existing connection had failed, we need to create a // connection if the queue is not empty and client is running. if (!_queue.isEmpty() && _client.isStarted()) startConnection = true; } } if (startConnection) startNewConnection(); if (connect_failure != null) { try { _newQueue.put(connect_failure); } catch (InterruptedException e) { LOG.ignore(e); } } } public void onException(Throwable throwable) { synchronized (this) { _pendingConnections--; if (_queue.size() > 0) { HttpExchange ex = _queue.remove(0); if(ex.setStatus(HttpExchange.STATUS_EXCEPTED)) ex.getEventListener().onException(throwable); } } } public void onNewConnection(final AbstractHttpConnection connection) throws IOException { Connection q_connection = null; synchronized (this) { _pendingConnections--; _connections.add(connection); if (_newConnection > 0) { q_connection = connection; _newConnection--; } else if (_queue.size() == 0) { connection.setIdleTimeout(); _idle.add(connection); } else { EndPoint endPoint = connection.getEndPoint(); if (isProxied() && endPoint instanceof SelectConnector.UpgradableEndPoint) { SelectConnector.UpgradableEndPoint proxyEndPoint = (SelectConnector.UpgradableEndPoint)endPoint; HttpExchange exchange = _queue.get(0); ConnectExchange connect = new ConnectExchange(getAddress(), proxyEndPoint, exchange); connect.setAddress(getProxy()); send(connection, connect); } else { HttpExchange exchange = _queue.remove(0); send(connection, exchange); } } } if (q_connection != null) { try { _newQueue.put(q_connection); } catch (InterruptedException e) { LOG.ignore(e); } } } public void returnConnection(AbstractHttpConnection connection, boolean close) throws IOException { if (connection.isReserved()) connection.setReserved(false); if (close) { try { connection.close(); } catch (IOException e) { LOG.ignore(e); } } if (!_client.isStarted()) return; if (!close && connection.getEndPoint().isOpen()) { synchronized (this) { if (_queue.size() == 0) { connection.setIdleTimeout(); _idle.add(connection); } else { HttpExchange ex = _queue.remove(0); send(connection, ex); } this.notifyAll(); } } else { boolean startConnection = false; synchronized (this) { _connections.remove(connection); if (!_queue.isEmpty()) startConnection = true; } if (startConnection) startNewConnection(); } } public void returnIdleConnection(AbstractHttpConnection connection) { // TODO work out the real idle time; long idleForMs=connection!=null&&connection.getEndPoint()!=null?connection.getEndPoint().getMaxIdleTime():-1; connection.onIdleExpired(idleForMs); boolean startConnection = false; synchronized (this) { _idle.remove(connection); _connections.remove(connection); if (!_queue.isEmpty() && _client.isStarted()) startConnection = true; } if (startConnection) startNewConnection(); } public void send(HttpExchange ex) throws IOException { LinkedList listeners = _client.getRegisteredListeners(); if (listeners != null) { // Add registered listeners, fail if we can't load them for (int i = listeners.size(); i > 0; --i) { String listenerClass = listeners.get(i - 1); try { Class listener = Class.forName(listenerClass); Constructor constructor = listener.getDeclaredConstructor(HttpDestination.class, HttpExchange.class); HttpEventListener elistener = (HttpEventListener)constructor.newInstance(this, ex); ex.setEventListener(elistener); } catch (final Exception e) { throw new IOException("Unable to instantiate registered listener for destination: " + listenerClass) { {initCause(e);} }; } } } // Security is supported by default and should be the first consulted if (_client.hasRealms()) { ex.setEventListener(new SecurityListener(this, ex)); } doSend(ex); } public void resend(HttpExchange ex) throws IOException { ex.getEventListener().onRetry(); ex.reset(); doSend(ex); } protected void doSend(HttpExchange ex) throws IOException { // add cookies // TODO handle max-age etc. if (_cookies != null) { StringBuilder buf = null; for (HttpCookie cookie : _cookies) { if (buf == null) buf = new StringBuilder(); else buf.append("; "); buf.append(cookie.getName()); // TODO quotes buf.append("="); buf.append(cookie.getValue()); // TODO quotes } if (buf != null) ex.addRequestHeader(HttpHeaders.COOKIE, buf.toString()); } // Add any known authorizations if (_authorizations != null) { Authentication auth = (Authentication)_authorizations.match(ex.getRequestURI()); if (auth != null) (auth).setCredentials(ex); } // Schedule the timeout here, before we queue the exchange // so that we count also the queue time in the timeout ex.scheduleTimeout(this); AbstractHttpConnection connection = getIdleConnection(); if (connection != null) { send(connection, ex); } else { boolean startConnection = false; synchronized (this) { if (_queue.size() == _maxQueueSize) throw new RejectedExecutionException("Queue full for address " + _address); _queue.add(ex); if (_connections.size() + _pendingConnections < _maxConnections) startConnection = true; } if (startConnection) startNewConnection(); } } protected void exchangeExpired(HttpExchange exchange) { // The exchange may expire while waiting in the // destination queue, make sure it is removed synchronized (this) { _queue.remove(exchange); } } protected void send(AbstractHttpConnection connection, HttpExchange exchange) throws IOException { synchronized (this) { // If server closes the connection, put the exchange back // to the exchange queue and recycle the connection if (!connection.send(exchange)) { if (exchange.getStatus() <= HttpExchange.STATUS_WAITING_FOR_CONNECTION) _queue.add(0, exchange); returnIdleConnection(connection); } } } @Override public synchronized String toString() { return String.format("HttpDestination@%x//%s:%d(%d/%d,%d,%d/%d)%n",hashCode(),_address.getHost(),_address.getPort(),_connections.size(),_maxConnections,_idle.size(),_queue.size(),_maxQueueSize); } public synchronized String toDetailString() { StringBuilder b = new StringBuilder(); b.append(toString()); b.append('\n'); synchronized (this) { for (AbstractHttpConnection connection : _connections) { b.append(connection.toDetailString()); if (_idle.contains(connection)) b.append(" IDLE"); b.append('\n'); } } b.append("--"); b.append('\n'); return b.toString(); } public void setProxy(Address proxy) { _proxy = proxy; } public Address getProxy() { return _proxy; } public Authentication getProxyAuthentication() { return _proxyAuthentication; } public void setProxyAuthentication(Authentication authentication) { _proxyAuthentication = authentication; } public boolean isProxied() { return _proxy != null; } public void close() throws IOException { synchronized (this) { for (AbstractHttpConnection connection : _connections) { connection.close(); } } } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.util.component.Dumpable#dump() */ public String dump() { return AggregateLifeCycle.dump(this); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.util.component.Dumpable#dump(java.lang.Appendable, java.lang.String) */ public void dump(Appendable out, String indent) throws IOException { synchronized (this) { out.append(String.valueOf(this)+"idle="+_idle.size()+" pending="+_pendingConnections).append("\n"); AggregateLifeCycle.dump(out,indent,_connections); } } private class ConnectExchange extends ContentExchange { private final SelectConnector.UpgradableEndPoint proxyEndPoint; private final HttpExchange exchange; public ConnectExchange(Address serverAddress, SelectConnector.UpgradableEndPoint proxyEndPoint, HttpExchange exchange) { this.proxyEndPoint = proxyEndPoint; this.exchange = exchange; setMethod(HttpMethods.CONNECT); setVersion(exchange.getVersion()); String serverHostAndPort = serverAddress.toString(); setRequestURI(serverHostAndPort); addRequestHeader(HttpHeaders.HOST, serverHostAndPort); addRequestHeader(HttpHeaders.PROXY_CONNECTION, "keep-alive"); addRequestHeader(HttpHeaders.USER_AGENT, "Jetty-Client"); } @Override protected void onResponseComplete() throws IOException { int responseStatus = getResponseStatus(); if (responseStatus == HttpStatus.OK_200) { proxyEndPoint.upgrade(); } else if(responseStatus == HttpStatus.GATEWAY_TIMEOUT_504) { onExpire(); } else { onException(new ProtocolException("Proxy: " + proxyEndPoint.getRemoteAddr() +":" + proxyEndPoint.getRemotePort() + " didn't return http return code 200, but " + responseStatus + " while trying to request: " + exchange.getAddress().toString())); } } @Override protected void onConnectionFailed(Throwable x) { HttpDestination.this.onConnectionFailed(x); } @Override protected void onException(Throwable x) { _queue.remove(exchange); if (exchange.setStatus(STATUS_EXCEPTED)) exchange.getEventListener().onException(x); } @Override protected void onExpire() { _queue.remove(exchange); if (exchange.setStatus(STATUS_EXPIRED)) exchange.getEventListener().onExpire(); } } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/HttpEventListener.java000066400000000000000000000032101174773561500311570ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import org.eclipse.jetty.io.Buffer; /** * * * */ public interface HttpEventListener { // TODO review the methods here, we can probably trim these down on what to expose public void onRequestCommitted() throws IOException; public void onRequestComplete() throws IOException; public void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException; public void onResponseHeader(Buffer name, Buffer value) throws IOException; public void onResponseHeaderComplete() throws IOException; public void onResponseContent(Buffer content) throws IOException; public void onResponseComplete() throws IOException; public void onConnectionFailed(Throwable ex); public void onException(Throwable ex); public void onExpire(); public void onRetry(); } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/HttpEventListenerWrapper.java000066400000000000000000000102051174773561500325220ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import org.eclipse.jetty.io.Buffer; public class HttpEventListenerWrapper implements HttpEventListener { HttpEventListener _listener; boolean _delegatingRequests; boolean _delegatingResponses; boolean _delegationResult = true; private Buffer _version; private int _status; private Buffer _reason; public HttpEventListenerWrapper() { _listener=null; _delegatingRequests=false; _delegatingResponses=false; } public HttpEventListenerWrapper(HttpEventListener eventListener,boolean delegating) { _listener=eventListener; _delegatingRequests=delegating; _delegatingResponses=delegating; } public HttpEventListener getEventListener() { return _listener; } public void setEventListener(HttpEventListener listener) { _listener = listener; } public boolean isDelegatingRequests() { return _delegatingRequests; } public boolean isDelegatingResponses() { return _delegatingResponses; } public void setDelegatingRequests(boolean delegating) { _delegatingRequests = delegating; } public void setDelegatingResponses(boolean delegating) { _delegatingResponses = delegating; } public void setDelegationResult( boolean result ) { _delegationResult = result; } public void onConnectionFailed(Throwable ex) { if (_delegatingRequests) _listener.onConnectionFailed(ex); } public void onException(Throwable ex) { if (_delegatingRequests||_delegatingResponses) _listener.onException(ex); } public void onExpire() { if (_delegatingRequests||_delegatingResponses) _listener.onExpire(); } public void onRequestCommitted() throws IOException { if (_delegatingRequests) _listener.onRequestCommitted(); } public void onRequestComplete() throws IOException { if (_delegatingRequests) _listener.onRequestComplete(); } public void onResponseComplete() throws IOException { if (_delegatingResponses) { if (_delegationResult == false) { _listener.onResponseStatus(_version,_status,_reason); } _listener.onResponseComplete(); } } public void onResponseContent(Buffer content) throws IOException { if (_delegatingResponses) _listener.onResponseContent(content); } public void onResponseHeader(Buffer name, Buffer value) throws IOException { if (_delegatingResponses) _listener.onResponseHeader(name,value); } public void onResponseHeaderComplete() throws IOException { if (_delegatingResponses) _listener.onResponseHeaderComplete(); } public void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { if (_delegatingResponses) { _listener.onResponseStatus(version,status,reason); } else { _version = version; _status = status; _reason = reason; } } public void onRetry() { if (_delegatingRequests) _listener.onRetry(); } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java000066400000000000000000001126001174773561500301160ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jetty.client.security.SecurityListener; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersions; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.Timeout; /** *

* An HTTP client API that encapsulates an exchange (a request and its response) with a HTTP server. *

* * This object encapsulates: *
    *
  • The HTTP server address, see {@link #setAddress(Address)}, or {@link #setURI(URI)}, or {@link #setURL(String)}) *
  • The HTTP request method, URI and HTTP version (see {@link #setMethod(String)}, {@link #setRequestURI(String)}, and {@link #setVersion(int)}) *
  • The request headers (see {@link #addRequestHeader(String, String)} or {@link #setRequestHeader(String, String)}) *
  • The request content (see {@link #setRequestContent(Buffer)} or {@link #setRequestContentSource(InputStream)}) *
  • The status of the exchange (see {@link #getStatus()}) *
  • Callbacks to handle state changes (see the onXxx methods such as {@link #onRequestComplete()} or {@link #onResponseComplete()}) *
  • The ability to intercept callbacks (see {@link #setEventListener(HttpEventListener)} *
* *

* The HttpExchange class is intended to be used by a developer wishing to have close asynchronous interaction with the the exchange.
* Typically a developer will extend the HttpExchange class with a derived class that overrides some or all of the onXxx callbacks.
* There are also some predefined HttpExchange subtypes that can be used as a basis, see {@link org.eclipse.jetty.client.ContentExchange} and * {@link org.eclipse.jetty.client.CachedExchange}. *

* *

* Typically the HttpExchange is passed to the {@link HttpClient#send(HttpExchange)} method, which in turn selects a {@link HttpDestination} and calls its * {@link HttpDestination#send(HttpExchange)}, which then creates or selects a {@link AbstractHttpConnection} and calls its {@link AbstractHttpConnection#send(HttpExchange)}. A * developer may wish to directly call send on the destination or connection if they wish to bypass some handling provided (eg Cookie handling in the * HttpDestination). *

* *

* In some circumstances, the HttpClient or HttpDestination may wish to retry a HttpExchange (eg. failed pipeline request, authentication retry or redirection). * In such cases, the HttpClient and/or HttpDestination may insert their own HttpExchangeListener to intercept and filter the call backs intended for the * HttpExchange. *

*/ public class HttpExchange { static final Logger LOG = Log.getLogger(HttpExchange.class); public static final int STATUS_START = 0; public static final int STATUS_WAITING_FOR_CONNECTION = 1; public static final int STATUS_WAITING_FOR_COMMIT = 2; public static final int STATUS_SENDING_REQUEST = 3; public static final int STATUS_WAITING_FOR_RESPONSE = 4; public static final int STATUS_PARSING_HEADERS = 5; public static final int STATUS_PARSING_CONTENT = 6; public static final int STATUS_COMPLETED = 7; public static final int STATUS_EXPIRED = 8; public static final int STATUS_EXCEPTED = 9; public static final int STATUS_CANCELLING = 10; public static final int STATUS_CANCELLED = 11; // HTTP protocol fields private String _method = HttpMethods.GET; private Buffer _scheme = HttpSchemes.HTTP_BUFFER; private String _uri; private int _version = HttpVersions.HTTP_1_1_ORDINAL; private Address _address; private final HttpFields _requestFields = new HttpFields(); private Buffer _requestContent; private InputStream _requestContentSource; private AtomicInteger _status = new AtomicInteger(STATUS_START); private boolean _retryStatus = false; // controls if the exchange will have listeners autoconfigured by the destination private boolean _configureListeners = true; private HttpEventListener _listener = new Listener(); private volatile AbstractHttpConnection _connection; private Address _localAddress = null; // a timeout for this exchange private long _timeout = -1; private volatile Timeout.Task _timeoutTask; private long _lastStateChange=System.currentTimeMillis(); private long _sent=-1; private int _lastState=-1; private int _lastStatePeriod=-1; boolean _onRequestCompleteDone; boolean _onResponseCompleteDone; boolean _onDone; // == onConnectionFail || onException || onExpired || onCancelled || onResponseCompleted && onRequestCompleted protected void expire(HttpDestination destination) { if (getStatus() < HttpExchange.STATUS_COMPLETED) setStatus(HttpExchange.STATUS_EXPIRED); destination.exchangeExpired(this); AbstractHttpConnection connection = _connection; if (connection != null) connection.exchangeExpired(this); } public int getStatus() { return _status.get(); } /** * @param status * the status to wait for * @throws InterruptedException * if the waiting thread is interrupted * @deprecated Use {@link #waitForDone()} instead */ @Deprecated public void waitForStatus(int status) throws InterruptedException { throw new UnsupportedOperationException(); } /** * Wait until the exchange is "done". Done is defined as when a final state has been passed to the HttpExchange via the associated onXxx call. Note that an * exchange can transit a final state when being used as part of a dialog (eg {@link SecurityListener}. Done status is thus defined as: * *
     * done == onConnectionFailed || onException || onExpire || onRequestComplete && onResponseComplete
     * 
* * @return the done status * @throws InterruptedException */ public int waitForDone() throws InterruptedException { synchronized (this) { while (!isDone()) this.wait(); return _status.get(); } } public void reset() { // TODO - this should do a cancel and wakeup everybody that was waiting. // might need a version number concept synchronized (this) { _timeoutTask = null; _onRequestCompleteDone = false; _onResponseCompleteDone = false; _onDone = false; setStatus(STATUS_START); } } /* ------------------------------------------------------------ */ /** * @param newStatus * @return True if the status was actually set. */ boolean setStatus(int newStatus) { boolean set = false; try { int oldStatus = _status.get(); boolean ignored = false; if (oldStatus != newStatus) { long now = System.currentTimeMillis(); _lastStatePeriod=(int)(now-_lastStateChange); _lastState=oldStatus; _lastStateChange=now; if (newStatus==STATUS_SENDING_REQUEST) _sent=_lastStateChange; } // State machine: from which old status you can go into which new status switch (oldStatus) { case STATUS_START: switch (newStatus) { case STATUS_START: case STATUS_WAITING_FOR_CONNECTION: case STATUS_WAITING_FOR_COMMIT: case STATUS_CANCELLING: case STATUS_EXCEPTED: set = _status.compareAndSet(oldStatus,newStatus); break; case STATUS_EXPIRED: set = setStatusExpired(newStatus,oldStatus); break; } break; case STATUS_WAITING_FOR_CONNECTION: switch (newStatus) { case STATUS_WAITING_FOR_COMMIT: case STATUS_CANCELLING: case STATUS_EXCEPTED: set = _status.compareAndSet(oldStatus,newStatus); break; case STATUS_EXPIRED: set = setStatusExpired(newStatus,oldStatus); break; } break; case STATUS_WAITING_FOR_COMMIT: switch (newStatus) { case STATUS_SENDING_REQUEST: case STATUS_CANCELLING: case STATUS_EXCEPTED: set = _status.compareAndSet(oldStatus,newStatus); break; case STATUS_EXPIRED: set = setStatusExpired(newStatus,oldStatus); break; } break; case STATUS_SENDING_REQUEST: switch (newStatus) { case STATUS_WAITING_FOR_RESPONSE: if (set = _status.compareAndSet(oldStatus,newStatus)) getEventListener().onRequestCommitted(); break; case STATUS_CANCELLING: case STATUS_EXCEPTED: set = _status.compareAndSet(oldStatus,newStatus); break; case STATUS_EXPIRED: set = setStatusExpired(newStatus,oldStatus); break; } break; case STATUS_WAITING_FOR_RESPONSE: switch (newStatus) { case STATUS_PARSING_HEADERS: case STATUS_CANCELLING: case STATUS_EXCEPTED: set = _status.compareAndSet(oldStatus,newStatus); break; case STATUS_EXPIRED: set = setStatusExpired(newStatus,oldStatus); break; } break; case STATUS_PARSING_HEADERS: switch (newStatus) { case STATUS_PARSING_CONTENT: if (set = _status.compareAndSet(oldStatus,newStatus)) getEventListener().onResponseHeaderComplete(); break; case STATUS_CANCELLING: case STATUS_EXCEPTED: set = _status.compareAndSet(oldStatus,newStatus); break; case STATUS_EXPIRED: set = setStatusExpired(newStatus,oldStatus); break; } break; case STATUS_PARSING_CONTENT: switch (newStatus) { case STATUS_COMPLETED: if (set = _status.compareAndSet(oldStatus,newStatus)) getEventListener().onResponseComplete(); break; case STATUS_CANCELLING: case STATUS_EXCEPTED: set = _status.compareAndSet(oldStatus,newStatus); break; case STATUS_EXPIRED: set = setStatusExpired(newStatus,oldStatus); break; } break; case STATUS_COMPLETED: switch (newStatus) { case STATUS_START: case STATUS_EXCEPTED: case STATUS_WAITING_FOR_RESPONSE: set = _status.compareAndSet(oldStatus,newStatus); break; case STATUS_CANCELLING: case STATUS_EXPIRED: // Don't change the status, it's too late ignored = true; break; } break; case STATUS_CANCELLING: switch (newStatus) { case STATUS_EXCEPTED: case STATUS_CANCELLED: if (set = _status.compareAndSet(oldStatus,newStatus)) done(); break; default: // Ignore other statuses, we're cancelling ignored = true; break; } break; case STATUS_EXCEPTED: case STATUS_EXPIRED: case STATUS_CANCELLED: switch (newStatus) { case STATUS_START: set = _status.compareAndSet(oldStatus,newStatus); break; case STATUS_COMPLETED: ignored = true; done(); break; default: ignored = true; break; } break; default: // Here means I allowed to set a state that I don't recognize throw new AssertionError(oldStatus + " => " + newStatus); } if (!set && !ignored) throw new IllegalStateException(toState(oldStatus) + " => " + toState(newStatus)); LOG.debug("setStatus {} {}",newStatus,this); } catch (IOException x) { LOG.warn(x); } return set; } private boolean setStatusExpired(int newStatus, int oldStatus) { boolean set; if (set = _status.compareAndSet(oldStatus,newStatus)) getEventListener().onExpire(); return set; } public boolean isDone() { synchronized (this) { return _onDone; } } /** * @deprecated */ @Deprecated public boolean isDone(int status) { return isDone(); } public HttpEventListener getEventListener() { return _listener; } public void setEventListener(HttpEventListener listener) { _listener = listener; } public void setTimeout(long timeout) { _timeout = timeout; } public long getTimeout() { return _timeout; } /** * @param url * an absolute URL (for example 'http://localhost/foo/bar?a=1') */ public void setURL(String url) { setURI(URI.create(url)); } /** * @param address * the address of the server */ public void setAddress(Address address) { _address = address; } /** * @return the address of the server */ public Address getAddress() { return _address; } /** * the local address used by the connection * * Note: this method will not be populated unless the exchange has been executed by the HttpClient * * @return the local address used for the running of the exchange if available, null otherwise. */ public Address getLocalAddress() { return _localAddress; } /** * @param scheme * the scheme of the URL (for example 'http') */ public void setScheme(Buffer scheme) { _scheme = scheme; } /** * @param scheme * the scheme of the URL (for example 'http') */ public void setScheme(String scheme) { if (scheme != null) { if (HttpSchemes.HTTP.equalsIgnoreCase(scheme)) setScheme(HttpSchemes.HTTP_BUFFER); else if (HttpSchemes.HTTPS.equalsIgnoreCase(scheme)) setScheme(HttpSchemes.HTTPS_BUFFER); else setScheme(new ByteArrayBuffer(scheme)); } } /** * @return the scheme of the URL */ public Buffer getScheme() { return _scheme; } /** * @param version * the HTTP protocol version as integer, 9, 10 or 11 for 0.9, 1.0 or 1.1 */ public void setVersion(int version) { _version = version; } /** * @param version * the HTTP protocol version as string */ public void setVersion(String version) { CachedBuffer v = HttpVersions.CACHE.get(version); if (v == null) _version = 10; else _version = v.getOrdinal(); } /** * @return the HTTP protocol version as integer * @see #setVersion(int) */ public int getVersion() { return _version; } /** * @param method * the HTTP method (for example 'GET') */ public void setMethod(String method) { _method = method; } /** * @return the HTTP method */ public String getMethod() { return _method; } /** * @return request URI * @see #getRequestURI() * @deprecated */ @Deprecated public String getURI() { return getRequestURI(); } /** * @return request URI */ public String getRequestURI() { return _uri; } /** * Set the request URI * * @param uri * new request URI * @see #setRequestURI(String) * @deprecated */ @Deprecated public void setURI(String uri) { setRequestURI(uri); } /** * Set the request URI * * Per RFC 2616 sec5, Request-URI = "*" | absoluteURI | abs_path | authority
* where:
*
* "*" - request applies to server itself
* absoluteURI - required for proxy requests, e.g. http://localhost:8080/context
* (this form is generated automatically by HttpClient)
* abs_path - used for most methods, e.g. /context
* authority - used for CONNECT method only, e.g. localhost:8080
*
* For complete definition of URI components, see RFC 2396 sec3.
* * @param uri * new request URI */ public void setRequestURI(String uri) { _uri = uri; } /* ------------------------------------------------------------ */ /** * @param uri * an absolute URI (for example 'http://localhost/foo/bar?a=1') */ public void setURI(URI uri) { if (!uri.isAbsolute()) throw new IllegalArgumentException("!Absolute URI: " + uri); if (uri.isOpaque()) throw new IllegalArgumentException("Opaque URI: " + uri); if (LOG.isDebugEnabled()) LOG.debug("URI = {}",uri.toASCIIString()); String scheme = uri.getScheme(); int port = uri.getPort(); if (port <= 0) port = "https".equalsIgnoreCase(scheme)?443:80; setScheme(scheme); setAddress(new Address(uri.getHost(),port)); HttpURI httpUri = new HttpURI(uri); String completePath = httpUri.getCompletePath(); setRequestURI(completePath == null?"/":completePath); } /** * Adds the specified request header * * @param name * the header name * @param value * the header value */ public void addRequestHeader(String name, String value) { getRequestFields().add(name,value); } /** * Adds the specified request header * * @param name * the header name * @param value * the header value */ public void addRequestHeader(Buffer name, Buffer value) { getRequestFields().add(name,value); } /** * Sets the specified request header * * @param name * the header name * @param value * the header value */ public void setRequestHeader(String name, String value) { getRequestFields().put(name,value); } /** * Sets the specified request header * * @param name * the header name * @param value * the header value */ public void setRequestHeader(Buffer name, Buffer value) { getRequestFields().put(name,value); } /** * @param value * the content type of the request */ public void setRequestContentType(String value) { getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,value); } /** * @return the request headers */ public HttpFields getRequestFields() { return _requestFields; } /** * @param requestContent * the request content */ public void setRequestContent(Buffer requestContent) { _requestContent = requestContent; } /** * @param stream * the request content as a stream */ public void setRequestContentSource(InputStream stream) { _requestContentSource = stream; if (_requestContentSource != null && _requestContentSource.markSupported()) _requestContentSource.mark(Integer.MAX_VALUE); } /** * @return the request content as a stream */ public InputStream getRequestContentSource() { return _requestContentSource; } public Buffer getRequestContentChunk(Buffer buffer) throws IOException { synchronized (this) { if (_requestContentSource!=null) { if (buffer == null) buffer = new ByteArrayBuffer(8192); // TODO configure int space = buffer.space(); int length = _requestContentSource.read(buffer.array(),buffer.putIndex(),space); if (length >= 0) { buffer.setPutIndex(buffer.putIndex()+length); return buffer; } } return null; } } /** * @return the request content */ public Buffer getRequestContent() { return _requestContent; } /** * @return whether a retry will be attempted or not */ public boolean getRetryStatus() { return _retryStatus; } /** * @param retryStatus * whether a retry will be attempted or not */ public void setRetryStatus(boolean retryStatus) { _retryStatus = retryStatus; } /** * Initiates the cancelling of this exchange. The status of the exchange is set to {@link #STATUS_CANCELLING}. Cancelling the exchange is an asynchronous * operation with respect to the request/response, and as such checking the request/response status of a cancelled exchange may return undefined results * (for example it may have only some of the response headers being sent by the server). The cancelling of the exchange is completed when the exchange * status (see {@link #getStatus()}) is {@link #STATUS_CANCELLED}, and this can be waited using {@link #waitForDone()}. */ public void cancel() { setStatus(STATUS_CANCELLING); abort(); } private void done() { synchronized (this) { disassociate(); _onDone = true; notifyAll(); } } private void abort() { AbstractHttpConnection httpConnection = _connection; if (httpConnection != null) { try { // Closing the connection here will cause the connection // to be returned in HttpConnection.handle() httpConnection.close(); } catch (IOException x) { LOG.debug(x); } finally { disassociate(); } } } void associate(AbstractHttpConnection connection) { if (connection.getEndPoint().getLocalAddr() != null) _localAddress = new Address(connection.getEndPoint().getLocalAddr(),connection.getEndPoint().getLocalPort()); _connection = connection; if (getStatus() == STATUS_CANCELLING) abort(); } boolean isAssociated() { return this._connection != null; } AbstractHttpConnection disassociate() { AbstractHttpConnection result = _connection; this._connection = null; if (getStatus() == STATUS_CANCELLING) setStatus(STATUS_CANCELLED); return result; } public static String toState(int s) { String state; switch (s) { case STATUS_START: state = "START"; break; case STATUS_WAITING_FOR_CONNECTION: state = "CONNECTING"; break; case STATUS_WAITING_FOR_COMMIT: state = "CONNECTED"; break; case STATUS_SENDING_REQUEST: state = "SENDING"; break; case STATUS_WAITING_FOR_RESPONSE: state = "WAITING"; break; case STATUS_PARSING_HEADERS: state = "HEADERS"; break; case STATUS_PARSING_CONTENT: state = "CONTENT"; break; case STATUS_COMPLETED: state = "COMPLETED"; break; case STATUS_EXPIRED: state = "EXPIRED"; break; case STATUS_EXCEPTED: state = "EXCEPTED"; break; case STATUS_CANCELLING: state = "CANCELLING"; break; case STATUS_CANCELLED: state = "CANCELLED"; break; default: state = "UNKNOWN"; } return state; } @Override public String toString() { String state=toState(getStatus()); long now=System.currentTimeMillis(); long forMs = now -_lastStateChange; String s= _lastState>=0 ?String.format("%s@%x=%s//%s%s#%s(%dms)->%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,toState(_lastState),_lastStatePeriod,state,forMs) :String.format("%s@%x=%s//%s%s#%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,state,forMs); if (getStatus()>=STATUS_SENDING_REQUEST && _sent>0) s+="sent="+(now-_sent)+"ms"; return s; } /** */ protected Connection onSwitchProtocol(EndPoint endp) throws IOException { return null; } /** * Callback called when the request headers have been sent to the server. This implementation does nothing. * * @throws IOException * allowed to be thrown by overriding code */ protected void onRequestCommitted() throws IOException { } /** * Callback called when the request and its body have been sent to the server. This implementation does nothing. * * @throws IOException * allowed to be thrown by overriding code */ protected void onRequestComplete() throws IOException { } /** * Callback called when a response status line has been received from the server. This implementation does nothing. * * @param version * the HTTP version * @param status * the HTTP status code * @param reason * the HTTP status reason string * @throws IOException * allowed to be thrown by overriding code */ protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { } /** * Callback called for each response header received from the server. This implementation does nothing. * * @param name * the header name * @param value * the header value * @throws IOException * allowed to be thrown by overriding code */ protected void onResponseHeader(Buffer name, Buffer value) throws IOException { } /** * Callback called when the response headers have been completely received from the server. This implementation does nothing. * * @throws IOException * allowed to be thrown by overriding code */ protected void onResponseHeaderComplete() throws IOException { } /** * Callback called for each chunk of the response content received from the server. This implementation does nothing. * * @param content * the buffer holding the content chunk * @throws IOException * allowed to be thrown by overriding code */ protected void onResponseContent(Buffer content) throws IOException { } /** * Callback called when the entire response has been received from the server This implementation does nothing. * * @throws IOException * allowed to be thrown by overriding code */ protected void onResponseComplete() throws IOException { } /** * Callback called when an exception was thrown during an attempt to establish the connection with the server (for example the server is not listening). * This implementation logs a warning. * * @param x * the exception thrown attempting to establish the connection with the server */ protected void onConnectionFailed(Throwable x) { LOG.warn("CONNECTION FAILED " + this,x); } /** * Callback called when any other exception occurs during the handling of this exchange. This implementation logs a warning. * * @param x * the exception thrown during the handling of this exchange */ protected void onException(Throwable x) { LOG.warn("EXCEPTION " + this,x); } /** * Callback called when no response has been received within the timeout. This implementation logs a warning. */ protected void onExpire() { LOG.warn("EXPIRED " + this); } /** * Callback called when the request is retried (due to failures or authentication). Implementations must reset any consumable content that needs to be sent. * * @throws IOException * allowed to be thrown by overriding code */ protected void onRetry() throws IOException { if (_requestContentSource != null) { if (_requestContentSource.markSupported()) { _requestContent = null; _requestContentSource.reset(); } else { throw new IOException("Unsupported retry attempt"); } } } /** * @return true if the exchange should have listeners configured for it by the destination, false if this is being managed elsewhere * @see #setConfigureListeners(boolean) */ public boolean configureListeners() { return _configureListeners; } /** * @param autoConfigure * whether the listeners are configured by the destination or elsewhere */ public void setConfigureListeners(boolean autoConfigure) { this._configureListeners = autoConfigure; } protected void scheduleTimeout(final HttpDestination destination) { assert _timeoutTask == null; _timeoutTask = new Timeout.Task() { @Override public void expired() { HttpExchange.this.expire(destination); } }; HttpClient httpClient = destination.getHttpClient(); long timeout = getTimeout(); if (timeout > 0) httpClient.schedule(_timeoutTask,timeout); else httpClient.schedule(_timeoutTask); } protected void cancelTimeout(HttpClient httpClient) { Timeout.Task task = _timeoutTask; if (task != null) httpClient.cancel(task); _timeoutTask = null; } private class Listener implements HttpEventListener { public void onConnectionFailed(Throwable ex) { try { HttpExchange.this.onConnectionFailed(ex); } finally { done(); } } public void onException(Throwable ex) { try { HttpExchange.this.onException(ex); } finally { done(); } } public void onExpire() { try { HttpExchange.this.onExpire(); } finally { done(); } } public void onRequestCommitted() throws IOException { HttpExchange.this.onRequestCommitted(); } public void onRequestComplete() throws IOException { try { HttpExchange.this.onRequestComplete(); } finally { synchronized (HttpExchange.this) { _onRequestCompleteDone = true; // Member _onDone may already be true, for example // because the exchange expired or has been canceled _onDone |= _onResponseCompleteDone; if (_onDone) disassociate(); HttpExchange.this.notifyAll(); } } } public void onResponseComplete() throws IOException { try { HttpExchange.this.onResponseComplete(); } finally { synchronized (HttpExchange.this) { _onResponseCompleteDone = true; // Member _onDone may already be true, for example // because the exchange expired or has been canceled _onDone |= _onRequestCompleteDone; if (_onDone) disassociate(); HttpExchange.this.notifyAll(); } } } public void onResponseContent(Buffer content) throws IOException { HttpExchange.this.onResponseContent(content); } public void onResponseHeader(Buffer name, Buffer value) throws IOException { HttpExchange.this.onResponseHeader(name,value); } public void onResponseHeaderComplete() throws IOException { HttpExchange.this.onResponseHeaderComplete(); } public void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { HttpExchange.this.onResponseStatus(version,status,reason); } public void onRetry() { HttpExchange.this.setRetryStatus(true); try { HttpExchange.this.onRetry(); } catch (IOException e) { LOG.debug(e); } } } /** * @deprecated use {@link org.eclipse.jetty.client.CachedExchange} instead */ @Deprecated public static class CachedExchange extends org.eclipse.jetty.client.CachedExchange { public CachedExchange(boolean cacheFields) { super(cacheFields); } } /** * @deprecated use {@link org.eclipse.jetty.client.ContentExchange} instead */ @Deprecated public static class ContentExchange extends org.eclipse.jetty.client.ContentExchange { } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/RedirectListener.java000066400000000000000000000137661174773561500310200ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.Buffer; /** * RedirectListener * * Detect and handle the redirect responses */ public class RedirectListener extends HttpEventListenerWrapper { private final HttpExchange _exchange; private HttpDestination _destination; private String _location; private int _attempts; private boolean _requestComplete; private boolean _responseComplete; private boolean _redirected; public RedirectListener(HttpDestination destination, HttpExchange ex) { // Start of sending events through to the wrapped listener // Next decision point is the onResponseStatus super(ex.getEventListener(),true); _destination = destination; _exchange = ex; } @Override public void onResponseStatus( Buffer version, int status, Buffer reason ) throws IOException { _redirected = ((status == HttpStatus.MOVED_PERMANENTLY_301 || status == HttpStatus.MOVED_TEMPORARILY_302) && _attempts < _destination.getHttpClient().maxRedirects()); if (_redirected) { setDelegatingRequests(false); setDelegatingResponses(false); } super.onResponseStatus(version,status,reason); } @Override public void onResponseHeader( Buffer name, Buffer value ) throws IOException { if (_redirected) { int header = HttpHeaders.CACHE.getOrdinal(name); switch (header) { case HttpHeaders.LOCATION_ORDINAL: _location = value.toString(); break; } } super.onResponseHeader(name,value); } @Override public void onRequestComplete() throws IOException { _requestComplete = true; if (checkExchangeComplete()) { super.onRequestComplete(); } } @Override public void onResponseComplete() throws IOException { _responseComplete = true; if (checkExchangeComplete()) { super.onResponseComplete(); } } public boolean checkExchangeComplete() throws IOException { if (_redirected && _requestComplete && _responseComplete) { if (_location != null) { if (_location.indexOf("://")>0) { _exchange.setURL(_location); } else { _exchange.setRequestURI(_location); } // destination may have changed boolean isHttps = HttpSchemes.HTTPS.equals(String.valueOf(_exchange.getScheme())); HttpDestination destination=_destination.getHttpClient().getDestination(_exchange.getAddress(),isHttps); if (_destination==destination) { _destination.resend(_exchange); } else { // unwrap to find ultimate listener. HttpEventListener listener=this; while(listener instanceof HttpEventListenerWrapper) { listener=((HttpEventListenerWrapper)listener).getEventListener(); } //reset the listener _exchange.getEventListener().onRetry(); _exchange.reset(); _exchange.setEventListener(listener); // Set the new Host header Address address = _exchange.getAddress(); int port = address.getPort(); StringBuilder hostHeader = new StringBuilder( 64 ); hostHeader.append( address.getHost() ); if( !( ( port == 80 && !isHttps ) || ( port == 443 && isHttps ) ) ) { hostHeader.append( ':' ); hostHeader.append( port ); } _exchange.setRequestHeader( HttpHeaders.HOST, hostHeader.toString() ); destination.send(_exchange); } return false; } else { setDelegationResult(false); } } return true; } public void onRetry() { _redirected=false; _attempts++; setDelegatingRequests(true); setDelegatingResponses(true); _requestComplete=false; _responseComplete=false; super.onRetry(); } /** * Delegate failed connection */ @Override public void onConnectionFailed( Throwable ex ) { setDelegatingRequests(true); setDelegatingResponses(true); super.onConnectionFailed( ex ); } /** * Delegate onException */ @Override public void onException( Throwable ex ) { setDelegatingRequests(true); setDelegatingResponses(true); super.onException( ex ); } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/SelectConnector.java000066400000000000000000000325001174773561500306260ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import java.net.SocketTimeoutException; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; import java.nio.channels.UnresolvedAddressException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.net.ssl.SSLEngine; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.nio.AsyncConnection; import org.eclipse.jetty.io.nio.SelectChannelEndPoint; import org.eclipse.jetty.io.nio.SelectorManager; import org.eclipse.jetty.io.nio.SslConnection; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.Timeout; import org.eclipse.jetty.util.thread.Timeout.Task; class SelectConnector extends AggregateLifeCycle implements HttpClient.Connector, Dumpable { private static final Logger LOG = Log.getLogger(SelectConnector.class); private final HttpClient _httpClient; private final Manager _selectorManager=new Manager(); private final Map _connectingChannels = new ConcurrentHashMap(); /* ------------------------------------------------------------ */ /** * @param httpClient the HttpClient this connector is associated to. It is * added via the {@link #addBean(Object, boolean)} as an unmanaged bean. */ SelectConnector(HttpClient httpClient) { _httpClient = httpClient; addBean(_httpClient,false); addBean(_selectorManager,true); } /* ------------------------------------------------------------ */ public void startConnection( HttpDestination destination ) throws IOException { SocketChannel channel = null; try { channel = SocketChannel.open(); Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress(); channel.socket().setTcpNoDelay(true); if (_httpClient.isConnectBlocking()) { channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout()); channel.configureBlocking(false); _selectorManager.register( channel, destination ); } else { channel.configureBlocking(false); channel.connect(address.toSocketAddress()); _selectorManager.register(channel,destination); ConnectTimeout connectTimeout = new ConnectTimeout(channel,destination); _httpClient.schedule(connectTimeout,_httpClient.getConnectTimeout()); _connectingChannels.put(channel,connectTimeout); } } catch (UnresolvedAddressException ex) { if (channel != null) channel.close(); destination.onConnectionFailed(ex); } catch(IOException ex) { if (channel != null) channel.close(); destination.onConnectionFailed(ex); } } /* ------------------------------------------------------------ */ class Manager extends SelectorManager { Logger LOG = SelectConnector.LOG; @Override public boolean dispatch(Runnable task) { return _httpClient._threadPool.dispatch(task); } @Override protected void endPointOpened(SelectChannelEndPoint endpoint) { } @Override protected void endPointClosed(SelectChannelEndPoint endpoint) { } @Override protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection) { } @Override public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment) { return new AsyncHttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint); } @Override protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException { // We're connected, cancel the connect timeout Timeout.Task connectTimeout = _connectingChannels.remove(channel); if (connectTimeout != null) connectTimeout.cancel(); if (LOG.isDebugEnabled()) LOG.debug("Channels with connection pending: {}", _connectingChannels.size()); // key should have destination at this point (will be replaced by endpoint after this call) HttpDestination dest=(HttpDestination)key.attachment(); SelectChannelEndPoint scep = new SelectChannelEndPoint(channel, selectSet, key, (int)_httpClient.getIdleTimeout()); AsyncEndPoint ep = scep; if (dest.isSecure()) { LOG.debug("secure to {}, proxied={}",channel,dest.isProxied()); ep = new UpgradableEndPoint(ep,newSslEngine(channel)); } AsyncConnection connection = selectSet.getManager().newConnection(channel,ep, key.attachment()); ep.setConnection(connection); AbstractHttpConnection httpConnection=(AbstractHttpConnection)connection; httpConnection.setDestination(dest); if (dest.isSecure() && !dest.isProxied()) ((UpgradableEndPoint)ep).upgrade(); dest.onNewConnection(httpConnection); return scep; } private synchronized SSLEngine newSslEngine(SocketChannel channel) throws IOException { SslContextFactory sslContextFactory = _httpClient.getSslContextFactory(); SSLEngine sslEngine; if (channel != null) { String peerHost = channel.socket().getInetAddress().getHostAddress(); int peerPort = channel.socket().getPort(); sslEngine = sslContextFactory.newSslEngine(peerHost, peerPort); } else { sslEngine = sslContextFactory.newSslEngine(); } sslEngine.setUseClientMode(true); sslEngine.beginHandshake(); return sslEngine; } /* ------------------------------------------------------------ */ /* (non-Javadoc) * @see org.eclipse.io.nio.SelectorManager#connectionFailed(java.nio.channels.SocketChannel, java.lang.Throwable, java.lang.Object) */ @Override protected void connectionFailed(SocketChannel channel, Throwable ex, Object attachment) { Timeout.Task connectTimeout = _connectingChannels.remove(channel); if (connectTimeout != null) connectTimeout.cancel(); if (attachment instanceof HttpDestination) ((HttpDestination)attachment).onConnectionFailed(ex); else super.connectionFailed(channel,ex,attachment); } } private class ConnectTimeout extends Timeout.Task { private final SocketChannel channel; private final HttpDestination destination; public ConnectTimeout(SocketChannel channel, HttpDestination destination) { this.channel = channel; this.destination = destination; } @Override public void expired() { if (channel.isConnectionPending()) { LOG.debug("Channel {} timed out while connecting, closing it", channel); try { // This will unregister the channel from the selector channel.close(); } catch (IOException x) { LOG.ignore(x); } destination.onConnectionFailed(new SocketTimeoutException()); } } } public static class UpgradableEndPoint implements AsyncEndPoint { AsyncEndPoint _endp; SSLEngine _engine; public UpgradableEndPoint(AsyncEndPoint endp, SSLEngine engine) throws IOException { _engine=engine; _endp=endp; } public void upgrade() { AsyncHttpConnection connection = (AsyncHttpConnection)_endp.getConnection(); SslConnection sslConnection = new SslConnection(_engine,_endp); _endp.setConnection(sslConnection); _endp=sslConnection.getSslEndPoint(); sslConnection.getSslEndPoint().setConnection(connection); LOG.debug("upgrade {} to {} for {}",this,sslConnection,connection); } public Connection getConnection() { return _endp.getConnection(); } public void setConnection(Connection connection) { _endp.setConnection(connection); } public void shutdownOutput() throws IOException { _endp.shutdownOutput(); } public void dispatch() { _endp.asyncDispatch(); } public void asyncDispatch() { _endp.asyncDispatch(); } public boolean isOutputShutdown() { return _endp.isOutputShutdown(); } public void shutdownInput() throws IOException { _endp.shutdownInput(); } public void scheduleWrite() { _endp.scheduleWrite(); } public boolean isInputShutdown() { return _endp.isInputShutdown(); } public void close() throws IOException { _endp.close(); } public int fill(Buffer buffer) throws IOException { return _endp.fill(buffer); } public boolean isWritable() { return _endp.isWritable(); } public boolean hasProgressed() { return _endp.hasProgressed(); } public int flush(Buffer buffer) throws IOException { return _endp.flush(buffer); } public void scheduleTimeout(Task task, long timeoutMs) { _endp.scheduleTimeout(task,timeoutMs); } public void cancelTimeout(Task task) { _endp.cancelTimeout(task); } public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException { return _endp.flush(header,buffer,trailer); } public String getLocalAddr() { return _endp.getLocalAddr(); } public String getLocalHost() { return _endp.getLocalHost(); } public int getLocalPort() { return _endp.getLocalPort(); } public String getRemoteAddr() { return _endp.getRemoteAddr(); } public String getRemoteHost() { return _endp.getRemoteHost(); } public int getRemotePort() { return _endp.getRemotePort(); } public boolean isBlocking() { return _endp.isBlocking(); } public boolean blockReadable(long millisecs) throws IOException { return _endp.blockReadable(millisecs); } public boolean blockWritable(long millisecs) throws IOException { return _endp.blockWritable(millisecs); } public boolean isOpen() { return _endp.isOpen(); } public Object getTransport() { return _endp.getTransport(); } public void flush() throws IOException { _endp.flush(); } public int getMaxIdleTime() { return _endp.getMaxIdleTime(); } public void setMaxIdleTime(int timeMs) throws IOException { _endp.setMaxIdleTime(timeMs); } public void onIdleExpired(long idleForMs) { _endp.onIdleExpired(idleForMs); } public void setCheckForIdle(boolean check) { _endp.setCheckForIdle(check); } public boolean isCheckForIdle() { return _endp.isCheckForIdle(); } public String toString() { return "Upgradable:"+_endp.toString(); } } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/SocketConnector.java000066400000000000000000000070241174773561500306420ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import java.io.InterruptedIOException; import java.net.Socket; import javax.net.SocketFactory; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.bio.SocketEndPoint; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector { private static final Logger LOG = Log.getLogger(SocketConnector.class); /** * */ private final HttpClient _httpClient; /** * @param httpClient */ SocketConnector(HttpClient httpClient) { _httpClient = httpClient; } public void startConnection(final HttpDestination destination) throws IOException { Socket socket= destination.isSecure() ?_httpClient.getSslContextFactory().newSslSocket() :SocketFactory.getDefault().createSocket(); socket.setSoTimeout(0); socket.setTcpNoDelay(true); Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress(); socket.connect(address.toSocketAddress(), _httpClient.getConnectTimeout()); final EndPoint endpoint=new SocketEndPoint(socket); final AbstractHttpConnection connection=new BlockingHttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint); connection.setDestination(destination); destination.onNewConnection(connection); _httpClient.getThreadPool().dispatch(new Runnable() { public void run() { try { Connection con = connection; while(true) { final Connection next = con.handle(); if (next!=con) { con=next; continue; } break; } } catch (IOException e) { if (e instanceof InterruptedIOException) LOG.ignore(e); else { LOG.debug(e); destination.onException(e); } } finally { try { destination.returnConnection(connection,true); } catch (IOException e) { LOG.debug(e); } } } }); } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/security/000077500000000000000000000000001174773561500265405ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/security/Authentication.java000066400000000000000000000020611174773561500323610ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.security; import java.io.IOException; import org.eclipse.jetty.client.HttpExchange; /** * Simple authentication interface that sets required fields on the exchange. */ public interface Authentication { public void setCredentials( HttpExchange exchange) throws IOException; } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/security/BasicAuthentication.java000066400000000000000000000035231174773561500333270ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.security; import java.io.IOException; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.util.B64Code; import org.eclipse.jetty.util.StringUtil; /** * Sets authentication headers for BASIC authentication challenges * * */ public class BasicAuthentication implements Authentication { private Buffer _authorization; public BasicAuthentication(Realm realm) throws IOException { String authenticationString = "Basic " + B64Code.encode( realm.getPrincipal() + ":" + realm.getCredentials(), StringUtil.__ISO_8859_1); _authorization= new ByteArrayBuffer(authenticationString); } /** * BASIC authentication is of the form * * encoded credentials are of the form: username:password * * */ public void setCredentials( HttpExchange exchange ) throws IOException { exchange.setRequestHeader( HttpHeaders.AUTHORIZATION_BUFFER, _authorization); } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/security/DigestAuthentication.java000066400000000000000000000125001174773561500335200ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.security; import java.io.IOException; import java.security.MessageDigest; import java.util.Map; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; public class DigestAuthentication implements Authentication { private static final String NC = "00000001"; Realm securityRealm; Map details; public DigestAuthentication(Realm realm, Map details) { this.securityRealm=realm; this.details=details; } public void setCredentials( HttpExchange exchange ) throws IOException { StringBuilder buffer = new StringBuilder().append("Digest"); buffer.append(" ").append("username").append('=').append('"').append(securityRealm.getPrincipal()).append('"'); buffer.append(", ").append("realm").append('=').append('"').append(String.valueOf(details.get("realm"))).append('"'); buffer.append(", ").append("nonce").append('=').append('"').append(String.valueOf(details.get("nonce"))).append('"'); buffer.append(", ").append("uri").append('=').append('"').append(exchange.getURI()).append('"'); buffer.append(", ").append("algorithm").append('=').append(String.valueOf(details.get("algorithm"))); String cnonce = newCnonce(exchange, securityRealm, details); buffer.append(", ").append("response").append('=').append('"').append(newResponse(cnonce, exchange, securityRealm, details)).append('"'); buffer.append(", ").append("qop").append('=').append(String.valueOf(details.get("qop"))); buffer.append(", ").append("nc").append('=').append(NC); buffer.append(", ").append("cnonce").append('=').append('"').append(cnonce).append('"'); exchange.setRequestHeader( HttpHeaders.AUTHORIZATION, new String(buffer.toString().getBytes(StringUtil.__ISO_8859_1))); } protected String newResponse(String cnonce, HttpExchange exchange, Realm securityRealm, Map details) { try{ MessageDigest md = MessageDigest.getInstance("MD5"); // calc A1 digest md.update(securityRealm.getPrincipal().getBytes(StringUtil.__ISO_8859_1)); md.update((byte)':'); md.update(String.valueOf(details.get("realm")).getBytes(StringUtil.__ISO_8859_1)); md.update((byte)':'); md.update(securityRealm.getCredentials().getBytes(StringUtil.__ISO_8859_1)); byte[] ha1 = md.digest(); // calc A2 digest md.reset(); md.update(exchange.getMethod().getBytes(StringUtil.__ISO_8859_1)); md.update((byte)':'); md.update(exchange.getURI().getBytes(StringUtil.__ISO_8859_1)); byte[] ha2=md.digest(); md.update(TypeUtil.toString(ha1,16).getBytes(StringUtil.__ISO_8859_1)); md.update((byte)':'); md.update(String.valueOf(details.get("nonce")).getBytes(StringUtil.__ISO_8859_1)); md.update((byte)':'); md.update(NC.getBytes(StringUtil.__ISO_8859_1)); md.update((byte)':'); md.update(cnonce.getBytes(StringUtil.__ISO_8859_1)); md.update((byte)':'); md.update(String.valueOf(details.get("qop")).getBytes(StringUtil.__ISO_8859_1)); md.update((byte)':'); md.update(TypeUtil.toString(ha2,16).getBytes(StringUtil.__ISO_8859_1)); byte[] digest=md.digest(); // check digest return encode(digest); } catch(Exception e) { throw new RuntimeException(e); } } protected String newCnonce(HttpExchange exchange, Realm securityRealm, Map details) { try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] b= md.digest(String.valueOf(System.currentTimeMillis()).getBytes(StringUtil.__ISO_8859_1)); return encode(b); } catch(Exception e) { throw new RuntimeException(e); } } private static String encode(byte[] data) { StringBuilder buffer = new StringBuilder(); for (int i=0; i>> 4)); buffer.append(Integer.toHexString(data[i] & 0x0f)); } return buffer.toString(); } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/security/HashRealmResolver.java000066400000000000000000000026051174773561500327740ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.security; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.eclipse.jetty.client.HttpDestination; public class HashRealmResolver implements RealmResolver { private Map_realmMap; public void addSecurityRealm( Realm realm ) { if (_realmMap == null) { _realmMap = new HashMap(); } _realmMap.put( realm.getId(), realm ); } public Realm getRealm( String realmName, HttpDestination destination, String path ) throws IOException { return _realmMap.get( realmName ); } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/security/ProxyAuthorization.java000066400000000000000000000035351174773561500333130ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.security; import java.io.IOException; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.util.B64Code; import org.eclipse.jetty.util.StringUtil; /** * Sets proxy authentication headers for BASIC authentication challenges * * */ public class ProxyAuthorization implements Authentication { private Buffer _authorization; public ProxyAuthorization(String username,String password) throws IOException { String authenticationString = "Basic " + B64Code.encode( username + ":" + password, StringUtil.__ISO_8859_1); _authorization= new ByteArrayBuffer(authenticationString); } /** * BASIC proxy authentication is of the form * * encoded credentials are of the form: username:password * * */ public void setCredentials( HttpExchange exchange ) throws IOException { exchange.setRequestHeader( HttpHeaders.PROXY_AUTHORIZATION_BUFFER, _authorization); } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/security/Realm.java000066400000000000000000000017111174773561500304430ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.security; /** * Simple security realm interface. */ public interface Realm { public String getId(); public String getPrincipal(); public String getCredentials(); } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/security/RealmResolver.java000066400000000000000000000017761174773561500322000ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.security; import java.io.IOException; import org.eclipse.jetty.client.HttpDestination; public interface RealmResolver { public Realm getRealm( String realmName, HttpDestination destination, String path ) throws IOException; } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/security/SecurityListener.java000066400000000000000000000223301174773561500327200ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.security; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import org.eclipse.jetty.client.HttpDestination; import org.eclipse.jetty.client.HttpEventListenerWrapper; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * SecurityListener * * Allow for insertion of security dialog when performing an * HttpExchange. */ public class SecurityListener extends HttpEventListenerWrapper { private static final Logger LOG = Log.getLogger(SecurityListener.class); private HttpDestination _destination; private HttpExchange _exchange; private boolean _requestComplete; private boolean _responseComplete; private boolean _needIntercept; private int _attempts = 0; // TODO remember to settle on winning solution public SecurityListener(HttpDestination destination, HttpExchange ex) { // Start of sending events through to the wrapped listener // Next decision point is the onResponseStatus super(ex.getEventListener(),true); _destination=destination; _exchange=ex; } /** * scrapes an authentication type from the authString * * @param authString * @return the authentication type */ protected String scrapeAuthenticationType( String authString ) { String authType; if ( authString.indexOf( " " ) == -1 ) { authType = authString.toString().trim(); } else { String authResponse = authString.toString(); authType = authResponse.substring( 0, authResponse.indexOf( " " ) ).trim(); } return authType; } /** * scrapes a set of authentication details from the authString * * @param authString * @return the authentication details */ protected Map scrapeAuthenticationDetails( String authString ) { Map authenticationDetails = new HashMap(); authString = authString.substring( authString.indexOf( " " ) + 1, authString.length() ); StringTokenizer strtok = new StringTokenizer( authString, ","); while ( strtok.hasMoreTokens() ) { String token = strtok.nextToken(); String[] pair = token.split( "=" ); // authentication details ought to come in two parts, if not then just skip if ( pair.length == 2 ) { String itemName = pair[0].trim(); String itemValue = pair[1].trim(); itemValue = StringUtil.unquote( itemValue ); authenticationDetails.put( itemName, itemValue ); } else { LOG.debug("SecurityListener: missed scraping authentication details - " + token ); } } return authenticationDetails; } @Override public void onResponseStatus( Buffer version, int status, Buffer reason ) throws IOException { if (LOG.isDebugEnabled()) LOG.debug("SecurityListener:Response Status: " + status ); if ( status == HttpStatus.UNAUTHORIZED_401 && _attempts<_destination.getHttpClient().maxRetries()) { // Let's absorb events until we have done some retries setDelegatingResponses(false); _needIntercept = true; } else { setDelegatingResponses(true); setDelegatingRequests(true); _needIntercept = false; } super.onResponseStatus(version,status,reason); } @Override public void onResponseHeader( Buffer name, Buffer value ) throws IOException { if (LOG.isDebugEnabled()) LOG.debug( "SecurityListener:Header: " + name.toString() + " / " + value.toString() ); if (!isDelegatingResponses()) { int header = HttpHeaders.CACHE.getOrdinal(name); switch (header) { case HttpHeaders.WWW_AUTHENTICATE_ORDINAL: // TODO don't hard code this bit. String authString = value.toString(); String type = scrapeAuthenticationType( authString ); // TODO maybe avoid this map creation Map details = scrapeAuthenticationDetails( authString ); String pathSpec="/"; // TODO work out the real path spec RealmResolver realmResolver = _destination.getHttpClient().getRealmResolver(); if ( realmResolver == null ) { break; } Realm realm = realmResolver.getRealm( details.get("realm"), _destination, pathSpec ); // TODO work our realm correctly if ( realm == null ) { LOG.warn( "Unknown Security Realm: " + details.get("realm") ); } else if ("digest".equalsIgnoreCase(type)) { _destination.addAuthorization("/",new DigestAuthentication(realm,details)); } else if ("basic".equalsIgnoreCase(type)) { _destination.addAuthorization(pathSpec,new BasicAuthentication(realm)); } break; } } super.onResponseHeader(name,value); } @Override public void onRequestComplete() throws IOException { _requestComplete = true; if (_needIntercept) { if (_requestComplete && _responseComplete) { if (LOG.isDebugEnabled()) LOG.debug("onRequestComplete, Both complete: Resending from onResponseComplete "+_exchange); _responseComplete = false; _requestComplete = false; setDelegatingRequests(true); setDelegatingResponses(true); _destination.resend(_exchange); } else { if (LOG.isDebugEnabled()) LOG.debug("onRequestComplete, Response not yet complete onRequestComplete, calling super for "+_exchange); super.onRequestComplete(); } } else { if (LOG.isDebugEnabled()) LOG.debug("onRequestComplete, delegating to super with Request complete="+_requestComplete+", response complete="+_responseComplete+" "+_exchange); super.onRequestComplete(); } } @Override public void onResponseComplete() throws IOException { _responseComplete = true; if (_needIntercept) { if (_requestComplete && _responseComplete) { if (LOG.isDebugEnabled()) LOG.debug("onResponseComplete, Both complete: Resending from onResponseComplete"+_exchange); _responseComplete = false; _requestComplete = false; setDelegatingResponses(true); setDelegatingRequests(true); _destination.resend(_exchange); } else { if (LOG.isDebugEnabled()) LOG.debug("onResponseComplete, Request not yet complete from onResponseComplete, calling super "+_exchange); super.onResponseComplete(); } } else { if (LOG.isDebugEnabled()) LOG.debug("OnResponseComplete, delegating to super with Request complete="+_requestComplete+", response complete="+_responseComplete+" "+_exchange); super.onResponseComplete(); } } @Override public void onRetry() { _attempts++; setDelegatingRequests(true); setDelegatingResponses(true); _requestComplete=false; _responseComplete=false; _needIntercept=false; super.onRetry(); } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/security/SimpleRealmResolver.java000066400000000000000000000024111174773561500333350ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.security; import java.io.IOException; import org.eclipse.jetty.client.HttpDestination; /** * Simple Realm Resolver. *

A Realm Resolver that wraps a single realm. * * */ public class SimpleRealmResolver implements RealmResolver { private Realm _realm; public SimpleRealmResolver( Realm realm ) { _realm=realm; } public Realm getRealm( String realmName, HttpDestination destination, String path ) throws IOException { return _realm; } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/webdav/000077500000000000000000000000001174773561500261415ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/webdav/MkcolExchange.java000066400000000000000000000036431174773561500315220ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.webdav; import java.io.IOException; import org.eclipse.jetty.client.CachedExchange; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public class MkcolExchange extends CachedExchange { private static final Logger LOG = Log.getLogger(MkcolExchange.class); boolean exists = false; public MkcolExchange() { super(true); } /* ------------------------------------------------------------ */ @Override protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { if ( status == HttpStatus.CREATED_201 ) { LOG.debug( "MkcolExchange:Status: Successfully created resource" ); exists = true; } if ( status == HttpStatus.METHOD_NOT_ALLOWED_405 ) // returned when resource exists { LOG.debug( "MkcolExchange:Status: Resource must exist" ); exists = true; } super.onResponseStatus(version, status, reason); } public boolean exists() { return exists; } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/webdav/PropfindExchange.java000066400000000000000000000033711174773561500322340ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.webdav; import java.io.IOException; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public class PropfindExchange extends HttpExchange { private static final Logger LOG = Log.getLogger(PropfindExchange.class); boolean _propertyExists = false; /* ------------------------------------------------------------ */ @Override protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { if ( status == HttpStatus.OK_200 ) { LOG.debug( "PropfindExchange:Status: Exists" ); _propertyExists = true; } else { LOG.debug( "PropfindExchange:Status: Not Exists" ); } super.onResponseStatus(version, status, reason); } public boolean exists() { return _propertyExists; } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/webdav/WebdavListener.java000066400000000000000000000251711174773561500317300ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.webdav; import java.io.IOException; import org.eclipse.jetty.client.HttpDestination; import org.eclipse.jetty.client.HttpEventListenerWrapper; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.client.security.SecurityListener; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * WebdavListener * * * * */ public class WebdavListener extends HttpEventListenerWrapper { private static final Logger LOG = Log.getLogger(WebdavListener.class); private HttpDestination _destination; private HttpExchange _exchange; private boolean _requestComplete; private boolean _responseComplete; private boolean _webdavEnabled; private boolean _needIntercept; public WebdavListener(HttpDestination destination, HttpExchange ex) { // Start of sending events through to the wrapped listener // Next decision point is the onResponseStatus super(ex.getEventListener(),true); _destination=destination; _exchange=ex; // We'll only enable webdav if this is a PUT request if ( HttpMethods.PUT.equalsIgnoreCase( _exchange.getMethod() ) ) { _webdavEnabled = true; } } @Override public void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { if ( !_webdavEnabled ) { _needIntercept = false; super.onResponseStatus(version, status, reason); return; } if (LOG.isDebugEnabled()) LOG.debug("WebdavListener:Response Status: " + status ); // The dav spec says that CONFLICT should be returned when the parent collection doesn't exist but I am seeing // FORBIDDEN returned instead so running with that. if ( status == HttpStatus.FORBIDDEN_403 || status == HttpStatus.CONFLICT_409 ) { if ( _webdavEnabled ) { if (LOG.isDebugEnabled()) LOG.debug("WebdavListener:Response Status: dav enabled, taking a stab at resolving put issue" ); setDelegatingResponses( false ); // stop delegating, we can try and fix this request _needIntercept = true; } else { if (LOG.isDebugEnabled()) LOG.debug("WebdavListener:Response Status: Webdav Disabled" ); setDelegatingResponses( true ); // just make sure we delegate setDelegatingRequests( true ); _needIntercept = false; } } else { _needIntercept = false; setDelegatingResponses( true ); setDelegatingRequests( true ); } super.onResponseStatus(version, status, reason); } @Override public void onResponseComplete() throws IOException { _responseComplete = true; if (_needIntercept) { if ( _requestComplete && _responseComplete) { try { // we have some work to do before retrying this if ( resolveCollectionIssues() ) { setDelegatingRequests( true ); setDelegatingResponses(true); _requestComplete = false; _responseComplete = false; _destination.resend(_exchange); } else { // admit defeat but retry because someone else might have setDelegationResult(false); setDelegatingRequests( true ); setDelegatingResponses(true); super.onResponseComplete(); } } catch ( IOException ioe ) { LOG.debug("WebdavListener:Complete:IOException: might not be dealing with dav server, delegate"); super.onResponseComplete(); } } else { if (LOG.isDebugEnabled()) LOG.debug("WebdavListener:Not ready, calling super"); super.onResponseComplete(); } } else { super.onResponseComplete(); } } @Override public void onRequestComplete () throws IOException { _requestComplete = true; if (_needIntercept) { if ( _requestComplete && _responseComplete) { try { // we have some work to do before retrying this if ( resolveCollectionIssues() ) { setDelegatingRequests( true ); setDelegatingResponses(true); _requestComplete = false; _responseComplete = false; _destination.resend(_exchange); } else { // admit defeat but retry because someone else might have setDelegatingRequests( true ); setDelegatingResponses(true); super.onRequestComplete(); } } catch ( IOException ioe ) { LOG.debug("WebdavListener:Complete:IOException: might not be dealing with dav server, delegate"); super.onRequestComplete(); } } else { if (LOG.isDebugEnabled()) LOG.debug("WebdavListener:Not ready, calling super"); super.onRequestComplete(); } } else { super.onRequestComplete(); } } /** * walk through the steps to try and resolve missing parent collection issues via webdav * * TODO this really ought to use URI itself for this resolution * * @return * @throws IOException */ private boolean resolveCollectionIssues() throws IOException { String uri = _exchange.getURI(); String[] uriCollection = _exchange.getURI().split("/"); int checkNum = uriCollection.length; int rewind = 0; String parentUri = URIUtil.parentPath( uri ); while ( parentUri != null && !checkExists(parentUri) ) { ++rewind; parentUri = URIUtil.parentPath( parentUri ); } // confirm webdav is supported for this collection if ( checkWebdavSupported() ) { for (int i = 0; i < rewind;) { makeCollection(parentUri + "/" + uriCollection[checkNum - rewind - 1]); parentUri = parentUri + "/" + uriCollection[checkNum - rewind - 1]; --rewind; } } else { return false; } return true; } private boolean checkExists( String uri ) throws IOException { if (uri == null) { System.out.println("have failed miserably"); return false; } PropfindExchange propfindExchange = new PropfindExchange(); propfindExchange.setAddress( _exchange.getAddress() ); propfindExchange.setMethod( HttpMethods.GET ); // PROPFIND acts wonky, just use get propfindExchange.setScheme( _exchange.getScheme() ); propfindExchange.setEventListener( new SecurityListener( _destination, propfindExchange ) ); propfindExchange.setConfigureListeners( false ); propfindExchange.setRequestURI( uri ); _destination.send( propfindExchange ); try { propfindExchange.waitForDone(); return propfindExchange.exists(); } catch ( InterruptedException ie ) { LOG.ignore( ie ); return false; } } private boolean makeCollection( String uri ) throws IOException { MkcolExchange mkcolExchange = new MkcolExchange(); mkcolExchange.setAddress( _exchange.getAddress() ); mkcolExchange.setMethod( "MKCOL " + uri + " HTTP/1.1" ); mkcolExchange.setScheme( _exchange.getScheme() ); mkcolExchange.setEventListener( new SecurityListener( _destination, mkcolExchange ) ); mkcolExchange.setConfigureListeners( false ); mkcolExchange.setRequestURI( uri ); _destination.send( mkcolExchange ); try { mkcolExchange.waitForDone(); return mkcolExchange.exists(); } catch ( InterruptedException ie ) { LOG.ignore( ie ); return false; } } private boolean checkWebdavSupported() throws IOException { WebdavSupportedExchange supportedExchange = new WebdavSupportedExchange(); supportedExchange.setAddress( _exchange.getAddress() ); supportedExchange.setMethod( HttpMethods.OPTIONS ); supportedExchange.setScheme( _exchange.getScheme() ); supportedExchange.setEventListener( new SecurityListener( _destination, supportedExchange ) ); supportedExchange.setConfigureListeners( false ); supportedExchange.setRequestURI( _exchange.getURI() ); _destination.send( supportedExchange ); try { supportedExchange.waitTilCompletion(); return supportedExchange.isWebdavSupported(); } catch (InterruptedException ie ) { LOG.ignore( ie ); return false; } } } jetty8-8.1.3/jetty-client/src/main/java/org/eclipse/jetty/client/webdav/WebdavSupportedExchange.java000066400000000000000000000042311174773561500335650ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.webdav; import java.io.IOException; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public class WebdavSupportedExchange extends HttpExchange { private static final Logger LOG = Log.getLogger(WebdavSupportedExchange.class); private boolean _webdavSupported = false; private boolean _isComplete = false; @Override protected void onResponseHeader(Buffer name, Buffer value) throws IOException { if (LOG.isDebugEnabled()) LOG.debug("WebdavSupportedExchange:Header:" + name.toString() + " / " + value.toString() ); if ( "DAV".equals( name.toString() ) ) { if ( value.toString().indexOf( "1" ) >= 0 || value.toString().indexOf( "2" ) >= 0 ) { _webdavSupported = true; } } super.onResponseHeader(name, value); } public void waitTilCompletion() throws InterruptedException { synchronized (this) { while ( !_isComplete) { this.wait(); } } } @Override protected void onResponseComplete() throws IOException { _isComplete = true; super.onResponseComplete(); } public boolean isWebdavSupported() { return _webdavSupported; } } jetty8-8.1.3/jetty-client/src/test/000077500000000000000000000000001174773561500171535ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/000077500000000000000000000000001174773561500200745ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/000077500000000000000000000000001174773561500206635ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/000077500000000000000000000000001174773561500223075ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500234465ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/000077500000000000000000000000001174773561500247245ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractConnectionTest.java000066400000000000000000000343041174773561500322160ustar00rootroot00000000000000/* * Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.junit.Test; /** * @version $Revision$ $Date$ */ public abstract class AbstractConnectionTest { protected HttpClient newHttpClient() { HttpClient httpClient = new HttpClient(); // httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET); return httpClient; } protected ServerSocket newServerSocket() throws IOException { ServerSocket serverSocket=new ServerSocket(); serverSocket.bind(null); return serverSocket; } @Test public void testServerClosedConnection() throws Exception { ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(null); int port=serverSocket.getLocalPort(); HttpClient httpClient = newHttpClient(); httpClient.setMaxConnectionsPerAddress(1); httpClient.start(); try { CountDownLatch latch = new CountDownLatch(1); HttpExchange exchange = new ConnectionExchange(latch); exchange.setAddress(new Address("localhost", port)); exchange.setRequestURI("/"); httpClient.send(exchange); Socket remote = serverSocket.accept(); // HttpClient.send() above is async, so if we write the response immediately // there is a chance that it arrives before the request is being sent, so we // read the request before sending the response to avoid the race InputStream input = remote.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); String line; while ((line = reader.readLine()) != null) { if (line.length() == 0) break; } OutputStream output = remote.getOutputStream(); output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8")); output.write("Content-Length: 0\r\n".getBytes("UTF-8")); output.write("\r\n".getBytes("UTF-8")); output.flush(); assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); remote.close(); // Need to wait a bit to allow the client to detect // that the server has closed the connection Thread.sleep(500); // The server has closed the connection and another attempt to send // with the same connection would fail because the connection has been // closed by the client as well. // The client must open a new connection in this case, and we check // that the new request completes correctly exchange.reset(); httpClient.send(exchange); remote = serverSocket.accept(); input = remote.getInputStream(); reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); while ((line = reader.readLine()) != null) { if (line.length() == 0) break; } output = remote.getOutputStream(); output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8")); output.write("Content-Length: 0\r\n".getBytes("UTF-8")); output.write("\r\n".getBytes("UTF-8")); output.flush(); assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); } finally { httpClient.stop(); } } protected String getScheme() { return "http"; } @Test public void testServerClosedIncomplete() throws Exception { ServerSocket serverSocket = newServerSocket(); int port=serverSocket.getLocalPort(); HttpClient httpClient = newHttpClient(); httpClient.setMaxConnectionsPerAddress(1); httpClient.start(); try { CountDownLatch latch = new CountDownLatch(1); HttpExchange exchange = new ConnectionExchange(latch); exchange.setScheme(getScheme()); exchange.setAddress(new Address("localhost", port)); exchange.setRequestURI("/"); httpClient.send(exchange); Socket remote = serverSocket.accept(); // HttpClient.send() above is async, so if we write the response immediately // there is a chance that it arrives before the request is being sent, so we // read the request before sending the response to avoid the race InputStream input = remote.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); String line; while ((line = reader.readLine()) != null) { if (line.length() == 0) break; } OutputStream output = remote.getOutputStream(); output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8")); output.write("Content-Length: 10\r\n".getBytes("UTF-8")); output.write("\r\n".getBytes("UTF-8")); output.flush(); remote.close(); int status = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_EXCEPTED, status); } finally { httpClient.stop(); } } @Test public void testServerHalfClosedIncomplete() throws Exception { ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(null); int port=serverSocket.getLocalPort(); HttpClient httpClient = newHttpClient(); httpClient.setIdleTimeout(10000); httpClient.setMaxConnectionsPerAddress(1); httpClient.start(); try { CountDownLatch latch = new CountDownLatch(1); HttpExchange exchange = new ConnectionExchange(latch); exchange.setAddress(new Address("localhost", port)); exchange.setRequestURI("/"); httpClient.send(exchange); Socket remote = serverSocket.accept(); // HttpClient.send() above is async, so if we write the response immediately // there is a chance that it arrives before the request is being sent, so we // read the request before sending the response to avoid the race InputStream input = remote.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); String line; while ((line = reader.readLine()) != null) { if (line.length() == 0) break; } OutputStream output = remote.getOutputStream(); output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8")); output.write("Content-Length: 10\r\n".getBytes("UTF-8")); output.write("\r\n".getBytes("UTF-8")); output.flush(); remote.shutdownOutput(); assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.waitForDone()); } finally { httpClient.stop(); } } @Test public void testConnectionFailed() throws Exception { ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(null); int port=serverSocket.getLocalPort(); serverSocket.close(); HttpClient httpClient = newHttpClient(); httpClient.start(); try { CountDownLatch latch = new CountDownLatch(1); HttpExchange exchange = new ConnectionExchange(latch); exchange.setAddress(new Address("localhost", port)); exchange.setRequestURI("/"); httpClient.send(exchange); boolean passed = latch.await(4000, TimeUnit.MILLISECONDS); assertTrue(passed); long wait = 100; long maxWait = 10 * wait; long curWait = wait; while (curWait < maxWait && !exchange.isDone()) { Thread.sleep(wait); curWait += wait; } assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.getStatus()); } finally { httpClient.stop(); } } @Test public void testMultipleConnectionsFailed() throws Exception { ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(null); int port=serverSocket.getLocalPort(); serverSocket.close(); HttpClient httpClient = newHttpClient(); httpClient.setMaxConnectionsPerAddress(1); httpClient.start(); try { HttpExchange[] exchanges = new HttpExchange[20]; final CountDownLatch latch = new CountDownLatch(exchanges.length); for (int i = 0; i < exchanges.length; ++i) { HttpExchange exchange = new HttpExchange() { @Override protected void onConnectionFailed(Throwable x) { latch.countDown(); } }; exchange.setAddress(new Address("localhost", port)); exchange.setRequestURI("/"); exchanges[i] = exchange; } for (HttpExchange exchange : exchanges) httpClient.send(exchange); for (HttpExchange exchange : exchanges) assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.waitForDone()); assertTrue(latch.await(1000, TimeUnit.MILLISECONDS)); } finally { httpClient.stop(); } } @Test public void testConnectionTimeout() throws Exception { HttpClient httpClient = newHttpClient(); int connectTimeout = 5000; httpClient.setConnectTimeout(connectTimeout); httpClient.start(); try { CountDownLatch latch = new CountDownLatch(1); HttpExchange exchange = new ConnectionExchange(latch); // Using a IP address has a different behavior than using a host name exchange.setAddress(new Address("127.0.0.1", 1)); exchange.setRequestURI("/"); httpClient.send(exchange); boolean passed = latch.await(connectTimeout * 2L, TimeUnit.MILLISECONDS); assertTrue(passed); int status = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_EXCEPTED, status); } finally { httpClient.stop(); } } @Test public void testIdleConnection() throws Exception { ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(null); int port=serverSocket.getLocalPort(); HttpClient httpClient = newHttpClient(); httpClient.setIdleTimeout(700); httpClient.start(); try { HttpExchange exchange = new ConnectionExchange(); exchange.setAddress(new Address("localhost", port)); exchange.setRequestURI("/"); HttpDestination dest = httpClient.getDestination(new Address("localhost", port),false); httpClient.send(exchange); Socket server = serverSocket.accept(); server.setSoTimeout(5000); byte[] buf = new byte[4096]; int len=server.getInputStream().read(buf); assertEquals(1,dest.getConnections()); assertEquals(0,dest.getIdleConnections()); server.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes()); assertEquals(HttpExchange.STATUS_COMPLETED,exchange.waitForDone()); Thread.sleep(200); // TODO get rid of this assertEquals(1,dest.getConnections()); assertEquals(1,dest.getIdleConnections()); exchange = new ConnectionExchange(); exchange.setAddress(new Address("localhost", port)); exchange.setRequestURI("/"); httpClient.send(exchange); assertEquals(1,dest.getConnections()); assertEquals(0,dest.getIdleConnections()); len=server.getInputStream().read(buf); assertEquals(1,dest.getConnections()); assertEquals(0,dest.getIdleConnections()); server.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes()); Thread.sleep(500); assertEquals(1,dest.getConnections()); assertEquals(1,dest.getIdleConnections()); Thread.sleep(500); assertEquals(0,dest.getConnections()); assertEquals(0,dest.getIdleConnections()); serverSocket.close(); } finally { httpClient.stop(); } } protected class ConnectionExchange extends HttpExchange { private final CountDownLatch latch; protected ConnectionExchange() { this.latch = null; } protected ConnectionExchange(CountDownLatch latch) { this.latch = latch; } @Override protected void onConnectionFailed(Throwable ex) { if (latch!=null) latch.countDown(); } @Override protected void onException(Throwable x) { if (latch!=null) latch.countDown(); } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpExchangeCancelTest.java000066400000000000000000000415321174773561500336100ustar00rootroot00000000000000/* * Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package org.eclipse.jetty.client; import java.io.IOException; import java.net.SocketTimeoutException; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.server.AbstractHttpConnection; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.StdErrLog; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; /** */ public abstract class AbstractHttpExchangeCancelTest { private Server server; private Connector connector; @Before public void setUp() throws Exception { server = new Server(); connector = new SelectChannelConnector(); server.addConnector(connector); server.setHandler(new EmptyHandler()); server.start(); } @After public void tearDown() throws Exception { server.stop(); server.join(); } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeCancelOnSend1() throws Exception { // One of the first things that HttpClient.send() does // is to change the status of the exchange // We exploit that to be sure the exchange is canceled // without race conditions TestHttpExchange exchange = new TestHttpExchange() { @Override boolean setStatus(int status) { // Cancel before setting the new status if (getStatus() == HttpExchange.STATUS_START && status == STATUS_WAITING_FOR_CONNECTION) cancel(); return super.setStatus(status); } }; exchange.setAddress(newAddress()); exchange.setRequestURI("/"); getHttpClient().send(exchange); // Cancelling here is wrong and makes the test fail spuriously // due to a race condition with send(): the send() can complete // before the exchange is canceled so it will be in STATUS_COMPLETE // which will fail the test. // exchange.cancel(); int status = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_CANCELLED, status); assertFalse(exchange.isResponseCompleted()); assertFalse(exchange.isFailed()); assertFalse(exchange.isAssociated()); } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeCancelOnSend2() throws Exception { // One of the first things that HttpClient.send() does // is to change the status of the exchange // We exploit that to be sure the exchange is canceled // without race conditions TestHttpExchange exchange = new TestHttpExchange() { @Override boolean setStatus(int status) { // Cancel after setting the new status int oldStatus = getStatus(); boolean set = super.setStatus(status); if (oldStatus == STATUS_START && getStatus() == HttpExchange.STATUS_WAITING_FOR_CONNECTION) cancel(); return set; } }; exchange.setAddress(newAddress()); exchange.setRequestURI("/"); getHttpClient().send(exchange); // Cancelling here is wrong and makes the test fail spuriously // due to a race condition with send(): the send() can complete // before the exchange is canceled so it will be in STATUS_COMPLETE // which will fail the test. // exchange.cancel(); int status = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_CANCELLED, status); assertFalse(exchange.isResponseCompleted()); assertFalse(exchange.isFailed()); assertFalse(exchange.isAssociated()); } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeCancelOnRequestCommitted() throws Exception { TestHttpExchange exchange = new TestHttpExchange() { @Override protected void onRequestCommitted() throws IOException { super.onRequestCommitted(); cancel(); } }; exchange.setAddress(newAddress()); exchange.setRequestURI("/"); getHttpClient().send(exchange); int status = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_CANCELLED, status); assertFalse(exchange.isResponseCompleted()); assertFalse(exchange.isFailed()); assertFalse(exchange.isAssociated()); } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeCancelOnRequestComplete() throws Exception { TestHttpExchange exchange = new TestHttpExchange() { @Override protected void onRequestComplete() throws IOException { super.onRequestComplete(); cancel(); } }; exchange.setAddress(newAddress()); exchange.setRequestURI("/"); getHttpClient().send(exchange); int status = exchange.waitForDone(); assertThat("Exchange Status", status, is(HttpExchange.STATUS_CANCELLED)); assertThat("Exchange.isResponseCompleted", exchange.isResponseCompleted(), is(false)); assertThat("Exchange.isFailed", exchange.isFailed(), is(false)); assertThat("Exchange.isAssociated", exchange.isAssociated(), is(false)); } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeCancelOnResponseStatus() throws Exception { TestHttpExchange exchange = new TestHttpExchange() { @Override protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { super.onResponseStatus(version, status, reason); cancel(); } }; exchange.setAddress(newAddress()); exchange.setRequestURI("/"); getHttpClient().send(exchange); int status = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_CANCELLED, status); assertFalse(exchange.isResponseCompleted()); assertFalse(exchange.isFailed()); assertFalse(exchange.isAssociated()); } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeCancelOnResponseHeader() throws Exception { TestHttpExchange exchange = new TestHttpExchange() { @Override protected void onResponseHeader(Buffer name, Buffer value) throws IOException { super.onResponseHeader(name, value); cancel(); } }; exchange.setAddress(newAddress()); exchange.setRequestURI("/"); getHttpClient().send(exchange); int status = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_CANCELLED, status); assertFalse(exchange.isResponseCompleted()); assertFalse(exchange.isFailed()); assertFalse(exchange.isAssociated()); } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeCancelOnResponseHeadersComplete() throws Exception { TestHttpExchange exchange = new TestHttpExchange() { @Override protected void onResponseHeaderComplete() throws IOException { super.onResponseHeaderComplete(); cancel(); } }; exchange.setAddress(newAddress()); exchange.setRequestURI("/"); getHttpClient().send(exchange); int status = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_CANCELLED, status); assertFalse(exchange.isResponseCompleted()); assertFalse(exchange.isFailed()); assertFalse(exchange.isAssociated()); } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeCancelOnResponseContent() throws Exception { TestHttpExchange exchange = new TestHttpExchange() { @Override protected void onResponseContent(Buffer content) throws IOException { super.onResponseContent(content); cancel(); } }; exchange.setAddress(newAddress()); exchange.setRequestURI("/?action=body"); getHttpClient().send(exchange); int status = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_CANCELLED, status); assertFalse(exchange.isResponseCompleted()); assertFalse(exchange.isFailed()); assertFalse(exchange.isAssociated()); } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeCancelOnResponseComplete() throws Exception { TestHttpExchange exchange = new TestHttpExchange() { @Override protected void onResponseComplete() throws IOException { super.onResponseComplete(); cancel(); } }; exchange.setAddress(newAddress()); exchange.setRequestURI("/"); getHttpClient().send(exchange); int status = exchange.waitForDone(); assertTrue(exchange.isResponseCompleted()); assertFalse(exchange.isFailed()); assertFalse(exchange.isAssociated()); assertEquals(HttpExchange.STATUS_COMPLETED, status); } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeOnServerException() throws Exception { try { ((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(true); TestHttpExchange exchange = new TestHttpExchange(); exchange.setAddress(newAddress()); exchange.setRequestURI("/?action=throw"); getHttpClient().send(exchange); int status = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_COMPLETED, status); assertTrue(exchange.isResponseCompleted()); assertFalse(exchange.isFailed()); assertFalse(exchange.isAssociated()); } finally { ((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(false); } } /* ------------------------------------------------------------ */ @Test public void testHttpExchangeOnExpire() throws Exception { HttpClient httpClient = getHttpClient(); httpClient.stop(); httpClient.setTimeout(1000); httpClient.start(); TestHttpExchange exchange = new TestHttpExchange(); exchange.setAddress(newAddress()); exchange.setRequestURI("/?action=wait5000"); long start = System.currentTimeMillis(); httpClient.send(exchange); int status = exchange.waitForDone(); long end = System.currentTimeMillis(); assertTrue(HttpExchange.STATUS_EXPIRED==status||HttpExchange.STATUS_EXCEPTED==status); assertFalse(exchange.isResponseCompleted()); assertTrue(end-start<4000); assertTrue(exchange.isExpired()); assertFalse(exchange.isFailed()); assertFalse(exchange.isAssociated()); } @Test public void testHttpExchangeCancelReturnsConnection() throws Exception { TestHttpExchange exchange = new TestHttpExchange(); Address address = newAddress(); exchange.setAddress(address); long delay = 5000; exchange.setRequestURI("/?action=wait" + delay); HttpClient httpClient = getHttpClient(); HttpDestination destination = httpClient.getDestination(address, false); int connections = destination.getConnections(); httpClient.send(exchange); Thread.sleep(delay / 2); Assert.assertEquals(connections + 1, destination.getConnections()); exchange.cancel(); Assert.assertEquals(connections, destination.getConnections()); } /* ------------------------------------------------------------ */ protected abstract HttpClient getHttpClient(); /* ------------------------------------------------------------ */ protected Address newAddress() { return new Address("localhost", connector.getLocalPort()); } /* ------------------------------------------------------------ */ private static class EmptyHandler extends AbstractHandler { /* ------------------------------------------------------------ */ public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { request.setHandled(true); String action = httpRequest.getParameter("action"); if (action != null) { if ("body".equals(action)) { ServletOutputStream output = httpResponse.getOutputStream(); output.write("body".getBytes("UTF-8")); // output.flush(); } else if ("throw".equals(action)) { throw new ServletException(); } else if (action.startsWith("wait")) { long sleep = Long.valueOf(action.substring("wait".length())); long start=System.currentTimeMillis(); try { Thread.sleep(sleep); long end=System.currentTimeMillis(); assertTrue("Duration "+(end-start)+" >~ "+sleep,(end-start)>sleep-100); } catch (InterruptedException x) { Thread.currentThread().interrupt(); } } } } } /* ------------------------------------------------------------ */ protected static class TestHttpExchange extends ContentExchange { private boolean responseCompleted; private boolean failed = false; private boolean expired = false; /* ------------------------------------------------------------ */ protected TestHttpExchange() { super(true); } /* ------------------------------------------------------------ */ @Override protected synchronized void onResponseComplete() throws IOException { this.responseCompleted = true; } /* ------------------------------------------------------------ */ public synchronized boolean isResponseCompleted() { return responseCompleted; } /* ------------------------------------------------------------ */ @Override protected synchronized void onException(Throwable ex) { LOG.debug(ex); if (ex instanceof SocketTimeoutException || ex.getCause() instanceof SocketTimeoutException) expired=true; else failed = true; } /* ------------------------------------------------------------ */ public synchronized boolean isFailed() { return failed; } /* ------------------------------------------------------------ */ @Override protected synchronized void onExpire() { this.expired = true; } /* ------------------------------------------------------------ */ public synchronized boolean isExpired() { return expired; } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncCallbackHttpExchangeTest.java000066400000000000000000000073431174773561500334330ustar00rootroot00000000000000/* * Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package org.eclipse.jetty.client; import static org.junit.Assert.assertNull; import java.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; /* ------------------------------------------------------------ */ /** * @version $Revision$ $Date$ */ public class AsyncCallbackHttpExchangeTest { /* ------------------------------------------------------------ */ /** * If the HttpExchange callbacks are called holding the lock on HttpExchange, * it will be impossible for the callback to perform some work asynchronously * and contemporarly accessing the HttpExchange instance synchronized state. * This test verifies that this situation does not happen. * * @throws Exception if the test fails */ @Test public void testAsyncCallback() throws Exception { ExecutorService executor = Executors.newCachedThreadPool(); try { AtomicReference failure = new AtomicReference(); TestHttpExchange exchange = new TestHttpExchange(executor, failure); exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_COMMIT); exchange.setStatus(HttpExchange.STATUS_SENDING_REQUEST); // This status change triggers onRequestCommitted() exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE); assertNull(failure.get()); } finally { executor.shutdown(); } } /* ------------------------------------------------------------ */ private class TestHttpExchange extends HttpExchange { private final ExecutorService executor; private final AtomicReference failure; /* ------------------------------------------------------------ */ private TestHttpExchange(ExecutorService executor, AtomicReference failure) { this.executor = executor; this.failure = failure; } /* ------------------------------------------------------------ */ @Override protected void onRequestCommitted() throws IOException { Future future = executor.submit(new Callable() { /* ------------------------------------------------------------ */ public Integer call() throws Exception { // Method getStatus() reads synchronized state return TestHttpExchange.this.getStatus(); } }); // We're waiting for the future to complete, thus never exiting // this method; if this method is called with the lock held, // this method never completes try { future.get(1000, TimeUnit.MILLISECONDS); // Test green here } catch (Exception x) { // Timed out, the test did not pass failure.set(x); } } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSelectConnectionTest.java000066400000000000000000000041271174773561500326700ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import java.net.ServerSocket; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.BeforeClass; public class AsyncSelectConnectionTest extends AbstractConnectionTest { protected HttpClient newHttpClient() { HttpClient httpClient = new HttpClient(); httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); httpClient.setConnectBlocking(false); return httpClient; } static SslContextFactory ctx = new SslContextFactory(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath()); @BeforeClass public static void initKS() throws Exception { ctx.setKeyStorePassword("storepwd"); ctx.setKeyManagerPassword("keypwd"); ctx.start(); } @Override protected String getScheme() { return "https"; } @Override protected ServerSocket newServerSocket() throws IOException { return ctx.newSslServerSocket(null,0,100); } @Override public void testServerHalfClosedIncomplete() throws Exception { // SSL doesn't do half closes } @Override public void testServerClosedIncomplete() throws Exception { super.testServerClosedIncomplete(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSslHttpExchangeTest.java000066400000000000000000000032351174773561500324740ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import org.eclipse.jetty.client.helperClasses.AsyncSslServerAndClientCreator; import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator; import org.junit.Before; import org.junit.Test; public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest { private static ServerAndClientCreator serverAndClientCreator = new AsyncSslServerAndClientCreator(); @Before public void setUpOnce() throws Exception { _scheme="https"; _server = serverAndClientCreator.createServer(); _httpClient = serverAndClientCreator.createClient(3000L,3500L,2000); _port = _server.getConnectors()[0].getLocalPort(); } @Test public void testPerf1() throws Exception { sender(1,true); } @Override public void testBigPostWithContentExchange() throws Exception { super.testBigPostWithContentExchange(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSslSecurityListenerTest.java000066400000000000000000000022441174773561500334260ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import org.junit.Before; /* ------------------------------------------------------------ */ public class AsyncSslSecurityListenerTest extends SslSecurityListenerTest { /* ------------------------------------------------------------ */ @Before @Override public void setUp() throws Exception { _type = HttpClient.CONNECTOR_SELECT_CHANNEL; super.setUp(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/BlockingHttpExchangeCancelTest.java000066400000000000000000000027751174773561500336030ustar00rootroot00000000000000/* * Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package org.eclipse.jetty.client; import org.junit.After; import org.junit.Before; /* ------------------------------------------------------------ */ /** * @version $Revision$ $Date$ */ public class BlockingHttpExchangeCancelTest extends AbstractHttpExchangeCancelTest { private HttpClient httpClient; /* ------------------------------------------------------------ */ @Before @Override public void setUp() throws Exception { super.setUp(); httpClient = new HttpClient(); httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET); httpClient.start(); } /* ------------------------------------------------------------ */ @After @Override public void tearDown() throws Exception { httpClient.stop(); super.tearDown(); } /* ------------------------------------------------------------ */ @Override protected HttpClient getHttpClient() { return httpClient; } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/CachedHeadersIsolationTest.java000066400000000000000000000071251174773561500327610ustar00rootroot00000000000000package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.junit.After; import org.junit.Before; import org.junit.Test; /* ------------------------------------------------------------ */ public class CachedHeadersIsolationTest { Server server; HttpClient client; int port; @Before public void setUp() throws Exception { server = new Server(); Connector connector = new SelectChannelConnector(); server.addConnector(connector); server.setHandler(new AbstractHandler() { /* ------------------------------------------------------------ */ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setStatus(HttpStatus.OK_200); response.addHeader("For",request.getQueryString()); response.addHeader("Name","Value"); response.getOutputStream().print("blah"); response.flushBuffer(); } }); server.start(); port = server.getConnectors()[0].getLocalPort(); client = new HttpClient(); client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); client.setConnectTimeout(5); client.start(); } /* ------------------------------------------------------------ */ @After public void tearDown() throws Exception { server.stop(); client.stop(); } /* ------------------------------------------------------------ */ @Test public void testHeaderWhenReadEarly() throws Exception { CachedExchange e1 = new CachedExchange(true); CachedExchange e2 = new CachedExchange(true); e1.setURL("http://localhost:" + port + "/?a=short"); e2.setURL("http://localhost:" + port + "/?a=something_longer"); client.send(e1); while (!e1.isDone()) Thread.sleep(100); assertEquals("Read buffer","Value",e1.getResponseFields().getStringField("Name")); client.send(e2); while (!e2.isDone()) Thread.sleep(100); assertEquals("Overwritten buffer","Value",e1.getResponseFields().getStringField("Name")); } /* ------------------------------------------------------------ */ @Test public void testHeaderWhenReadLate() throws Exception { CachedExchange e1 = new CachedExchange(true); CachedExchange e2 = new CachedExchange(true); e1.setURL("http://localhost:" + port + "/?a=short"); e2.setURL("http://localhost:" + port + "/?a=something_longer"); client.send(e1); while (!e1.isDone()) Thread.sleep(100); client.send(e2); while (!e2.isDone()) Thread.sleep(100); for ( Enumeration e = e1.getResponseFields().getValues("Name"); e.hasMoreElements();) { System.out.println(e.nextElement()); } assertEquals("Overwritten buffer","Value",e1.getResponseFields().getStringField("Name")); } }jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java000066400000000000000000000305751174773561500315160ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLDecoder; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.client.security.SimpleRealmResolver; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.IO; import org.junit.After; import org.junit.Before; import org.junit.Test; public class ContentExchangeTest { private static String _content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+ "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+ "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+ "Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+ "at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+ "velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+ "Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+ "eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+ "sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+ "consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+ "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+ "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque."; private File _docRoot; private Server _server; private HttpClient _client; private Realm _realm; private String _protocol; private String _baseUrl; private String _requestContent; /* ------------------------------------------------------------ */ @Before public void setUp() throws Exception { _docRoot = new File("target/test-output/docroot/"); _docRoot.mkdirs(); _docRoot.deleteOnExit(); File content = new File(_docRoot,"input.txt"); FileOutputStream out = new FileOutputStream(content); out.write(_content.getBytes("utf-8")); out.close(); _server = new Server(); configureServer(_server); _server.start(); int port = _server.getConnectors()[0].getLocalPort(); _baseUrl = _protocol+"://localhost:"+port+ "/"; } /* ------------------------------------------------------------ */ @After public void tearDown() throws Exception { if (_server != null) { _server.stop(); _server = null; } } /* ------------------------------------------------------------ */ @Test public void testPut() throws Exception { startClient(_realm); ContentExchange putExchange = new ContentExchange(); putExchange.setURL(getBaseUrl() + "output.txt"); putExchange.setMethod(HttpMethods.PUT); putExchange.setRequestContent(new ByteArrayBuffer(_content.getBytes())); _client.send(putExchange); int state = putExchange.waitForDone(); int responseStatus = putExchange.getResponseStatus(); stopClient(); boolean statusOk = (responseStatus == 200 || responseStatus == 201); assertTrue(statusOk); String content = IO.toString(new FileInputStream(new File(_docRoot,"output.txt"))); assertEquals(_content,content); } /* ------------------------------------------------------------ */ @Test public void testGet() throws Exception { startClient(_realm); ContentExchange getExchange = new ContentExchange(); getExchange.setURL(getBaseUrl() + "input.txt"); getExchange.setMethod(HttpMethods.GET); _client.send(getExchange); int state = getExchange.waitForDone(); String content = ""; int responseStatus = getExchange.getResponseStatus(); if (responseStatus == HttpStatus.OK_200) { content = getExchange.getResponseContent(); } stopClient(); assertEquals(HttpStatus.OK_200,responseStatus); assertEquals(_content,content); } /* ------------------------------------------------------------ */ @Test public void testHead() throws Exception { startClient(_realm); ContentExchange getExchange = new ContentExchange(); getExchange.setURL(getBaseUrl() + "input.txt"); getExchange.setMethod(HttpMethods.HEAD); _client.send(getExchange); getExchange.waitForDone(); int responseStatus = getExchange.getResponseStatus(); stopClient(); assertEquals(HttpStatus.OK_200,responseStatus); } /* ------------------------------------------------------------ */ @Test public void testPost() throws Exception { startClient(_realm); ContentExchange postExchange = new ContentExchange(); postExchange.setURL(getBaseUrl() + "test"); postExchange.setMethod(HttpMethods.POST); postExchange.setRequestContent(new ByteArrayBuffer(_content.getBytes())); _client.send(postExchange); int state = postExchange.waitForDone(); int responseStatus = postExchange.getResponseStatus(); stopClient(); assertEquals(HttpStatus.OK_200,responseStatus); assertEquals(_content,_requestContent); } /* ------------------------------------------------------------ */ protected void configureServer(Server server) throws Exception { setProtocol("http"); SelectChannelConnector connector = new SelectChannelConnector(); server.addConnector(connector); Handler handler = new TestHandler(getBasePath()); ServletContextHandler root = new ServletContextHandler(); root.setContextPath("/"); root.setResourceBase(_docRoot.getAbsolutePath()); ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); servletHolder.setInitParameter( "gzip", "true" ); root.addServlet( servletHolder, "/*" ); HandlerCollection handlers = new HandlerCollection(); handlers.setHandlers(new Handler[]{handler, root}); server.setHandler( handlers ); } /* ------------------------------------------------------------ */ protected void startClient(Realm realm) throws Exception { _client = new HttpClient(); configureClient(_client); if (realm != null) _client.setRealmResolver(new SimpleRealmResolver(realm)); _client.start(); } /* ------------------------------------------------------------ */ protected void configureClient(HttpClient client) throws Exception { client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); } /* ------------------------------------------------------------ */ protected void stopClient() throws Exception { if (_client != null) { _client.stop(); _client = null; } } /* ------------------------------------------------------------ */ protected String getBasePath() { return _docRoot.getAbsolutePath(); } /* ------------------------------------------------------------ */ protected String getBaseUrl() { return _baseUrl; } /* ------------------------------------------------------------ */ protected HttpClient getClient() { return _client; } /* ------------------------------------------------------------ */ protected Realm getRealm() { return _realm; } /* ------------------------------------------------------------ */ protected String getContent() { return _content; } /* ------------------------------------------------------------ */ protected void setProtocol(String protocol) { _protocol = protocol; } /* ------------------------------------------------------------ */ protected void setRealm(Realm realm) { _realm = realm; } /* ------------------------------------------------------------ */ public static void copyStream(InputStream in, OutputStream out) { try { byte[] buffer=new byte[1024]; int len; while ((len=in.read(buffer))>=0) { out.write(buffer,0,len); } } catch (EofException e) { System.err.println(e); } catch (IOException e) { e.printStackTrace(); } } /* ------------------------------------------------------------ */ protected class TestHandler extends AbstractHandler { private final String resourcePath; /* ------------------------------------------------------------ */ public TestHandler(String repositoryPath) { this.resourcePath = repositoryPath; } /* ------------------------------------------------------------ */ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (baseRequest.isHandled()) { return; } OutputStream out = null; if (baseRequest.getMethod().equals("PUT")) { baseRequest.setHandled(true); File file = new File(resourcePath, URLDecoder.decode(request.getPathInfo())); file.getParentFile().mkdirs(); file.deleteOnExit(); out = new FileOutputStream(file); response.setStatus(HttpServletResponse.SC_CREATED); } if (baseRequest.getMethod().equals("POST")) { baseRequest.setHandled(true); out = new ByteArrayOutputStream(); response.setStatus(HttpServletResponse.SC_OK); } if (out != null) { ServletInputStream in = request.getInputStream(); try { copyStream( in, out ); } finally { in.close(); out.close(); } if (!(out instanceof FileOutputStream)) _requestContent = out.toString(); } } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java000066400000000000000000000133321174773561500264760ustar00rootroot00000000000000package org.eclipse.jetty.client; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.io.Buffer; /* ------------------------------------------------------------ */ /** A simple test http client like curl. *

* Usage is java -cp $CLASSPATH org.eclipse.jetty.client.Curl [ option | URL ] ... * Options supported are:

    *
  • --async : The following URLs are fetched in parallel (default) *
  • --sync : The following URLs are fetched in sequence *
  • --dump : The content is dumped to stdout *
  • --nodump : The content is suppressed (default) *
*/ public class Curl { public static void main(String[] args) throws Exception { if (args.length==0) args=new String[] { "--sync", "http://www.sun.com/robots.txt", "http://www.sun.com/favicon.ico" , "--dump", "http://www.sun.com/robots.txt"}; HttpClient client = new HttpClient(); client.setIdleTimeout(2000); client.start(); boolean async=true; boolean dump= false; boolean verbose= false; int urls=0; for (String arg : args) { if (!arg.startsWith("-")) urls++; } final CountDownLatch latch = new CountDownLatch(urls); for (String arg : args) { if ("--verbose".equals(arg)) { verbose=true; continue; } if ("--sync".equals(arg)) { async=false; continue; } if ("--async".equals(arg)) { async=true; continue; } if ("--dump".equals(arg)) { dump=true; continue; } if ("--nodump".equals(arg)) { dump=false; continue; } final boolean d = dump; final boolean v = verbose; HttpExchange ex = new HttpExchange() { AtomicBoolean counted=new AtomicBoolean(false); @Override protected void onConnectionFailed(Throwable ex) { if (!counted.getAndSet(true)) latch.countDown(); super.onConnectionFailed(ex); } @Override protected void onException(Throwable ex) { if (!counted.getAndSet(true)) latch.countDown(); super.onException(ex); } @Override protected void onExpire() { if (!counted.getAndSet(true)) latch.countDown(); super.onExpire(); } @Override protected void onResponseComplete() throws IOException { if (!counted.getAndSet(true)) latch.countDown(); super.onResponseComplete(); } @Override protected void onResponseContent(Buffer content) throws IOException { super.onResponseContent(content); if (d) System.out.print(content.toString()); if (v) System.err.println("got "+content.length()); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onResponseHeader(org.eclipse.jetty.io.Buffer, org.eclipse.jetty.io.Buffer) */ @Override protected void onResponseHeader(Buffer name, Buffer value) throws IOException { super.onResponseHeader(name,value); if (v) System.err.println(name+": "+value); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onResponseHeaderComplete() */ @Override protected void onResponseHeaderComplete() throws IOException { super.onResponseHeaderComplete(); if (v) System.err.println(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.Buffer, int, org.eclipse.jetty.io.Buffer) */ @Override protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { super.onResponseStatus(version,status,reason); if (v) System.err.println(version+" "+status+" "+reason); } }; ex.setMethod(HttpMethods.GET); ex.setURL(arg); System.err.println("\nSending "+ex); client.send(ex); if (!async) { System.err.println("waiting..."); ex.waitForDone(); System.err.println("Done"); } } latch.await(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/ErrorStatusTest.java000066400000000000000000000212451174773561500307300ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.junit.Test; /* ------------------------------------------------------------ */ public class ErrorStatusTest extends ContentExchangeTest { /* ------------------------------------------------------------ */ @Test public void testPutBadRequest() throws Exception { doPutFail(HttpStatus.BAD_REQUEST_400); } /* ------------------------------------------------------------ */ @Test public void testPutUnauthorized() throws Exception { doPutFail(HttpStatus.UNAUTHORIZED_401); } /* ------------------------------------------------------------ */ @Test public void testPutForbidden() throws Exception { doPutFail(HttpStatus.FORBIDDEN_403); } /* ------------------------------------------------------------ */ @Test public void testPutNotFound() throws Exception { doPutFail(HttpStatus.NOT_FOUND_404); } /* ------------------------------------------------------------ */ @Test public void testPutServerError() throws Exception { doPutFail(HttpStatus.INTERNAL_SERVER_ERROR_500); } /* ------------------------------------------------------------ */ @Test public void testGetBadRequest() throws Exception { doGetFail(HttpStatus.BAD_REQUEST_400); } /* ------------------------------------------------------------ */ @Test public void testGetUnauthorized() throws Exception { doGetFail(HttpStatus.UNAUTHORIZED_401); } /* ------------------------------------------------------------ */ @Test public void testGetNotFound() throws Exception { doGetFail(HttpStatus.NOT_FOUND_404); } /* ------------------------------------------------------------ */ @Test public void testGetServerError() throws Exception { doGetFail(HttpStatus.INTERNAL_SERVER_ERROR_500); } /* ------------------------------------------------------------ */ @Test public void testPostBadRequest() throws Exception { doPostFail(HttpStatus.BAD_REQUEST_400); } /* ------------------------------------------------------------ */ @Test public void testPostUnauthorized() throws Exception { doPostFail(HttpStatus.UNAUTHORIZED_401); } /* ------------------------------------------------------------ */ @Test public void testPostForbidden() throws Exception { doPostFail(HttpStatus.FORBIDDEN_403); } /* ------------------------------------------------------------ */ @Test public void testPostNotFound() throws Exception { doPostFail(HttpStatus.NOT_FOUND_404); } /* ------------------------------------------------------------ */ @Test public void testPostServerError() throws Exception { doPostFail(HttpStatus.INTERNAL_SERVER_ERROR_500); } /* ------------------------------------------------------------ */ protected void doPutFail(int status) throws Exception { startClient(getRealm()); ContentExchange putExchange = new ContentExchange(); putExchange.setURL(getBaseUrl() + "output.txt"); putExchange.setMethod(HttpMethods.PUT); putExchange.setRequestHeader("X-Response-Status",Integer.toString(status)); putExchange.setRequestContent(new ByteArrayBuffer(getContent().getBytes())); getClient().send(putExchange); int state = putExchange.waitForDone(); int responseStatus = putExchange.getResponseStatus(); stopClient(); assertEquals(status, responseStatus); } /* ------------------------------------------------------------ */ protected void doGetFail(int status) throws Exception { startClient(getRealm()); ContentExchange getExchange = new ContentExchange(); getExchange.setURL(getBaseUrl() + "input.txt"); getExchange.setMethod(HttpMethods.GET); getExchange.setRequestHeader("X-Response-Status",Integer.toString(status)); getClient().send(getExchange); int state = getExchange.waitForDone(); String content; int responseStatus = getExchange.getResponseStatus(); if (responseStatus == HttpStatus.OK_200) { content = getExchange.getResponseContent(); } stopClient(); assertEquals(status, responseStatus); } /* ------------------------------------------------------------ */ protected void doPostFail(int status) throws Exception { startClient(getRealm()); ContentExchange postExchange = new ContentExchange(); postExchange.setURL(getBaseUrl() + "test"); postExchange.setMethod(HttpMethods.POST); postExchange.setRequestHeader("X-Response-Status",Integer.toString(status)); postExchange.setRequestContent(new ByteArrayBuffer(getContent().getBytes())); getClient().send(postExchange); int state = postExchange.waitForDone(); int responseStatus = postExchange.getResponseStatus(); stopClient(); assertEquals(status, responseStatus); } /* ------------------------------------------------------------ */ protected void configureServer(Server server) throws Exception { setProtocol("http"); SelectChannelConnector connector = new SelectChannelConnector(); server.addConnector(connector); ServletContextHandler root = new ServletContextHandler(); root.setContextPath("/"); root.setResourceBase(getBasePath()); ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); servletHolder.setInitParameter( "gzip", "true" ); root.addServlet( servletHolder, "/*" ); Handler status = new StatusHandler(); Handler test = new TestHandler(getBasePath()); HandlerCollection handlers = new HandlerCollection(); handlers.setHandlers(new Handler[]{status, test, root}); server.setHandler( handlers ); } /* ------------------------------------------------------------ */ protected static class StatusHandler extends AbstractHandler { /* ------------------------------------------------------------ */ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (baseRequest.isHandled()) return; int statusValue = 0; String statusHeader = request.getHeader("X-Response-Status"); if (statusHeader != null) { statusValue = Integer.parseInt(statusHeader); } if (statusValue != 0) { response.setStatus(statusValue); baseRequest.setHandled(true); } } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/ExpireTest.java000066400000000000000000000066521174773561500276740ustar00rootroot00000000000000package org.eclipse.jetty.client; // ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * Test contributed by: Michiel Thuys for JETTY-806 */ public class ExpireTest { private Server server; private HttpClient client; private int port; @Before public void init() throws Exception { server = new Server(); SelectChannelConnector connector = new SelectChannelConnector(); connector.setHost("localhost"); connector.setPort(0); server.addConnector(connector); server.setHandler(new AbstractHandler() { public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { request.setHandled(true); try { Thread.sleep(2000); } catch (InterruptedException x) { } } }); server.start(); port = connector.getLocalPort(); client = new HttpClient(); client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); client.setTimeout(200); client.setMaxRetries(0); client.setMaxConnectionsPerAddress(100); client.start(); } @After public void destroy() throws Exception { client.stop(); server.stop(); server.join(); } @Test public void testExpire() throws Exception { String baseUrl = "http://" + "localhost" + ":" + port + "/"; int count = 200; final CountDownLatch expires = new CountDownLatch(count); for (int i=0;i names = Collections.list(headers.getFieldNames()); StringBuilder err = new StringBuilder(); err.append("Missing expected header key [").append(expectedKey); err.append("] (of ").append(names.size()).append(" header fields)"); for (int i = 0; i < names.size(); i++) { String value = headers.getStringField(names.get(i)); err.append("\n").append(i).append("] ").append(names.get(i)); err.append(": ").append(value); } Assert.fail(err.toString()); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/HttpDestinationQueueTest.java000066400000000000000000000164701174773561500325650ustar00rootroot00000000000000package org.eclipse.jetty.client; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.RejectedExecutionException; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; public class HttpDestinationQueueTest { private static HttpClient _httpClient; private static long _timeout = 200; @BeforeClass public static void beforeOnce() throws Exception { _httpClient = new HttpClient(); _httpClient.setMaxConnectionsPerAddress(1); _httpClient.setMaxQueueSizePerAddress(1); _httpClient.setTimeout(_timeout); _httpClient.start(); } @Test public void testDestinationMaxQueueSize() throws Exception { ServerSocket server = new ServerSocket(0); // This will keep the connection busy HttpExchange exchange1 = new HttpExchange(); exchange1.setMethod("GET"); exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1"); _httpClient.send(exchange1); // Read request so we are sure that this exchange is out of the queue Socket socket = server.accept(); byte[] buffer = new byte[1024]; StringBuilder request = new StringBuilder(); while (true) { int read = socket.getInputStream().read(buffer); request.append(new String(buffer,0,read,"UTF-8")); if (request.toString().endsWith("\r\n\r\n")) break; } Assert.assertTrue(request.toString().contains("exchange1")); // This will be queued HttpExchange exchange2 = new HttpExchange(); exchange2.setMethod("GET"); exchange2.setURL("http://localhost:" + server.getLocalPort() + "/exchange2"); _httpClient.send(exchange2); // This will be rejected, since the connection is busy and the queue is full HttpExchange exchange3 = new HttpExchange(); exchange3.setMethod("GET"); exchange3.setURL("http://localhost:" + server.getLocalPort() + "/exchange3"); try { _httpClient.send(exchange3); Assert.fail(); } catch (RejectedExecutionException x) { // Expected } // Send the response to avoid exceptions in the console socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes("UTF-8")); Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange1.waitForDone()); // Be sure that the second exchange can be sent request.setLength(0); while (true) { int read = socket.getInputStream().read(buffer); request.append(new String(buffer,0,read,"UTF-8")); if (request.toString().endsWith("\r\n\r\n")) break; } Assert.assertTrue(request.toString().contains("exchange2")); socket.getOutputStream().write("HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n".getBytes("UTF-8")); socket.close(); Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange2.waitForDone()); server.close(); } @Test public void testDefaultTimeoutIncludesQueuingExchangeExpiresInQueue() throws Exception { ServerSocket server = new ServerSocket(0); // This will keep the connection busy HttpExchange exchange1 = new HttpExchange(); exchange1.setTimeout(_timeout * 3); // Be sure it does not expire exchange1.setMethod("GET"); exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1"); _httpClient.send(exchange1); // Read request so we are sure that this exchange is out of the queue Socket socket = server.accept(); byte[] buffer = new byte[1024]; StringBuilder request = new StringBuilder(); while (true) { int read = socket.getInputStream().read(buffer); request.append(new String(buffer,0,read,"UTF-8")); if (request.toString().endsWith("\r\n\r\n")) break; } Assert.assertTrue(request.toString().contains("exchange1")); // This will be queued HttpExchange exchange2 = new HttpExchange(); exchange2.setMethod("GET"); exchange2.setURL("http://localhost:" + server.getLocalPort() + "/exchange2"); _httpClient.send(exchange2); // Wait until the queued exchange times out in the queue Thread.sleep(_timeout * 2); Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange2.getStatus()); // Send the response to the first exchange to avoid exceptions in the console socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes("UTF-8")); Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange1.waitForDone()); socket.close(); server.close(); } @Test public void testDefaultTimeoutIncludesQueuingExchangeExpiresDuringRequest() throws Exception { ServerSocket server = new ServerSocket(0); HttpExchange exchange1 = new HttpExchange(); exchange1.setMethod("GET"); exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1"); _httpClient.send(exchange1); // Read request so we are sure that this exchange is out of the queue Socket socket = server.accept(); byte[] buffer = new byte[1024]; StringBuilder request = new StringBuilder(); while (true) { int read = socket.getInputStream().read(buffer); request.append(new String(buffer,0,read,"UTF-8")); if (request.toString().endsWith("\r\n\r\n")) break; } Assert.assertTrue(request.toString().contains("exchange1")); // Wait until the exchange times out during the request Thread.sleep(_timeout * 2); Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange1.getStatus()); socket.close(); server.close(); } @Test public void testExchangeTimeoutIncludesQueuingExchangeExpiresDuringResponse() throws Exception { ServerSocket server = new ServerSocket(0); long timeout = 1000; HttpExchange exchange1 = new HttpExchange(); exchange1.setTimeout(timeout); exchange1.setMethod("GET"); exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1"); _httpClient.send(exchange1); // Read request so we are sure that this exchange is out of the queue Socket socket = server.accept(); byte[] buffer = new byte[1024]; StringBuilder request = new StringBuilder(); while (true) { int read = socket.getInputStream().read(buffer); request.append(new String(buffer,0,read,"UTF-8")); if (request.toString().endsWith("\r\n\r\n")) break; } Assert.assertTrue(request.toString().contains("exchange1")); // Write part of the response socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Length: 1\r\n\r\n".getBytes("UTF-8")); // Wait until the exchange times out during the response Thread.sleep(timeout * 2); Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange1.getStatus()); socket.close(); server.close(); } }jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java000066400000000000000000000613441174773561500310210ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.matchers.JUnitMatchers.containsString; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jetty.client.helperClasses.HttpServerAndClientCreator; import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator; import org.eclipse.jetty.client.security.ProxyAuthorization; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.nio.DirectNIOBuffer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.toolchain.test.Stress; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.junit.After; import org.junit.Before; import org.junit.Test; /* ------------------------------------------------------------ */ /** * Functional testing for HttpExchange. */ public class HttpExchangeTest { final static boolean verbose=HttpExchange.LOG.isDebugEnabled(); protected static int _maxConnectionsPerAddress = 2; protected static String _scheme = "http"; protected static Server _server; protected static int _port; protected static HttpClient _httpClient; protected static AtomicInteger _count = new AtomicInteger(); protected static ServerAndClientCreator serverAndClientCreator = new HttpServerAndClientCreator(); protected static URI getBaseURI() { return URI.create(_scheme + "://localhost:" + _port + "/"); } /* ------------------------------------------------------------ */ // TODO work out why BeforeClass does not work here? @Before public void setUpOnce() throws Exception { _scheme = "http"; _server = serverAndClientCreator.createServer(); _httpClient = serverAndClientCreator.createClient(3000L,3500L,2000); _port = _server.getConnectors()[0].getLocalPort(); } /* ------------------------------------------------------------ */ @After public void tearDownOnce() throws Exception { _httpClient.stop(); long startTime = System.currentTimeMillis(); while (!_httpClient.getState().equals(AbstractLifeCycle.STOPPED)) { if (System.currentTimeMillis() - startTime > 1000) break; Thread.sleep(5); } _server.stop(); } /* ------------------------------------------------------------ */ @Test public void testResetNewExchange() throws Exception { HttpExchange exchange = new HttpExchange(); exchange.reset(); } /* ------------------------------------------------------------ */ @Test public void testPerf() throws Exception { sender(1,false); sender(1,true); sender(10,false); sender(10,true); if (Stress.isEnabled()) { sender(100,false); sender(100,true); sender(10000,false); sender(10000,true); } } /* ------------------------------------------------------------ */ /** * Test sending data through the exchange. * * @throws IOException */ public void sender(final int nb, final boolean close) throws Exception { // System.err.printf("%nSENDER %d %s%n",nb,close); _count.set(0); final CountDownLatch complete = new CountDownLatch(nb); final AtomicInteger allcontent = new AtomicInteger(nb); HttpExchange[] httpExchange = new HttpExchange[nb]; long start = System.currentTimeMillis(); for (int i = 0; i < nb; i++) { final int n = i; httpExchange[n] = new HttpExchange() { String result = "pending"; int len = 0; /* ------------------------------------------------------------ */ @Override protected void onRequestCommitted() { if (verbose) System.err.println(n+" [ "+this); result = "committed"; } /* ------------------------------------------------------------ */ @Override protected void onRequestComplete() throws IOException { if (verbose) System.err.println(n+" [ =="); result = "sent"; } @Override /* ------------------------------------------------------------ */ protected void onResponseStatus(Buffer version, int status, Buffer reason) { if (verbose) System.err.println(n+" ] "+version+" "+status+" "+reason); result = "status"; } /* ------------------------------------------------------------ */ @Override protected void onResponseHeader(Buffer name, Buffer value) { if (verbose) System.err.println(n+" ] "+name+": "+value); } /* ------------------------------------------------------------ */ @Override protected void onResponseHeaderComplete() throws IOException { if (verbose) System.err.println(n+" ] -"); result = "content"; super.onResponseHeaderComplete(); } /* ------------------------------------------------------------ */ @Override protected void onResponseContent(Buffer content) { len += content.length(); if (verbose) System.err.println(n+" ] "+content.length()+" -> "+len); } /* ------------------------------------------------------------ */ @Override protected void onResponseComplete() { if (verbose) System.err.println(n+" ] == "+len+" "+complete.getCount()+"/"+nb); result = "complete"; if (len == 2009) allcontent.decrementAndGet(); else System.err.println(n+ " ONLY " + len+ "/2009"); complete.countDown(); } /* ------------------------------------------------------------ */ @Override protected void onConnectionFailed(Throwable ex) { if (verbose) System.err.println(n+" ] "+ex); complete.countDown(); result = "failed"; System.err.println(n+ " FAILED " + ex); super.onConnectionFailed(ex); } /* ------------------------------------------------------------ */ @Override protected void onException(Throwable ex) { if (verbose) System.err.println(n+" ] "+ex); complete.countDown(); result = "excepted"; System.err.println(n+ " EXCEPTED " + ex); super.onException(ex); } /* ------------------------------------------------------------ */ @Override protected void onExpire() { if (verbose) System.err.println(n+" ] expired"); complete.countDown(); result = "expired"; System.err.println(n + " EXPIRED " + len); super.onExpire(); } /* ------------------------------------------------------------ */ @Override public String toString() { return n+"/"+result+"/"+len+"/"+super.toString(); } }; httpExchange[n].setURI(getBaseURI().resolve("/" + n)); httpExchange[n].addRequestHeader("arbitrary","value"); if (close) httpExchange[n].setRequestHeader("Connection","close"); _httpClient.send(httpExchange[n]); } if (!complete.await(2,TimeUnit.SECONDS)) System.err.println(_httpClient.dump()); assertTrue(complete.await(20,TimeUnit.SECONDS)); assertEquals("nb="+nb+" close="+close,0,allcontent.get()); } /* ------------------------------------------------------------ */ @Test public void testPostWithContentExchange() throws Exception { for (int i=0;i<20;i++) { ContentExchange httpExchange=new ContentExchange(); httpExchange.setURI(getBaseURI()); httpExchange.setMethod(HttpMethods.POST); httpExchange.setRequestContent(new ByteArrayBuffer("")); _httpClient.send(httpExchange); int status = httpExchange.waitForDone(); //httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED); String result=httpExchange.getResponseContent(); assertEquals(HttpExchange.STATUS_COMPLETED, status); assertEquals("i="+i,"",result); } } /* ------------------------------------------------------------ */ @Test public void testGetWithContentExchange() throws Exception { for (int i=0;i<10;i++) { ContentExchange httpExchange=new ContentExchange(); URI uri = getBaseURI().resolve("?i=" + i); httpExchange.setURI(uri); httpExchange.setMethod(HttpMethods.GET); _httpClient.send(httpExchange); int status = httpExchange.waitForDone(); //httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED); String result=httpExchange.getResponseContent(); assertNotNull("Should have received response content", result); assertEquals("i="+i,0,result.indexOf("")); assertEquals("i="+i,result.length()-10,result.indexOf("")); assertEquals(HttpExchange.STATUS_COMPLETED, status); Thread.sleep(5); } } /* ------------------------------------------------------------ */ @Test public void testLocalAddressAvailabilityWithContentExchange() throws Exception { for (int i=0;i<10;i++) { ContentExchange httpExchange=new ContentExchange(); URI uri = getBaseURI().resolve("?i=" + i); httpExchange.setURI(uri); httpExchange.setMethod(HttpMethods.GET); _httpClient.send(httpExchange); int status = httpExchange.waitForDone(); assertNotNull(httpExchange.getLocalAddress()); String result=httpExchange.getResponseContent(); assertNotNull("Should have received response content", result); assertEquals("i="+i,0,result.indexOf("")); assertEquals("i="+i,result.length()-10,result.indexOf("")); assertEquals(HttpExchange.STATUS_COMPLETED, status); Thread.sleep(5); } } /* ------------------------------------------------------------ */ @Test public void testShutdownWithExchange() throws Exception { final AtomicReference throwable=new AtomicReference(); HttpExchange httpExchange=new HttpExchange() { /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onException(java.lang.Throwable) */ @Override protected void onException(Throwable x) { throwable.set(x); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onConnectionFailed(java.lang.Throwable) */ @Override protected void onConnectionFailed(Throwable x) { throwable.set(x); } }; httpExchange.setURI(getBaseURI()); httpExchange.setMethod("SLEEP"); _httpClient.send(httpExchange); new Thread() { @Override public void run() { try { Thread.sleep(500); _httpClient.stop(); } catch(Exception e) {e.printStackTrace();} } }.start(); int status = httpExchange.waitForDone(); System.err.println(throwable.get()); assertTrue(throwable.get().toString().indexOf("close")>=0); assertEquals(HttpExchange.STATUS_EXCEPTED, status); _httpClient.start(); } /* ------------------------------------------------------------ */ @Test public void testBigPostWithContentExchange() throws Exception { int size =32; ContentExchange httpExchange=new ContentExchange() { int total; @Override protected synchronized void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { if (verbose) System.err.println("] "+version+" "+status+" "+reason); super.onResponseStatus(version,status,reason); } @Override protected synchronized void onResponseHeader(Buffer name, Buffer value) throws IOException { if (verbose) System.err.println("] "+name+": "+value); super.onResponseHeader(name,value); } @Override protected synchronized void onResponseContent(Buffer content) throws IOException { if (verbose) { total+=content.length(); System.err.println("] "+content.length()+" -> "+total); } super.onResponseContent(content); } @Override protected void onRequestComplete() throws IOException { if (verbose) System.err.println("] =="); super.onRequestComplete(); } @Override protected void onResponseHeaderComplete() throws IOException { if (verbose) System.err.println("] --"); super.onResponseHeaderComplete(); } }; Buffer babuf = new ByteArrayBuffer(size*36*1024); Buffer niobuf = new DirectNIOBuffer(size*36*1024); byte[] bytes="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes(); for (int i=0;i=10000) { System.err.println("TEST IS TAKING TOOOOO LONG!!!!!!!!!!!!!!!!!!!!"); System.err.println("CLIENT:"); System.err.println(_httpClient.dump()); System.err.println("SERVER:"); _server.dumpStdErr(); break; } Thread.sleep(100); } int status = httpExchange.waitForDone(); assertEquals(HttpExchange.STATUS_COMPLETED,status); String result=httpExchange.getResponseContent(); assertEquals(babuf.length(),result.length()); httpExchange.reset(); httpExchange.setURI(getBaseURI()); httpExchange.setMethod(HttpMethods.POST); httpExchange.setRequestContentType("application/data"); httpExchange.setRequestContent(niobuf); _httpClient.send(httpExchange); start=System.currentTimeMillis(); while(!httpExchange.isDone()) { long now=System.currentTimeMillis(); if ((now-start)>=10000) { System.err.println("TEST IS TAKING TOOOOO LONG!!!!!!!!!!!!!!!!!!!!"); System.err.println("CLIENT:"); System.err.println(_httpClient.dump()); System.err.println("SERVER:"); _server.dumpStdErr(); break; } Thread.sleep(100); } status = httpExchange.waitForDone(); assertEquals(HttpExchange.STATUS_COMPLETED, status); result=httpExchange.getResponseContent(); assertEquals(niobuf.length(),result.length()); } /* ------------------------------------------------------------ */ @Test public void testSlowPost() throws Exception { ContentExchange httpExchange=new ContentExchange(); httpExchange.setURI(getBaseURI()); httpExchange.setMethod(HttpMethods.POST); final String data="012345678901234567890123456789012345678901234567890123456789"; InputStream content = new InputStream() { int _index=0; @Override public int read() throws IOException { // System.err.printf("reading 1 of %d/%d%n",_index,data.length()); if (_index>=data.length()) return -1; try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } // System.err.printf("read 1%n"); return data.charAt(_index++); } @Override public int read(byte[] b, int off, int len) throws IOException { // System.err.printf("reading %d of %d/%d%n",len,_index,data.length()); if (_index >= data.length()) return -1; try { Thread.sleep(25); } catch (InterruptedException e) { e.printStackTrace(); } int l = 0; while (l < 5 && _index < data.length() && l < len) b[off + l++] = (byte)data.charAt(_index++); // System.err.printf("read %d%n",l); return l; } }; httpExchange.setRequestContentSource(content); _httpClient.send(httpExchange); int status = httpExchange.waitForDone(); String result = httpExchange.getResponseContent(); assertEquals(HttpExchange.STATUS_COMPLETED,status); assertEquals(data,result); } /* ------------------------------------------------------------ */ @Test public void testProxy() throws Exception { if (_scheme.equals("https")) return; try { _httpClient.setProxy(new Address("127.0.0.1",_port)); _httpClient.setProxyAuthentication(new ProxyAuthorization("user","password")); ContentExchange httpExchange=new ContentExchange(); httpExchange.setAddress(new Address("jetty.eclipse.org",8080)); httpExchange.setMethod(HttpMethods.GET); httpExchange.setRequestURI("/jetty-6"); _httpClient.send(httpExchange); int status = httpExchange.waitForDone(); //httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED); String result=httpExchange.getResponseContent(); assertNotNull("Should have received response content", result); result=result.trim(); assertEquals(HttpExchange.STATUS_COMPLETED, status); assertTrue(result.startsWith("Proxy request: http://jetty.eclipse.org:8080/jetty-6")); assertTrue(result.endsWith("Basic dXNlcjpwYXNzd29yZA==")); } finally { _httpClient.setProxy(null); } } /* ------------------------------------------------------------ */ @Test public void testReserveConnections () throws Exception { _httpClient = serverAndClientCreator.createClient(3000L,3500L,2000); final HttpDestination destination = _httpClient.getDestination(new Address("localhost",_port),_scheme.equalsIgnoreCase("https")); final org.eclipse.jetty.client.AbstractHttpConnection[] connections = new org.eclipse.jetty.client.AbstractHttpConnection[_maxConnectionsPerAddress]; for (int i = 0; i < _maxConnectionsPerAddress; i++) { connections[i] = destination.reserveConnection(200); assertNotNull(connections[i]); HttpExchange ex = new ContentExchange(); ex.setURI(getBaseURI().resolve("?i=" + i)); ex.setMethod(HttpMethods.GET); connections[i].send(ex); } // try to get a connection, and only wait 500ms, as we have // already reserved the max, should return null Connection c = destination.reserveConnection(500); assertNull(c); // unreserve first connection destination.returnConnection(connections[0],false); // reserving one should now work c = destination.reserveConnection(500); assertNotNull(c); // release connections for (AbstractHttpConnection httpConnection : connections){ destination.returnConnection(httpConnection,false); } } @Test public void testOptionsWithExchange() throws Exception { ContentExchange httpExchange = new ContentExchange(true); httpExchange.setURL(getBaseURI().toASCIIString()); httpExchange.setRequestURI("*"); httpExchange.setMethod(HttpMethods.OPTIONS); // httpExchange.setRequestHeader("Connection","close"); _httpClient.send(httpExchange); int state = httpExchange.waitForDone(); assertEquals(HttpExchange.STATUS_COMPLETED, state); assertEquals(HttpStatus.OK_200,httpExchange.getResponseStatus()); HttpFields headers = httpExchange.getResponseFields(); HttpAsserts.assertContainsHeaderKey("Content-Length", headers); assertEquals("Content-Length header value", 0, headers.getLongField("Content-Length")); HttpAsserts.assertContainsHeaderKey("Allow",headers); String allow = headers.getStringField("Allow"); String expectedMethods[] = { "GET", "HEAD", "POST", "PUT", "DELETE", "MOVE", "OPTIONS", "TRACE" }; for (String expectedMethod : expectedMethods) { assertThat(allow,containsString(expectedMethod)); } } /* ------------------------------------------------------------ */ public static void copyStream(InputStream in, OutputStream out) { try { byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) >= 0) { out.write(buffer,0,len); } } catch (EofException e) { System.err.println("HttpExchangeTest#copyStream: " + e); } catch (IOException e) { e.printStackTrace(); } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/HttpGetRedirectTest.java000066400000000000000000000200001174773561500314600ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.client.security.SimpleRealmResolver; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.junit.After; import org.junit.Before; import org.junit.Test; /* ------------------------------------------------------------ */ public class HttpGetRedirectTest { private static String _content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+ "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+ "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+ "Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+ "at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+ "velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+ "Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+ "eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+ "sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+ "consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+ "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+ "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque."; private File _docRoot; private Server _server; private HttpClient _client; private Realm _realm; private String _protocol; private String _requestUrl; private String _requestUrl2; private RedirectHandler _handler; /* ------------------------------------------------------------ */ @Before public void setUp() throws Exception { _docRoot = new File("target/test-output/docroot/"); _docRoot.mkdirs(); _docRoot.deleteOnExit(); _server = new Server(); configureServer(_server); org.eclipse.jetty.server.bio.SocketConnector connector = new org.eclipse.jetty.server.bio.SocketConnector(); _server.addConnector(connector); _server.start(); int port = _server.getConnectors()[0].getLocalPort(); _requestUrl = _protocol+"://localhost:"+port+ "/content.txt"; _handler._toURL=_protocol+"://localhost:"+connector.getLocalPort()+ "/moved.txt"; } /* ------------------------------------------------------------ */ @After public void tearDown() throws Exception { if (_server != null) { _server.stop(); _server = null; } } /* ------------------------------------------------------------ */ @Test public void testGet() throws Exception { startClient(_realm); ContentExchange getExchange = new ContentExchange(); getExchange.setURL(_requestUrl); getExchange.setMethod(HttpMethods.GET); _client.send(getExchange); int state = getExchange.waitForDone(); String content = ""; int responseStatus = getExchange.getResponseStatus(); if (responseStatus == HttpStatus.OK_200) { content = getExchange.getResponseContent(); } assertEquals(HttpStatus.OK_200,responseStatus); assertEquals(_content,content); stopClient(); } /* ------------------------------------------------------------ */ protected void configureServer(Server server) throws Exception { setProtocol("http"); SelectChannelConnector connector = new SelectChannelConnector(); server.addConnector(connector); _handler = new RedirectHandler(HttpStatus.MOVED_PERMANENTLY_301, "/content.txt", "WAIT FOR IT", 2); server.setHandler( _handler ); } /* ------------------------------------------------------------ */ protected void startClient(Realm realm) throws Exception { _client = new HttpClient(); _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); _client.registerListener("org.eclipse.jetty.client.RedirectListener"); if (realm != null) _client.setRealmResolver(new SimpleRealmResolver(realm)); _client.start(); } /* ------------------------------------------------------------ */ protected void stopClient() throws Exception { if (_client != null) { _client.stop(); _client = null; } } /* ------------------------------------------------------------ */ protected String getBasePath() { return _docRoot.getAbsolutePath(); } /* ------------------------------------------------------------ */ protected void setProtocol(String protocol) { _protocol = protocol; } /* ------------------------------------------------------------ */ protected void setRealm(Realm realm) { _realm = realm; } /* ------------------------------------------------------------ */ private static class RedirectHandler extends AbstractHandler { private final String _fromURI; private final int _code; private final int _maxRedirects; private int _redirectCount = 0; private String _toURL; /* ------------------------------------------------------------ */ public RedirectHandler( final int code, final String fromURI, final String toURL, final int maxRedirects ) { this._code = code; this._fromURI = fromURI; this._toURL = toURL; this._maxRedirects = maxRedirects; if (_fromURI==null || _toURL==null) throw new IllegalArgumentException(); } /* ------------------------------------------------------------ */ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if ( baseRequest.isHandled() ) { return; } if (request.getRequestURI().equals(_fromURI)) { _redirectCount++; String location = ( _redirectCount <= _maxRedirects )?_fromURI:_toURL; response.setStatus( _code ); response.setHeader( "Location", location ); ( (Request) request ).setHandled( true ); } else { PrintWriter out = response.getWriter(); out.write(_content); baseRequest.setHandled( true ); } } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/HttpHeadersTest.java000066400000000000000000000152201174773561500306420ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.junit.After; import org.junit.Before; import org.junit.Test; public class HttpHeadersTest { private static final Logger LOG = Log.getLogger(HttpHeadersTest.class); private static final String CONTENT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. " + "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque " + "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. " + "Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam " + "at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate " + "velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. " + "Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum " + "eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa " + "sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam " + "consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. " + "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse " + "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque."; private Server _server; private TestHeaderHandler _handler; private int _port; @Before public void init() throws Exception { File docRoot = new File("target/test-output/docroot/"); if (!docRoot.exists()) assertTrue(docRoot.mkdirs()); docRoot.deleteOnExit(); _server = new Server(); Connector connector = new SelectChannelConnector(); _server.addConnector(connector); _handler = new TestHeaderHandler(); _server.setHandler(_handler); _server.start(); _port = connector.getLocalPort(); } @After public void destroy() throws Exception { _server.stop(); _server.join(); } @Test public void testHttpHeaders() throws Exception { HttpClient httpClient = new HttpClient(); httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); httpClient.start(); try { String requestUrl = "http://localhost:" + _port + "/header"; ContentExchange exchange = new ContentExchange(); exchange.setURL(requestUrl); exchange.setMethod(HttpMethods.GET); exchange.addRequestHeader("User-Agent","Jetty-Client/7.0"); httpClient.send(exchange); int state = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_COMPLETED, state); int responseStatus = exchange.getResponseStatus(); assertEquals(HttpStatus.OK_200,responseStatus); String content = exchange.getResponseContent(); assertEquals(HttpHeadersTest.CONTENT,content); assertEquals("Jetty-Client/7.0",_handler.headers.get("User-Agent")); } finally { httpClient.stop(); } } @Test public void testHttpHeadersSize() throws Exception { HttpClient httpClient = new HttpClient(); httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); httpClient.start(); try { String requestUrl = "http://localhost:" + _port + "/header"; ContentExchange exchange = new ContentExchange() { @Override protected void onException(Throwable x) { // suppress exception LOG.ignore(x); } }; exchange.setURL(requestUrl); exchange.setMethod(HttpMethods.GET); for (int i = 0; i < 4; i++) { for (int j = 0; j < 1024; j++) { exchange.addRequestHeader("header" + i + "-" + j,"v"); } } httpClient.send(exchange); int state = exchange.waitForDone(); assertEquals(HttpExchange.STATUS_EXCEPTED, state); } finally { httpClient.stop(); } } private static class TestHeaderHandler extends AbstractHandler { protected Map headers; public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (baseRequest.isHandled()) return; headers = new HashMap(); for (Enumeration e = request.getHeaderNames(); e.hasMoreElements();) { String name = (String)e.nextElement(); headers.put(name,request.getHeader(name)); } response.setContentType("text/plain"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().print(CONTENT); baseRequest.setHandled(true); } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/HttpsProxyAuthenticationTest.java000066400000000000000000000075761174773561500335120ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.security.Authentication; import org.eclipse.jetty.client.security.BasicAuthentication; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ConnectHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.junit.After; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Test; public class HttpsProxyAuthenticationTest { private Server _proxy = new Server(); private HttpClient _client = new HttpClient(); private boolean authHandlerSend; @Before public void init() throws Exception { SelectChannelConnector connector = new SelectChannelConnector(); _proxy.addConnector(connector); _proxy.setHandler(new ConnectHandler() { @Override protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) throws ServletException, IOException { String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.length() > 0) authHandlerSend = true; return super.handleAuthentication(request,response,address); } }); _proxy.start(); int proxyPort = connector.getLocalPort(); Authentication authentication = new BasicAuthentication(new Realm() { public String getId() { return "MyRealm"; } public String getPrincipal() { return "jetty"; } public String getCredentials() { return "jetty"; } }); _client.setProxy(new Address("localhost", proxyPort)); _client.setProxyAuthentication(authentication); _client.start(); } @After public void destroy() throws Exception { _client.stop(); _proxy.stop(); _proxy.join(); } @Test public void httpsViaProxyThatReturns504ErrorTest() throws Exception { // Assume that we can connect to google String host = "google.com"; int port = 443; Socket socket = new Socket(); try { socket.connect(new InetSocketAddress(host, port), 1000); } catch (IOException x) { Assume.assumeNoException(x); } finally { socket.close(); } HttpExchange exchange = new ContentExchange(); exchange.setURL("https://" + host + ":" + port); exchange.addRequestHeader("behaviour", "google"); _client.send(exchange); Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); Assert.assertTrue("Authorization header not set!", authHandlerSend); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/HttpsViaBrokenHttpProxyTest.java000066400000000000000000000114171174773561500332400ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.net.ProtocolException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.AbstractHttpConnection; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ConnectHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.junit.After; import org.junit.Before; import org.junit.Test; /* ------------------------------------------------------------ */ /** * This UnitTest class executes two tests. Both will send a http request to https://google.com through a misbehaving proxy server. *

* The first test runs against a proxy which simply closes the connection (as nginx does) for a connect request. The second proxy server always responds with a * 500 error. *

* The expected result for both tests is an exception and the HttpExchange should have status HttpExchange.STATUS_EXCEPTED. */ public class HttpsViaBrokenHttpProxyTest { private Server _proxy = new Server(); private HttpClient _client = new HttpClient(); @Before public void init() throws Exception { // setup proxies with different behaviour _proxy.addConnector(new SelectChannelConnector()); _proxy.setHandler(new BadBehavingConnectHandler()); _proxy.start(); int proxyClosingConnectionPort = _proxy.getConnectors()[0].getLocalPort(); _client.setProxy(new Address("localhost", proxyClosingConnectionPort)); _client.start(); } @After public void destroy() throws Exception { _client.stop(); _proxy.stop(); } @Test public void httpsViaProxyThatClosesConnectionOnConnectRequestTest() throws Exception { sendRequestThroughProxy(new ContentExchange() { @Override protected void onException(Throwable x) { } }, "close", 9); } @Test public void httpsViaProxyThatReturns500ErrorTest() throws Exception { HttpExchange exchange = new ContentExchange() { @Override protected void onException(Throwable x) { // Suppress logging for expected exception if (!(x instanceof ProtocolException)) super.onException(x); } }; sendRequestThroughProxy(exchange, "error500", 9); } @Test public void httpsViaProxyThatReturns504ErrorTest() throws Exception { sendRequestThroughProxy(new ContentExchange(), "error504", 8); } private void sendRequestThroughProxy(HttpExchange exchange, String desiredBehaviour, int exptectedStatus) throws Exception { String url = "https://" + desiredBehaviour + ".com/"; exchange.setURL(url); exchange.addRequestHeader("behaviour", desiredBehaviour); _client.send(exchange); assertEquals(HttpExchange.toState(exptectedStatus) + " status awaited", exptectedStatus, exchange.waitForDone()); } private class BadBehavingConnectHandler extends ConnectHandler { @Override protected void handleConnect(Request baseRequest, HttpServletRequest request, HttpServletResponse response, String serverAddress) throws ServletException, IOException { if (serverAddress.contains("close")) { AbstractHttpConnection.getCurrentConnection().getEndPoint().close(); } else if (serverAddress.contains("error500")) { response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500); } else if (serverAddress.contains("error504")) { response.setStatus(HttpStatus.GATEWAY_TIMEOUT_504); } baseRequest.setHandled(true); } } } NonBlockingHttpExchangeCancelTest.java000066400000000000000000000033371174773561500341720ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/* * Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package org.eclipse.jetty.client; import org.junit.After; import org.junit.Before; /* ------------------------------------------------------------ */ /** * @version $Revision$ $Date$ */ public class NonBlockingHttpExchangeCancelTest extends AbstractHttpExchangeCancelTest { private HttpClient httpClient; /* ------------------------------------------------------------ */ @Before @Override public void setUp() throws Exception { super.setUp(); httpClient = new HttpClient(); httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); httpClient.start(); } /* ------------------------------------------------------------ */ @After @Override public void tearDown() throws Exception { httpClient.stop(); super.tearDown(); } /* ------------------------------------------------------------ */ @Override protected HttpClient getHttpClient() { return httpClient; } /* ------------------------------------------------------------ */ public void testHttpExchangeCancelOnRequestComplete() throws Exception { super.testHttpExchangeCancelOnRequestComplete(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java000066400000000000000000000154241174773561500315330ustar00rootroot00000000000000package org.eclipse.jetty.client; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import org.eclipse.jetty.toolchain.test.IO; public class ProxyFakeTunnelTest extends ProxyTunnellingTest { ServerSocket _proxySocket; Thread _proxyThread; protected int proxyPort() { return _proxySocket.getLocalPort(); } protected void startProxy() throws Exception { _proxySocket = new ServerSocket(0); _proxyThread = new Thread() { @Override public void run() { while (!_proxySocket.isClosed()) { try { Socket socket=_proxySocket.accept(); System.err.println("accepted "+socket); new FakeProxy(socket).start(); } catch (IOException e) { } } } }; _proxyThread.setDaemon(true); _proxyThread.start(); } protected void stopProxy() throws Exception { _proxySocket.close(); _proxyThread.interrupt(); } static class FakeProxy extends Thread { Socket _socket; public FakeProxy(Socket socket) { _socket=socket; } public void run() { Socket toserver=null; final InputStream in; final OutputStream out; try { in = _socket.getInputStream(); out = _socket.getOutputStream(); String address=""; int state=0; for (int b=in.read();b>=0;b=in.read()) { switch(state) { case 0: if (' '==b) state=1; break; case 1: if (' '==b) state=2; else address+=(char)b; break; case 2: if ('\r'==b) state=3; break; case 3: if ('\n'==b) state=4; else state=2; break; case 4: if ('\r'==b) state=5; else state=2; break; case 5: if ('\n'==b) { state=6; System.err.println("address="+address); String[] parts=address.split(":"); try { toserver = new Socket(parts[0],Integer.parseInt(parts[1])); out.write(( "HTTP/1.1 200 OK\r\n"+ "Server: fake\r\n"+ // "Content-Length: 0\r\n"+ "\r\n" ).getBytes()); } catch(IOException e) { out.write(( "HTTP/1.1 503 Unavailable\r\n"+ "Server: fake\r\n"+ "Content-Length: 0\r\n"+ "\r\n" ).getBytes()); } out.flush(); if (toserver!=null) { final InputStream from = toserver.getInputStream(); Thread copy = new Thread() { public void run() { try { IO.copy(from,out); out.close(); } catch (IOException e) { } finally { try { out.close(); } catch (IOException e) { } } } }; copy.setDaemon(true); copy.start(); } } else state=2; break; case 6: toserver.getOutputStream().write((byte)b); } } } catch (IOException e) { e.printStackTrace(); } finally { if (toserver!=null) { try { toserver.close(); } catch (IOException e) { e.printStackTrace(); } } } } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java000066400000000000000000000204061174773561500316120ustar00rootroot00000000000000package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.net.URLEncoder; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.ConnectHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.After; import org.junit.Test; public class ProxyTunnellingTest { private Server server; private Connector serverConnector; private Server proxy; private Connector proxyConnector; private int serverConnectTimeout = 1000; protected int proxyPort() { return proxyConnector.getLocalPort(); } protected void startSSLServer(Handler handler) throws Exception { SslSelectChannelConnector connector = new SslSelectChannelConnector(); String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); SslContextFactory cf = connector.getSslContextFactory(); cf.setKeyStorePath(keyStorePath); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); startServer(connector, handler); } protected void startServer(Connector connector, Handler handler) throws Exception { server = new Server(); serverConnector = connector; server.addConnector(serverConnector); server.setHandler(handler); server.start(); } protected void startProxy() throws Exception { proxy = new Server(); proxyConnector = new SelectChannelConnector(); proxy.addConnector(proxyConnector); ConnectHandler connectHandler = new ConnectHandler(); // Under Windows, it takes a while to detect that a connection // attempt fails, so use an explicit timeout connectHandler.setConnectTimeout(serverConnectTimeout); proxy.setHandler(connectHandler); proxy.start(); } @After public void stop() throws Exception { stopProxy(); stopServer(); } protected void stopServer() throws Exception { server.stop(); server.join(); } protected void stopProxy() throws Exception { proxy.stop(); proxy.join(); } @Test public void testOneMessageSSL() throws Exception { startSSLServer(new ServerHandler()); startProxy(); HttpClient httpClient = new HttpClient(); httpClient.setProxy(new Address("localhost", proxyPort())); httpClient.start(); try { ContentExchange exchange = new ContentExchange(true); exchange.setMethod(HttpMethods.GET); String body = "BODY"; exchange.setURL("https://localhost:" + serverConnector.getLocalPort() + "/echo?body=" + URLEncoder.encode(body, "UTF-8")); httpClient.send(exchange); assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); String content = exchange.getResponseContent(); assertEquals(body, content); } finally { httpClient.stop(); } } @Test public void testTwoMessagesSSL() throws Exception { startSSLServer(new ServerHandler()); startProxy(); HttpClient httpClient = new HttpClient(); httpClient.setProxy(new Address("localhost", proxyPort())); httpClient.start(); try { ContentExchange exchange = new ContentExchange(true); exchange.setMethod(HttpMethods.GET); String body = "BODY"; exchange.setURL("https://localhost:" + serverConnector.getLocalPort() + "/echo?body=" + URLEncoder.encode(body, "UTF-8")); httpClient.send(exchange); assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); String content = exchange.getResponseContent(); assertEquals(body, content); exchange = new ContentExchange(true); exchange.setMethod(HttpMethods.POST); exchange.setURL("https://localhost:" + serverConnector.getLocalPort() + "/echo"); exchange.setRequestHeader(HttpHeaders.CONTENT_TYPE, MimeTypes.FORM_ENCODED); content = "body=" + body; exchange.setRequestHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(content.length())); exchange.setRequestContent(new ByteArrayBuffer(content, "UTF-8")); httpClient.send(exchange); assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); content = exchange.getResponseContent(); assertEquals(body, content); } finally { httpClient.stop(); } } @Test public void testProxyDown() throws Exception { startSSLServer(new ServerHandler()); startProxy(); int proxyPort = proxyPort(); stopProxy(); HttpClient httpClient = new HttpClient(); httpClient.setProxy(new Address("localhost", proxyPort)); httpClient.start(); try { final CountDownLatch latch = new CountDownLatch(1); ContentExchange exchange = new ContentExchange(true) { @Override protected void onConnectionFailed(Throwable x) { latch.countDown(); } }; exchange.setMethod(HttpMethods.GET); String body = "BODY"; exchange.setURL("https://localhost:" + serverConnector.getLocalPort() + "/echo?body=" + URLEncoder.encode(body, "UTF-8")); httpClient.send(exchange); assertTrue(latch.await(1000, TimeUnit.MILLISECONDS)); } finally { httpClient.stop(); } } @Test public void testServerDown() throws Exception { startSSLServer(new ServerHandler()); int serverPort = serverConnector.getLocalPort(); stopServer(); startProxy(); HttpClient httpClient = new HttpClient(); httpClient.setProxy(new Address("localhost", proxyPort())); httpClient.start(); try { final CountDownLatch latch = new CountDownLatch(1); ContentExchange exchange = new ContentExchange(true) { @Override protected void onException(Throwable x) { latch.countDown(); } }; exchange.setMethod(HttpMethods.GET); String body = "BODY"; exchange.setURL("https://localhost:" + serverPort + "/echo?body=" + URLEncoder.encode(body, "UTF-8")); httpClient.send(exchange); assertTrue(latch.await(serverConnectTimeout * 2, TimeUnit.MILLISECONDS)); } finally { httpClient.stop(); } } private static class ServerHandler extends AbstractHandler { public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { request.setHandled(true); String uri = httpRequest.getRequestURI(); if ("/echo".equals(uri)) { String body = httpRequest.getParameter("body"); ServletOutputStream output = httpResponse.getOutputStream(); output.print(body); } else { throw new ServletException(); } } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SecuredContentExchangeTest.java000066400000000000000000000100761174773561500330230ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.File; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.security.Constraint; public class SecuredContentExchangeTest extends ContentExchangeTest { protected void configureServer(Server server) throws Exception { setProtocol("http"); setRealm(new Realm() { public String getId() { return "MyRealm"; } public String getPrincipal() { return "jetty"; } public String getCredentials() { return "jetty"; } }); SelectChannelConnector connector = new SelectChannelConnector(); server.addConnector(connector); File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties"); LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath()); server.addBean(loginService); ConstraintSecurityHandler security = new ConstraintSecurityHandler(); server.setHandler(security); Constraint constraint = new Constraint(); constraint.setName("auth"); constraint.setAuthenticate( true ); constraint.setRoles(new String[]{"user", "admin"}); ConstraintMapping mapping = new ConstraintMapping(); mapping.setPathSpec( "/*" ); mapping.setConstraint( constraint ); Set knownRoles = new HashSet(); knownRoles.add("user"); knownRoles.add("admin"); security.setConstraintMappings(Collections.singletonList(mapping), knownRoles); security.setAuthenticator(new BasicAuthenticator()); security.setLoginService(loginService); security.setStrict(false); ServletContextHandler root = new ServletContextHandler(); root.setContextPath("/"); root.setResourceBase(getBasePath()); ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); servletHolder.setInitParameter( "gzip", "true" ); root.addServlet( servletHolder, "/*" ); Handler handler = new TestHandler(getBasePath()); HandlerCollection handlers = new HandlerCollection(); handlers.setHandlers(new Handler[]{handler, root}); security.setHandler(handlers); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SecuredErrorStatusTest.java000066400000000000000000000156211174773561500322440ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.File; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.security.Constraint; import org.junit.Test; public class SecuredErrorStatusTest extends ErrorStatusTest { private Realm _testRealm; private Realm _dummyRealm; /* ------------------------------------------------------------ */ @Test @Override public void testPutUnauthorized() throws Exception { setRealm(null); doPutFail(HttpStatus.UNAUTHORIZED_401); setRealm(_testRealm); } /* ------------------------------------------------------------ */ @Test public void testPutWrongPassword() throws Exception { setRealm(_dummyRealm); doPutFail(HttpStatus.UNAUTHORIZED_401); setRealm(_testRealm); } /* ------------------------------------------------------------ */ @Test @Override public void testGetUnauthorized() throws Exception { setRealm(null); doGetFail(HttpStatus.UNAUTHORIZED_401); setRealm(_testRealm); } /* ------------------------------------------------------------ */ @Test public void testGetWrongPassword() throws Exception { setRealm(_dummyRealm); doGetFail(HttpStatus.UNAUTHORIZED_401); setRealm(_testRealm); } /* ------------------------------------------------------------ */ @Override protected void configureServer(Server server) throws Exception { setProtocol("http"); _testRealm = new Realm() { /* ------------------------------------------------------------ */ public String getId() { return "MyRealm"; } /* ------------------------------------------------------------ */ public String getPrincipal() { return "jetty"; } /* ------------------------------------------------------------ */ public String getCredentials() { return "jetty"; } }; _dummyRealm = new Realm() { /* ------------------------------------------------------------ */ public String getId() { return "MyRealm"; } /* ------------------------------------------------------------ */ public String getPrincipal() { return "jetty"; } /* ------------------------------------------------------------ */ public String getCredentials() { return "dummy"; } }; setRealm(_testRealm); SelectChannelConnector connector = new SelectChannelConnector(); server.addConnector(connector); File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties"); LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath()); server.addBean(loginService); ConstraintSecurityHandler security = new ConstraintSecurityHandler(); server.setHandler(security); Constraint constraint = new Constraint(); constraint.setName("auth"); constraint.setAuthenticate( true ); constraint.setRoles(new String[]{"user", "admin"}); ConstraintMapping mapping = new ConstraintMapping(); mapping.setPathSpec( "/*" ); mapping.setConstraint( constraint ); Set knownRoles = new HashSet(); knownRoles.add("user"); knownRoles.add("admin"); security.setConstraintMappings(Collections.singletonList(mapping), knownRoles); security.setAuthenticator(new BasicAuthenticator()); security.setLoginService(loginService); security.setStrict(false); ServletContextHandler root = new ServletContextHandler(); root.setContextPath("/"); root.setResourceBase(getBasePath()); ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); servletHolder.setInitParameter( "gzip", "true" ); root.addServlet( servletHolder, "/*" ); Handler status = new StatusHandler(); Handler test = new TestHandler(getBasePath()); HandlerCollection handlers = new HandlerCollection(); handlers.setHandlers(new Handler[]{status, test, root}); security.setHandler(handlers); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SecurityListenerTest.java000066400000000000000000000267351174773561500317610ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.client.security.SimpleRealmResolver; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.security.Constraint; import org.junit.After; import org.junit.Before; import org.junit.Test; /* ------------------------------------------------------------ */ /** * Functional testing for HttpExchange. */ public class SecurityListenerTest { private Server _server; private int _port; private HttpClient _httpClient; private Realm _jettyRealm; private static final String APP_CONTEXT = "localhost /"; /* ------------------------------------------------------------ */ @Before public void setUp() throws Exception { startServer(); _httpClient=new HttpClient(); _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); _httpClient.setMaxConnectionsPerAddress(2); _httpClient.start(); _jettyRealm = new Realm() { public String getId() { return "MyRealm"; } public String getPrincipal() { return "jetty"; } public String getCredentials() { return "jetty"; } }; _httpClient.setRealmResolver( new SimpleRealmResolver(_jettyRealm) ); } /* ------------------------------------------------------------ */ @After public void tearDown() throws Exception { stopServer(); _httpClient.stop(); } /* ------------------------------------------------------------ */ // @Test public void xtestPerf() throws Exception { sender(1); Thread.sleep(200); sender(10); Thread.sleep(200); sender(100); Thread.sleep(200); sender(1000); Thread.sleep(200); sender(10000); } /* ------------------------------------------------------------ */ public void sender(final int nb) throws Exception { final CountDownLatch latch=new CountDownLatch(nb); long l0=System.currentTimeMillis(); for (int i=0; i0) { // System.err.println("waiting for "+last+" sent "+(System.currentTimeMillis()-l0)/1000 + "s ago ..."); latch.await(5,TimeUnit.SECONDS); long next=latch.getCount(); if (last==next) break; last=next; } // System.err.println("missed "+latch.getCount()+" sent "+(System.currentTimeMillis()-l0)/1000 + "s ago."); assertEquals(0,latch.getCount()); long l1=System.currentTimeMillis(); } //TODO jaspi hangs ??? // public void testGetWithContentExchange() throws Exception // { // int i = 1; // // final CyclicBarrier barrier = new CyclicBarrier(2); // ContentExchange httpExchange = new ContentExchange() // { // protected void onResponseComplete() throws IOException // { // super.onResponseComplete(); // try{barrier.await();}catch(Exception e){} // } // }; // httpExchange.setURL("http://localhost:" + _port + "/?i=" + i); // httpExchange.setMethod(HttpMethods.GET); // // _httpClient.send(httpExchange); // // try{barrier.await();}catch(Exception e){} // // } /* ------------------------------------------------------------ */ @Test public void testDestinationSecurityCaching() throws Exception { final CyclicBarrier barrier = new CyclicBarrier(2); ContentExchange httpExchange = new ContentExchange() { @Override protected void onResponseComplete() throws IOException { super.onResponseComplete(); try{barrier.await();}catch(Exception e){} } }; httpExchange.setURL("http://localhost:" + _port + "/?i=1"); httpExchange.setMethod(HttpMethods.GET); _httpClient.send(httpExchange); try{barrier.await();}catch(Exception e){} barrier.reset(); ContentExchange httpExchange2 = new ContentExchange() { @Override protected void onResponseComplete() throws IOException { super.onResponseComplete(); try{barrier.await();}catch(Exception e){} } }; httpExchange2.setURL("http://localhost:" + _port + "/?i=2"); httpExchange2.setMethod(HttpMethods.GET); _httpClient.send(httpExchange2); try{barrier.await();}catch(Exception e){} assertFalse( "exchange was retried", httpExchange2.getRetryStatus() ); } /* ------------------------------------------------------------ */ public static void copyStream(InputStream in, OutputStream out) { try { byte[] buffer=new byte[1024]; int len; while ((len=in.read(buffer))>=0) { out.write(buffer,0,len); } } catch (EofException e) { System.err.println(e); } catch (IOException e) { e.printStackTrace(); } } /* ------------------------------------------------------------ */ private void startServer() throws Exception { _server = new Server(); _server.setGracefulShutdown(500); Connector connector = new SelectChannelConnector(); connector.setPort(0); _server.setConnectors(new Connector[]{connector}); Constraint constraint = new Constraint(); constraint.setName("Need User or Admin"); constraint.setRoles(new String[]{"user", "admin"}); constraint.setAuthenticate(true); ConstraintMapping cm = new ConstraintMapping(); cm.setConstraint(constraint); cm.setPathSpec("/*"); File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties"); LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath()); ConstraintSecurityHandler sh = new ConstraintSecurityHandler(); sh.setLoginService(loginService); sh.setAuthenticator(new BasicAuthenticator()); //ServerAuthentication serverAuthentication = new BasicServerAuthentication(loginService, "MyRealm"); //sh.setServerAuthentication(serverAuthentication); _server.setHandler(sh); Handler testHandler = new AbstractHandler() { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // System.out.println("passed authentication!"); baseRequest.setHandled(true); response.setStatus(200); if (request.getServerName().equals("jetty.eclipse.org")) { response.getOutputStream().println("Proxy request: "+request.getRequestURL()); } else if (request.getMethod().equalsIgnoreCase("GET")) { response.getOutputStream().println(""); for (int i=0; i<100; i++) { response.getOutputStream().println(" "+i+""); if (i%20==0) response.getOutputStream().flush(); } response.getOutputStream().println(""); } else { copyStream(request.getInputStream(),response.getOutputStream()); } } }; sh.setHandler(testHandler); _server.start(); _port = connector.getLocalPort(); } /* ------------------------------------------------------------ */ private void stopServer() throws Exception { _server.stop(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SelectConnectionTest.java000066400000000000000000000021211174773561500316620ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; public class SelectConnectionTest extends AbstractConnectionTest { protected HttpClient newHttpClient() { HttpClient httpClient = new HttpClient(); httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); httpClient.setConnectBlocking(true); return httpClient; } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java000066400000000000000000000141611174773561500266260ustar00rootroot00000000000000package org.eclipse.jetty.client; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.util.thread.QueuedThreadPool; /* ------------------------------------------------------------ */ /** */ public class Siege { private static final class ConcurrentExchange extends HttpExchange { private final long _start=System.currentTimeMillis(); private final HttpClient _client; private final CountDownLatch _latch; volatile int _status; volatile int _count; volatile long _bytes; final List _uris; final int _repeats; int _u; int _r; AtomicBoolean counted=new AtomicBoolean(false); public ConcurrentExchange(HttpClient client,CountDownLatch latch, List uris, int repeats) { _client = client; _latch = latch; _uris = uris; _repeats = repeats; } @Override protected void onConnectionFailed(Throwable ex) { if (!counted.getAndSet(true)) _latch.countDown(); super.onConnectionFailed(ex); } @Override protected void onException(Throwable ex) { if (!counted.getAndSet(true)) _latch.countDown(); super.onException(ex); } @Override protected void onExpire() { if (!counted.getAndSet(true)) _latch.countDown(); super.onExpire(); } @Override protected void onResponseComplete() throws IOException { if (_status==200) _count++; if (!next() && !counted.getAndSet(true)) { _latch.countDown(); long duration=System.currentTimeMillis()-_start; System.err.printf("Got %d/%d with %dB in %dms %d%n",_count,_uris.size()*_repeats,_bytes,duration,_latch.getCount()); } } /* ------------------------------------------------------------ */ @Override protected void onResponseContent(Buffer content) throws IOException { _bytes+=content.length(); super.onResponseContent(content); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onResponseHeader(org.eclipse.jetty.io.Buffer, org.eclipse.jetty.io.Buffer) */ @Override protected void onResponseHeader(Buffer name, Buffer value) throws IOException { super.onResponseHeader(name,value); if ("Set-Cookie".equalsIgnoreCase(name.toString())) { String v=value.toString(); int c = v.indexOf(';'); if (c>=0) v=v.substring(0,c); addRequestHeader("Cookie",v); } } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onResponseHeaderComplete() */ @Override protected void onResponseHeaderComplete() throws IOException { super.onResponseHeaderComplete(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.Buffer, int, org.eclipse.jetty.io.Buffer) */ @Override protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { _status=status; super.onResponseStatus(version,status,reason); } public boolean next() { if (_u>=_uris.size()) { _u=0; _r++; if (_r>=_repeats) return false; } String uri=_uris.get(_u++); reset(); setMethod(HttpMethods.GET); setURL(uri); try { _client.send(this); } catch(IOException e) { e.printStackTrace(); return false; } return true; } } public static void main(String[] args) throws Exception { if (args.length==0) args=new String[] { "-c", "2", "-r", "2", "http://localhost:8080/dump", "http://localhost:8080/d.txt"}; int concurrent=1; int repeats=1; final List uris = new ArrayList(); for (int i=0; i accumulatedRequest; public SluggishHandler(int requestSize) { accumulatedRequest = new ArrayList(requestSize); } public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { accumulatedRequest.clear(); ServletInputStream input = request.getInputStream(); byte[] buffer = new byte[16384]; int bytesAvailable; while ((bytesAvailable = input.read(buffer,0,buffer.length)) > 0) { //System.err.println("AVAILABLE FOR READ = " + bytesAvailable); for (int n = 0; n < bytesAvailable; ++n) { accumulatedRequest.add(buffer[n]); } try { Thread.sleep(READ_DELAY); } catch (InterruptedException e) { e.printStackTrace(); } } response.setStatus(HttpServletResponse.SC_OK); baseRequest.setHandled(true); //System.err.println("HANDLED"); } public byte[] getAccumulatedRequest() { byte[] buffer = new byte[accumulatedRequest.size()]; int pos = 0; for (Byte b : accumulatedRequest) { buffer[pos++] = b; } return buffer; } } private static boolean compareBuffers(byte[] sent, byte[] received) { if (sent.length != received.length) { System.err.format("Mismatch in sent/received lengths: sent=%d received=%d\n",sent.length,received.length); return false; } else { for (int n = 0; n < sent.length; ++n) { if (sent[n] != received[n]) { System.err.format("Mismatch at offset %d: request=%d response=%d\n",n,sent[n],received[n]); return false; } } } return true; } @Test public void test0() throws Exception { goSlow(20000,10); } @Test public void test1() throws Exception { goSlow(200000,5); } @Test public void test2() throws Exception { goSlow(2000000,2); } void goSlow(int requestSize,int iterations) throws Exception { Server server = new Server(); SocketConnector connector = new SocketConnector(); server.addConnector(connector); SluggishHandler handler = new SluggishHandler(requestSize); server.setHandler(handler); server.start(); int port = connector.getLocalPort(); HttpClient client = new HttpClient(); client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); client.setConnectTimeout(5000); client.setIdleTimeout(60000); client.start(); try { for (int i = 0; i < iterations; ++i) { //System.err.format("-------------- ITERATION %d ------------------\n",i); SluggishExchange exchange = new SluggishExchange(port,requestSize); long startTime = System.currentTimeMillis(); client.send(exchange); exchange.waitForDone(); long endTime = System.currentTimeMillis(); //System.err.println("EXCHANGE STATUS = " + exchange); //System.err.println("ELAPSED MSEC = " + (endTime - startTime)); Assert.assertTrue(compareBuffers(exchange.getRequestBody(),handler.getAccumulatedRequest())); } } finally { server.stop(); server.join(); } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SocketConnectionTest.java000066400000000000000000000067331174773561500317100ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.CountDownLatch; public class SocketConnectionTest extends AbstractConnectionTest { protected HttpClient newHttpClient() { HttpClient httpClient = new HttpClient(); httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET); return httpClient; } @Override public void testServerClosedConnection() throws Exception { // Differently from the SelectConnector, the SocketConnector cannot detect server closes. // Therefore, upon a second send, the exchange will fail. // Applications needs to retry it explicitly. ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(null); int port=serverSocket.getLocalPort(); HttpClient httpClient = this.newHttpClient(); httpClient.setMaxConnectionsPerAddress(1); httpClient.start(); try { CountDownLatch latch = new CountDownLatch(1); HttpExchange exchange = new ConnectionExchange(latch); exchange.setAddress(new Address("localhost", port)); exchange.setRequestURI("/"); httpClient.send(exchange); Socket remote = serverSocket.accept(); // HttpClient.send() above is async, so if we write the response immediately // there is a chance that it arrives before the request is being sent, so we // read the request before sending the response to avoid the race InputStream input = remote.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); String line; while ((line = reader.readLine()) != null) { if (line.length() == 0) break; } OutputStream output = remote.getOutputStream(); output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8")); output.write("Content-Length: 0\r\n".getBytes("UTF-8")); output.write("\r\n".getBytes("UTF-8")); output.flush(); assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); remote.close(); exchange.reset(); httpClient.send(exchange); assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.waitForDone()); } finally { httpClient.stop(); } } public void testIdleConnection() throws Exception { super.testIdleConnection(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesClientTest.java000066400000000000000000000120171174773561500313370ustar00rootroot00000000000000package org.eclipse.jetty.client; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLSocket; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class SslBytesClientTest extends SslBytesTest { private ExecutorService threadPool; private HttpClient client; private SimpleProxy proxy; private SSLServerSocket acceptor; @Before public void init() throws Exception { threadPool = Executors.newCachedThreadPool(); client = new HttpClient(); client.setMaxConnectionsPerAddress(1); client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); File keyStore = MavenTestingUtils.getTestResourceFile("keystore"); SslContextFactory cf = client.getSslContextFactory(); cf.setKeyStorePath(keyStore.getAbsolutePath()); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); client.start(); SSLContext sslContext = cf.getSslContext(); acceptor = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket(0); int serverPort = acceptor.getLocalPort(); proxy = new SimpleProxy(threadPool, "localhost", serverPort); proxy.start(); logger.debug(":{} <==> :{}", proxy.getPort(), serverPort); } @After public void destroy() throws Exception { if (acceptor != null) acceptor.close(); if (proxy != null) proxy.stop(); if (client != null) client.stop(); if (threadPool != null) threadPool.shutdownNow(); } @Test public void testHandshake() throws Exception { ContentExchange exchange = new ContentExchange(true); exchange.setURL("https://localhost:" + proxy.getPort()); String method = HttpMethods.GET; exchange.setMethod(method); client.send(exchange); Assert.assertTrue(proxy.awaitClient(5, TimeUnit.SECONDS)); final SSLSocket server = (SSLSocket)acceptor.accept(); server.setUseClientMode(false); Future handshake = threadPool.submit(new Callable() { public Object call() throws Exception { server.startHandshake(); return null; } }); // Client Hello TLSRecord record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToServer(record); // Server Hello + Certificate + Server Done record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToClient(record); // Client Key Exchange record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToServer(record); // Change Cipher Spec record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType()); proxy.flushToServer(record); // Client Done record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToServer(record); // Change Cipher Spec record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType()); proxy.flushToClient(record); // Server Done record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToClient(record); Assert.assertNull(handshake.get(5, TimeUnit.SECONDS)); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); // Read request BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream(), "UTF-8")); String line = reader.readLine(); Assert.assertTrue(line.startsWith(method)); while (line.length() > 0) line = reader.readLine(); // Write response OutputStream output = server.getOutputStream(); output.write(("HTTP/1.1 200 OK\r\n" + "Content-Length: 0\r\n" + "\r\n").getBytes("UTF-8")); output.flush(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); Assert.assertEquals(HttpStatus.OK_200, exchange.getResponseStatus()); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java000066400000000000000000001755701174773561500314050ustar00rootroot00000000000000package org.eclipse.jetty.client; import static org.hamcrest.Matchers.*; import java.io.BufferedReader; import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.SocketTimeoutException; import java.nio.channels.SocketChannel; import java.util.Arrays; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSocket; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.nio.AsyncConnection; import org.eclipse.jetty.io.nio.SslConnection; import org.eclipse.jetty.server.AsyncHttpConnection; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.OS; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.After; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Test; public class SslBytesServerTest extends SslBytesTest { private final AtomicInteger sslHandles = new AtomicInteger(); private final AtomicInteger sslFlushes = new AtomicInteger(); private final AtomicInteger httpParses = new AtomicInteger(); private final AtomicReference serverEndPoint = new AtomicReference(); private final int idleTimeout = 2000; private ExecutorService threadPool; private Server server; private int serverPort; private SSLContext sslContext; private SimpleProxy proxy; private Runnable idleHook; @Before public void init() throws Exception { threadPool = Executors.newCachedThreadPool(); server = new Server(); SslSelectChannelConnector connector = new SslSelectChannelConnector() { @Override protected SslConnection newSslConnection(AsyncEndPoint endPoint, SSLEngine engine) { serverEndPoint.set(endPoint); return new SslConnection(engine, endPoint) { @Override public Connection handle() throws IOException { sslHandles.incrementAndGet(); return super.handle(); } @Override protected SslEndPoint newSslEndPoint() { return new SslEndPoint() { @Override public int flush(Buffer buffer) throws IOException { sslFlushes.incrementAndGet(); return super.flush(buffer); } }; } @Override public void onIdleExpired(long idleForMs) { final Runnable idleHook = SslBytesServerTest.this.idleHook; if (idleHook != null) idleHook.run(); super.onIdleExpired(idleForMs); } }; } @Override protected AsyncConnection newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint) { return new AsyncHttpConnection(this, endPoint, getServer()) { @Override protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endPoint, HttpParser.EventHandler requestHandler) { return new HttpParser(requestBuffers, endPoint, requestHandler) { @Override public int parseNext() throws IOException { httpParses.incrementAndGet(); return super.parseNext(); } }; } }; } }; connector.setMaxIdleTime(idleTimeout); // connector.setPort(5870); connector.setPort(0); File keyStore = MavenTestingUtils.getTestResourceFile("keystore"); SslContextFactory cf = connector.getSslContextFactory(); cf.setKeyStorePath(keyStore.getAbsolutePath()); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); server.addConnector(connector); server.setHandler(new AbstractHandler() { public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { try { request.setHandled(true); String contentLength = request.getHeader("Content-Length"); if (contentLength != null) { int length = Integer.parseInt(contentLength); ServletInputStream input = httpRequest.getInputStream(); ServletOutputStream output = httpResponse.getOutputStream(); byte[] buffer = new byte[32 * 1024]; while (length > 0) { int read = input.read(buffer); if (read < 0) throw new EOFException(); length -= read; if (target.startsWith("/echo")) output.write(buffer, 0, read); } } } catch (IOException x) { if (!(target.endsWith("suppress_exception"))) throw x; } } }); server.start(); serverPort = connector.getLocalPort(); sslContext = cf.getSslContext(); proxy = new SimpleProxy(threadPool, "localhost", serverPort); proxy.start(); logger.debug(":{} <==> :{}", proxy.getPort(), serverPort); } @After public void destroy() throws Exception { if (proxy != null) proxy.stop(); if (server != null) server.stop(); if (threadPool != null) threadPool.shutdownNow(); } @Test public void testHandshake() throws Exception { final SSLSocket client = newClient(); Future handshake = threadPool.submit(new Callable() { public Object call() throws Exception { client.startHandshake(); return null; } }); // Client Hello TLSRecord record = proxy.readFromClient(); Assert.assertNotNull(record); proxy.flushToServer(record); // Server Hello + Certificate + Server Done record = proxy.readFromServer(); Assert.assertNotNull(record); proxy.flushToClient(record); // Client Key Exchange record = proxy.readFromClient(); Assert.assertNotNull(record); proxy.flushToServer(record); // Change Cipher Spec record = proxy.readFromClient(); Assert.assertNotNull(record); proxy.flushToServer(record); // Client Done record = proxy.readFromClient(); Assert.assertNotNull(record); proxy.flushToServer(record); // Change Cipher Spec record = proxy.readFromServer(); Assert.assertNotNull(record); proxy.flushToClient(record); // Server Done record = proxy.readFromServer(); Assert.assertNotNull(record); proxy.flushToClient(record); Assert.assertNull(handshake.get(5, TimeUnit.SECONDS)); // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); closeClient(client); } @Test public void testHandshakeWithSplitBoundary() throws Exception { final SSLSocket client = newClient(); Future handshake = threadPool.submit(new Callable() { public Object call() throws Exception { client.startHandshake(); return null; } }); // Client Hello TLSRecord record = proxy.readFromClient(); byte[] bytes = record.getBytes(); byte[] chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); byte[] chunk2 = new byte[bytes.length - chunk1.length]; System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length); proxy.flushToServer(100, chunk1); proxy.flushToServer(100, chunk2); // Server Hello + Certificate + Server Done record = proxy.readFromServer(); proxy.flushToClient(record); // Client Key Exchange record = proxy.readFromClient(); bytes = record.getBytes(); chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); chunk2 = new byte[bytes.length - chunk1.length]; System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length); proxy.flushToServer(100, chunk1); proxy.flushToServer(100, chunk2); // Change Cipher Spec record = proxy.readFromClient(); bytes = record.getBytes(); chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); chunk2 = new byte[bytes.length - chunk1.length]; System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length); proxy.flushToServer(100, chunk1); proxy.flushToServer(100, chunk2); // Client Done record = proxy.readFromClient(); bytes = record.getBytes(); chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); chunk2 = new byte[bytes.length - chunk1.length]; System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length); proxy.flushToServer(100, chunk1); proxy.flushToServer(100, chunk2); // Change Cipher Spec record = proxy.readFromServer(); Assert.assertNotNull(record); proxy.flushToClient(record); // Server Done record = proxy.readFromServer(); Assert.assertNotNull(record); proxy.flushToClient(record); Assert.assertNull(handshake.get(5, TimeUnit.SECONDS)); // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); client.close(); // Close Alert record = proxy.readFromClient(); bytes = record.getBytes(); chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); chunk2 = new byte[bytes.length - chunk1.length]; System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length); proxy.flushToServer(100, chunk1); proxy.flushToServer(100, chunk2); // Socket close record = proxy.readFromClient(); Assert.assertNull(String.valueOf(record), record); proxy.flushToServer(record); // Close Alert record = proxy.readFromServer(); proxy.flushToClient(record); // Socket close record = proxy.readFromServer(); Assert.assertNull(String.valueOf(record), record); proxy.flushToClient(record); } @Test public void testClientHelloIncompleteThenReset() throws Exception { final SSLSocket client = newClient(); threadPool.submit(new Callable() { public Object call() throws Exception { client.startHandshake(); return null; } }); // Client Hello TLSRecord record = proxy.readFromClient(); byte[] bytes = record.getBytes(); byte[] chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); proxy.flushToServer(100, chunk1); proxy.sendRSTToServer(); // Wait a while to detect spinning TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); client.close(); } @Test public void testClientHelloThenReset() throws Exception { final SSLSocket client = newClient(); threadPool.submit(new Callable() { public Object call() throws Exception { client.startHandshake(); return null; } }); // Client Hello TLSRecord record = proxy.readFromClient(); Assert.assertNotNull(record); proxy.flushToServer(record); proxy.sendRSTToServer(); // Wait a while to detect spinning TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); client.close(); } @Test public void testHandshakeThenReset() throws Exception { final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); proxy.sendRSTToServer(); // Wait a while to detect spinning TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); client.close(); } @Test public void testRequestIncompleteThenReset() throws Exception { final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n").getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Application data TLSRecord record = proxy.readFromClient(); byte[] bytes = record.getBytes(); byte[] chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); proxy.flushToServer(100, chunk1); proxy.sendRSTToServer(); // Wait a while to detect spinning TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); client.close(); } @Test public void testRequestResponse() throws Exception { final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); Future request = threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n").getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Application data TLSRecord record = proxy.readFromClient(); proxy.flushToServer(record); Assert.assertNull(request.get(5, TimeUnit.SECONDS)); // Application data record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToClient(record); BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8")); String line = reader.readLine(); Assert.assertNotNull(line); Assert.assertTrue(line.startsWith("HTTP/1.1 200 ")); while ((line = reader.readLine()) != null) { if (line.trim().length() == 0) break; } // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); closeClient(client); } @Test public void testHandshakeAndRequestOneByteAtATime() throws Exception { final SSLSocket client = newClient(); Future handshake = threadPool.submit(new Callable() { public Object call() throws Exception { client.startHandshake(); return null; } }); // Client Hello TLSRecord record = proxy.readFromClient(); for (byte b : record.getBytes()) proxy.flushToServer(50, b); // Server Hello + Certificate + Server Done record = proxy.readFromServer(); proxy.flushToClient(record); // Client Key Exchange record = proxy.readFromClient(); for (byte b : record.getBytes()) proxy.flushToServer(50, b); // Change Cipher Spec record = proxy.readFromClient(); for (byte b : record.getBytes()) proxy.flushToServer(50, b); // Client Done record = proxy.readFromClient(); for (byte b : record.getBytes()) proxy.flushToServer(50, b); // Change Cipher Spec record = proxy.readFromServer(); proxy.flushToClient(record); // Server Done record = proxy.readFromServer(); proxy.flushToClient(record); Assert.assertNull(handshake.get(5, TimeUnit.SECONDS)); Future request = threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n").getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Application data record = proxy.readFromClient(); for (byte b : record.getBytes()) proxy.flushToServer(50, b); Assert.assertNull(request.get(5, TimeUnit.SECONDS)); // Application data record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToClient(record); BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8")); String line = reader.readLine(); Assert.assertNotNull(line); Assert.assertTrue(line.startsWith("HTTP/1.1 200 ")); while ((line = reader.readLine()) != null) { if (line.trim().length() == 0) break; } // Check that we did not spin TimeUnit.MILLISECONDS.sleep(1000); Assert.assertThat(sslHandles.get(), lessThan(750)); Assert.assertThat(sslFlushes.get(), lessThan(750)); // An average of 958 httpParses is seen in standard Oracle JDK's // An average of 1183 httpParses is seen in OpenJDK JVMs. Assert.assertThat(httpParses.get(), lessThan(1500)); client.close(); // Close Alert record = proxy.readFromClient(); for (byte b : record.getBytes()) proxy.flushToServer(50, b); // Socket close record = proxy.readFromClient(); Assert.assertNull(String.valueOf(record), record); proxy.flushToServer(record); // Close Alert record = proxy.readFromServer(); proxy.flushToClient(record); // Socket close record = proxy.readFromServer(); Assert.assertNull(String.valueOf(record), record); proxy.flushToClient(record); } @Test public void testRequestWithCloseAlertAndShutdown() throws Exception { // See next test on why we only run in Linux Assume.assumeTrue(OS.IS_LINUX); final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); Future request = threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n").getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Application data TLSRecord record = proxy.readFromClient(); proxy.flushToServer(record); Assert.assertNull(request.get(5, TimeUnit.SECONDS)); client.close(); // Close Alert record = proxy.readFromClient(); proxy.flushToServer(record); // Socket close record = proxy.readFromClient(); Assert.assertNull(String.valueOf(record), record); proxy.flushToServer(record); // Expect response from server // SSLSocket is limited and we cannot read the response, but we make sure // it is application data and not a close alert record = proxy.readFromServer(); Assert.assertNotNull(record); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToClient(record); // Close Alert record = proxy.readFromServer(); Assert.assertNotNull(record); Assert.assertEquals(TLSRecord.Type.ALERT, record.getType()); // We can't forward to the client, its socket is already closed // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); // Socket close record = proxy.readFromServer(); Assert.assertNull(String.valueOf(record), record); proxy.flushToClient(record); } @Test public void testRequestWithCloseAlert() throws Exception { // Currently we are ignoring this test on anything other then linux // http://tools.ietf.org/html/rfc2246#section-7.2.1 // TODO (react to this portion which seems to allow win/mac behavior) // It is required that the other party respond with a close_notify alert of its own // and close down the connection immediately, discarding any pending writes. It is not // required for the initiator of the close to wait for the responding // close_notify alert before closing the read side of the connection. Assume.assumeTrue(OS.IS_LINUX); final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); Future request = threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n").getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Application data TLSRecord record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToServer(record); Assert.assertNull(request.get(5, TimeUnit.SECONDS)); client.close(); // Close Alert record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.ALERT, record.getType()); proxy.flushToServer(record); // Do not close the raw socket yet // Expect response from server // SSLSocket is limited and we cannot read the response, but we make sure // it is application data and not a close alert record = proxy.readFromServer(); Assert.assertNotNull(record); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToClient(record); // Close Alert record = proxy.readFromServer(); Assert.assertNotNull(record); Assert.assertEquals(TLSRecord.Type.ALERT, record.getType()); // We can't forward to the client, its socket is already closed // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); // Socket close record = proxy.readFromClient(); Assert.assertNull(String.valueOf(record), record); proxy.flushToServer(record); // Socket close record = proxy.readFromServer(); Assert.assertNull(String.valueOf(record), record); proxy.flushToClient(record); } @Test public void testRequestWithRawClose() throws Exception { final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); Future request = threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n").getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Application data TLSRecord record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToServer(record); Assert.assertNull(request.get(5, TimeUnit.SECONDS)); // Application data record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToClient(record); // Close the raw socket, this generates a truncation attack proxy.flushToServer((TLSRecord)null); // Expect raw close from server record = proxy.readFromServer(); Assert.assertNull(String.valueOf(record), record); proxy.flushToClient(record); // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); client.close(); } @Test public void testRequestWithBigContentWriteBlockedThenReset() throws Exception { final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); byte[] data = new byte[128 * 1024]; Arrays.fill(data, (byte)'X'); final String content = new String(data, "UTF-8"); Future request = threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "GET /echo HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Length: " + content.length() + "\r\n" + "\r\n" + content).getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Nine TLSRecords will be generated for the request for (int i = 0; i < 9; ++i) { // Application data TLSRecord record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToServer(record, 0); } Assert.assertNull(request.get(5, TimeUnit.SECONDS)); // We asked the server to echo back the data we sent // but we do not read it, thus causing a write interest // on the server. // However, we then simulate that the client resets the // connection, and this will cause an exception in the // server that is trying to write the data TimeUnit.MILLISECONDS.sleep(500); proxy.sendRSTToServer(); // Wait a while to detect spinning TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); client.close(); } @Test public void testRequestWithBigContentReadBlockedThenReset() throws Exception { final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); byte[] data = new byte[128 * 1024]; Arrays.fill(data, (byte)'X'); final String content = new String(data, "UTF-8"); Future request = threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "GET /echo_suppress_exception HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Length: " + content.length() + "\r\n" + "\r\n" + content).getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Nine TLSRecords will be generated for the request, // but we write only 5 of them, so the server goes in read blocked state for (int i = 0; i < 5; ++i) { // Application data TLSRecord record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToServer(record, 0); } Assert.assertNull(request.get(5, TimeUnit.SECONDS)); // The server should be read blocked, and we send a RST TimeUnit.MILLISECONDS.sleep(500); proxy.sendRSTToServer(); // Wait a while to detect spinning TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); client.close(); } @Test public void testRequestWithCloseAlertWithSplitBoundary() throws Exception { if ( !OS.IS_LINUX ) { // currently we are ignoring this test on anything other then linux //http://tools.ietf.org/html/rfc2246#section-7.2.1 // TODO (react to this portion which seems to allow win/mac behavior) //It is required that the other party respond with a close_notify alert of its own //and close down the connection immediately, discarding any pending writes. It is not //required for the initiator of the close to wait for the responding //close_notify alert before closing the read side of the connection. return; } final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); Future request = threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n").getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Application data TLSRecord dataRecord = proxy.readFromClient(); Assert.assertNull(request.get(5, TimeUnit.SECONDS)); client.close(); // Close Alert TLSRecord closeRecord = proxy.readFromClient(); // Send request and half of the close alert bytes byte[] dataBytes = dataRecord.getBytes(); byte[] closeBytes = closeRecord.getBytes(); byte[] bytes = new byte[dataBytes.length + closeBytes.length / 2]; System.arraycopy(dataBytes, 0, bytes, 0, dataBytes.length); System.arraycopy(closeBytes, 0, bytes, dataBytes.length, closeBytes.length / 2); proxy.flushToServer(100, bytes); bytes = new byte[closeBytes.length - closeBytes.length / 2]; System.arraycopy(closeBytes, closeBytes.length / 2, bytes, 0, bytes.length); proxy.flushToServer(100, bytes); // Do not close the raw socket yet // Expect response from server // SSLSocket is limited and we cannot read the response, but we make sure // it is application data and not a close alert TLSRecord record = proxy.readFromServer(); Assert.assertNotNull(record); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToClient(record); // Close Alert record = proxy.readFromServer(); Assert.assertNotNull(record); Assert.assertEquals(TLSRecord.Type.ALERT, record.getType()); // We can't forward to the client, its socket is already closed // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); // Socket close record = proxy.readFromClient(); Assert.assertNull(String.valueOf(record), record); proxy.flushToServer(record); // Socket close record = proxy.readFromServer(); Assert.assertNull(String.valueOf(record), record); proxy.flushToClient(record); } @Test public void testRequestWithContentWithSplitBoundary() throws Exception { final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); final String content = "0123456789ABCDEF"; Future request = threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "POST / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: " + content.length() + "\r\n" + "\r\n" + content).getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Application data TLSRecord record = proxy.readFromClient(); Assert.assertNull(request.get(5, TimeUnit.SECONDS)); byte[] chunk1 = new byte[2 * record.getBytes().length / 3]; System.arraycopy(record.getBytes(), 0, chunk1, 0, chunk1.length); proxy.flushToServer(100, chunk1); byte[] chunk2 = new byte[record.getBytes().length - chunk1.length]; System.arraycopy(record.getBytes(), chunk1.length, chunk2, 0, chunk2.length); proxy.flushToServer(100, chunk2); record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToClient(record); BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8")); String line = reader.readLine(); Assert.assertNotNull(line); Assert.assertTrue(line.startsWith("HTTP/1.1 200 ")); while ((line = reader.readLine()) != null) { if (line.trim().length() == 0) break; } // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); closeClient(client); } @Test public void testRequestWithBigContentWithSplitBoundary() throws Exception { final SSLSocket client = newClient(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); // Use a content that is larger than the TLS record which is 2^14 (around 16k) byte[] data = new byte[128 * 1024]; Arrays.fill(data, (byte)'X'); final String content = new String(data, "UTF-8"); Future request = threadPool.submit(new Callable() { public Object call() throws Exception { OutputStream clientOutput = client.getOutputStream(); clientOutput.write(("" + "POST / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: " + content.length() + "\r\n" + "\r\n" + content).getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Nine TLSRecords will be generated for the request for (int i = 0; i < 9; ++i) { // Application data TLSRecord record = proxy.readFromClient(); byte[] bytes = record.getBytes(); byte[] chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); byte[] chunk2 = new byte[bytes.length - chunk1.length]; System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length); proxy.flushToServer(100, chunk1); proxy.flushToServer(100, chunk2); } // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(150)); Assert.assertNull(request.get(5, TimeUnit.SECONDS)); TLSRecord record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToClient(record); BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8")); String line = reader.readLine(); Assert.assertNotNull(line); Assert.assertTrue(line.startsWith("HTTP/1.1 200 ")); while ((line = reader.readLine()) != null) { if (line.trim().length() == 0) break; } // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(150)); closeClient(client); } @Test public void testRequestWithBigContentWithRenegotiationInMiddleOfContent() throws Exception { assumeJavaVersionSupportsTLSRenegotiations(); final SSLSocket client = newClient(); final OutputStream clientOutput = client.getOutputStream(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); // Use a content that is larger than the TLS record which is 2^14 (around 16k) byte[] data1 = new byte[80 * 1024]; Arrays.fill(data1, (byte)'X'); String content1 = new String(data1, "UTF-8"); byte[] data2 = new byte[48 * 1024]; Arrays.fill(data2, (byte)'Y'); final String content2 = new String(data2, "UTF-8"); // Write only part of the body automaticProxyFlow = proxy.startAutomaticFlow(); clientOutput.write(("" + "POST / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: " + (content1.length() + content2.length()) + "\r\n" + "\r\n" + content1).getBytes("UTF-8")); clientOutput.flush(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); // Renegotiate Future renegotiation = threadPool.submit(new Callable() { public Object call() throws Exception { client.startHandshake(); return null; } }); // Renegotiation Handshake TLSRecord record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToServer(record); // Renegotiation Handshake record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToClient(record); // Renegotiation Change Cipher record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType()); proxy.flushToClient(record); // Renegotiation Handshake record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToClient(record); // Trigger a read to have the client write the final renegotiation steps client.setSoTimeout(100); try { client.getInputStream().read(); Assert.fail(); } catch (SocketTimeoutException x) { // Expected } // Renegotiation Change Cipher record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType()); proxy.flushToServer(record); // Renegotiation Handshake record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToServer(record); Assert.assertNull(renegotiation.get(5, TimeUnit.SECONDS)); // Write the rest of the request Future request = threadPool.submit(new Callable() { public Object call() throws Exception { clientOutput.write(content2.getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Three TLSRecords will be generated for the remainder of the content for (int i = 0; i < 3; ++i) { // Application data record = proxy.readFromClient(); proxy.flushToServer(record); } Assert.assertNull(request.get(5, TimeUnit.SECONDS)); // Read response // Application Data record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToClient(record); BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8")); String line = reader.readLine(); Assert.assertNotNull(line); Assert.assertTrue(line.startsWith("HTTP/1.1 200 ")); while ((line = reader.readLine()) != null) { if (line.trim().length() == 0) break; } // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); closeClient(client); } @Test public void testRequestWithBigContentWithRenegotiationInMiddleOfContentWithSplitBoundary() throws Exception { assumeJavaVersionSupportsTLSRenegotiations(); final SSLSocket client = newClient(); final OutputStream clientOutput = client.getOutputStream(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); // Use a content that is larger than the TLS record which is 2^14 (around 16k) byte[] data1 = new byte[80 * 1024]; Arrays.fill(data1, (byte)'X'); String content1 = new String(data1, "UTF-8"); byte[] data2 = new byte[48 * 1024]; Arrays.fill(data2, (byte)'Y'); final String content2 = new String(data2, "UTF-8"); // Write only part of the body automaticProxyFlow = proxy.startAutomaticFlow(); clientOutput.write(("" + "POST / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: " + (content1.length() + content2.length()) + "\r\n" + "\r\n" + content1).getBytes("UTF-8")); clientOutput.flush(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); // Renegotiate Future renegotiation = threadPool.submit(new Callable() { public Object call() throws Exception { client.startHandshake(); return null; } }); // Renegotiation Handshake TLSRecord record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); byte[] bytes = record.getBytes(); byte[] chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); byte[] chunk2 = new byte[bytes.length - chunk1.length]; System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length); proxy.flushToServer(100, chunk1); proxy.flushToServer(100, chunk2); // Renegotiation Handshake record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToClient(record); // Renegotiation Change Cipher record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType()); proxy.flushToClient(record); // Renegotiation Handshake record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); proxy.flushToClient(record); // Trigger a read to have the client write the final renegotiation steps client.setSoTimeout(100); try { client.getInputStream().read(); Assert.fail(); } catch (SocketTimeoutException x) { // Expected } // Renegotiation Change Cipher record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType()); bytes = record.getBytes(); chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); chunk2 = new byte[bytes.length - chunk1.length]; System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length); proxy.flushToServer(100, chunk1); proxy.flushToServer(100, chunk2); // Renegotiation Handshake record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType()); bytes = record.getBytes(); chunk1 = new byte[2 * bytes.length / 3]; System.arraycopy(bytes, 0, chunk1, 0, chunk1.length); chunk2 = new byte[bytes.length - chunk1.length]; System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length); proxy.flushToServer(100, chunk1); // Do not write the second chunk now, but merge it with content, see below Assert.assertNull(renegotiation.get(5, TimeUnit.SECONDS)); // Write the rest of the request Future request = threadPool.submit(new Callable() { public Object call() throws Exception { clientOutput.write(content2.getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Three TLSRecords will be generated for the remainder of the content // Merge the last chunk of the renegotiation with the first data record record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); byte[] dataBytes = record.getBytes(); byte[] mergedBytes = new byte[chunk2.length + dataBytes.length]; System.arraycopy(chunk2, 0, mergedBytes, 0, chunk2.length); System.arraycopy(dataBytes, 0, mergedBytes, chunk2.length, dataBytes.length); proxy.flushToServer(100, mergedBytes); // Write the remaining 2 TLS records for (int i = 0; i < 2; ++i) { // Application data record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToServer(record); } Assert.assertNull(request.get(5, TimeUnit.SECONDS)); // Read response // Application Data record = proxy.readFromServer(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToClient(record); BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8")); String line = reader.readLine(); Assert.assertNotNull(line); Assert.assertTrue(line.startsWith("HTTP/1.1 200 ")); while ((line = reader.readLine()) != null) { if (line.trim().length() == 0) break; } // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(100)); closeClient(client); } @Test public void testServerShutdownOutputClientDoesNotCloseServerCloses() throws Exception { final SSLSocket client = newClient(); final OutputStream clientOutput = client.getOutputStream(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); byte[] data = new byte[3 * 1024]; Arrays.fill(data, (byte)'Y'); String content = new String(data, "UTF-8"); automaticProxyFlow = proxy.startAutomaticFlow(); clientOutput.write(("" + "POST / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: " + content.length() + "\r\n" + "Connection: close\r\n" + "\r\n" + content).getBytes("UTF-8")); clientOutput.flush(); BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8")); String line = reader.readLine(); Assert.assertNotNull(line); Assert.assertTrue(line.startsWith("HTTP/1.1 200 ")); while ((line = reader.readLine()) != null) { if (line.trim().length() == 0) break; } Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); // Check client is at EOF Assert.assertEquals(-1,client.getInputStream().read()); // Client should close the socket, but let's hold it open. // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); // The server has shutdown the output since the client sent a Connection: close // but the client does not close, so the server must idle timeout the endPoint. TimeUnit.MILLISECONDS.sleep(idleTimeout + idleTimeout/2); Assert.assertFalse(serverEndPoint.get().isOpen()); } @Test public void testPlainText() throws Exception { final SSLSocket client = newClient(); threadPool.submit(new Callable() { public Object call() throws Exception { client.startHandshake(); return null; } }); // Instead of passing the Client Hello, we simulate plain text was passed in proxy.flushToServer(0, "GET / HTTP/1.1\r\n".getBytes("UTF-8")); // We expect that the server closes the connection immediately TLSRecord record = proxy.readFromServer(); Assert.assertNull(String.valueOf(record), record); // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); client.close(); } @Test public void testRequestConcurrentWithIdleExpiration() throws Exception { final SSLSocket client = newClient(); final OutputStream clientOutput = client.getOutputStream(); final CountDownLatch latch = new CountDownLatch(1); idleHook = new Runnable() { public void run() { if (latch.getCount()==0) return; try { // Send request clientOutput.write(("" + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n").getBytes("UTF-8")); clientOutput.flush(); latch.countDown(); } catch (Exception x) { // Latch won't trigger and test will fail x.printStackTrace(); } } }; SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); Assert.assertTrue(latch.await(idleTimeout * 2, TimeUnit.MILLISECONDS)); // Be sure that the server sent a SSL close alert TLSRecord record = proxy.readFromServer(); Assert.assertNotNull(record); Assert.assertEquals(TLSRecord.Type.ALERT, record.getType()); // Write the request to the server, to simulate a request // concurrent with the SSL close alert record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToServer(record, 0); // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); //System.err.println(((Dumpable)server.getConnectors()[0]).dump()); Assert.assertThat(((Dumpable)server.getConnectors()[0]).dump(),containsString("SCEP@")); completeClose(client); TimeUnit.MILLISECONDS.sleep(200); //System.err.println(((Dumpable)server.getConnectors()[0]).dump()); Assert.assertThat(((Dumpable)server.getConnectors()[0]).dump(),not(containsString("SCEP@"))); } /* @Test public void testRequestWriteBlockedWithPipelinedRequest() throws Exception { final SSLSocket client = newClient(); final OutputStream clientOutput = client.getOutputStream(); SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); client.startHandshake(); Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); byte[] data = new byte[128 * 1024]; Arrays.fill(data, (byte)'X'); final String content = new String(data, "UTF-8"); Future request = threadPool.submit(new Callable() { public Object call() throws Exception { clientOutput.write(("" + "POST /echo HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Length: " + content.length() + "\r\n" + "\r\n" + content).getBytes("UTF-8")); clientOutput.flush(); return null; } }); // Nine TLSRecords will be generated for the request for (int i = 0; i < 9; ++i) { // Application data TLSRecord record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToServer(record, 0); } Assert.assertNull(request.get(5, TimeUnit.SECONDS)); // We do not read the big request to cause a write blocked on the server TimeUnit.MILLISECONDS.sleep(500); // Now send the pipelined request Future pipelined = threadPool.submit(new Callable() { public Object call() throws Exception { clientOutput.write(("" + "GET /pipelined HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n").getBytes("UTF-8")); clientOutput.flush(); return null; } }); TLSRecord record = proxy.readFromClient(); Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); proxy.flushToServer(record, 0); Assert.assertNull(pipelined.get(5, TimeUnit.SECONDS)); // Check that we did not spin TimeUnit.MILLISECONDS.sleep(500); Assert.assertThat(sslHandles.get(), lessThan(20)); Assert.assertThat(sslFlushes.get(), lessThan(20)); Assert.assertThat(httpParses.get(), lessThan(50)); Thread.sleep(5000); // closeClient(client); } */ private void assumeJavaVersionSupportsTLSRenegotiations() { // Due to a security bug, TLS renegotiations were disabled in JDK 1.6.0_19-21 // so we check the java version in order to avoid to fail the test. String javaVersion = System.getProperty("java.version"); Pattern regexp = Pattern.compile("1\\.6\\.0_(\\d{2})"); Matcher matcher = regexp.matcher(javaVersion); if (matcher.matches()) { String nano = matcher.group(1); Assume.assumeThat(Integer.parseInt(nano), greaterThan(21)); } } private SSLSocket newClient() throws IOException, InterruptedException { SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket("localhost", proxy.getPort()); client.setUseClientMode(true); Assert.assertTrue(proxy.awaitClient(5, TimeUnit.SECONDS)); return client; } private void closeClient(SSLSocket client) throws Exception { client.close(); // Close Alert TLSRecord record = proxy.readFromClient(); proxy.flushToServer(record); // Socket close record = proxy.readFromClient(); Assert.assertNull(String.valueOf(record), record); proxy.flushToServer(record); // Close Alert record = proxy.readFromServer(); proxy.flushToClient(record); // Socket close record = proxy.readFromServer(); Assert.assertNull(String.valueOf(record), record); proxy.flushToClient(record); } private void completeClose(SSLSocket client) throws Exception { client.close(); // Close Alert TLSRecord record = proxy.readFromClient(); proxy.flushToServer(record); // Socket close record = proxy.readFromClient(); Assert.assertNull(String.valueOf(record), record); proxy.flushToServer(record); // Close Alert record = proxy.readFromServer(); proxy.flushToClient(record); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java000066400000000000000000000261061174773561500302040ustar00rootroot00000000000000package org.eclipse.jetty.client; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.junit.Assert; public abstract class SslBytesTest { protected final Logger logger = Log.getLogger(getClass()); public static class TLSRecord { private final SslBytesServerTest.TLSRecord.Type type; private final byte[] bytes; public TLSRecord(SslBytesServerTest.TLSRecord.Type type, byte[] bytes) { this.type = type; this.bytes = bytes; } public SslBytesServerTest.TLSRecord.Type getType() { return type; } public byte[] getBytes() { return bytes; } @Override public String toString() { return "TLSRecord [" + type + "] " + bytes.length + " bytes"; } public enum Type { CHANGE_CIPHER_SPEC(20), ALERT(21), HANDSHAKE(22), APPLICATION(23); private int code; private Type(int code) { this.code = code; SslBytesServerTest.TLSRecord.Type.Mapper.codes.put(this.code, this); } public static SslBytesServerTest.TLSRecord.Type from(int code) { SslBytesServerTest.TLSRecord.Type result = SslBytesServerTest.TLSRecord.Type.Mapper.codes.get(code); if (result == null) throw new IllegalArgumentException("Invalid TLSRecord.Type " + code); return result; } private static class Mapper { private static final Map codes = new HashMap(); } } } public class SimpleProxy implements Runnable { private final CountDownLatch latch = new CountDownLatch(1); private final ExecutorService threadPool; private final String serverHost; private final int serverPort; private volatile ServerSocket serverSocket; private volatile Socket server; private volatile Socket client; public SimpleProxy(ExecutorService threadPool, String serverHost, int serverPort) { this.threadPool = threadPool; this.serverHost = serverHost; this.serverPort = serverPort; } public void start() throws Exception { // serverSocket = new ServerSocket(5871); serverSocket = new ServerSocket(0); Thread acceptor = new Thread(this); acceptor.start(); server = new Socket(serverHost, serverPort); } public void stop() throws Exception { serverSocket.close(); } public void run() { try { client = serverSocket.accept(); latch.countDown(); } catch (IOException x) { x.printStackTrace(); } } public int getPort() { return serverSocket.getLocalPort(); } public TLSRecord readFromClient() throws IOException { TLSRecord record = read(client); logger.debug("C --> P {}", record); return record; } private TLSRecord read(Socket socket) throws IOException { InputStream input = socket.getInputStream(); int first = -2; while (true) { try { socket.setSoTimeout(500); first = input.read(); break; } catch (SocketTimeoutException x) { if (Thread.currentThread().isInterrupted()) break; } } if (first == -2) throw new InterruptedIOException(); else if (first == -1) return null; if (first >= 0x80) { // SSLv2 Record int hiLength = first & 0x3F; int loLength = input.read(); int length = (hiLength << 8) + loLength; byte[] bytes = new byte[2 + length]; bytes[0] = (byte)first; bytes[1] = (byte)loLength; return read(TLSRecord.Type.HANDSHAKE, input, bytes, 2, length); } else { // TLS Record int major = input.read(); int minor = input.read(); int hiLength = input.read(); int loLength = input.read(); int length = (hiLength << 8) + loLength; byte[] bytes = new byte[1 + 2 + 2 + length]; bytes[0] = (byte)first; bytes[1] = (byte)major; bytes[2] = (byte)minor; bytes[3] = (byte)hiLength; bytes[4] = (byte)loLength; return read(TLSRecord.Type.from(first), input, bytes, 5, length); } } private TLSRecord read(SslBytesServerTest.TLSRecord.Type type, InputStream input, byte[] bytes, int offset, int length) throws IOException { while (length > 0) { int read = input.read(bytes, offset, length); if (read < 0) throw new EOFException(); offset += read; length -= read; } return new TLSRecord(type, bytes); } public void flushToServer(TLSRecord record) throws Exception { flushToServer(record, 100); } public void flushToServer(TLSRecord record, long sleep) throws Exception { if (record == null) { server.shutdownOutput(); if (client.isOutputShutdown()) { client.close(); server.close(); } } else { flush(sleep, server, record.getBytes()); } } public void flushToServer(long sleep, byte... bytes) throws Exception { flush(sleep, server, bytes); } private void flush(long sleep, Socket socket, byte... bytes) throws Exception { OutputStream output = socket.getOutputStream(); output.write(bytes); output.flush(); if (sleep > 0) TimeUnit.MILLISECONDS.sleep(sleep); } public TLSRecord readFromServer() throws IOException { TLSRecord record = read(server); logger.debug("P <-- S {}", record); return record; } public void flushToClient(TLSRecord record) throws Exception { if (record == null) { client.shutdownOutput(); if (server.isOutputShutdown()) { server.close(); client.close(); } } else { flush(0, client, record.getBytes()); } } public SslBytesServerTest.SimpleProxy.AutomaticFlow startAutomaticFlow() throws InterruptedException { final CountDownLatch startLatch = new CountDownLatch(2); final CountDownLatch stopLatch = new CountDownLatch(2); Future clientToServer = threadPool.submit(new Callable() { public Object call() throws Exception { startLatch.countDown(); logger.debug("Automatic flow C --> S started"); try { while (true) { flushToServer(readFromClient(), 0); } } catch (InterruptedIOException x) { return null; } finally { stopLatch.countDown(); logger.debug("Automatic flow C --> S finished"); } } }); Future serverToClient = threadPool.submit(new Callable() { public Object call() throws Exception { startLatch.countDown(); logger.debug("Automatic flow C <-- S started"); try { while (true) { flushToClient(readFromServer()); } } catch (InterruptedIOException x) { return null; } finally { stopLatch.countDown(); logger.debug("Automatic flow C <-- S finished"); } } }); Assert.assertTrue(startLatch.await(5, TimeUnit.SECONDS)); return new SslBytesServerTest.SimpleProxy.AutomaticFlow(stopLatch, clientToServer, serverToClient); } public boolean awaitClient(int time, TimeUnit unit) throws InterruptedException { return latch.await(time, unit); } public void sendRSTToServer() throws IOException { // Calling setSoLinger(true, 0) causes close() // to send a RST instead of a FIN, causing an // exception to be thrown on the other end server.setSoLinger(true, 0); server.close(); } public class AutomaticFlow { private final CountDownLatch stopLatch; private final Future clientToServer; private final Future serverToClient; public AutomaticFlow(CountDownLatch stopLatch, Future clientToServer, Future serverToClient) { this.stopLatch = stopLatch; this.clientToServer = clientToServer; this.serverToClient = serverToClient; } public boolean stop(long time, TimeUnit unit) throws InterruptedException { clientToServer.cancel(true); serverToClient.cancel(true); return stopLatch.await(time, unit); } } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslCertSecuredExchangeTest.java000066400000000000000000000154501174773561500327710ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.security.Principal; import java.util.Collections; import java.util.HashSet; import java.util.Set; import javax.security.auth.Subject; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.MappedLoginService.KnownUser; import org.eclipse.jetty.security.authentication.ClientCertAuthenticator; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.util.security.Credential; import org.eclipse.jetty.util.ssl.SslContextFactory; public class SslCertSecuredExchangeTest// extends ContentExchangeTest { // certificate is valid until Jan 1, 2050 private String _keypath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-valid.keystore").getAbsolutePath(); private String _trustpath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-trust.keystore").getAbsolutePath(); private String _clientpath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-client.keystore").getAbsolutePath(); private String _crlpath = MavenTestingUtils.getTargetFile("test-policy/validation/crlfile.pem").getAbsolutePath(); private String _password = "OBF:1wnl1sw01ta01z0f1tae1svy1wml"; protected void configureServer(Server server) throws Exception { //setProtocol("https"); SslSelectChannelConnector connector = new SslSelectChannelConnector(); SslContextFactory cf = connector.getSslContextFactory(); cf.setValidateCerts(true); cf.setCrlPath(_crlpath); cf.setNeedClientAuth(true); cf.setKeyStorePath(_keypath); cf.setKeyStorePassword(_password); cf.setKeyManagerPassword(_password); cf.setTrustStore(_trustpath); cf.setTrustStorePassword(_password); server.addConnector(connector); LoginService loginService = new LoginService() { public String getName() { return "MyLoginService"; } public UserIdentity login(String username, Object credentials) { return new UserIdentity() { public Subject getSubject() { Subject subject = new Subject(); subject.getPrincipals().add(getUserPrincipal()); subject.setReadOnly(); return subject; } public Principal getUserPrincipal() { return new KnownUser("client", new Credential() { @Override public boolean check(Object credentials) { return true; } }); } public boolean isUserInRole(String role, Scope scope) { return true; } }; } public boolean validate(UserIdentity user) { return true; } public IdentityService getIdentityService() { return null; } public void setIdentityService(IdentityService service) {} public void logout(UserIdentity user) {} }; server.addBean(loginService); ConstraintSecurityHandler security = new ConstraintSecurityHandler(); server.setHandler(security); Constraint constraint = new Constraint(); constraint.setName("auth"); constraint.setAuthenticate( true ); constraint.setRoles(new String[]{"user", "admin"}); ConstraintMapping mapping = new ConstraintMapping(); mapping.setPathSpec( "/*" ); mapping.setConstraint( constraint ); Set knownRoles = new HashSet(); knownRoles.add("user"); knownRoles.add("admin"); security.setConstraintMappings(Collections.singletonList(mapping), knownRoles); security.setLoginService(loginService); ClientCertAuthenticator auth = new ClientCertAuthenticator(); auth.setValidateCerts(true); auth.setCrlPath(_crlpath); auth.setTrustStore(_trustpath); auth.setTrustStorePassword(_password); security.setAuthenticator(auth); security.setAuthMethod(auth.getAuthMethod()); security.setRealmName("MyRealm"); security.setStrict(true); ServletContextHandler root = new ServletContextHandler(); root.setContextPath("/"); // root.setResourceBase(getBasePath()); ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); servletHolder.setInitParameter( "gzip", "true" ); root.addServlet( servletHolder, "/*" ); // Handler handler = new TestHandler(getBasePath()); HandlerCollection handlers = new HandlerCollection(); // handlers.setHandlers(new Handler[]{handler, root}); security.setHandler(handlers); } // @Override // protected void configureClient(HttpClient client) throws Exception // { // SslContextFactory cf = client.getSslContextFactory(); // cf.setValidateCerts(true); // cf.setCrlPath(_crlpath); // // cf.setCertAlias("client"); // cf.setKeyStorePath(_clientpath); // cf.setKeyStorePassword(_password); // cf.setKeyManagerPassword(_password); // // cf.setTrustStore(_trustpath); // cf.setTrustStorePassword(_password); // } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslContentExchangeTest.java000066400000000000000000000052741174773561500321760ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.File; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; public class SslContentExchangeTest extends ContentExchangeTest { protected void configureServer(Server server) throws Exception { setProtocol("https"); SslSelectChannelConnector connector = new SslSelectChannelConnector(); File keystore = MavenTestingUtils.getTestResourceFile("keystore"); SslContextFactory cf = connector.getSslContextFactory(); cf.setKeyStorePath(keystore.getAbsolutePath()); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); cf.setSessionCachingEnabled(true); server.addConnector(connector); Handler handler = new TestHandler(getBasePath()); ServletContextHandler root = new ServletContextHandler(); root.setContextPath("/"); root.setResourceBase(getBasePath()); ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); servletHolder.setInitParameter( "gzip", "true" ); root.addServlet( servletHolder, "/*" ); HandlerCollection handlers = new HandlerCollection(); handlers.setHandlers(new Handler[]{handler, root}); server.setHandler( handlers ); } @Override protected void configureClient(HttpClient client) throws Exception { client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); SslContextFactory cf = client.getSslContextFactory(); cf.setSessionCachingEnabled(true); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslHttpExchangeTest.java000066400000000000000000000074051174773561500315010ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator; import org.eclipse.jetty.client.helperClasses.SslServerAndClientCreator; import org.eclipse.jetty.server.Connector; import org.junit.Assume; import org.junit.Before; import org.junit.Test; /** * Functional testing for HttpExchange. */ public class SslHttpExchangeTest extends HttpExchangeTest { protected static ServerAndClientCreator serverAndClientCreator = new SslServerAndClientCreator(); /* ------------------------------------------------------------ */ @Before public void setUpOnce() throws Exception { _scheme="https"; _server = serverAndClientCreator.createServer(); _httpClient = serverAndClientCreator.createClient(3000L,3500L,2000); Connector[] connectors = _server.getConnectors(); _port = connectors[0].getLocalPort(); } /* ------------------------------------------------------------ */ private void IgnoreTestOnBuggyIBM() { // Use Junit 4.x to flag test as ignored if encountering IBM JVM // Will show up in various junit reports as an ignored test as well. Assume.assumeThat(System.getProperty("java.vendor").toLowerCase(),not(containsString("ibm"))); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchangeTest#testGetWithContentExchange() */ @Test @Override public void testGetWithContentExchange() throws Exception { // TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532 IgnoreTestOnBuggyIBM(); super.testGetWithContentExchange(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchangeTest#testPerf() */ @Test @Override public void testPerf() throws Exception { // TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532 IgnoreTestOnBuggyIBM(); super.testPerf(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchangeTest#testPostWithContentExchange() */ @Test @Override public void testPostWithContentExchange() throws Exception { // TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532 IgnoreTestOnBuggyIBM(); super.testPostWithContentExchange(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchangeTest#testReserveConnections() */ @Test @Override public void testReserveConnections() throws Exception { // TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532 IgnoreTestOnBuggyIBM(); super.testReserveConnections(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslSecuredContentExchangeTest.java000066400000000000000000000106201174773561500335000ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.File; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.util.ssl.SslContextFactory; public class SslSecuredContentExchangeTest extends ContentExchangeTest { protected void configureServer(Server server) throws Exception { setProtocol("https"); setRealm(new Realm() { public String getId() { return "MyRealm"; } public String getPrincipal() { return "jetty"; } public String getCredentials() { return "jetty"; } }); SslSelectChannelConnector connector = new SslSelectChannelConnector(); File keystore = MavenTestingUtils.getTestResourceFile("keystore"); SslContextFactory cf = connector.getSslContextFactory(); cf.setKeyStorePath(keystore.getAbsolutePath()); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); server.addConnector(connector); File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties"); LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath()); server.addBean(loginService); ConstraintSecurityHandler security = new ConstraintSecurityHandler(); server.setHandler(security); Constraint constraint = new Constraint(); constraint.setName("auth"); constraint.setAuthenticate( true ); constraint.setRoles(new String[]{"user", "admin"}); ConstraintMapping mapping = new ConstraintMapping(); mapping.setPathSpec( "/*" ); mapping.setConstraint( constraint ); Set knownRoles = new HashSet(); knownRoles.add("user"); knownRoles.add("admin"); security.setConstraintMappings(Collections.singletonList(mapping), knownRoles); security.setAuthenticator(new BasicAuthenticator()); security.setLoginService(loginService); security.setStrict(false); ServletContextHandler root = new ServletContextHandler(); root.setContextPath("/"); root.setResourceBase(getBasePath()); ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); servletHolder.setInitParameter( "gzip", "true" ); root.addServlet( servletHolder, "/*" ); Handler handler = new TestHandler(getBasePath()); HandlerCollection handlers = new HandlerCollection(); handlers.setHandlers(new Handler[]{handler, root}); security.setHandler(handlers); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslSecuredErrorStatusTest.java000066400000000000000000000156501174773561500327300ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.File; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.security.Constraint; import org.junit.Test; /* ------------------------------------------------------------ */ public class SslSecuredErrorStatusTest extends ErrorStatusTest { private Realm _testRealm; private Realm _dummyRealm; /* ------------------------------------------------------------ */ @Test public void testPutUnauthorized() throws Exception { setRealm(null); doPutFail(HttpStatus.UNAUTHORIZED_401); setRealm(_testRealm); } /* ------------------------------------------------------------ */ @Test public void testPutWrongPassword() throws Exception { setRealm(_dummyRealm); doPutFail(HttpStatus.UNAUTHORIZED_401); setRealm(_testRealm); } /* ------------------------------------------------------------ */ @Test public void testGetUnauthorized() throws Exception { setRealm(null); doGetFail(HttpStatus.UNAUTHORIZED_401); setRealm(_testRealm); } /* ------------------------------------------------------------ */ @Test public void testGetWrongPassword() throws Exception { setRealm(_dummyRealm); doGetFail(HttpStatus.UNAUTHORIZED_401); setRealm(_testRealm); } /* ------------------------------------------------------------ */ protected void configureServer(Server server) throws Exception { setProtocol("http"); _testRealm = new Realm() { /* ------------------------------------------------------------ */ public String getId() { return "MyRealm"; } /* ------------------------------------------------------------ */ public String getPrincipal() { return "jetty"; } /* ------------------------------------------------------------ */ public String getCredentials() { return "jetty"; } }; _dummyRealm = new Realm() { /* ------------------------------------------------------------ */ public String getId() { return "MyRealm"; } /* ------------------------------------------------------------ */ public String getPrincipal() { return "jetty"; } /* ------------------------------------------------------------ */ public String getCredentials() { return "dummy"; } }; setRealm(_testRealm); SelectChannelConnector connector = new SelectChannelConnector(); server.addConnector(connector); File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties"); LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath()); server.addBean(loginService); ConstraintSecurityHandler security = new ConstraintSecurityHandler(); server.setHandler(security); Constraint constraint = new Constraint(); constraint.setName("auth"); constraint.setAuthenticate( true ); constraint.setRoles(new String[]{"user", "admin"}); ConstraintMapping mapping = new ConstraintMapping(); mapping.setPathSpec( "/*" ); mapping.setConstraint( constraint ); Set knownRoles = new HashSet(); knownRoles.add("user"); knownRoles.add("admin"); security.setConstraintMappings(Collections.singletonList(mapping), knownRoles); security.setAuthenticator(new BasicAuthenticator()); security.setLoginService(loginService); security.setStrict(false); ServletContextHandler root = new ServletContextHandler(); root.setContextPath("/"); root.setResourceBase(getBasePath()); ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); servletHolder.setInitParameter( "gzip", "true" ); root.addServlet( servletHolder, "/*" ); Handler status = new StatusHandler(); Handler test = new TestHandler(getBasePath()); HandlerCollection handlers = new HandlerCollection(); handlers.setHandlers(new Handler[]{status, test, root}); security.setHandler(handlers); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslSecurityListenerTest.java000066400000000000000000000223151174773561500324310ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.security.HashRealmResolver; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.ssl.SslSocketConnector; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; /* ------------------------------------------------------------ */ /** * Functional testing. */ public class SslSecurityListenerTest { private static final Logger LOG = Log.getLogger(SslSecurityListenerTest.class); protected Server _server; protected int _port; protected HttpClient _httpClient; protected Realm _jettyRealm; protected int _type = HttpClient.CONNECTOR_SOCKET; private static final String APP_CONTEXT = "localhost /"; /* ------------------------------------------------------------ */ @Before public void setUp() throws Exception { startServer(); _httpClient = new HttpClient(); _httpClient.setConnectorType(_type); _httpClient.setMaxConnectionsPerAddress(2); _httpClient.start(); _jettyRealm = new Realm() { /* ------------------------------------------------------------ */ public String getId() { return "MyRealm"; } /* ------------------------------------------------------------ */ public String getPrincipal() { return "jetty"; } /* ------------------------------------------------------------ */ public String getCredentials() { return "jetty"; } }; HashRealmResolver resolver = new HashRealmResolver(); resolver.addSecurityRealm(_jettyRealm); _httpClient.setRealmResolver(resolver); } /* ------------------------------------------------------------ */ @After public void tearDown() throws Exception { Thread.sleep(1000); _httpClient.stop(); Thread.sleep(1000); stopServer(); } /* ------------------------------------------------------------ */ @Test public void testSslGet() throws Exception { // TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532 if (System.getProperty("java.vendor").toLowerCase().indexOf("ibm")>=0) { LOG.warn("Skipped SSL testSslGet on IBM JVM"); return; } final CyclicBarrier barrier = new CyclicBarrier(2); ContentExchange httpExchange = new ContentExchange(true) { /* ------------------------------------------------------------ */ @Override protected void onResponseComplete() throws IOException { super.onResponseComplete(); try{barrier.await();}catch(Exception e){} } }; httpExchange.setURL("https://127.0.0.1:" + _port + "/"); httpExchange.setMethod(HttpMethods.GET); _httpClient.send(httpExchange); barrier.await(10000,TimeUnit.SECONDS); assertEquals(HttpServletResponse.SC_OK,httpExchange.getResponseStatus()); assertTrue(httpExchange.getResponseContent().length()>400); } /* ------------------------------------------------------------ */ protected void startServer() throws Exception { _server = new Server(); //SslSelectChannelConnector connector = new SslSelectChannelConnector(); SslSocketConnector connector = new SslSocketConnector(); String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); connector.setPort(0); SslContextFactory cf = connector.getSslContextFactory(); cf.setKeyStorePath(keystore); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); _server.setConnectors(new Connector[] { connector }); Constraint constraint = new Constraint(); constraint.setName("Need User or Admin"); constraint.setRoles(new String[] { "user", "admin" }); constraint.setAuthenticate(true); ConstraintMapping cm = new ConstraintMapping(); cm.setConstraint(constraint); cm.setPathSpec("/*"); File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties"); LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath()); _server.addBean(loginService); BasicAuthenticator authenticator = new BasicAuthenticator(); ConstraintSecurityHandler sh = new ConstraintSecurityHandler(); sh.setAuthenticator(authenticator); Set roles = new HashSet(Arrays.asList(new String[]{"user", "admin"})); sh.setConstraintMappings(Collections.singletonList(cm), roles); _server.setHandler(sh); Handler testHandler = new AbstractHandler() { /* ------------------------------------------------------------ */ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // System.err.println("passed authentication!\n"+((Request)request).getConnection().getRequestFields()); baseRequest.setHandled(true); response.setStatus(200); response.setContentType("text/plain"); if (request.getServerName().equals("jetty.eclipse.org")) { response.getOutputStream().println("Proxy request: " + request.getRequestURL()); } else if (request.getMethod().equalsIgnoreCase("GET")) { response.getOutputStream().println(""); for (int i = 0; i < 100; i++) { response.getOutputStream().println(" " + i + ""); if (i % 20 == 0) response.getOutputStream().flush(); } response.getOutputStream().println(""); } else { copyStream(request.getInputStream(),response.getOutputStream()); } } }; sh.setHandler(testHandler); _server.start(); _port = connector.getLocalPort(); } /* ------------------------------------------------------------ */ public static void copyStream(InputStream in, OutputStream out) { try { byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) >= 0) { out.write(buffer,0,len); } } catch (EofException e) { System.err.println(e); } catch (IOException e) { e.printStackTrace(); } } /* ------------------------------------------------------------ */ private void stopServer() throws Exception { _server.stop(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslSelectChannelValidationTest.java000066400000000000000000000004661174773561500336420ustar00rootroot00000000000000package org.eclipse.jetty.client; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; public class SslSelectChannelValidationTest extends SslValidationTestBase { static { __klass = SslSelectChannelConnector.class; __konnector = HttpClient.CONNECTOR_SELECT_CHANNEL; } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslSocketValidationTest.java000066400000000000000000000004311174773561500323520ustar00rootroot00000000000000package org.eclipse.jetty.client; import org.eclipse.jetty.server.ssl.SslSocketConnector; public class SslSocketValidationTest extends SslValidationTestBase { static { __klass = SslSocketConnector.class; __konnector = HttpClient.CONNECTOR_SOCKET; } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/SslValidationTestBase.java000066400000000000000000000077521174773561500320110ustar00rootroot00000000000000package org.eclipse.jetty.client; import java.io.InputStream; import java.lang.reflect.Constructor; import java.security.KeyStore; import java.security.cert.CRL; import java.util.Collection; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.ssl.SslConnector; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.security.CertificateUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; public abstract class SslValidationTestBase //extends ContentExchangeTest { protected static Class __klass; protected static int __konnector; // certificate is valid until Jan 1, 2050 private String _keypath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-valid.keystore").getAbsolutePath(); private String _trustpath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-trust.keystore").getAbsolutePath(); private String _clientpath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-client.keystore").getAbsolutePath(); private String _crlpath = MavenTestingUtils.getTargetFile("test-policy/validation/crlfile.pem").getAbsolutePath(); private String _password = "OBF:1wnl1sw01ta01z0f1tae1svy1wml"; protected void configureServer(Server server) throws Exception { // setProtocol("https"); // // SslContextFactory srvFactory = new SslContextFactory() { // @Override // protected KeyStore getKeyStore(InputStream storeStream, String storePath, String storeType, String storeProvider, String storePassword) throws Exception // { // return CertificateUtils.getKeyStore(storeStream, storePath, storeType, storeProvider, storePassword); // } // // @Override // protected Collection loadCRL(String crlPath) throws Exception // { // return CertificateUtils.loadCRL(crlPath); // } // }; // srvFactory.setValidateCerts(true); // srvFactory.setCrlPath(_crlpath); // srvFactory.setNeedClientAuth(true); // // srvFactory.setKeyStorePath(_keypath); // srvFactory.setKeyStorePassword(_password); // srvFactory.setKeyManagerPassword(_password); // // srvFactory.setTrustStore(_trustpath); // srvFactory.setTrustStorePassword(_password); // // Constructor constructor = __klass.getConstructor(SslContextFactory.class); // SslConnector connector = constructor.newInstance(srvFactory); // connector.setMaxIdleTime(5000); // server.addConnector(connector); // // Handler handler = new TestHandler(getBasePath()); // // ServletContextHandler root = new ServletContextHandler(); // root.setContextPath("/"); // root.setResourceBase(getBasePath()); // ServletHolder servletHolder = new ServletHolder( new DefaultServlet() ); // servletHolder.setInitParameter( "gzip", "true" ); // root.addServlet( servletHolder, "/*" ); // // HandlerCollection handlers = new HandlerCollection(); // handlers.setHandlers(new Handler[]{handler, root}); // server.setHandler( handlers ); // } // // @Override // protected void configureClient(HttpClient client) // throws Exception // { // client.setConnectorType(__konnector); // // SslContextFactory cf = client.getSslContextFactory(); // cf.setValidateCerts(true); // cf.setCrlPath(_crlpath); // // cf.setKeyStorePath(_clientpath); // cf.setKeyStorePassword(_password); // cf.setKeyManagerPassword(_password); // // cf.setTrustStore(_trustpath); // cf.setTrustStorePassword(_password); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutExchangeTest.java000066400000000000000000000303521174773561500315230ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.Assert; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class TimeoutExchangeTest { private static HttpClient _httpClient; private static Server _server; private static int _port; @BeforeClass public static void startServer() throws Exception { _server = new Server(); _server.setGracefulShutdown(500); Connector _connector = new SelectChannelConnector(); _server.addConnector(_connector); Handler handler = new AbstractHandler() { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { Long sleep = Long.parseLong(request.getParameter("sleep")); Thread.sleep(sleep); response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("

Hello

"); baseRequest.setHandled(true); } catch (InterruptedException x) { Thread.currentThread().interrupt(); throw new ServletException(x); } } }; _server.setHandler(handler); _server.start(); _port = _connector.getLocalPort(); } @AfterClass public static void stopServer() throws Exception { _server.stop(); _server.join(); _server = null; } @After public void stopClient() throws Exception { if (_httpClient != null) { _httpClient.stop(); _httpClient = null; } } private void startClient(long clientTimeout) throws Exception { startClient(clientTimeout, 20000); } private void startClient(long clientTimeout, long maxIdleTimeout) throws Exception { _httpClient = new HttpClient(); _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); _httpClient.setMaxConnectionsPerAddress(2); _httpClient.setTimeout(clientTimeout); _httpClient.setIdleTimeout(maxIdleTimeout); _httpClient.start(); } @Test public void testDefaultTimeoutNotExpiring() throws Exception { startClient(300); long serverSleep = 100; CustomContentExchange httpExchange = new CustomContentExchange(); httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); httpExchange.setMethod(HttpMethods.POST); httpExchange.setRequestContent(new ByteArrayBuffer("

??

")); _httpClient.send(httpExchange); Assert.assertTrue(httpExchange.getDoneLatch().await(4 * serverSleep, TimeUnit.MILLISECONDS)); Assert.assertFalse(httpExchange.isTimeoutOccurred()); Assert.assertTrue(httpExchange.isResponseReceived()); Assert.assertFalse(httpExchange.isErrorOccurred()); } @Test public void testDefaultTimeoutExpiring() throws Exception { startClient(100); long serverSleep = 200; CustomContentExchange httpExchange = new CustomContentExchange(); httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); httpExchange.setMethod(HttpMethods.POST); httpExchange.setRequestContent(new ByteArrayBuffer("

??

")); _httpClient.send(httpExchange); Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS)); Assert.assertTrue(httpExchange.isTimeoutOccurred()); Assert.assertFalse(httpExchange.isResponseReceived()); Assert.assertFalse(httpExchange.isErrorOccurred()); } @Test public void testExchangeTimeoutNotExpiring() throws Exception { startClient(100); long serverSleep = 200; long exchangeTimeout = 300; CustomContentExchange httpExchange = new CustomContentExchange(); httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); httpExchange.setMethod(HttpMethods.POST); httpExchange.setRequestContent(new ByteArrayBuffer("

??

")); httpExchange.setTimeout(exchangeTimeout); _httpClient.send(httpExchange); Assert.assertTrue(httpExchange.getDoneLatch().await(2 * exchangeTimeout, TimeUnit.MILLISECONDS)); Assert.assertFalse(httpExchange.isTimeoutOccurred()); Assert.assertTrue(httpExchange.isResponseReceived()); Assert.assertFalse(httpExchange.isErrorOccurred()); } @Test public void testExchangeTimeoutExpiring() throws Exception { startClient(500); long serverSleep = 300; long exchangeTimeout = 100; CustomContentExchange httpExchange = new CustomContentExchange(); httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); httpExchange.setMethod(HttpMethods.POST); httpExchange.setRequestContent(new ByteArrayBuffer("

??

")); httpExchange.setTimeout(exchangeTimeout); _httpClient.send(httpExchange); Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS)); Assert.assertTrue(httpExchange.isTimeoutOccurred()); Assert.assertFalse(httpExchange.isResponseReceived()); Assert.assertFalse(httpExchange.isErrorOccurred()); } @Test public void testDefaultTimeoutWithSmallerIdleTimeoutNotExpiring() throws Exception { startClient(500,150); long serverSleep = 300; // The idle timeout is shorter than the default timeout, but will be // temporarily increased on the endpoint in order for the exchange to complete. CustomContentExchange httpExchange = new CustomContentExchange(); httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); httpExchange.setMethod(HttpMethods.POST); httpExchange.setRequestContent(new ByteArrayBuffer("

??

")); _httpClient.send(httpExchange); Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS)); Assert.assertFalse(httpExchange.isTimeoutOccurred()); Assert.assertTrue(httpExchange.isResponseReceived()); Assert.assertFalse(httpExchange.isErrorOccurred()); } @Test public void testExchangeTimeoutWithSmallerIdleTimeoutNotExpiring() throws Exception { startClient(500,150); long serverSleep = 150; long exchangeTimeout = 300; // The idle timeout is shorter than the default timeout, but will be // temporarily increased on the endpoint in order for the exchange to complete. CustomContentExchange httpExchange = new CustomContentExchange(); httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); httpExchange.setMethod(HttpMethods.POST); httpExchange.setRequestContent(new ByteArrayBuffer("

??

")); httpExchange.setTimeout(exchangeTimeout); _httpClient.send(httpExchange); Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS)); Assert.assertFalse(httpExchange.isTimeoutOccurred()); Assert.assertTrue(httpExchange.isResponseReceived()); Assert.assertFalse(httpExchange.isErrorOccurred()); } private class CustomContentExchange extends ContentExchange { private final CountDownLatch _doneLatch = new CountDownLatch(1); private boolean _errorOccurred = false; private boolean _timeoutOccurred = false; private boolean _responseReceived = false; public boolean isErrorOccurred() { return _errorOccurred; } public boolean isTimeoutOccurred() { return _timeoutOccurred; } public boolean isResponseReceived() { return _responseReceived; } public CustomContentExchange() { super(true); } @Override protected void onResponseComplete() throws IOException { try { super.onResponseComplete(); } finally { doTaskCompleted(); } } @Override protected void onExpire() { try { super.onExpire(); } finally { doTaskCompleted(); } } @Override protected void onException(Throwable ex) { try { super.onException(ex); } finally { doTaskCompleted(ex); } } @Override protected void onConnectionFailed(Throwable ex) { try { super.onConnectionFailed(ex); } finally { doTaskCompleted(ex); } } protected void doTaskCompleted() { int exchangeState = getStatus(); try { if (exchangeState == HttpExchange.STATUS_COMPLETED) { // process the response as the state is ok try { int responseCode = getResponseStatus(); if (responseCode >= HttpStatus.CONTINUE_100 && responseCode < HttpStatus.MULTIPLE_CHOICES_300) { _responseReceived = true; } else { _errorOccurred = true; } } catch (Exception e) { _errorOccurred = true; e.printStackTrace(); } } else if (exchangeState == HttpExchange.STATUS_EXPIRED) { _timeoutOccurred = true; } else { _errorOccurred = true; } } finally { // make sure to lower the latch getDoneLatch().countDown(); } } protected void doTaskCompleted(Throwable ex) { try { _errorOccurred = true; } finally { // make sure to lower the latch getDoneLatch().countDown(); } } public CountDownLatch getDoneLatch() { return _doneLatch; } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutTest.java000066400000000000000000000346511174773561500300660ustar00rootroot00000000000000package org.eclipse.jetty.client; import static org.hamcrest.Matchers.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; import java.net.SocketException; import java.nio.channels.SocketChannel; import java.util.Arrays; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.nio.AsyncConnection; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.toolchain.test.IO; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; public class TimeoutTest { private static final Logger logger = Log.getLogger(TimeoutTest.class); private final AtomicInteger httpParses = new AtomicInteger(); private final AtomicInteger httpRequests = new AtomicInteger(); private ExecutorService threadPool; private Server server; private int serverPort; private final AtomicReference serverEndPoint = new AtomicReference(); @Before public void init() throws Exception { threadPool = Executors.newCachedThreadPool(); server = new Server(); SelectChannelConnector connector = new SelectChannelConnector() { @Override protected AsyncConnection newConnection(SocketChannel channel, final AsyncEndPoint endPoint) { serverEndPoint.set(endPoint); return new org.eclipse.jetty.server.AsyncHttpConnection(this,endPoint,getServer()) { @Override protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endPoint, HttpParser.EventHandler requestHandler) { return new HttpParser(requestBuffers,endPoint,requestHandler) { @Override public int parseNext() throws IOException { httpParses.incrementAndGet(); return super.parseNext(); } }; } }; } }; connector.setMaxIdleTime(2000); // connector.setPort(5870); connector.setPort(0); server.addConnector(connector); server.setHandler(new AbstractHandler() { public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { httpRequests.incrementAndGet(); request.setHandled(true); String contentLength = request.getHeader("Content-Length"); if (contentLength != null) { int length = Integer.parseInt(contentLength); ServletInputStream input = request.getInputStream(); for (int i = 0; i < length; ++i) input.read(); } } }); server.start(); serverPort = connector.getLocalPort(); httpRequests.set(0); logger.debug(" => :{}",serverPort); } @After public void destroy() throws Exception { if (server != null) server.stop(); if (threadPool != null) threadPool.shutdownNow(); } private Socket newClient() throws IOException, InterruptedException { Socket client = new Socket("localhost",serverPort); return client; } /** * Test that performs a normal http POST request, with connection:close. * Check that shutdownOutput is sufficient to close the server connection. */ @Test public void testServerCloseClientDoesClose() throws Exception { // Log.getLogger("").setDebugEnabled(true); final Socket client = newClient(); final OutputStream clientOutput = client.getOutputStream(); byte[] data = new byte[3 * 1024]; Arrays.fill(data,(byte)'Y'); String content = new String(data,"UTF-8"); // The request section StringBuilder req = new StringBuilder(); req.append("POST / HTTP/1.1\r\n"); req.append("Host: localhost\r\n"); req.append("Content-Type: text/plain\r\n"); req.append("Content-Length: ").append(content.length()).append("\r\n"); req.append("Connection: close\r\n"); req.append("\r\n"); // and now, the POST content section. req.append(content); // Send request to server clientOutput.write(req.toString().getBytes("UTF-8")); clientOutput.flush(); InputStream in = null; InputStreamReader isr = null; BufferedReader reader = null; try { in = client.getInputStream(); isr = new InputStreamReader(in); reader = new BufferedReader(isr); // Read the response header String line = reader.readLine(); Assert.assertNotNull(line); Assert.assertThat(line,startsWith("HTTP/1.1 200 ")); while ((line = reader.readLine()) != null) { if (line.trim().length() == 0) { break; } } Assert.assertEquals("one request handled",1,httpRequests.get()); Assert.assertEquals("EOF received",-1,client.getInputStream().read()); // shutdown the output client.shutdownOutput(); // Check that we did not spin int httpParseCount = httpParses.get(); Assert.assertThat(httpParseCount,lessThan(50)); // Try to write another request (to prove that stream is closed) try { clientOutput.write(req.toString().getBytes("UTF-8")); clientOutput.flush(); Assert.fail("Should not have been able to send a second POST request (connection: close)"); } catch(SocketException e) { } Assert.assertEquals("one request handled",1,httpRequests.get()); } finally { IO.close(reader); IO.close(isr); IO.close(in); closeClient(client); } } /** * Test that performs a seemingly normal http POST request, but with * a client that issues "connection: close", and then attempts to * write a second POST request. *

* The connection should be closed by the server */ @Test public void testServerCloseClientMoreDataSent() throws Exception { // Log.getLogger("").setDebugEnabled(true); final Socket client = newClient(); final OutputStream clientOutput = client.getOutputStream(); byte[] data = new byte[3 * 1024]; Arrays.fill(data,(byte)'Y'); String content = new String(data,"UTF-8"); // The request section StringBuilder req = new StringBuilder(); req.append("POST / HTTP/1.1\r\n"); req.append("Host: localhost\r\n"); req.append("Content-Type: text/plain\r\n"); req.append("Content-Length: ").append(content.length()).append("\r\n"); req.append("Connection: close\r\n"); req.append("\r\n"); // and now, the POST content section. req.append(content); // Send request to server clientOutput.write(req.toString().getBytes("UTF-8")); clientOutput.flush(); InputStream in = null; InputStreamReader isr = null; BufferedReader reader = null; try { in = client.getInputStream(); isr = new InputStreamReader(in); reader = new BufferedReader(isr); // Read the response header String line = reader.readLine(); Assert.assertNotNull(line); Assert.assertThat(line,startsWith("HTTP/1.1 200 ")); while ((line = reader.readLine()) != null) { if (line.trim().length() == 0) { break; } } Assert.assertEquals("EOF received",-1,client.getInputStream().read()); Assert.assertEquals("one request handled",1,httpRequests.get()); // Don't shutdown the output // client.shutdownOutput(); // server side seeking EOF Assert.assertTrue("is open",serverEndPoint.get().isOpen()); Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown()); Assert.assertFalse("close not received",serverEndPoint.get().isInputShutdown()); // Check that we did not spin TimeUnit.SECONDS.sleep(1); int httpParseCount = httpParses.get(); Assert.assertThat(httpParseCount,lessThan(50)); // Write another request (which is ignored as the stream is closing), which causes real close. clientOutput.write(req.toString().getBytes("UTF-8")); clientOutput.flush(); // Check that we did not spin TimeUnit.SECONDS.sleep(1); httpParseCount = httpParses.get(); Assert.assertThat(httpParseCount,lessThan(50)); // server side is closed Assert.assertFalse("is open",serverEndPoint.get().isOpen()); Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown()); Assert.assertTrue("close not received",serverEndPoint.get().isInputShutdown()); Assert.assertEquals("one request handled",1,httpRequests.get()); } finally { IO.close(reader); IO.close(isr); IO.close(in); closeClient(client); } } /** * Test that performs a seemingly normal http POST request, but with * a client that issues "connection: close", and then does not close * the connection after reading the response. *

* The connection should be closed by the server after a timeout. */ @Test public void testServerCloseClientDoesNotClose() throws Exception { // Log.getLogger("").setDebugEnabled(true); final Socket client = newClient(); final OutputStream clientOutput = client.getOutputStream(); byte[] data = new byte[3 * 1024]; Arrays.fill(data,(byte)'Y'); String content = new String(data,"UTF-8"); // The request section StringBuilder req = new StringBuilder(); req.append("POST / HTTP/1.1\r\n"); req.append("Host: localhost\r\n"); req.append("Content-Type: text/plain\r\n"); req.append("Content-Length: ").append(content.length()).append("\r\n"); req.append("Connection: close\r\n"); req.append("\r\n"); // and now, the POST content section. req.append(content); // Send request to server clientOutput.write(req.toString().getBytes("UTF-8")); clientOutput.flush(); InputStream in = null; InputStreamReader isr = null; BufferedReader reader = null; try { in = client.getInputStream(); isr = new InputStreamReader(in); reader = new BufferedReader(isr); // Read the response header String line = reader.readLine(); Assert.assertNotNull(line); Assert.assertThat(line,startsWith("HTTP/1.1 200 ")); while ((line = reader.readLine()) != null) { if (line.trim().length() == 0) { break; } } Assert.assertEquals("EOF received",-1,client.getInputStream().read()); Assert.assertEquals("one request handled",1,httpRequests.get()); // Don't shutdown the output // client.shutdownOutput(); // server side seeking EOF Assert.assertTrue("is open",serverEndPoint.get().isOpen()); Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown()); Assert.assertFalse("close not received",serverEndPoint.get().isInputShutdown()); // Wait for the server idle timeout TimeUnit.SECONDS.sleep(3); int httpParseCount = httpParses.get(); Assert.assertThat(httpParseCount,lessThan(50)); // server side is closed Assert.assertFalse("is open",serverEndPoint.get().isOpen()); Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown()); Assert.assertTrue("close not received",serverEndPoint.get().isInputShutdown()); Assert.assertEquals("one request handled",1,httpRequests.get()); // client will eventually get broken pipe if it keeps writing try { for (int i=0;i<1000;i++) { clientOutput.write(req.toString().getBytes("UTF-8")); clientOutput.flush(); } Assert.fail("Client should have seen a broken pipe"); } catch(IOException e) { // expected broken pipe } } finally { IO.close(reader); IO.close(isr); IO.close(in); closeClient(client); } } private void closeClient(Socket client) throws IOException { client.close(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/UnexpectedDataTest.java000066400000000000000000000143101174773561500313240ustar00rootroot00000000000000// ======================================================================== // Copyright 2006-2007 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ======================================================================== package org.eclipse.jetty.client; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.util.IO; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * Functional testing for HttpExchange. * * @author Matthew Purland * @author Greg Wilkins */ public class UnexpectedDataTest { private Server _server; private int _port; private HttpClient _httpClient; private Connector _connector; private AtomicInteger _count = new AtomicInteger(); @Before public void setUp() throws Exception { startServer(); _httpClient = new HttpClient(); _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); _httpClient.setMaxConnectionsPerAddress(1); _httpClient.start(); } @After public void tearDown() throws Exception { _httpClient.stop(); Thread.sleep(500); stopServer(); } @Test public void testUnexpectedData() throws Exception { for (int i = 0; i < 4; ++i) { final CountDownLatch done = new CountDownLatch(1); ContentExchange httpExchange = new ContentExchange() { protected void onResponseComplete() throws IOException { super.onResponseComplete(); done.countDown(); } }; httpExchange.setURL("http://localhost:" + _port + "/?i=" + i); httpExchange.setMethod(HttpMethods.GET); _httpClient.send(httpExchange); Assert.assertTrue(done.await(1000, TimeUnit.SECONDS)); int status = httpExchange.getStatus(); String result = httpExchange.getResponseContent(); Assert.assertEquals("i=" + i, 0, result.indexOf("")); Assert.assertEquals("i=" + i, result.length() - 10, result.indexOf("")); Assert.assertEquals(HttpExchange.STATUS_COMPLETED, status); // Give the client the time to read -1 from server before issuing the next request // There is currently no simple way to be notified of connection closed. Thread.sleep(500); } } protected void newServer() throws Exception { _server = new Server(); _server.setGracefulShutdown(500); _connector = new SelectChannelConnector(); _connector.setPort(0); _server.setConnectors(new Connector[]{_connector}); } protected void startServer() throws Exception { newServer(); _server.setHandler(new AbstractHandler() { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { int i = 0; try { baseRequest.setHandled(true); response.setStatus(200); _count.incrementAndGet(); if (request.getMethod().equalsIgnoreCase("GET")) { StringBuilder buffer = new StringBuilder(); buffer.append("\r\n"); for (; i < 100; i++) { buffer.append(" ").append(i).append("\r\n"); } buffer.append("\r\n"); byte[] buff = buffer.toString().getBytes(); response.setContentLength(buff.length); buffer.append("extra data"); buff = buffer.toString().getBytes(); OutputStream out = response.getOutputStream(); out.write(buff, 0, buff.length); out.flush(); } else { response.setContentType(request.getContentType()); int size = request.getContentLength(); ByteArrayOutputStream bout = new ByteArrayOutputStream(size > 0 ? size : 32768); IO.copy(request.getInputStream(), bout); response.getOutputStream().write(bout.toByteArray()); } } catch (IOException e) { e.printStackTrace(); throw e; } catch (Throwable e) { e.printStackTrace(); throw new ServletException(e); } } }); _server.start(); _port = _connector.getLocalPort(); } private void stopServer() throws Exception { _server.stop(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/WebSocketUpgradeTest.java000066400000000000000000000222221174773561500316250ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.websocket.WebSocket; import org.eclipse.jetty.websocket.WebSocketBuffers; import org.eclipse.jetty.websocket.WebSocketConnectionD00; import org.eclipse.jetty.websocket.WebSocketHandler; import org.junit.After; import org.junit.Before; import org.junit.Test; /* ------------------------------------------------------------ */ /** * Functional testing for HttpExchange. */ public class WebSocketUpgradeTest { protected Server _server; protected int _port; protected HttpClient _httpClient; protected Connector _connector; protected ConcurrentLinkedQueue _webSockets= new ConcurrentLinkedQueue(); protected WebSocketHandler _handler; protected TestWebSocket _websocket; final BlockingQueue _results = new ArrayBlockingQueue(100); /* ------------------------------------------------------------ */ @Before public void setUp() throws Exception { startServer(); _httpClient=new HttpClient(); _httpClient.setIdleTimeout(2000); _httpClient.setTimeout(2500); _httpClient.setConnectTimeout(1000); _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); _httpClient.setMaxConnectionsPerAddress(10); _httpClient.start(); } /* ------------------------------------------------------------ */ @After public void tearDown() throws Exception { _httpClient.stop(); Thread.sleep(500); stopServer(); } /* ------------------------------------------------------------ */ @Test public void testGetWithContentExchange() throws Exception { final WebSocket clientWS = new WebSocket.OnTextMessage() { Connection _connection; /* ------------------------------------------------------------ */ public void onClose(int closeCode, String message) { } /* ------------------------------------------------------------ */ public void onOpen(Connection connection) { _connection=connection; _results.add("clientWS.onConnect"); _results.add(_connection); } /* ------------------------------------------------------------ */ public void onMessage(String data) { _results.add("clientWS.onMessage"); _results.add(data); } }; HttpExchange httpExchange=new HttpExchange() { /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.Buffer, int, org.eclipse.jetty.io.Buffer) */ @Override protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { waitFor(2); _results.add(new Integer(status)); super.onResponseStatus(version,status,reason); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onSwitchProtocol(org.eclipse.jetty.io.EndPoint) */ @Override protected Connection onSwitchProtocol(EndPoint endp) throws IOException { waitFor(3); WebSocketConnectionD00 connection = new WebSocketConnectionD00(clientWS,endp,new WebSocketBuffers(4096),System.currentTimeMillis(),1000,""); _results.add("onSwitchProtocol"); _results.add(connection); clientWS.onOpen(connection); return connection; } /* ------------------------------------------------------------ */ private void waitFor(int results) { try { int c=10; while(_results.size()0) Thread.sleep(10); } catch(InterruptedException e) { e.printStackTrace(); } } }; httpExchange.setURL("http://localhost:"+_port+"/"); httpExchange.setMethod(HttpMethods.GET); httpExchange.addRequestHeader("Upgrade","WebSocket"); httpExchange.addRequestHeader("Connection","Upgrade"); _httpClient.send(httpExchange); int status = httpExchange.waitForDone(); assertEquals(HttpExchange.STATUS_COMPLETED, status); assertEquals("serverWS.onConnect", _results.poll(1,TimeUnit.SECONDS)); TestWebSocket serverWS = (TestWebSocket)_results.poll(1,TimeUnit.SECONDS); assertEquals(new Integer(101), _results.poll(1,TimeUnit.SECONDS)); assertEquals("onSwitchProtocol", _results.poll(1,TimeUnit.SECONDS)); WebSocketConnectionD00 client_conn=(WebSocketConnectionD00)_results.poll(1,TimeUnit.SECONDS); assertEquals("clientWS.onConnect", _results.poll(1,TimeUnit.SECONDS)); assertEquals(client_conn, _results.poll(1,TimeUnit.SECONDS)); client_conn.sendMessage("hello world"); assertEquals("serverWS.onMessage", _results.poll(1,TimeUnit.SECONDS)); assertEquals("hello world", _results.poll(1,TimeUnit.SECONDS)); serverWS.sendMessage("buongiorno"); assertEquals("clientWS.onMessage", _results.poll(1,TimeUnit.SECONDS)); assertEquals("buongiorno", _results.poll(1,TimeUnit.SECONDS)); } /* ------------------------------------------------------------ */ protected void newServer() throws Exception { _server=new Server(); _server.setGracefulShutdown(500); _connector=new SelectChannelConnector(); _connector.setPort(0); _server.setConnectors(new Connector[] { _connector }); } /* ------------------------------------------------------------ */ protected void startServer() throws Exception { newServer(); _handler= new WebSocketHandler() { /* ------------------------------------------------------------ */ public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { _websocket = new TestWebSocket(); return _websocket; } }; _server.setHandler(_handler); _server.start(); _port=_connector.getLocalPort(); } /* ------------------------------------------------------------ */ private void stopServer() throws Exception { _server.stop(); _server.join(); } /* ------------------------------------------------------------ */ class TestWebSocket implements WebSocket.OnTextMessage { Connection _connection; /* ------------------------------------------------------------ */ public void onOpen(Connection connection) { _connection=connection; _webSockets.add(this); _results.add("serverWS.onConnect"); _results.add(this); } /* ------------------------------------------------------------ */ public void onMessage(final String data) { _results.add("serverWS.onMessage"); _results.add(data); } /* ------------------------------------------------------------ */ public void onClose(int code, String message) { _results.add("onClose"); _webSockets.remove(this); } /* ------------------------------------------------------------ */ public void sendMessage(String msg) throws IOException { _connection.sendMessage(msg); } } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/WebdavListenerTest.java000066400000000000000000000121761174773561500313540ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import java.io.File; import org.eclipse.jetty.client.security.Realm; import org.eclipse.jetty.client.security.SimpleRealmResolver; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.PathAssert; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; /** * Functional testing for HttpExchange. */ public class WebdavListenerTest { protected String _scheme = "http://"; protected Server _server; protected int _port; protected HttpClient _httpClient; protected Connector _connector; private String _username = "janb"; private String _password = "xxxxx"; private String _singleFileURL; private String _dirFileURL; private String _dirURL; @Before public void setUp() throws Exception { _singleFileURL = "https://dav.codehaus.org/user/" + _username + "/foo.txt"; _dirURL = "https://dav.codehaus.org/user/" + _username + "/ttt/"; _dirFileURL = _dirURL+"foo.txt"; _scheme="https://"; _httpClient=new HttpClient(); _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); //_httpClient.setMaxConnectionsPerAddress(4); _httpClient.setRealmResolver( new SimpleRealmResolver ( new Realm(){ public String getId() { return _username + "'s webspace"; //To change body of implemented methods use File | Settings | File Templates. } public String getPrincipal() { return _username; //To change body of implemented methods use File | Settings | File Templates. } public String getCredentials() { return _password; //To change body of implemented methods use File | Settings | File Templates. } } )); _httpClient.registerListener( "org.eclipse.jetty.client.webdav.WebdavListener"); _httpClient.start(); } @After public void tearDown () throws Exception { _httpClient.stop(); } @Test @Ignore("Only works with real WebDAV server") public void testPUTandDELETEwithSSL() throws Exception { File file = MavenTestingUtils.getTestResourceFile("foo.txt"); PathAssert.assertFileExists("WebDAV test file", file); //PUT a FILE ContentExchange singleFileExchange = new ContentExchange(); singleFileExchange.setURL(_singleFileURL); singleFileExchange.setMethod( HttpMethods.PUT ); singleFileExchange.setFileForUpload(file); singleFileExchange.setRequestHeader( "Content-Type", "application/octet-stream"); singleFileExchange.setRequestHeader("Content-Length", String.valueOf( file.length() )); _httpClient.send(singleFileExchange); singleFileExchange.waitForDone(); String result = singleFileExchange.getResponseContent(); Assert.assertEquals(201, singleFileExchange.getResponseStatus()); //PUT a FILE in a directory hierarchy ContentExchange dirFileExchange = new ContentExchange(); dirFileExchange.setURL(_dirFileURL); dirFileExchange.setMethod( HttpMethods.PUT ); dirFileExchange.setFileForUpload(file); dirFileExchange.setRequestHeader( "Content-Type", "application/octet-stream"); dirFileExchange.setRequestHeader("Content-Length", String.valueOf( file.length() )); _httpClient.send(dirFileExchange); dirFileExchange.waitForDone(); result = dirFileExchange.getResponseContent(); Assert.assertEquals(201, singleFileExchange.getResponseStatus()); //DELETE the single file HttpExchange del = new HttpExchange(); del.setURL(_singleFileURL); del.setMethod(HttpMethods.DELETE); _httpClient.send(del); del.waitForDone(); //DELETE the whole dir del.setURL(_dirURL); del.setMethod(HttpMethods.DELETE); del.setRequestHeader("Depth", "infinity"); _httpClient.send(del); del.waitForDone(); } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/000077500000000000000000000000001174773561500275215ustar00rootroot00000000000000AbstractSslServerAndClientCreator.java000066400000000000000000000042331174773561500370250ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.helperClasses; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ssl.SslSocketConnector; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.ssl.SslContextFactory; /* ------------------------------------------------------------ */ /** */ public abstract class AbstractSslServerAndClientCreator implements ServerAndClientCreator { private static final Logger LOG = Log.getLogger(AbstractSslServerAndClientCreator.class); /* ------------------------------------------------------------ */ public Server createServer() throws Exception { Server server = new Server(); // SslSelectChannelConnector connector = new SslSelectChannelConnector(); SslSocketConnector connector = new SslSocketConnector(); String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); connector.setPort(0); SslContextFactory cf = connector.getSslContextFactory(); cf.setKeyStorePath(keystore); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); server.setConnectors(new Connector[]{ connector }); server.setHandler(new GenericServerHandler()); server.start(); return server; } } AsyncSslServerAndClientCreator.java000066400000000000000000000017631174773561500363440ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/helperClassespackage org.eclipse.jetty.client.helperClasses; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; public class AsyncSslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator { /* ------------------------------------------------------------ */ public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception { HttpClient httpClient = new HttpClient(); httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); httpClient.setMaxConnectionsPerAddress(2); String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); httpClient.getSslContextFactory().setKeyStorePath(keystore); httpClient.getSslContextFactory().setKeyStorePassword("storepwd"); httpClient.getSslContextFactory().setKeyManagerPassword("keypwd"); httpClient.start(); return httpClient; } } ExternalKeyStoreAsyncSslServerAndClientCreator.java000066400000000000000000000016661174773561500415370ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/helperClassespackage org.eclipse.jetty.client.helperClasses; import java.io.FileInputStream; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; public class ExternalKeyStoreAsyncSslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator { public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception { HttpClient httpClient = new HttpClient(); httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); httpClient.setMaxConnectionsPerAddress(2); String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); httpClient.setKeyStoreInputStream(new FileInputStream(keystore)); httpClient.setKeyStorePassword("storepwd"); httpClient.setKeyManagerPassword("keypwd"); httpClient.start(); return httpClient; } } GenericServerHandler.java000066400000000000000000000060311174773561500343460ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/helperClassespackage org.eclipse.jetty.client.helperClasses; import java.io.ByteArrayOutputStream; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * Generic Server Handler used for various client tests. */ public class GenericServerHandler extends AbstractHandler { private static final Logger LOG = Log.getLogger(GenericServerHandler.class); public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { int i = 0; try { baseRequest.setHandled(true); response.setStatus(200); if (request.getServerName().equals("jetty.eclipse.org")) { response.getOutputStream().println("Proxy request: " + request.getRequestURL()); response.getOutputStream().println(request.getHeader(HttpHeaders.PROXY_AUTHORIZATION)); } else if (request.getMethod().equalsIgnoreCase("GET")) { response.getOutputStream().println(""); for (; i < 100; i++) { response.getOutputStream().println(" " + i + ""); } else if (request.getMethod().equalsIgnoreCase("OPTIONS")) { if ("*".equals(target)) { response.setContentLength(0); response.setHeader("Allow","GET,HEAD,POST,PUT,DELETE,MOVE,OPTIONS,TRACE"); } } else if (request.getMethod().equalsIgnoreCase("SLEEP")) { Thread.sleep(10000); } else { response.setContentType(request.getContentType()); int size = request.getContentLength(); ByteArrayOutputStream bout = new ByteArrayOutputStream(size > 0?size:32768); IO.copy(request.getInputStream(),bout); response.getOutputStream().write(bout.toByteArray()); } } catch (InterruptedException e) { LOG.debug(e); } catch (EofException e) { LOG.info(e.toString()); LOG.debug(e); throw e; } catch (IOException e) { LOG.warn(e); throw e; } catch (Throwable e) { LOG.warn(e); throw new ServletException(e); } } } HttpServerAndClientCreator.java000066400000000000000000000023501174773561500355150ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/helperClassespackage org.eclipse.jetty.client.helperClasses; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; public class HttpServerAndClientCreator implements ServerAndClientCreator { public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception { HttpClient httpClient = new HttpClient(); httpClient.setIdleTimeout(idleTimeout); httpClient.setTimeout(timeout); httpClient.setConnectTimeout(connectTimeout); httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); httpClient.setMaxConnectionsPerAddress(2); httpClient.start(); return httpClient; } public Server createServer() throws Exception { Server _server = new Server(); _server.setGracefulShutdown(500); Connector _connector = new SelectChannelConnector(); _connector.setMaxIdleTime(3000000); _connector.setPort(0); _server.setConnectors(new Connector[]{ _connector }); _server.setHandler(new GenericServerHandler()); _server.start(); return _server; } } ServerAndClientCreator.java000066400000000000000000000005051174773561500346550ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/helperClassespackage org.eclipse.jetty.client.helperClasses; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.server.Server; public interface ServerAndClientCreator { Server createServer() throws Exception; HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception; } SslServerAndClientCreator.java000066400000000000000000000012661174773561500353440ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/helperClassespackage org.eclipse.jetty.client.helperClasses; import org.eclipse.jetty.client.HttpClient; public class SslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator { public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception { HttpClient httpClient = new HttpClient(); httpClient.setIdleTimeout(idleTimeout); httpClient.setTimeout(timeout); httpClient.setConnectTimeout(connectTimeout); httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET); httpClient.setMaxConnectionsPerAddress(2); httpClient.start(); return httpClient; } } jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/security/000077500000000000000000000000001174773561500265735ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/java/org/eclipse/jetty/client/security/SecurityResolverTest.java000066400000000000000000000033551174773561500336350ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client.security; import org.junit.Test; public class SecurityResolverTest { @Test public void testNothing() { } /* TODO public void testCredentialParsing() throws Exception { SecurityListener resolver = new SecurityListener(); Buffer value = new ByteArrayBuffer("basic a=b".getBytes()); assertEquals( "basic", resolver.scrapeAuthenticationType( value.toString() ) ); assertEquals( 1, resolver.scrapeAuthenticationDetails( value.toString() ).size() ); value = new ByteArrayBuffer("digest a=boo, c=\"doo\" , egg=foo".getBytes()); assertEquals( "digest", resolver.scrapeAuthenticationType( value.toString() ) ); Map testMap = resolver.scrapeAuthenticationDetails( value.toString() ); assertEquals( 3, testMap.size() ); assertEquals( "boo", testMap.get("a") ); assertEquals( "doo", testMap.get("c") ); assertEquals( "foo", testMap.get("egg") ); } */ } jetty8-8.1.3/jetty-client/src/test/resources/000077500000000000000000000000001174773561500211655ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/resources/foo.txt000066400000000000000000000000071174773561500225060ustar00rootroot00000000000000jetty8-8.1.3/jetty-client/src/test/resources/keystore000066400000000000000000000026221174773561500227570ustar00rootroot00000000000000mykey]A00 +*+!אu䛪7lMꔄ\%p.G#ݥzgZ-mv[¸73i:2$

C $,ʉ@g Alx q* Iq"?1~jܩOl"[z{5anb],*Lu||<6=a$c+9ܢwmŝ`X.5090090  *H 010UUnknown10UUnknown10UUnknown10U Mort Bay Consulting1 0U Open Source Development10U Jetty Server0 001022135544Z 010120135544Z010UUnknown10UUnknown10UUnknown10U Mort Bay Consulting1 0U Open Source Development10U Jetty Server00  *H 04銴*?TVhUzi-. H?Ӡq9>?*]R@NbaI\@`Ŏ L~o==uzջI l E;rNT+4JPd`0  *H =6Bkј@Ъ>hT8V$Gwc\2Hz%eNs"øֶh.[7C|x5mp7=Ogi?QCDOALrPp>羴V[׼q"x?js>!sIAмx8*l:jetty8-8.1.3/jetty-client/src/test/resources/realm.properties000066400000000000000000000014361174773561500244070ustar00rootroot00000000000000# # This file defines users passwords and roles for a HashUserRealm # # The format is # : [, ...] # # Passwords may be clear text, obfuscated or checksummed. The class # org.eclipse.util.Password should be used to generate obfuscated # passwords or password checksums # # If DIGEST Authentication is used, the password must be in a recoverable # format, either plain text or OBF:. # # if using digest authentication, do not MD5-hash the password jetty: jetty,user admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin,user other: OBF:1xmk1w261u9r1w1c1xmq,user plain: plain,user user: password,user # This entry is for digest auth. The credential is a MD5 hash of username:realmname:password digest: MD5:6e120743ad67abfbc385bc2bb754e297,user jetty8-8.1.3/jetty-continuation/000077500000000000000000000000001174773561500166415ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/pom.xml000066400000000000000000000052041174773561500201570ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 jetty-continuation Jetty :: Continuation Asynchronous API ${project.groupId}.continuation org.apache.felix maven-bundle-plugin true manifest javax.servlet.*;version="2.6.0",org.mortbay.log.*;version="[6.1,7)";resolution:=optional,org.mortbay.util.ajax.*;version="[6.1,7)";resolution:=optional,* org.apache.maven.plugins maven-jar-plugin artifact-jar jar test-jar test-jar ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.continuation.* org.eclipse.jetty.orbit javax.servlet 3.0.0.v201112011016 provided org.mortbay.jetty jetty-util 6.1.26 provided jetty8-8.1.3/jetty-continuation/src/000077500000000000000000000000001174773561500174305ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/000077500000000000000000000000001174773561500203545ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/java/000077500000000000000000000000001174773561500212755ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/java/org/000077500000000000000000000000001174773561500220645ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/000077500000000000000000000000001174773561500235105ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500246475ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/000077500000000000000000000000001174773561500273615ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Continuation.java000066400000000000000000000415051174773561500327030ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.continuation; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.Servlet; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.ServletResponseWrapper; /* ------------------------------------------------------------ */ /** * Continuation. * * A continuation is a mechanism by which a HTTP Request can be suspended and * restarted after a timeout or an asynchronous event has occurred. *

* The continuation mechanism is a portable mechanism that will work * asynchronously without additional configuration of all jetty-7, * jetty-8 and Servlet 3.0 containers. With the addition of * the {@link ContinuationFilter}, the mechanism will also work * asynchronously on jetty-6 and non-asynchronously on any * servlet 2.5 container. *

* The Continuation API is a simplification of the richer async API * provided by the servlet-3.0 and an enhancement of the continuation * API that was introduced with jetty-6. *

*

Continuation Usage

*

* A continuation object is obtained for a request by calling the * factory method {@link ContinuationSupport#getContinuation(ServletRequest)}. * The continuation type returned will depend on the servlet container * being used. *

*

* There are two distinct style of operation of the continuation API. *

*

Suspend/Resume Usage

*

The suspend/resume style is used when a servlet and/or * filter is used to generate the response after a asynchronous wait that is * terminated by an asynchronous handler. *

*
 * Filter/Servlet:
 *   // if we need to get asynchronous results
 *   Object results = request.getAttribute("results);
 *   if (results==null)
 *   {
 *     Continuation continuation = ContinuationSupport.getContinuation(request);
 *     continuation.suspend();
 *     myAsyncHandler.register(continuation);
 *     return; // or continuation.undispatch();
 *   }
 * 
 * async wait ...
 * 
 * Async Handler:
 *   // when the waited for event happens
 *   continuation.setAttribute("results",event);
 *   continuation.resume();
 *   
 * Filter/Servlet:
 *   // when the request is redispatched 
 *   if (results==null)
 *   {
 *     ... // see above
 *   }
 *   else
 *   {
 *     response.getOutputStream().write(process(results));
 *   }
 * 
*

Suspend/Complete Usage

*

* The suspend/complete style is used when an asynchronous handler is used to * generate the response: *

*
 * Filter/Servlet:
 *   // when we want to enter asynchronous mode
 *   Continuation continuation = ContinuationSupport.getContinuation(request);
 *   continuation.suspend(response); // response may be wrapped
 *   myAsyncHandler.register(continuation);
 *   return; // or continuation.undispatch();
 *
 * Wrapping Filter:
 *   // any filter that had wrapped the response should be implemented like:
 *   try
 *   {
 *     chain.doFilter(request,wrappedResponse);
 *   }
 *   finally
 *   {
 *     if (!continuation.isResponseWrapped())
 *       wrappedResponse.finish()
 *     else
 *       continuation.addContinuationListener(myCompleteListener)
 *   }
 *
 * async wait ...
 *
 * Async Handler:
 *   // when the async event happens
 *   continuation.getServletResponse().getOutputStream().write(process(event));
 *   continuation.complete()
 * 
* *

Continuation Timeout

*

* If a continuation is suspended, but neither {@link #complete()} or {@link #resume()} is * called during the period set by {@link #setTimeout(long)}, then the continuation will * expire and {@link #isExpired()} will return true. *

*

* When a continuation expires, the {@link ContinuationListener#onTimeout(Continuation)} * method is called on any {@link ContinuationListener} that has been registered via the * {@link #addContinuationListener(ContinuationListener)} method. The onTimeout handlers * may write a response and call {@link #complete()}. If {@link #complete()} is not called, * then the container will redispatch the request as if {@link #resume()} had been called, * except that {@link #isExpired()} will be true and {@link #isResumed()} will be false. *

* * @see ContinuationSupport * @see ContinuationListener * */ public interface Continuation { public final static String ATTRIBUTE = "org.eclipse.jetty.continuation"; /* ------------------------------------------------------------ */ /** * Set the continuation timeout. * * @param timeoutMs * The time in milliseconds to wait before expiring this * continuation after a call to {@link #suspend()} or {@link #suspend(ServletResponse)}. * A timeout of <=0 means the continuation will never expire. */ void setTimeout(long timeoutMs); /* ------------------------------------------------------------ */ /** * Suspend the processing of the request and associated * {@link ServletResponse}. * *

* After this method has been called, the lifecycle of the request will be * extended beyond the return to the container from the * {@link Servlet#service(ServletRequest, ServletResponse)} method and * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)} * calls. When a suspended request is returned to the container after * a dispatch, then the container will not commit the associated response * (unless an exception other than {@link ContinuationThrowable} is thrown). *

* *

* When the thread calling the filter chain and/or servlet has returned to * the container with a suspended request, the thread is freed for other * tasks and the request is held until either: *

    *
  • a call to {@link #resume()}.
  • *
  • a call to {@link #complete()}.
  • *
  • the timeout expires.
  • *
*

* Typically suspend with no arguments is uses when a call to {@link #resume()} * is expected. If a call to {@link #complete()} is expected, then the * {@link #suspend(ServletResponse)} method should be used instead of this method. *

* * @exception IllegalStateException * If the request cannot be suspended */ void suspend(); /* ------------------------------------------------------------ */ /** * Suspend the processing of the request and associated * {@link ServletResponse}. * *

* After this method has been called, the lifecycle of the request will be * extended beyond the return to the container from the * {@link Servlet#service(ServletRequest, ServletResponse)} method and * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)} * calls. When a suspended request is returned to the container after * a dispatch, then the container will not commit the associated response * (unless an exception other than {@link ContinuationThrowable} is thrown). *

*

* When the thread calling the filter chain and/or servlet has returned to * the container with a suspended request, the thread is freed for other * tasks and the request is held until either: *

    *
  • a call to {@link #resume()}.
  • *
  • a call to {@link #complete()}.
  • *
  • the timeout expires.
  • *
*

* Typically suspend with a response argument is uses when a call to {@link #complete()} * is expected. If a call to {@link #resume()} is expected, then the * {@link #suspend()} method should be used instead of this method. *

*

* Filters that may wrap the response object should check {@link #isResponseWrapped()} * to decide if they should destroy/finish the wrapper. If {@link #isResponseWrapped()} * returns true, then the wrapped request has been passed to the asynchronous * handler and the wrapper should not be destroyed/finished until after a call to * {@link #complete()} (potentially using a {@link ContinuationListener#onComplete(Continuation)} * listener). * * @param response The response to return via a call to {@link #getServletResponse()} * @exception IllegalStateException * If the request cannot be suspended */ void suspend(ServletResponse response); /* ------------------------------------------------------------ */ /** * Resume a suspended request. * *

* This method can be called by any thread that has been passed a reference * to a continuation. When called the request is redispatched to the * normal filter chain and servlet processing with {@link #isInitial()} false. *

*

* If resume is called before a suspended request is returned to the * container (ie the thread that called {@link #suspend()} is still * within the filter chain and/or servlet service method), then the resume * does not take effect until the call to the filter chain and/or servlet * returns to the container. In this case both {@link #isSuspended()} and * {@link #isResumed()} return true. Multiple calls to resume are ignored. *

*

* Typically resume() is used after a call to {@link #suspend()} with * no arguments. The dispatch after a resume call will use the original * request and response objects, even if {@link #suspend(ServletResponse)} * had been passed a wrapped response. *

* * @see #suspend() * @exception IllegalStateException if the request is not suspended. * */ void resume(); /* ------------------------------------------------------------ */ /** * Complete a suspended request. * *

* This method can be called by any thread that has been passed a reference * to a suspended request. When a request is completed, the associated * response object committed and flushed. The request is not redispatched. *

* *

* If complete is called before a suspended request is returned to the * container (ie the thread that called {@link #suspend()} is still * within the filter chain and/or servlet service method), then the complete * does not take effect until the call to the filter chain and/or servlet * returns to the container. In this case both {@link #isSuspended()} and * {@link #isResumed()} return true. *

* *

* Typically resume() is used after a call to {@link #suspend(ServletResponse)} with * a possibly wrapped response. The async handler should use the response * provided by {@link #getServletResponse()} to write the response before * calling {@link #complete()}. If the request was suspended with a * call to {@link #suspend()} then no response object will be available via * {@link #getServletResponse()}. *

* *

* Once complete has been called and any thread calling the filter chain * and/or servlet chain has returned to the container, the request lifecycle * is complete. The container is able to recycle request objects, so it is * not valid hold a request or continuation reference after the end of the * life cycle. * * @see #suspend() * @exception IllegalStateException * if the request is not suspended. * */ void complete(); /* ------------------------------------------------------------ */ /** * @return true after {@link #suspend()} has been called and before the * request has been redispatched due to being resumed, completed or * timed out. */ boolean isSuspended(); /* ------------------------------------------------------------ */ /** * @return true if the request has been redispatched by a call to * {@link #resume()}. Returns false after any subsequent call to * suspend */ boolean isResumed(); /* ------------------------------------------------------------ */ /** * @return true after a request has been redispatched as the result of a * timeout. Returns false after any subsequent call to suspend. */ boolean isExpired(); /* ------------------------------------------------------------ */ /** * @return true while the request is within the initial dispatch to the * filter chain and/or servlet. Will return false once the calling * thread has returned to the container after suspend has been * called and during any subsequent redispatch. */ boolean isInitial(); /* ------------------------------------------------------------ */ /** * Is the suspended response wrapped. *

* Filters that wrap the response object should check this method to * determine if they should destroy/finish the wrapped response. If * the request was suspended with a call to {@link #suspend(ServletResponse)} * that passed the wrapped response, then the filter should register * a {@link ContinuationListener} to destroy/finish the wrapped response * during a call to {@link ContinuationListener#onComplete(Continuation)}. * @return True if {@link #suspend(ServletResponse)} has been passed a * {@link ServletResponseWrapper} instance. */ boolean isResponseWrapped(); /* ------------------------------------------------------------ */ /** * Get the suspended response. * @return the {@link ServletResponse} passed to {@link #suspend(ServletResponse)}. */ ServletResponse getServletResponse(); /* ------------------------------------------------------------ */ /** * Add a ContinuationListener. * * @param listener */ void addContinuationListener(ContinuationListener listener); /* ------------------------------------------------------------ */ /** Set a request attribute. * This method is a convenience method to call the {@link ServletRequest#setAttribute(String, Object)} * method on the associated request object. * This is a thread safe call and may be called by any thread. * @param name the attribute name * @param attribute the attribute value */ public void setAttribute(String name, Object attribute); /* ------------------------------------------------------------ */ /** Get a request attribute. * This method is a convenience method to call the {@link ServletRequest#getAttribute(String)} * method on the associated request object. * This is a thread safe call and may be called by any thread. * @param name the attribute name * @return the attribute value */ public Object getAttribute(String name); /* ------------------------------------------------------------ */ /** Remove a request attribute. * This method is a convenience method to call the {@link ServletRequest#removeAttribute(String)} * method on the associated request object. * This is a thread safe call and may be called by any thread. * @param name the attribute name */ public void removeAttribute(String name); /* ------------------------------------------------------------ */ /** * Undispatch the request. *

* This method can be called on a suspended continuation in order * to exit the dispatch to the filter/servlet by throwing a {@link ContinuationThrowable} * which is caught either by the container or the {@link ContinuationFilter}. * This is an alternative to simply returning from the dispatch in the case * where filters in the filter chain may not be prepared to handle a suspended * request. *

* This method should only be used as a last resort and a normal return is a prefereable * solution if filters can be updated to handle that case. * * @throws ContinuationThrowable thrown if the request is suspended. The instance of the * exception may be reused on subsequent calls, so the stack frame may not be accurate. */ public void undispatch() throws ContinuationThrowable; } jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationFilter.java000066400000000000000000000120251174773561500340440ustar00rootroot00000000000000package org.eclipse.jetty.continuation; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /* ------------------------------------------------------------ */ /** *

ContinuationFilter must be applied to servlet paths that make use of * the asynchronous features provided by {@link Continuation} APIs, but that * are deployed in servlet containers that are neither Jetty (>= 7) nor a * compliant Servlet 3.0 container.

*

The following init parameters may be used to configure the filter (these are mostly for testing):

*
*
debug
Boolean controlling debug output
*
jetty6
Boolean to force use of Jetty 6 continuations
*
faux
Boolean to force use of faux continuations
*
*

If the servlet container is not Jetty (either 6 or 7) nor a Servlet 3 * container, then "faux" continuations will be used.

*

Faux continuations will just put the thread that called {@link Continuation#suspend()} * in wait, and will notify that thread when {@link Continuation#resume()} or * {@link Continuation#complete()} is called.

*

Faux continuations are not threadless continuations (they are "faux" - fake - for this reason) * and as such they will scale less than proper continuations.

*/ public class ContinuationFilter implements Filter { static boolean _initialized; static boolean __debug; // shared debug status private boolean _faux; private boolean _jetty6; private boolean _filtered; ServletContext _context; private boolean _debug; public void init(FilterConfig filterConfig) throws ServletException { boolean jetty_7_or_greater="org.eclipse.jetty.servlet".equals(filterConfig.getClass().getPackage().getName()); _context = filterConfig.getServletContext(); String param=filterConfig.getInitParameter("debug"); _debug=param!=null&&Boolean.parseBoolean(param); if (_debug) __debug=true; param=filterConfig.getInitParameter("jetty6"); if (param==null) param=filterConfig.getInitParameter("partial"); if (param!=null) _jetty6=Boolean.parseBoolean(param); else _jetty6=ContinuationSupport.__jetty6 && !jetty_7_or_greater; param=filterConfig.getInitParameter("faux"); if (param!=null) _faux=Boolean.parseBoolean(param); else _faux=!(jetty_7_or_greater || _jetty6 || _context.getMajorVersion()>=3); _filtered=_faux||_jetty6; if (_debug) _context.log("ContinuationFilter "+ " jetty="+jetty_7_or_greater+ " jetty6="+_jetty6+ " faux="+_faux+ " filtered="+_filtered+ " servlet3="+ContinuationSupport.__servlet3); _initialized=true; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (_filtered) { Continuation c = (Continuation) request.getAttribute(Continuation.ATTRIBUTE); FilteredContinuation fc; if (_faux && (c==null || !(c instanceof FauxContinuation))) { fc = new FauxContinuation(request); request.setAttribute(Continuation.ATTRIBUTE,fc); } else fc=(FilteredContinuation)c; boolean complete=false; while (!complete) { try { if (fc==null || (fc).enter(response)) chain.doFilter(request,response); } catch (ContinuationThrowable e) { debug("faux",e); } finally { if (fc==null) fc = (FilteredContinuation) request.getAttribute(Continuation.ATTRIBUTE); complete=fc==null || (fc).exit(); } } } else { try { chain.doFilter(request,response); } catch (ContinuationThrowable e) { debug("caught",e); } } } private void debug(String string) { if (_debug) { _context.log(string); } } private void debug(String string, Throwable th) { if (_debug) { if (th instanceof ContinuationThrowable) _context.log(string+":"+th); else _context.log(string,th); } } public void destroy() { } public interface FilteredContinuation extends Continuation { boolean enter(ServletResponse response); boolean exit(); } } ContinuationListener.java000066400000000000000000000023441174773561500343300ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/jetty/continuation package org.eclipse.jetty.continuation; import java.util.EventListener; import javax.servlet.ServletRequestListener; /* ------------------------------------------------------------ */ /** A Continuation Listener *

* A ContinuationListener may be registered with a call to * {@link Continuation#addContinuationListener(ContinuationListener)}. * */ public interface ContinuationListener extends EventListener { /* ------------------------------------------------------------ */ /** * Called when a continuation life cycle is complete and after * any calls to {@link ServletRequestListener#requestDestroyed(javax.servlet.ServletRequestEvent)} * The response may still be written to during the call. * * @param continuation */ public void onComplete(Continuation continuation); /* ------------------------------------------------------------ */ /** * Called when a suspended continuation has timed out. * The response may be written to and the methods * {@link Continuation#resume()} or {@link Continuation#complete()} * may be called by a onTimeout implementation, * @param continuation */ public void onTimeout(Continuation continuation); } ContinuationSupport.java000066400000000000000000000135341174773561500342220ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/jetty/continuation// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.continuation; import java.lang.reflect.Constructor; import javax.servlet.ServletRequest; import javax.servlet.ServletRequestWrapper; import javax.servlet.ServletResponse; /* ------------------------------------------------------------ */ /** ContinuationSupport. * * Factory class for accessing Continuation instances, which with either be * native to the container (jetty >= 6), a servlet 3.0 or a faux continuation. * */ public class ContinuationSupport { static final boolean __jetty6; static final boolean __servlet3; static final Class __waitingContinuation; static final Constructor __newServlet3Continuation; static final Constructor __newJetty6Continuation; static { boolean servlet3Support=false; Constructors3cc=null; try { boolean servlet3=ServletRequest.class.getMethod("startAsync")!=null; if (servlet3) { Class s3c = ContinuationSupport.class.getClassLoader().loadClass("org.eclipse.jetty.continuation.Servlet3Continuation").asSubclass(Continuation.class); s3cc=s3c.getConstructor(ServletRequest.class); servlet3Support=true; } } catch (Exception e) {} finally { __servlet3=servlet3Support; __newServlet3Continuation=s3cc; } boolean jetty6Support=false; Constructorj6cc=null; try { Class jetty6ContinuationClass = ContinuationSupport.class.getClassLoader().loadClass("org.mortbay.util.ajax.Continuation"); boolean jetty6=jetty6ContinuationClass!=null; if (jetty6) { Class j6c = ContinuationSupport.class.getClassLoader().loadClass("org.eclipse.jetty.continuation.Jetty6Continuation").asSubclass(Continuation.class); j6cc=j6c.getConstructor(ServletRequest.class, jetty6ContinuationClass); jetty6Support=true; } } catch (Exception e) {} finally { __jetty6=jetty6Support; __newJetty6Continuation=j6cc; } Class waiting=null; try { waiting=ContinuationSupport.class.getClassLoader().loadClass("org.mortbay.util.ajax.WaitingContinuation"); } catch (Exception e) { } finally { __waitingContinuation=waiting; } } /* ------------------------------------------------------------ */ /** * Get a Continuation. The type of the Continuation returned may * vary depending on the container in which the application is * deployed. It may be an implementation native to the container (eg * org.eclipse.jetty.server.AsyncContinuation) or one of the utility * implementations provided such as an internal FauxContinuation * or a real implementation like {@link org.eclipse.jetty.continuation.Servlet3Continuation}. * @param request The request * @return a Continuation instance */ public static Continuation getContinuation(ServletRequest request) { Continuation continuation = (Continuation) request.getAttribute(Continuation.ATTRIBUTE); if (continuation!=null) return continuation; while (request instanceof ServletRequestWrapper) request=((ServletRequestWrapper)request).getRequest(); if (__servlet3 ) { try { continuation=__newServlet3Continuation.newInstance(request); request.setAttribute(Continuation.ATTRIBUTE,continuation); return continuation; } catch(Exception e) { throw new RuntimeException(e); } } if (__jetty6) { Object c=request.getAttribute("org.mortbay.jetty.ajax.Continuation"); try { if (c==null || __waitingContinuation==null || __waitingContinuation.isInstance(c)) continuation=new FauxContinuation(request); else continuation= __newJetty6Continuation.newInstance(request,c); request.setAttribute(Continuation.ATTRIBUTE,continuation); return continuation; } catch(Exception e) { throw new RuntimeException(e); } } throw new IllegalStateException("!(Jetty || Servlet 3.0 || ContinuationFilter)"); } /* ------------------------------------------------------------ */ /** * @param request the servlet request * @param response the servlet response * @deprecated use {@link #getContinuation(ServletRequest)} * @return the continuation */ @Deprecated public static Continuation getContinuation(final ServletRequest request, final ServletResponse response) { return getContinuation(request); } } ContinuationThrowable.java000066400000000000000000000033601174773561500344710ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/jetty/continuation// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.continuation; /* ------------------------------------------------------------ */ /** ContinuationThrowable *

* A ContinuationThrowable is throw by {@link Continuation#undispatch()} * in order to exit the dispatch to a Filter or Servlet. Use of * ContinuationThrowable is discouraged and it is preferable to * allow return to be used. ContinuationThrowables should only be * used when there is a Filter/Servlet which cannot be modified * to avoid committing a response when {@link Continuation#isSuspended()} * is true. *

*

* ContinuationThrowable instances are often reused so that the * stack trace may be entirely unrelated to the calling stack. * A real stack trace may be obtained by enabling debug. *

*

* ContinuationThrowable extends Error as this is more likely * to be uncaught (or rethrown) by a Filter/Servlet. A ContinuationThrowable * does not represent and error condition. *

*/ public class ContinuationThrowable extends Error {}jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/FauxContinuation.java000066400000000000000000000342701174773561500335300ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.continuation; import java.util.ArrayList; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.ServletResponseWrapper; import org.eclipse.jetty.continuation.ContinuationFilter.FilteredContinuation; /* ------------------------------------------------------------ */ /** * A blocking implementation of Continuation. * This implementation of Continuation is used by the {@link ContinuationFilter} * when there are is no native or asynchronous continuation type available. */ class FauxContinuation implements FilteredContinuation { // common exception used for all continuations. // Turn on debug in ContinuationFilter to see real stack trace. private final static ContinuationThrowable __exception = new ContinuationThrowable(); private static final int __HANDLING=1; // Request dispatched to filter/servlet private static final int __SUSPENDING=2; // Suspend called, but not yet returned to container private static final int __RESUMING=3; // resumed while suspending private static final int __COMPLETING=4; // resumed while suspending or suspended private static final int __SUSPENDED=5; // Suspended and parked private static final int __UNSUSPENDING=6; private static final int __COMPLETE=7; private final ServletRequest _request; private ServletResponse _response; private int _state=__HANDLING; private boolean _initial=true; private boolean _resumed=false; private boolean _timeout=false; private boolean _responseWrapped=false; private long _timeoutMs=30000; // TODO configure private ArrayList _listeners; FauxContinuation(final ServletRequest request) { _request=request; } /* ------------------------------------------------------------ */ public void onComplete() { if (_listeners!=null) for (ContinuationListener l:_listeners) l.onComplete(this); } /* ------------------------------------------------------------ */ public void onTimeout() { if (_listeners!=null) for (ContinuationListener l:_listeners) l.onTimeout(this); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#isResponseWrapped() */ public boolean isResponseWrapped() { return _responseWrapped; } /* ------------------------------------------------------------ */ public boolean isInitial() { synchronized(this) { return _initial; } } /* ------------------------------------------------------------ */ public boolean isResumed() { synchronized(this) { return _resumed; } } /* ------------------------------------------------------------ */ public boolean isSuspended() { synchronized(this) { switch(_state) { case __HANDLING: return false; case __SUSPENDING: case __RESUMING: case __COMPLETING: case __SUSPENDED: return true; case __UNSUSPENDING: default: return false; } } } /* ------------------------------------------------------------ */ public boolean isExpired() { synchronized(this) { return _timeout; } } /* ------------------------------------------------------------ */ public void setTimeout(long timeoutMs) { _timeoutMs = timeoutMs; } /* ------------------------------------------------------------ */ public void suspend(ServletResponse response) { _response=response; _responseWrapped=response instanceof ServletResponseWrapper; suspend(); } /* ------------------------------------------------------------ */ public void suspend() { synchronized (this) { switch(_state) { case __HANDLING: _timeout=false; _resumed=false; _state=__SUSPENDING; return; case __SUSPENDING: case __RESUMING: return; case __COMPLETING: case __SUSPENDED: case __UNSUSPENDING: throw new IllegalStateException(this.getStatusString()); default: throw new IllegalStateException(""+_state); } } } /* ------------------------------------------------------------ */ /* (non-Javadoc) * @see org.mortbay.jetty.Suspendor#resume() */ public void resume() { synchronized (this) { switch(_state) { case __HANDLING: _resumed=true; return; case __SUSPENDING: _resumed=true; _state=__RESUMING; return; case __RESUMING: case __COMPLETING: return; case __SUSPENDED: fauxResume(); _resumed=true; _state=__UNSUSPENDING; break; case __UNSUSPENDING: _resumed=true; return; default: throw new IllegalStateException(this.getStatusString()); } } } /* ------------------------------------------------------------ */ public void complete() { // just like resume, except don't set _resumed=true; synchronized (this) { switch(_state) { case __HANDLING: throw new IllegalStateException(this.getStatusString()); case __SUSPENDING: _state=__COMPLETING; break; case __RESUMING: break; case __COMPLETING: return; case __SUSPENDED: _state=__COMPLETING; fauxResume(); break; case __UNSUSPENDING: return; default: throw new IllegalStateException(this.getStatusString()); } } } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#getServletResponse() */ public boolean enter(ServletResponse response) { _response=response; return true; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#getServletResponse() */ public ServletResponse getServletResponse() { return _response; } /* ------------------------------------------------------------ */ void handling() { synchronized (this) { _responseWrapped=false; switch(_state) { case __HANDLING: throw new IllegalStateException(this.getStatusString()); case __SUSPENDING: case __RESUMING: throw new IllegalStateException(this.getStatusString()); case __COMPLETING: return; case __SUSPENDED: fauxResume(); case __UNSUSPENDING: _state=__HANDLING; return; default: throw new IllegalStateException(""+_state); } } } /* ------------------------------------------------------------ */ /** * @return true if handling is complete */ public boolean exit() { synchronized (this) { switch(_state) { case __HANDLING: _state=__COMPLETE; onComplete(); return true; case __SUSPENDING: _initial=false; _state=__SUSPENDED; fauxSuspend(); // could block and change state. if (_state==__SUSPENDED || _state==__COMPLETING) { onComplete(); return true; } _initial=false; _state=__HANDLING; return false; case __RESUMING: _initial=false; _state=__HANDLING; return false; case __COMPLETING: _initial=false; _state=__COMPLETE; onComplete(); return true; case __SUSPENDED: case __UNSUSPENDING: default: throw new IllegalStateException(this.getStatusString()); } } } /* ------------------------------------------------------------ */ protected void expire() { // just like resume, except don't set _resumed=true; synchronized (this) { _timeout=true; } onTimeout(); synchronized (this) { switch(_state) { case __HANDLING: return; case __SUSPENDING: _timeout=true; _state=__RESUMING; fauxResume(); return; case __RESUMING: return; case __COMPLETING: return; case __SUSPENDED: _timeout=true; _state=__UNSUSPENDING; break; case __UNSUSPENDING: _timeout=true; return; default: throw new IllegalStateException(this.getStatusString()); } } } private void fauxSuspend() { long expire_at = System.currentTimeMillis()+_timeoutMs; long wait=_timeoutMs; while (_timeoutMs>0 && wait>0) { try { this.wait(wait); } catch (InterruptedException e) { break; } wait=expire_at-System.currentTimeMillis(); } if (_timeoutMs>0 && wait<=0) expire(); } private void fauxResume() { _timeoutMs=0; this.notifyAll(); } @Override public String toString() { return getStatusString(); } String getStatusString() { synchronized (this) { return ((_state==__HANDLING)?"HANDLING": (_state==__SUSPENDING)?"SUSPENDING": (_state==__SUSPENDED)?"SUSPENDED": (_state==__RESUMING)?"RESUMING": (_state==__UNSUSPENDING)?"UNSUSPENDING": (_state==__COMPLETING)?"COMPLETING": ("???"+_state))+ (_initial?",initial":"")+ (_resumed?",resumed":"")+ (_timeout?",timeout":""); } } public void addContinuationListener(ContinuationListener listener) { if (_listeners==null) _listeners=new ArrayList(); _listeners.add(listener); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String) */ public Object getAttribute(String name) { return _request.getAttribute(name); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String) */ public void removeAttribute(String name) { _request.removeAttribute(name); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object) */ public void setAttribute(String name, Object attribute) { _request.setAttribute(name,attribute); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#undispatch() */ public void undispatch() { if (isSuspended()) { if (ContinuationFilter.__debug) throw new ContinuationThrowable(); throw __exception; } throw new IllegalStateException("!suspended"); } } jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Jetty6Continuation.java000066400000000000000000000156351174773561500340160ustar00rootroot00000000000000package org.eclipse.jetty.continuation; import java.util.ArrayList; import java.util.List; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.ServletResponseWrapper; import org.mortbay.log.Log; import org.mortbay.log.Logger; /* ------------------------------------------------------------ */ /** * This implementation of Continuation is used by {@link ContinuationSupport} * when it detects that the application is deployed in a jetty-6 server. * This continuation requires the {@link ContinuationFilter} to be deployed. */ public class Jetty6Continuation implements ContinuationFilter.FilteredContinuation { private static final Logger LOG = Log.getLogger(Jetty6Continuation.class.getName()); // Exception reused for all continuations // Turn on debug in ContinuationFilter to see real stack trace. private final static ContinuationThrowable __exception = new ContinuationThrowable(); private final ServletRequest _request; private ServletResponse _response; private final org.mortbay.util.ajax.Continuation _j6Continuation; private Throwable _retry; private int _timeout; private boolean _initial=true; private volatile boolean _completed=false; private volatile boolean _resumed=false; private volatile boolean _expired=false; private boolean _responseWrapped=false; private List _listeners; public Jetty6Continuation(ServletRequest request, org.mortbay.util.ajax.Continuation continuation) { if (!ContinuationFilter._initialized) { LOG.warn("!ContinuationFilter installed",null,null); throw new IllegalStateException("!ContinuationFilter installed"); } _request=request; _j6Continuation=continuation; } public void addContinuationListener(final ContinuationListener listener) { if (_listeners==null) _listeners=new ArrayList(); _listeners.add(listener); } public void complete() { synchronized(this) { if (_resumed) throw new IllegalStateException(); _completed=true; if (_j6Continuation.isPending()) _j6Continuation.resume(); } } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String) */ public Object getAttribute(String name) { return _request.getAttribute(name); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String) */ public void removeAttribute(String name) { _request.removeAttribute(name); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object) */ public void setAttribute(String name, Object attribute) { _request.setAttribute(name,attribute); } /* ------------------------------------------------------------ */ public ServletResponse getServletResponse() { return _response; } /* ------------------------------------------------------------ */ public boolean isExpired() { return _expired; } /* ------------------------------------------------------------ */ public boolean isInitial() { return _initial; } /* ------------------------------------------------------------ */ public boolean isResumed() { return _resumed; } /* ------------------------------------------------------------ */ public boolean isSuspended() { return _retry!=null; } /* ------------------------------------------------------------ */ public void resume() { synchronized(this) { if (_completed) throw new IllegalStateException(); _resumed=true; if (_j6Continuation.isPending()) _j6Continuation.resume(); } } /* ------------------------------------------------------------ */ public void setTimeout(long timeoutMs) { _timeout=(timeoutMs>Integer.MAX_VALUE)?Integer.MAX_VALUE:(int)timeoutMs; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#suspend(javax.servlet.ServletResponse) */ public void suspend(ServletResponse response) { try { _response=response; _responseWrapped=_response instanceof ServletResponseWrapper; _resumed=false; _expired=false; _completed=false; _j6Continuation.suspend(_timeout); } catch(Throwable retry) { _retry=retry; } } /* ------------------------------------------------------------ */ public void suspend() { try { _response=null; _responseWrapped=false; _resumed=false; _expired=false; _completed=false; _j6Continuation.suspend(_timeout); } catch(Throwable retry) { _retry=retry; } } /* ------------------------------------------------------------ */ public boolean isResponseWrapped() { return _responseWrapped; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#undispatch() */ public void undispatch() { if (isSuspended()) { if (ContinuationFilter.__debug) throw new ContinuationThrowable(); throw __exception; } throw new IllegalStateException("!suspended"); } /* ------------------------------------------------------------ */ public boolean enter(ServletResponse response) { _response=response; _expired=!_j6Continuation.isResumed(); if (_initial) return true; _j6Continuation.reset(); if (_expired) { if (_listeners!=null) { for (ContinuationListener l: _listeners) l.onTimeout(this); } } return !_completed; } /* ------------------------------------------------------------ */ public boolean exit() { _initial=false; Throwable th=_retry; _retry=null; if (th instanceof Error) throw (Error)th; if (th instanceof RuntimeException) throw (RuntimeException)th; if (_listeners!=null) { for (ContinuationListener l: _listeners) l.onComplete(this); } return true; } } Servlet3Continuation.java000066400000000000000000000160201174773561500342460ustar00rootroot00000000000000jetty8-8.1.3/jetty-continuation/src/main/java/org/eclipse/jetty/continuationpackage org.eclipse.jetty.continuation; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; import javax.servlet.DispatcherType; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.ServletResponseWrapper; /* ------------------------------------------------------------ */ /** * This implementation of Continuation is used by {@link ContinuationSupport} * when it detects that the application has been deployed in a non-jetty Servlet 3 * server. */ public class Servlet3Continuation implements Continuation { // Exception reused for all continuations // Turn on debug in ContinuationFilter to see real stack trace. private final static ContinuationThrowable __exception = new ContinuationThrowable(); private final ServletRequest _request; private ServletResponse _response; private AsyncContext _context; private List _listeners=new ArrayList(); private volatile boolean _initial=true; private volatile boolean _resumed=false; private volatile boolean _expired=false; private volatile boolean _responseWrapped=false; private long _timeoutMs=-1; /* ------------------------------------------------------------ */ public Servlet3Continuation(ServletRequest request) { _request=request; _listeners.add(new AsyncListener() { public void onComplete(AsyncEvent event) throws IOException { } public void onError(AsyncEvent event) throws IOException { } public void onStartAsync(AsyncEvent event) throws IOException { event.getAsyncContext().addListener(this); } public void onTimeout(AsyncEvent event) throws IOException { _initial=false; event.getAsyncContext().dispatch(); } }); } /* ------------------------------------------------------------ */ public void addContinuationListener(final ContinuationListener listener) { AsyncListener wrapped = new AsyncListener() { public void onComplete(final AsyncEvent event) throws IOException { listener.onComplete(Servlet3Continuation.this); } public void onError(AsyncEvent event) throws IOException { listener.onComplete(Servlet3Continuation.this); } public void onStartAsync(AsyncEvent event) throws IOException { event.getAsyncContext().addListener(this); } public void onTimeout(AsyncEvent event) throws IOException { _expired=true; listener.onTimeout(Servlet3Continuation.this); } }; if (_context!=null) _context.addListener(wrapped); else _listeners.add(wrapped); } /* ------------------------------------------------------------ */ public void complete() { AsyncContext context=_context; if (context==null) throw new IllegalStateException(); _context.complete(); } /* ------------------------------------------------------------ */ public ServletResponse getServletResponse() { return _response; } /* ------------------------------------------------------------ */ public boolean isExpired() { return _expired; } /* ------------------------------------------------------------ */ public boolean isInitial() { // TODO - this is not perfect if non continuation API is used directly return _initial&&_request.getDispatcherType()!=DispatcherType.ASYNC; } /* ------------------------------------------------------------ */ public boolean isResumed() { return _resumed; } /* ------------------------------------------------------------ */ public boolean isSuspended() { return _request.isAsyncStarted(); } /* ------------------------------------------------------------ */ public void keepWrappers() { _responseWrapped=true; } /* ------------------------------------------------------------ */ public void resume() { AsyncContext context=_context; if (context==null) throw new IllegalStateException(); _resumed=true; _context.dispatch(); } /* ------------------------------------------------------------ */ public void setTimeout(long timeoutMs) { _timeoutMs=timeoutMs; if (_context!=null) _context.setTimeout(timeoutMs); } /* ------------------------------------------------------------ */ public void suspend(ServletResponse response) { _response=response; _responseWrapped=response instanceof ServletResponseWrapper; _resumed=false; _expired=false; _context=_request.startAsync(); _context.setTimeout(_timeoutMs); for (AsyncListener listener:_listeners) _context.addListener(listener); _listeners.clear(); } /* ------------------------------------------------------------ */ public void suspend() { _resumed=false; _expired=false; _context=_request.startAsync(); _context.setTimeout(_timeoutMs); for (AsyncListener listener:_listeners) _context.addListener(listener); _listeners.clear(); } /* ------------------------------------------------------------ */ public boolean isResponseWrapped() { return _responseWrapped; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String) */ public Object getAttribute(String name) { return _request.getAttribute(name); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String) */ public void removeAttribute(String name) { _request.removeAttribute(name); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object) */ public void setAttribute(String name, Object attribute) { _request.setAttribute(name,attribute); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.continuation.Continuation#undispatch() */ public void undispatch() { if (isSuspended()) { if (ContinuationFilter.__debug) throw new ContinuationThrowable(); throw __exception; } throw new IllegalStateException("!suspended"); } } jetty8-8.1.3/jetty-deploy/000077500000000000000000000000001174773561500154235ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/pom.xml000066400000000000000000000063051174773561500167440ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 jetty-deploy Jetty :: Deployers Jetty deployers ${project.groupId}.deploy org.apache.felix maven-bundle-plugin true manifest org.eclipse.jetty.jmx.*;version="8.0";resolution:=optional,* org.apache.maven.plugins maven-assembly-plugin package single config org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.deploy.* org.eclipse.jetty.toolchain jetty-test-helper test org.eclipse.jetty jetty-webapp ${project.version} org.eclipse.jetty jetty-xml ${project.version} org.eclipse.jetty jetty-jmx ${project.version} true org.eclipse.jetty jetty-websocket ${project.version} test jetty8-8.1.3/jetty-deploy/src/000077500000000000000000000000001174773561500162125ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/000077500000000000000000000000001174773561500171365ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/config/000077500000000000000000000000001174773561500204035ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/config/etc/000077500000000000000000000000001174773561500211565ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/config/etc/jetty-contexts.xml000066400000000000000000000022351174773561500247060ustar00rootroot00000000000000 /contexts 1 jetty8-8.1.3/jetty-deploy/src/main/config/etc/jetty-deploy.xml000066400000000000000000000040011174773561500243240ustar00rootroot00000000000000 org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern .*/servlet-api-[^/]*\.jar$ jetty8-8.1.3/jetty-deploy/src/main/config/etc/jetty-webapps.xml000066400000000000000000000026421174773561500245020ustar00rootroot00000000000000 /webapps /etc/webdefault.xml 1 /contexts true jetty8-8.1.3/jetty-deploy/src/main/java/000077500000000000000000000000001174773561500200575ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/000077500000000000000000000000001174773561500206465ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/000077500000000000000000000000001174773561500222725ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500234315ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/000077500000000000000000000000001174773561500247255ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/App.java000066400000000000000000000113061174773561500263110ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.AttributesMap; /** * The information about an App that is managed by the {@link DeploymentManager} */ public class App { private final DeploymentManager _manager; private final AppProvider _provider; private final String _originId; private ContextHandler _context; /** * Create an App with specified Origin ID and archivePath * * @param originId * the origin ID (The ID that the {@link AppProvider} knows * about) * @see App#getOriginId() * @see App#getContextPath() */ public App(DeploymentManager manager, AppProvider provider, String originId) { _manager = manager; _provider = provider; _originId = originId; } /** * Create an App with specified Origin ID and archivePath * * @param originId * the origin ID (The ID that the {@link AppProvider} knows * about) * @see App#getOriginId() * @see App#getContextPath() * @param context * Some implementations of AppProvider might have to use an * already created ContextHandler. */ public App(DeploymentManager manager, AppProvider provider, String originId, ContextHandler context) { this(manager,provider,originId); _context = context; } /* ------------------------------------------------------------ */ /** * @return The deployment manager */ public DeploymentManager getDeploymentManager() { return _manager; } /* ------------------------------------------------------------ */ /** * @return The AppProvider */ public AppProvider getAppProvider() { return _provider; } /** * Get ContextHandler for the App. * * Create it if needed. * * @return the {@link ContextHandler} to use for the App when fully started. * (Portions of which might be ignored when App is not yet * {@link AppLifeCycle#DEPLOYED} or {@link AppLifeCycle#STARTED}) * @throws Exception */ public ContextHandler getContextHandler() throws Exception { if (_context == null) { _context = getAppProvider().createContextHandler(this); AttributesMap attributes = _manager.getContextAttributes(); if (attributes!=null && attributes.size()>0) { // Merge the manager attributes under the existing attributes attributes = new AttributesMap(attributes); attributes.addAll(_context.getAttributes()); _context.setAttributes(attributes); } } return _context; } /** * The context path {@link App} relating to how it is installed on the * jetty server side. * * NOTE that although the method name indicates that this is a unique * identifier, it is not, as many contexts may have the same contextPath, * yet different virtual hosts. * * @deprecated Use getContextPath instead. * @return the context path for the App */ public String getContextId() { return getContextPath(); } /** * The context path {@link App} relating to how it is installed on the * jetty server side. * * @return the contextPath for the App */ public String getContextPath() { if (this._context == null) { return null; } return this._context.getContextPath(); } /** * The origin of this {@link App} as specified by the {@link AppProvider} * * @return String representing the origin of this app. */ public String getOriginId() { return this._originId; } @Override public String toString() { return "App[" + _context + "," + _originId + "]"; } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/AppLifeCycle.java000066400000000000000000000131571174773561500300770ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.jetty.deploy.graph.Graph; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * The lifecycle of an App in the {@link DeploymentManager}. * * Setups a the default {@link Graph}, and manages the bindings to the life cycle via the {@link AppLifeCycle.Binding} * annotation. *

* */ public class AppLifeCycle extends Graph { private static final Logger LOG = Log.getLogger(AppLifeCycle.class); private static final String ALL_NODES = "*"; public static interface Binding { /** * Get a list of targets that this implementation should bind to. * * @return the array of String node names to bind to. (use "*" to bind to all known node names) */ String[] getBindingTargets(); /** * Event called to process a {@link AppLifeCycle} binding. * * @param node * the node being processed * @param app * the app being processed * @throws Exception * if any problem severe enough to halt the AppLifeCycle processing */ void processBinding(Node node, App app) throws Exception; } // Well known existing lifecycle Nodes public static final String UNDEPLOYED = "undeployed"; public static final String DEPLOYING = "deploying"; public static final String DEPLOYED = "deployed"; public static final String STARTING = "starting"; public static final String STARTED = "started"; public static final String STOPPING = "stopping"; public static final String UNDEPLOYING = "undeploying"; private Map> lifecyclebindings = new HashMap>(); public AppLifeCycle() { // Define Default Graph // undeployed -> deployed addEdge(UNDEPLOYED,DEPLOYING); addEdge(DEPLOYING,DEPLOYED); // deployed -> started addEdge(DEPLOYED,STARTING); addEdge(STARTING,STARTED); // started -> deployed addEdge(STARTED,STOPPING); addEdge(STOPPING,DEPLOYED); // deployed -> undeployed addEdge(DEPLOYED,UNDEPLOYING); addEdge(UNDEPLOYING,UNDEPLOYED); } public void addBinding(AppLifeCycle.Binding binding) { for (String nodeName : binding.getBindingTargets()) { List bindings = lifecyclebindings.get(nodeName); if (bindings == null) { bindings = new ArrayList(); } bindings.add(binding); lifecyclebindings.put(nodeName,bindings); } } public void removeBinding(AppLifeCycle.Binding binding) { for (String nodeName : binding.getBindingTargets()) { List bindings = lifecyclebindings.get(nodeName); if (bindings != null) bindings.remove(binding); } } /** * Get all {@link Node} bound objects. * * @return Set of Object(s) for all lifecycle bindings. never null. */ public Set getBindings() { Set boundset = new HashSet(); for (List bindings : lifecyclebindings.values()) { boundset.addAll(bindings); } return boundset; } /** * Get all objects bound to a specific {@link Node} * * @return Set of Object(s) for specific lifecycle bindings. never null. */ public Set getBindings(Node node) { return getBindings(node.getName()); } /** * Get all objects bound to a specific {@link Node} * * @return Set of Object(s) for specific lifecycle bindings. never null. */ public Set getBindings(String nodeName) { Set boundset = new HashSet(); // Specific node binding List bindings = lifecyclebindings.get(nodeName); if (bindings != null) { boundset.addAll(bindings); } // Special 'all nodes' binding bindings = lifecyclebindings.get(ALL_NODES); if (bindings != null) { boundset.addAll(bindings); } return boundset; } public void runBindings(Node node, App app, DeploymentManager deploymentManager) throws Throwable { for (Binding binding : getBindings(node)) { if (LOG.isDebugEnabled()) LOG.debug("Calling " + binding.getClass().getName()+" for "+app); binding.processBinding(node,app); } } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/AppProvider.java000066400000000000000000000031021174773561500300170ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.io.IOException; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.component.LifeCycle; /** * Object responsible for providing {@link App}s to the {@link DeploymentManager} */ public interface AppProvider extends LifeCycle { /** * Set the Deployment Manager * * @param deploymentManager * @throws IllegalStateException * if the provider {@link #isRunning()}. */ void setDeploymentManager(DeploymentManager deploymentManager); /* ------------------------------------------------------------ */ /** Create a ContextHandler for an App * @param app The App * @return A ContextHandler * @throws IOException * @throws Exception */ ContextHandler createContextHandler(App app) throws Exception; } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/ConfigurationManager.java000066400000000000000000000020171174773561500316720ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.util.Map; /** * ConfigurationManager * * Type for allow injection of property values for replacement in jetty xml files during deployment. */ public interface ConfigurationManager { public Map getProperties(); } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/ContextDeployer.java000066400000000000000000000364351174773561500307330ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.io.File; import java.io.FilenameFilter; import java.util.HashMap; import java.util.Map; import org.eclipse.jetty.deploy.providers.ContextProvider; import org.eclipse.jetty.deploy.providers.ScanningAppProvider; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.util.AttributesMap; import org.eclipse.jetty.util.Scanner; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.xml.XmlConfiguration; /** * Legacy Context Deployer. * *

* Note: The WebAppDeployer is being phased out of Jetty in favor of the {@link DeploymentManager} and * {@link org.eclipse.jetty.deploy.providers.ContextProvider} implementation. * *

* This deployer scans a designated directory by {@link #setConfigurationDir(String)} for the appearance/disappearance * or changes to xml configuration files. The scan is performed at startup and at an optional hot deployment frequency * specified by {@link #setScanInterval(int)}. By default, the scanning is NOT recursive, but can be made so by * {@link #setRecursive(boolean)}. * *

* Each configuration file is in {@link XmlConfiguration} format and represents the configuration of a instance of * {@link ContextHandler} (or a subclass specified by the XML Configure element). * *

* The xml should configure the context and the instance is deployed to the {@link ContextHandlerCollection} specified * by {@link Server#setHandler(org.eclipse.jetty.server.Handler)}. * *

* Similarly, when one of these existing files is removed, the corresponding context is undeployed; when one of these * files is changed, the corresponding context is undeployed, the (changed) xml config file reapplied to it, and then * (re)deployed. * *

* Note that the context itself is NOT copied into the hot deploy directory. The webapp directory or war file can exist * anywhere. It is the xml config file that points to it's location and deploys it from there. * *

* It means, for example, that you can keep a "read-only" copy of your webapp somewhere, and apply different * configurations to it simply by dropping different xml configuration files into the configuration directory. * * @see DeploymentManager * @see ScanningAppProvider * * @org.apache.xbean.XBean element="hotDeployer" description="Creates a hot deployer to watch a directory for changes at * a configurable interval." * @deprecated replaced with {@link ContextProvider} from the {@link DeploymentManager} */ @SuppressWarnings("unchecked") @Deprecated public class ContextDeployer extends AbstractLifeCycle { private static final Logger LOG = Log.getLogger(ContextDeployer.class); private int _scanInterval=10; private Scanner _scanner; private ScannerListener _scannerListener; private Resource _contextsDir; private Map _currentDeployments = new HashMap(); private ContextHandlerCollection _contexts; private ConfigurationManager _configMgr; private boolean _recursive = false; private AttributesMap _contextAttributes = new AttributesMap(); /* ------------------------------------------------------------ */ protected class ScannerListener implements Scanner.DiscreteListener { /** * Handle a new deployment * * @see org.eclipse.jetty.util.Scanner.DiscreteListener#fileAdded(java.lang.String) */ public void fileAdded(String filename) throws Exception { deploy(filename); } /** * Handle a change to an existing deployment. Undeploy then redeploy. * * @see org.eclipse.jetty.util.Scanner.DiscreteListener#fileChanged(java.lang.String) */ public void fileChanged(String filename) throws Exception { redeploy(filename); } /** * Handle an undeploy. * * @see org.eclipse.jetty.util.Scanner.DiscreteListener#fileRemoved(java.lang.String) */ public void fileRemoved(String filename) throws Exception { undeploy(filename); } @Override public String toString() { return "ContextDeployer$Scanner"; } } /** * Constructor */ public ContextDeployer() { LOG.warn("ContextDeployer is deprecated. Use ContextProvider"); _scanner=new Scanner(); } /* ------------------------------------------------------------ */ /** * @return the ContextHandlerColletion to which to deploy the contexts */ public ContextHandlerCollection getContexts() { return _contexts; } /* ------------------------------------------------------------ */ /** * Associate with a {@link ContextHandlerCollection}. * * @param contexts * the ContextHandlerColletion to which to deploy the contexts */ public void setContexts(ContextHandlerCollection contexts) { if (isStarted()||isStarting()) throw new IllegalStateException("Cannot set Contexts after deployer start"); _contexts=contexts; } /* ------------------------------------------------------------ */ /** * @param seconds * The period in second between scans for changed configuration * files. A zero or negative interval disables hot deployment */ public void setScanInterval(int seconds) { if (isStarted()||isStarting()) throw new IllegalStateException("Cannot change scan interval after deployer start"); _scanInterval=seconds; } /* ------------------------------------------------------------ */ public int getScanInterval() { return _scanInterval; } /* ------------------------------------------------------------ */ /** * @param dir Directory to scan for context descriptors */ public void setContextsDir(String dir) { try { _contextsDir=Resource.newResource(dir); } catch(Exception e) { throw new IllegalArgumentException(e); } } /* ------------------------------------------------------------ */ public String getContextsDir() { return _contextsDir==null?null:_contextsDir.toString(); } /* ------------------------------------------------------------ */ /** * @param dir * @throws Exception * @deprecated use {@link #setContextsDir(String)} */ @Deprecated public void setConfigurationDir(String dir) throws Exception { setConfigurationDir(Resource.newResource(dir)); } /* ------------------------------------------------------------ */ /** * @param file * @throws Exception * @deprecated use {@link #setContextsDir(String)} */ @Deprecated public void setConfigurationDir(File file) throws Exception { setConfigurationDir(Resource.newResource(Resource.toURL(file))); } /* ------------------------------------------------------------ */ /** * @param resource * @deprecated use {@link #setContextsDir(String)} */ @Deprecated public void setConfigurationDir(Resource resource) { if (isStarted()||isStarting()) throw new IllegalStateException("Cannot change hot deploy dir after deployer start"); _contextsDir=resource; } /* ------------------------------------------------------------ */ /** * @param directory * @deprecated use {@link #setContextsDir(String)} */ @Deprecated public void setDirectory(String directory) throws Exception { setConfigurationDir(directory); } /* ------------------------------------------------------------ */ /** * @return the directory * @deprecated use {@link #setContextsDir(String)} */ @Deprecated public String getDirectory() { return getConfigurationDir().getName(); } /* ------------------------------------------------------------ */ /** * @return the configuration directory * @deprecated use {@link #setContextsDir(String)} */ @Deprecated public Resource getConfigurationDir() { return _contextsDir; } /* ------------------------------------------------------------ */ /** * @param configMgr */ public void setConfigurationManager(ConfigurationManager configMgr) { _configMgr=configMgr; } /* ------------------------------------------------------------ */ /** * @return the configuration manager */ public ConfigurationManager getConfigurationManager() { return _configMgr; } /* ------------------------------------------------------------ */ public void setRecursive (boolean recursive) { _recursive=recursive; } /* ------------------------------------------------------------ */ public boolean getRecursive () { return _recursive; } /* ------------------------------------------------------------ */ public boolean isRecursive() { return _recursive; } /* ------------------------------------------------------------ */ /** * Set a contextAttribute that will be set for every Context deployed by this deployer. * @param name * @param value */ public void setAttribute (String name, Object value) { _contextAttributes.setAttribute(name,value); } /* ------------------------------------------------------------ */ /** * Get a contextAttribute that will be set for every Context deployed by this deployer. * @param name * @return the attribute value */ public Object getAttribute (String name) { return _contextAttributes.getAttribute(name); } /* ------------------------------------------------------------ */ /** * Remove a contextAttribute that will be set for every Context deployed by this deployer. * @param name */ public void removeAttribute(String name) { _contextAttributes.removeAttribute(name); } /* ------------------------------------------------------------ */ private void deploy(String filename) throws Exception { ContextHandler context=createContext(filename); LOG.info("Deploy "+filename+" -> "+ context); _contexts.addHandler(context); _currentDeployments.put(filename,context); if (_contexts.isStarted()) context.start(); } /* ------------------------------------------------------------ */ private void undeploy(String filename) throws Exception { ContextHandler context=(ContextHandler)_currentDeployments.get(filename); LOG.info("Undeploy "+filename+" -> "+context); if (context==null) return; context.stop(); _contexts.removeHandler(context); _currentDeployments.remove(filename); } /* ------------------------------------------------------------ */ private void redeploy(String filename) throws Exception { undeploy(filename); deploy(filename); } /* ------------------------------------------------------------ */ /** * Start the hot deployer looking for webapps to deploy/undeploy * * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() */ @SuppressWarnings("deprecation") @Override protected void doStart() throws Exception { if (_contextsDir==null) throw new IllegalStateException("No configuration dir specified"); if (_contexts==null) throw new IllegalStateException("No context handler collection specified for deployer"); _scanner.setScanDir(_contextsDir.getFile()); _scanner.setScanInterval(getScanInterval()); _scanner.setRecursive(_recursive); //only look in the top level for deployment files? // Accept changes only in files that could be a deployment descriptor _scanner.setFilenameFilter(new FilenameFilter() { public boolean accept(File dir, String name) { try { if (name.endsWith(".xml")) return true; return false; } catch (Exception e) { LOG.warn(e); return false; } } }); _scannerListener=new ScannerListener(); _scanner.addListener(_scannerListener); _scanner.scan(); _scanner.start(); _contexts.getServer().getContainer().addBean(_scanner); } /* ------------------------------------------------------------ */ /** * Stop the hot deployer. * * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop() */ @Override protected void doStop() throws Exception { _scanner.removeListener(_scannerListener); _scanner.stop(); } /* ------------------------------------------------------------ */ /** * Create a WebAppContext for the webapp being hot deployed, then apply the * xml config file to it to configure it. * * @param filename * the config file found in the hot deploy directory * @return * @throws Exception */ private ContextHandler createContext(String filename) throws Exception { // The config file can call any method on WebAppContext to configure // the webapp being deployed. Resource resource = Resource.newResource(filename); if (!resource.exists()) return null; XmlConfiguration xmlConfiguration=new XmlConfiguration(resource.getURL()); xmlConfiguration.getIdMap().put("Server", _contexts.getServer()); if (_configMgr!=null) xmlConfiguration.getProperties().putAll(_configMgr.getProperties()); ContextHandler context=(ContextHandler)xmlConfiguration.configure(); // merge attributes if (_contextAttributes!=null && _contextAttributes.size()>0) { AttributesMap attributes = new AttributesMap(_contextAttributes); attributes.addAll(context.getAttributes()); context.setAttributes(attributes); } return context; } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/DeploymentManager.java000066400000000000000000000406561174773561500312160ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import org.eclipse.jetty.deploy.bindings.StandardDeployer; import org.eclipse.jetty.deploy.bindings.StandardStarter; import org.eclipse.jetty.deploy.bindings.StandardStopper; import org.eclipse.jetty.deploy.bindings.StandardUndeployer; import org.eclipse.jetty.deploy.graph.Edge; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.deploy.graph.Path; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.util.AttributesMap; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * The Deployment Manager. *

* Responsibilities: *

* *

    *
  1. Tracking Apps and their LifeCycle Location
  2. *
  3. Managing AppProviders and the Apps that they provide.
  4. *
  5. Executing AppLifeCycle on App based on current and desired LifeCycle Location.
  6. *
*

* */ public class DeploymentManager extends AggregateLifeCycle { private static final Logger LOG = Log.getLogger(DeploymentManager.class); /** * Represents a single tracked app within the deployment manager. */ public class AppEntry { /** * Version of the app. * * Note: Auto-increments on each {@link DeploymentManager#addApp(App)} */ private int version; /** * The app being tracked. */ private App app; /** * The lifecycle node location of this App */ private Node lifecyleNode; /** * Tracking the various AppState timestamps (in system milliseconds) */ private Map stateTimestamps = new HashMap(); public App getApp() { return app; } public Node getLifecyleNode() { return lifecyleNode; } public Map getStateTimestamps() { return stateTimestamps; } public int getVersion() { return version; } void setLifeCycleNode(Node node) { this.lifecyleNode = node; this.stateTimestamps.put(node,Long.valueOf(System.currentTimeMillis())); } } private final List _providers = new ArrayList(); private final AppLifeCycle _lifecycle = new AppLifeCycle(); private final Queue _apps = new ConcurrentLinkedQueue(); private AttributesMap _contextAttributes = new AttributesMap(); private ContextHandlerCollection _contexts; private boolean _useStandardBindings = true; private String _defaultLifeCycleGoal = AppLifeCycle.STARTED; /** * Receive an app for processing. * * Most commonly used by the various {@link AppProvider} implementations. */ public void addApp(App app) { LOG.info("Deployable added: " + app.getOriginId()); AppEntry entry = new AppEntry(); entry.app = app; entry.setLifeCycleNode(_lifecycle.getNodeByName("undeployed")); _apps.add(entry); if (isRunning() && _defaultLifeCycleGoal != null) { // Immediately attempt to go to default lifecycle state this.requestAppGoal(entry,_defaultLifeCycleGoal); } } /* ------------------------------------------------------------ */ /** Set the AppProviders. * The providers passed are added via {@link #addBean(Object)} so that * their lifecycles may be managed as a {@link AggregateLifeCycle}. * @param providers */ public void setAppProviders(Collection providers) { if (isRunning()) throw new IllegalStateException(); _providers.clear(); removeBeans(); for (AppProvider provider:providers) if (_providers.add(provider)) addBean(provider); } public Collection getAppProviders() { return Collections.unmodifiableList(_providers); } public void addAppProvider(AppProvider provider) { if (isRunning()) throw new IllegalStateException(); List old = new ArrayList(_providers); if (_providers.add(provider) && getServer()!=null) getServer().getContainer().update(this, null, provider, "provider"); addBean(provider); } public void setLifeCycleBindings(Collection bindings) { if (isRunning()) throw new IllegalStateException(); for (AppLifeCycle.Binding b : _lifecycle.getBindings()) _lifecycle.removeBinding(b); for (AppLifeCycle.Binding b : bindings) _lifecycle.addBinding(b); } public Collection getLifeCycleBindings() { return Collections.unmodifiableSet(_lifecycle.getBindings()); } public void addLifeCycleBinding(AppLifeCycle.Binding binding) { _lifecycle.addBinding(binding); } /** * Convenience method to allow for insertion of nodes into the lifecycle. * * @param existingFromNodeName * @param existingToNodeName * @param insertedNodeName */ public void insertLifeCycleNode(String existingFromNodeName, String existingToNodeName, String insertedNodeName) { Node fromNode = _lifecycle.getNodeByName(existingFromNodeName); Node toNode = _lifecycle.getNodeByName(existingToNodeName); Edge edge = new Edge(fromNode,toNode); _lifecycle.insertNode(edge,insertedNodeName); } @Override protected void doStart() throws Exception { if (_useStandardBindings) { LOG.debug("DeploymentManager using standard bindings"); addLifeCycleBinding(new StandardDeployer()); addLifeCycleBinding(new StandardStarter()); addLifeCycleBinding(new StandardStopper()); addLifeCycleBinding(new StandardUndeployer()); } // Start all of the AppProviders for (AppProvider provider : _providers) { startAppProvider(provider); } super.doStart(); } @Override protected void doStop() throws Exception { // Stop all of the AppProviders for (AppProvider provider : _providers) { try { provider.stop(); } catch (Exception e) { LOG.warn("Unable to start AppProvider",e); } } super.doStop(); } private AppEntry findAppByOriginId(String originId) { if (originId == null) { return null; } for (AppEntry entry : _apps) { if (originId.equals(entry.app.getOriginId())) { return entry; } } return null; } public App getAppByOriginId(String originId) { AppEntry entry = findAppByOriginId(originId); if (entry == null) { return null; } return entry.app; } public Collection getAppEntries() { return _apps; } public Collection getApps() { List ret = new ArrayList(); for (AppEntry entry : _apps) { ret.add(entry.app); } return ret; } /** * Get Set of {@link App}s by {@link Node} * * @param node * the node to look for. * @return the collection of apps for the node */ public Collection getApps(Node node) { List ret = new ArrayList(); for (AppEntry entry : _apps) { if (entry.lifecyleNode == node) { ret.add(entry.app); } } return ret; } public List getAppsWithSameContext(App app) { List ret = new ArrayList(); if (app == null) { return ret; } String contextId = app.getContextPath(); if (contextId == null) { // No context? Likely not deployed or started yet. return ret; } for (AppEntry entry : _apps) { if (entry.app.equals(app)) { // Its the input app. skip it. // TODO: is this filter needed? continue; } if (contextId.equals(entry.app.getContextPath())) { ret.add(entry.app); } } return ret; } /** * Get a contextAttribute that will be set for every Context deployed by this provider. * * @param name * @return the context attribute value */ public Object getContextAttribute(String name) { return _contextAttributes.getAttribute(name); } public AttributesMap getContextAttributes() { return _contextAttributes; } public ContextHandlerCollection getContexts() { return _contexts; } public String getDefaultLifeCycleGoal() { return _defaultLifeCycleGoal; } public AppLifeCycle getLifeCycle() { return _lifecycle; } public Server getServer() { if (_contexts == null) { return null; } return _contexts.getServer(); } /** * Remove the app from the tracking of the DeploymentManager * * @param app * if the app is Unavailable remove it from the deployment manager. */ public void removeApp(App app) { Iterator it = _apps.iterator(); while (it.hasNext()) { AppEntry entry = it.next(); if (entry.app.equals(app)) { if (! AppLifeCycle.UNDEPLOYED.equals(entry.lifecyleNode.getName())) requestAppGoal(entry.app,AppLifeCycle.UNDEPLOYED); it.remove(); LOG.info("Deployable removed: " + entry.app); } } } public void removeAppProvider(AppProvider provider) { if(_providers.remove(provider)) { removeBean(provider); if (getServer()!=null) getServer().getContainer().update(this, provider,null, "provider"); } try { provider.stop(); } catch (Exception e) { LOG.warn("Unable to stop Provider",e); } } /** * Remove a contextAttribute that will be set for every Context deployed by this provider. * * @param name */ public void removeContextAttribute(String name) { _contextAttributes.removeAttribute(name); } /** * Move an {@link App} through the {@link AppLifeCycle} to the desired {@link Node}, executing each lifecycle step * in the process to reach the desired state. * * @param app * the app to move through the process * @param nodeName * the name of the node to attain */ public void requestAppGoal(App app, String nodeName) { AppEntry appentry = findAppByOriginId(app.getOriginId()); if (appentry == null) { throw new IllegalStateException("App not being tracked by Deployment Manager: " + app); } requestAppGoal(appentry,nodeName); } /** * Move an {@link App} through the {@link AppLifeCycle} to the desired {@link Node}, executing each lifecycle step * in the process to reach the desired state. * * @param appentry * the internal appentry to move through the process * @param nodeName * the name of the node to attain */ private void requestAppGoal(AppEntry appentry, String nodeName) { Node destinationNode = _lifecycle.getNodeByName(nodeName); if (destinationNode == null) { throw new IllegalStateException("Node not present in Deployment Manager: " + nodeName); } // Compute lifecycle steps Path path = _lifecycle.getPath(appentry.lifecyleNode,destinationNode); if (path.isEmpty()) { // nothing to do. already there. return; } // Execute each Node binding. Stopping at any thrown exception. try { Iterator it = path.getNodes().iterator(); if (it.hasNext()) // Any entries? { // The first entry in the path is always the start node // We don't want to run bindings on that entry (again) it.next(); // skip first entry while (it.hasNext()) { Node node = it.next(); LOG.debug("Executing Node {}",node); _lifecycle.runBindings(node,appentry.app,this); appentry.setLifeCycleNode(node); } } } catch (Throwable t) { LOG.warn("Unable to reach node goal: " + nodeName,t); } } /** * Move an {@link App} through the {@link AppLifeCycle} to the desired {@link Node}, executing each lifecycle step * in the process to reach the desired state. * * @param appId * the id of the app to move through the process * @param nodeName * the name of the node to attain */ public void requestAppGoal(String appId, String nodeName) { AppEntry appentry = findAppByOriginId(appId); if (appentry == null) { throw new IllegalStateException("App not being tracked by Deployment Manager: " + appId); } requestAppGoal(appentry,nodeName); } /** * Set a contextAttribute that will be set for every Context deployed by this provider. * * @param name * @param value */ public void setContextAttribute(String name, Object value) { _contextAttributes.setAttribute(name,value); } public void setContextAttributes(AttributesMap contextAttributes) { this._contextAttributes = contextAttributes; } public void setContexts(ContextHandlerCollection contexts) { this._contexts = contexts; } public void setDefaultLifeCycleGoal(String defaultLifeCycleState) { this._defaultLifeCycleGoal = defaultLifeCycleState; } private void startAppProvider(AppProvider provider) { try { provider.setDeploymentManager(this); provider.start(); } catch (Exception e) { LOG.warn("Unable to start AppProvider",e); } } public void undeployAll() { LOG.info("Undeploy All"); for (AppEntry appentry : _apps) { requestAppGoal(appentry,"undeployed"); } } public boolean isUseStandardBindings() { return _useStandardBindings; } public void setUseStandardBindings(boolean useStandardBindings) { this._useStandardBindings = useStandardBindings; } public Collection getNodes() { return _lifecycle.getNodes(); } public Collection getApps(String nodeName) { return getApps(_lifecycle.getNodeByName(nodeName)); } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/FileConfigurationManager.java000066400000000000000000000042501174773561500324730ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.eclipse.jetty.util.resource.Resource; /** * FileConfigurationManager * * Supplies properties defined in a file. */ public class FileConfigurationManager implements ConfigurationManager { private Resource _file; private Map _map = new HashMap(); public FileConfigurationManager() { } public void setFile(String filename) throws MalformedURLException, IOException { _file = Resource.newResource(filename); } /** * @see org.eclipse.jetty.deploy.ConfigurationManager#getProperties() */ public Map getProperties() { try { loadProperties(); return _map; } catch (Exception e) { throw new RuntimeException(e); } } private void loadProperties() throws FileNotFoundException, IOException { if (_map.isEmpty() && _file!=null) { Properties properties = new Properties(); properties.load(_file.getInputStream()); for (Map.Entry entry : properties.entrySet()) _map.put(entry.getKey().toString(),String.valueOf(entry.getValue())); } } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/WebAppDeployer.java000066400000000000000000000241631174773561500304600ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.util.ArrayList; import org.eclipse.jetty.deploy.providers.ScanningAppProvider; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.util.AttributesMap; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.WebAppContext; /** * Legacy Web Application Deployer. * *

* Note: The WebAppDeployer is being phased out of Jetty in favor of the {@link DeploymentManager} and * {@link org.eclipse.jetty.deploy.providers.WebAppProvider} implementation. * *

* The class searches a directory for and deploys standard web application. At startup, the directory specified by * {@link #setWebAppDir(String)} is searched for subdirectories (excluding hidden and CVS) or files ending with ".zip" * or "*.war". For each webapp discovered is passed to a new instance of {@link WebAppContext} (or a subclass specified * by {@link #getContexts()}. {@link ContextHandlerCollection#getContextClass()} * *

* This deployer does not do hot deployment or undeployment. Nor does it support per web application configuration. For * these features see {@link ContextDeployer}. * * @deprecated * @see DeploymentManager * @see ScanningAppProvider * @see ContextDeployer */ @SuppressWarnings("unchecked") public class WebAppDeployer extends AbstractLifeCycle { private static final Logger LOG = Log.getLogger(WebAppDeployer.class); private HandlerCollection _contexts; private String _webAppDir; private String _defaultsDescriptor; private String[] _configurationClasses; private boolean _extract; private boolean _parentLoaderPriority; private boolean _allowDuplicates; private ArrayList _deployed; private AttributesMap _contextAttributes = new AttributesMap(); public WebAppDeployer() { LOG.warn("WebAppDeployer is deprecated. Use WebAppProvider"); } public String[] getConfigurationClasses() { return _configurationClasses; } public void setConfigurationClasses(String[] configurationClasses) { _configurationClasses=configurationClasses; } public HandlerCollection getContexts() { return _contexts; } public void setContexts(HandlerCollection contexts) { _contexts=contexts; } public String getDefaultsDescriptor() { return _defaultsDescriptor; } public void setDefaultsDescriptor(String defaultsDescriptor) { _defaultsDescriptor=defaultsDescriptor; } public boolean isExtract() { return _extract; } public void setExtract(boolean extract) { _extract=extract; } public boolean isParentLoaderPriority() { return _parentLoaderPriority; } public void setParentLoaderPriority(boolean parentPriorityClassLoading) { _parentLoaderPriority=parentPriorityClassLoading; } public String getWebAppDir() { return _webAppDir; } public void setWebAppDir(String dir) { _webAppDir=dir; } public boolean getAllowDuplicates() { return _allowDuplicates; } /* ------------------------------------------------------------ */ /** * @param allowDuplicates If false, do not deploy webapps that have already been deployed or duplicate context path */ public void setAllowDuplicates(boolean allowDuplicates) { _allowDuplicates=allowDuplicates; } /** * Set a contextAttribute that will be set for every Context deployed by this deployer. * @param name * @param value */ public void setAttribute (String name, Object value) { _contextAttributes.setAttribute(name,value); } /** * Get a contextAttribute that will be set for every Context deployed by this deployer. * @param name * @return the attribute value */ public Object getAttribute (String name) { return _contextAttributes.getAttribute(name); } /** * Remove a contextAttribute that will be set for every Context deployed by this deployer. * @param name */ public void removeAttribute(String name) { _contextAttributes.removeAttribute(name); } /* ------------------------------------------------------------ */ /** * @throws Exception */ @Override public void doStart() throws Exception { _deployed=new ArrayList(); scan(); } /* ------------------------------------------------------------ */ /** Scan for webapplications. * * @throws Exception */ public void scan() throws Exception { if (_contexts==null) throw new IllegalArgumentException("No HandlerContainer"); Resource r=Resource.newResource(_webAppDir); if (!r.exists()) throw new IllegalArgumentException("No such webapps resource "+r); if (!r.isDirectory()) throw new IllegalArgumentException("Not directory webapps resource "+r); String[] files=r.list(); files: for (int f=0; files!=null&&f0) context=context.substring(0,context.length()-1); // Check the context path has not already been added or the webapp itself is not already deployed if (!_allowDuplicates) { Handler[] installed=_contexts.getChildHandlersByClass(ContextHandler.class); for (int i=0; i0;) { ContextHandler wac = (ContextHandler)_deployed.get(i); wac.stop();// TODO Multi exception } } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/000077500000000000000000000000001174773561500265225ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/DebugBinding.java000066400000000000000000000030431174773561500317060ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.bindings; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public class DebugBinding implements AppLifeCycle.Binding { private static final Logger LOG = Log.getLogger(DebugBinding.class); final String[] _targets; public DebugBinding(String target) { _targets=new String[]{target}; } public DebugBinding(final String... targets) { _targets=targets; } public String[] getBindingTargets() { return _targets; } public void processBinding(Node node, App app) throws Exception { LOG.info("processBinding {} {}",node,app.getContextHandler()); } } GlobalWebappConfigBinding.java000066400000000000000000000064561174773561500343010ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindingspackage org.eclipse.jetty.deploy.bindings; //======================================================================== //Copyright (c) Webtide LLC //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. // //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html // //The Apache License v2.0 is available at //http://www.apache.org/licenses/LICENSE-2.0.txt // //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.net.URL; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.FileResource; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.xml.XmlConfiguration; /** * Provides a way of globally setting various aspects of webapp contexts. * * Adding this binding will allow the user to arbitrarily apply a file of * jetty-web.xml like settings to a webapp context. * * Example usage would be: * - adding a server or system class setting to all webapp contexts * - adding an override descriptor * * Note: Currently properties from startup will not be available for * reference. * */ public class GlobalWebappConfigBinding implements AppLifeCycle.Binding { private static final Logger LOG = Log.getLogger(GlobalWebappConfigBinding.class); private String _jettyXml; public String getJettyXml() { return _jettyXml; } public void setJettyXml(String jettyXml) { this._jettyXml = jettyXml; } public String[] getBindingTargets() { return new String[] { "deploying" }; } public void processBinding(Node node, App app) throws Exception { ContextHandler handler = app.getContextHandler(); if (handler == null) { throw new NullPointerException("No Handler created for App: " + app); } if (handler instanceof WebAppContext) { WebAppContext context = (WebAppContext)handler; if (LOG.isDebugEnabled()) { LOG.debug("Binding: Configuring webapp context with global settings from: " + _jettyXml); } if ( _jettyXml == null ) { LOG.warn("Binding: global context binding is enabled but no jetty-web.xml file has been registered"); } Resource globalContextSettings = Resource.newResource(_jettyXml); if (globalContextSettings.exists()) { XmlConfiguration jettyXmlConfig = new XmlConfiguration(globalContextSettings.getInputStream()); jettyXmlConfig.configure(context); } else { LOG.info("Binding: Unable to locate global webapp context settings: " + _jettyXml); } } } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/OrderedGroupBinding.java000066400000000000000000000042551174773561500332670ustar00rootroot00000000000000package org.eclipse.jetty.deploy.bindings; //======================================================================== //Copyright (c) Webtide LLC //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. // //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html // //The Apache License v2.0 is available at //http://www.apache.org/licenses/LICENSE-2.0.txt // //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.util.LinkedList; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.graph.Node; /** * Provides a way of forcing the ordered execution of bindings within * a declared binding target. * */ public class OrderedGroupBinding implements AppLifeCycle.Binding { private String[] _bindingTargets; private LinkedList _orderedBindings; public OrderedGroupBinding( String[] bindingTargets ) { _bindingTargets = bindingTargets; } public void addBinding(AppLifeCycle.Binding binding) { if ( _orderedBindings == null ) { _orderedBindings = new LinkedList(); } _orderedBindings.add(binding); } public void addBindings(AppLifeCycle.Binding[] bindings) { if ( _orderedBindings == null ) { _orderedBindings = new LinkedList(); } for (AppLifeCycle.Binding binding : bindings) { _orderedBindings.add(binding); } } public String[] getBindingTargets() { return _bindingTargets; } public void processBinding(Node node, App app) throws Exception { for ( AppLifeCycle.Binding binding : _orderedBindings ) { binding.processBinding(node,app); } } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardDeployer.java000066400000000000000000000026771174773561500326450ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.bindings; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.server.handler.ContextHandler; public class StandardDeployer implements AppLifeCycle.Binding { public String[] getBindingTargets() { return new String[] { "deploying" }; } public void processBinding(Node node, App app) throws Exception { ContextHandler handler = app.getContextHandler(); if (handler == null) { throw new NullPointerException("No Handler created for App: " + app); } app.getDeploymentManager().getContexts().addHandler(handler); } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardStarter.java000066400000000000000000000025071174773561500324760ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.bindings; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.server.handler.ContextHandler; public class StandardStarter implements AppLifeCycle.Binding { public String[] getBindingTargets() { return new String[] { "starting" }; } public void processBinding(Node node, App app) throws Exception { ContextHandler handler = app.getContextHandler(); if (!handler.isStarted()) { handler.start(); } } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardStopper.java000066400000000000000000000025061174773561500325050ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.bindings; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.server.handler.ContextHandler; public class StandardStopper implements AppLifeCycle.Binding { public String[] getBindingTargets() { return new String[] { "stopping" }; } public void processBinding(Node node, App app) throws Exception { ContextHandler handler = app.getContextHandler(); if (!handler.isStopped()) { handler.stop(); } } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardUndeployer.java000066400000000000000000000050551174773561500332010ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.bindings; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public class StandardUndeployer implements AppLifeCycle.Binding { private static final Logger LOG = Log.getLogger(StandardUndeployer.class); public String[] getBindingTargets() { return new String[] { "undeploying" }; } public void processBinding(Node node, App app) throws Exception { ContextHandler handler = app.getContextHandler(); ContextHandlerCollection chcoll = app.getDeploymentManager().getContexts(); recursiveRemoveContext(chcoll,handler); } private void recursiveRemoveContext(HandlerCollection coll, ContextHandler context) { Handler children[] = coll.getHandlers(); int originalCount = children.length; for (int i = 0, n = children.length; i < n; i++) { Handler child = children[i]; LOG.debug("Child handler {}",child); if (child.equals(context)) { LOG.debug("Removing handler {}",child); coll.removeHandler(child); child.destroy(); if (LOG.isDebugEnabled()) LOG.debug("After removal: {} (originally {})",coll.getHandlers().length,originalCount); } else if (child instanceof HandlerCollection) { recursiveRemoveContext((HandlerCollection)child,context); } } } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/graph/000077500000000000000000000000001174773561500260265ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/graph/Edge.java000066400000000000000000000037741174773561500275500ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.graph; /** * Basic Graph Edge */ public final class Edge { private Node _from; private Node _to; public Edge(Node from, Node to) { if (from==null || to==null || from==to) throw new IllegalArgumentException("from "+from+" to "+to); _from = from; _to = to; } @Override public int hashCode() { return _from.hashCode() ^ _to.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Edge other = (Edge)obj; if (_from == null) { if (other._from != null) return false; } else if (!_from.equals(other._from)) return false; if (_to == null) { if (other._to != null) return false; } else if (!_to.equals(other._to)) return false; return true; } public Node getFrom() { return _from; } public Node getTo() { return _to; } @Override public String toString() { return _from+"->"+_to; } }jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/graph/Graph.java000066400000000000000000000174661174773561500277500ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.graph; import java.util.HashSet; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; /** * Basic directed graph implementation */ public class Graph { private Set _nodes = new HashSet(); private Set _edges = new HashSet(); public void addEdge(Edge edge) { Node fromNode = getNodeByName(edge.getFrom().getName()); if (fromNode==null) addNode(fromNode=edge.getFrom()); Node toNode = getNodeByName(edge.getTo().getName()); if (toNode==null) addNode(toNode=edge.getTo()); // replace edge with normalized edge if (edge.getFrom()!=fromNode || edge.getTo()!=toNode) edge=new Edge(fromNode,toNode); this._edges.add(edge); } public void addEdge(String from, String to) { Node fromNode = getNodeByName(from); if (fromNode==null) { fromNode = new Node(from); addNode(fromNode); } Node toNode = getNodeByName(to); if (toNode==null) { toNode = new Node(to); addNode(toNode); } addEdge(fromNode,toNode); } private void addEdge(Node fromNode, Node toNode) { Edge edge = new Edge(fromNode,toNode); addEdge(edge); } public void addNode(Node node) { this._nodes.add(node); } /** * Convenience method for {@link #insertNode(Edge, Node)} * * @param edge * the edge to split and insert a node into * @param nodeName * the name of the node to insert along the edge */ public void insertNode(Edge edge, String nodeName) { Node node = getNodeByName(nodeName); if (node==null) { node = new Node(nodeName); } insertNode(edge,node); } /** * Insert an arbitrary node on an existing edge. * * @param edge * the edge to split and insert a node into * @param node * the node to insert along the edge */ public void insertNode(Edge edge, Node node) { // Remove existing edge removeEdge(edge); // Ensure node is added addNode(node); // Add start edge addEdge(edge.getFrom(),node); // Add second edge addEdge(node,edge.getTo()); } /** * Find all edges that are connected to the specific node, both as an outgoing {@link Edge#getFrom()} or incoming * {@link Edge#getTo()} end point. * * @param node * the node with potential end points * @return the set of edges connected to the node */ public Set findEdges(Node node) { Set fromedges = new HashSet(); for (Edge edge : this._edges) { if ((edge.getFrom() == node) || (edge.getTo() == node)) { fromedges.add(edge); } } return fromedges; } /** * Find all edges that are connected {@link Edge#getFrom()} the specific node. * * @param from * the node with potential edges from it * @return the set of edges from the node */ public Set findEdgesFrom(Node from) { Set fromedges = new HashSet(); for (Edge edge : this._edges) { if (edge.getFrom() == from) { fromedges.add(edge); } } return fromedges; } /** * Convenience method for {@link #getPath(Node, Node)} * * @param nodeNameOrigin * the name of the node to the path origin. * @param nodeNameDest * the name of the node to the path destination. * @return the path to take */ public Path getPath(String nodeNameOrigin, String nodeNameDest) { if (nodeNameOrigin.equals(nodeNameDest)) { return new Path(); } Node from = getNodeByName(nodeNameOrigin); Node to = getNodeByName(nodeNameDest); return getPath(from,to); } /** * Using BFS (Breadth First Search) return the path from a any arbitrary node to any other. * * @param from * the node from * @param to * the node to * @return the path to take or null if there is no path. */ public Path getPath(Node from, Node to) { if (from == to) { return new Path(); } // Perform a Breadth First Search (BFS) of the tree. Path path = breadthFirst(from,to,new CopyOnWriteArrayList(),new HashSet()); return path; } private Path breadthFirst(Node from, Node destination, CopyOnWriteArrayList paths, Set seen) { // Add next unseen segments to paths. boolean edgesAdded = false; if (paths.size()==0) paths.add(new Path()); for (Path path : paths) { Set next = findEdgesFrom(path.nodes()==0?from:path.lastNode()); if (next.size() == 0) continue; // no new edges // Split path for other edges int splits=0; for (Edge edge:next) { if (seen.contains(edge)) continue; seen.add(edge); Path nextPath = (++splits==next.size())?path:path.forkPath(); // Add segment to split'd path nextPath.add(edge); // Are we there yet? if (destination.equals(edge.getTo())) return nextPath; edgesAdded = true; // Add to extra paths if (nextPath!=path) paths.add(nextPath); } } if (edgesAdded) return breadthFirst(from,destination,paths,seen); return null; } public Set getEdges() { return _edges; } /** * Get the Node by Name. * * @param name * the name to lookup * @return the node if found or null if not found. */ public Node getNodeByName(String name) { for (Node node : _nodes) { if (node.getName().equals(name)) { return node; } } return null; } public Set getNodes() { return _nodes; } public void removeEdge(Edge edge) { this._edges.remove(edge); } public void removeEdge(String fromNodeName, String toNodeName) { Node fromNode = getNodeByName(fromNodeName); Node toNode = getNodeByName(toNodeName); Edge edge = new Edge(fromNode,toNode); removeEdge(edge); } public void removeNode(Node node) { this._nodes.remove(node); } public void setEdges(Set edges) { this._edges = edges; } public void setNodes(Set nodes) { this._nodes = nodes; } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/graph/GraphOutputDot.java000066400000000000000000000126711174773561500316310ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.graph; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.text.CollationKey; import java.text.Collator; import java.util.Comparator; import java.util.Set; import java.util.TreeSet; import org.eclipse.jetty.util.IO; /** * Output the Graph in GraphViz Dot format. */ public class GraphOutputDot { private GraphOutputDot() { } private static final String TOPNODE = "undeployed"; /** * Comparator that makes the 'undeployed' node the first node in the sort list. * * This makes the 'undeployed' node show up at the top of the generated graph. */ private static class TopNodeSort implements Comparator { private Collator collator = Collator.getInstance(); public int compare(Node o1, Node o2) { if (o1.getName().equals(TOPNODE)) { return -1; } if (o2.getName().equals(TOPNODE)) { return 1; } CollationKey key1 = toKey(o1); CollationKey key2 = toKey(o2); return key1.compareTo(key2); } private CollationKey toKey(Node node) { return collator.getCollationKey(node.getName()); } } public static void write(Graph graph, File outputFile) throws IOException { FileWriter writer = null; PrintWriter out = null; try { writer = new FileWriter(outputFile); out = new PrintWriter(writer); out.println("// Autogenerated by " + GraphOutputDot.class.getName()); out.println("digraph Graf {"); writeGraphDefaults(out); writeNodeDefaults(out); writeEdgeDefaults(out); Set nodes = new TreeSet(new TopNodeSort()); nodes.addAll(graph.getNodes()); for (Node node : nodes) { writeNode(out,node); } for (Edge edge : graph.getEdges()) { writeEdge(out,edge); } out.println("}"); } finally { IO.close(out); IO.close(writer); } } private static void writeEdge(PrintWriter out, Edge edge) { out.println(); out.println(" // Edge"); out.printf(" \"%s\" -> \"%s\" [%n",toId(edge.getFrom()),toId(edge.getTo())); out.println(" arrowtail=none,"); out.println(" arrowhead=normal"); out.println(" ];"); } private static void writeNode(PrintWriter out, Node node) { out.println(); out.println(" // Node"); out.printf(" \"%s\" [%n",toId(node)); out.printf(" label=\"%s\",%n",node.getName()); if (node.getName().endsWith("ed")) { out.println(" color=\"#ddddff\","); out.println(" style=filled,"); } out.println(" shape=box"); out.println(" ];"); } private static CharSequence toId(Node node) { StringBuilder buf = new StringBuilder(); for (char c : node.getName().toCharArray()) { if (Character.isLetter(c)) { buf.append(c); continue; } if (Character.isDigit(c)) { buf.append(c); continue; } if ((c == ' ') || (c == '-') || (c == '_')) { buf.append(c); continue; } } return buf; } private static void writeEdgeDefaults(PrintWriter out) { out.println(); out.println(" // Edge Defaults "); out.println(" edge ["); out.println(" arrowsize=\"0.8\","); out.println(" fontsize=\"11\""); out.println(" ];"); } private static void writeGraphDefaults(PrintWriter out) { out.println(); out.println(" // Graph Defaults "); out.println(" graph ["); out.println(" bgcolor=\"#ffffff\","); out.println(" fontname=\"Helvetica\","); out.println(" fontsize=\"11\","); out.println(" label=\"Graph\","); out.println(" labeljust=\"l\","); out.println(" rankdir=\"TD\""); out.println(" ];"); } private static void writeNodeDefaults(PrintWriter out) { out.println(); out.println(" // Node Defaults "); out.println(" node ["); out.println(" fontname=\"Helvetica\","); out.println(" fontsize=\"11\","); out.println(" shap=\"box\""); out.println(" ];"); } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/graph/Node.java000066400000000000000000000032071174773561500275600ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.graph; /** * Basic Graph Node */ public final class Node { private final String _name; public Node(String name) { assert name!=null; this._name = name; } public String getName() { return _name; } @Override public String toString() { return "Node[" + _name + "]"; } @Override public int hashCode() { return _name.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Node other = (Node)obj; if (_name == null) { if (other._name != null) return false; } else if (!_name.equals(other._name)) return false; return true; } }jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/graph/Path.java000066400000000000000000000053011174773561500275640ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.graph; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class Path { private final List _edges = new CopyOnWriteArrayList(); private final List _nodes = new CopyOnWriteArrayList(); public Path() { } public void add(Edge edge) { _edges.add(edge); if (_nodes.size() == 0) { _nodes.add(edge.getFrom()); } else { assert _nodes.get(_nodes.size() - 1).equals(edge.getFrom()); } _nodes.add(edge.getTo()); } public Path forkPath() { Path ep = new Path(); for (Edge edge : _edges) { ep.add(edge); } return ep; } public List getNodes() { return _nodes; } public List getEdges() { return _nodes; } public Node getNode(int index) { return _nodes.get(index); } public Node firstNode() { if (_nodes.size() == 0) { return null; } return _nodes.get(0); } public Node lastNode() { if (_nodes.size() == 0) { return null; } return _nodes.get(_nodes.size() - 1); } public int nodes() { return _nodes.size(); } public int edges() { return _edges.size(); } public boolean isEmpty() { return _edges.isEmpty(); } public Edge firstEdge() { if (_edges.size() == 0) { return null; } return _edges.get(0); } public Edge lastEdge() { if (_edges.size() == 0) { return null; } return _edges.get(_edges.size() - 1); } public Edge getEdge(int index) { return _edges.get(index); } @Override public String toString() { return super.toString() + _nodes.toString(); } }jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/000077500000000000000000000000001174773561500255235ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/DeploymentManagerMBean.java000066400000000000000000000034361174773561500327120ustar00rootroot00000000000000package org.eclipse.jetty.deploy.jmx; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppProvider; import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.jmx.ObjectMBean; import org.eclipse.jetty.server.handler.ContextHandler; public class DeploymentManagerMBean extends ObjectMBean { private final DeploymentManager _manager; public DeploymentManagerMBean(Object managedObject) { super(managedObject); _manager=(DeploymentManager)managedObject; } public Collection getNodes() { List nodes = new ArrayList(); for (Node node: _manager.getNodes()) nodes.add(node.getName()); return nodes; } public Collection getApps() { List apps=new ArrayList(); for (App app: _manager.getApps()) apps.add(app.getOriginId()); return apps; } public Collection getApps(String nodeName) { List apps=new ArrayList(); for (App app: _manager.getApps(nodeName)) apps.add(app.getOriginId()); return apps; } public Collection getContexts() throws Exception { List apps=new ArrayList(); for (App app: _manager.getApps()) apps.add(app.getContextHandler()); return apps; } public Collection getAppProviders() { return _manager.getAppProviders(); } public void requestAppGoal(String appId, String nodeName) { _manager.requestAppGoal(appId, nodeName); } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/000077500000000000000000000000001174773561500267425ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java000066400000000000000000000050371174773561500327510ustar00rootroot00000000000000package org.eclipse.jetty.deploy.providers; import java.io.File; import java.io.FilenameFilter; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.ConfigurationManager; import org.eclipse.jetty.deploy.util.FileID; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.xml.XmlConfiguration; /** Context directory App Provider. *

This specialization of {@link ScanningAppProvider} is the * replacement for the old (and deprecated) org.eclipse.jetty.deploy.ContextDeployer and it will scan a directory * only for context.xml files. */ public class ContextProvider extends ScanningAppProvider { private ConfigurationManager _configurationManager; public ContextProvider() { super( new FilenameFilter() { public boolean accept(File dir, String name) { if (!dir.exists()) return false; String lowername = name.toLowerCase(); if (lowername.startsWith(".")) return false; return (lowername.endsWith(".xml") && !new File(dir,name).isDirectory()); } }); } /* ------------------------------------------------------------ */ public ConfigurationManager getConfigurationManager() { return _configurationManager; } /* ------------------------------------------------------------ */ /** Set the configurationManager. * @param configurationManager the configurationManager to set */ public void setConfigurationManager(ConfigurationManager configurationManager) { _configurationManager = configurationManager; } /* ------------------------------------------------------------ */ public ContextHandler createContextHandler(App app) throws Exception { Resource resource = Resource.newResource(app.getOriginId()); File file = resource.getFile(); if (resource.exists() && FileID.isXmlFile(file)) { XmlConfiguration xmlc = new XmlConfiguration(resource.getURL()); xmlc.getIdMap().put("Server",getDeploymentManager().getServer()); if (getConfigurationManager() != null) xmlc.getProperties().putAll(getConfigurationManager().getProperties()); return (ContextHandler)xmlc.configure(); } throw new IllegalStateException("App resouce does not exist "+resource); } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ScanningAppProvider.java000066400000000000000000000203501174773561500335210ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.providers; import java.io.File; import java.io.FilenameFilter; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppProvider; import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.util.Scanner; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; /** */ public abstract class ScanningAppProvider extends AbstractLifeCycle implements AppProvider { private static final Logger LOG = Log.getLogger(ScanningAppProvider.class); private Map _appMap = new HashMap(); private DeploymentManager _deploymentManager; protected final FilenameFilter _filenameFilter; private Resource _monitoredDir; private boolean _recursive = false; private int _scanInterval = 10; private Scanner _scanner; /* ------------------------------------------------------------ */ private final Scanner.DiscreteListener _scannerListener = new Scanner.DiscreteListener() { public void fileAdded(String filename) throws Exception { ScanningAppProvider.this.fileAdded(filename); } public void fileChanged(String filename) throws Exception { ScanningAppProvider.this.fileChanged(filename); } public void fileRemoved(String filename) throws Exception { ScanningAppProvider.this.fileRemoved(filename); } }; /* ------------------------------------------------------------ */ protected ScanningAppProvider(FilenameFilter filter) { _filenameFilter = filter; } /* ------------------------------------------------------------ */ /** * @return The index of currently deployed applications. */ protected Map getDeployedApps() { return _appMap; } /* ------------------------------------------------------------ */ /** * Called by the Scanner.DiscreteListener to create a new App object. * Isolated in a method so that it is possible to override the default App * object for specialized implementations of the AppProvider. * * @param filename * The file that is the context.xml. It is resolved by * {@link Resource#newResource(String)} * @return The App object for this particular context definition file. */ protected App createApp(String filename) { return new App(_deploymentManager,this,filename); } /* ------------------------------------------------------------ */ @Override protected void doStart() throws Exception { if (LOG.isDebugEnabled()) LOG.debug(this.getClass().getSimpleName() + ".doStart()"); if (_monitoredDir == null) { throw new IllegalStateException("No configuration dir specified"); } File scandir = _monitoredDir.getFile(); LOG.info("Deployment monitor " + scandir + " at interval " + _scanInterval); _scanner = new Scanner(); _scanner.setScanDirs(Collections.singletonList(scandir)); _scanner.setScanInterval(_scanInterval); _scanner.setRecursive(_recursive); _scanner.setFilenameFilter(_filenameFilter); _scanner.setReportDirs(true); _scanner.addListener(_scannerListener); _scanner.start(); } /* ------------------------------------------------------------ */ @Override protected void doStop() throws Exception { if (_scanner!=null) { _scanner.stop(); _scanner.removeListener(_scannerListener); _scanner = null; } } /* ------------------------------------------------------------ */ protected void fileAdded(String filename) throws Exception { if (LOG.isDebugEnabled()) LOG.debug("added {}",filename); App app = ScanningAppProvider.this.createApp(filename); if (app != null) { _appMap.put(filename,app); _deploymentManager.addApp(app); } } /* ------------------------------------------------------------ */ protected void fileChanged(String filename) throws Exception { if (LOG.isDebugEnabled()) LOG.debug("changed {}",filename); App app = _appMap.remove(filename); if (app != null) { _deploymentManager.removeApp(app); } app = ScanningAppProvider.this.createApp(filename); if (app != null) { _appMap.put(filename,app); _deploymentManager.addApp(app); } } /* ------------------------------------------------------------ */ protected void fileRemoved(String filename) throws Exception { if (LOG.isDebugEnabled()) LOG.debug("removed {}",filename); App app = _appMap.remove(filename); if (app != null) _deploymentManager.removeApp(app); } /* ------------------------------------------------------------ */ /** * Get the deploymentManager. * * @return the deploymentManager */ public DeploymentManager getDeploymentManager() { return _deploymentManager; } /* ------------------------------------------------------------ */ public Resource getMonitoredDirResource() { return _monitoredDir; } /* ------------------------------------------------------------ */ public String getMonitoredDirName() { return _monitoredDir.toString(); } /* ------------------------------------------------------------ */ public int getScanInterval() { return _scanInterval; } /* ------------------------------------------------------------ */ public boolean isRecursive() { return _recursive; } /* ------------------------------------------------------------ */ public void setDeploymentManager(DeploymentManager deploymentManager) { _deploymentManager = deploymentManager; } /* ------------------------------------------------------------ */ public void setMonitoredDirResource(Resource contextsDir) { _monitoredDir = contextsDir; } /* ------------------------------------------------------------ */ public void addScannerListener(Scanner.Listener listener) { _scanner.addListener(listener); } /* ------------------------------------------------------------ */ /** * @deprecated Use {@link #setMonitoredDirName(String)} */ public void setMonitoredDir(String dir) { setMonitoredDirName(dir); } /* ------------------------------------------------------------ */ /** * @param dir * Directory to scan for context descriptors or war files */ public void setMonitoredDirName(String dir) { try { setMonitoredDirResource(Resource.newResource(dir)); } catch (Exception e) { throw new IllegalArgumentException(e); } } /* ------------------------------------------------------------ */ protected void setRecursive(boolean recursive) { _recursive = recursive; } /* ------------------------------------------------------------ */ public void setScanInterval(int scanInterval) { _scanInterval = scanInterval; } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java000066400000000000000000000230411174773561500324760ustar00rootroot00000000000000package org.eclipse.jetty.deploy.providers; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.net.MalformedURLException; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.util.FileID; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.WebAppContext; /* ------------------------------------------------------------ */ /** Context directory App Provider. *

This specialization of {@link ScanningAppProvider} is the * replacement for old (and deprecated) org.eclipse.jetty.deploy.WebAppDeployer and it will scan a directory * only for war files or directories files.

*

* Webapps with names root or starting with root- are deployed at /. * If the name is in the format root-hostname, then the webapp is deployed * at / in the virtual host hostname. */ public class WebAppProvider extends ScanningAppProvider { private boolean _extractWars = false; private boolean _parentLoaderPriority = false; private String _defaultsDescriptor; private Filter _filter; private File _tempDirectory; private String[] _configurationClasses; public static class Filter implements FilenameFilter { private File _contexts; public boolean accept(File dir, String name) { if (!dir.exists()) { return false; } String lowername = name.toLowerCase(); File file = new File(dir,name); // is it not a directory and not a war ? if (!file.isDirectory() && !lowername.endsWith(".war")) { return false; } //ignore hidden files if (lowername.startsWith(".")) return false; if (file.isDirectory()) { // is it a directory for an existing war file? if (new File(dir,name+".war").exists() || new File(dir,name+".WAR").exists()) return false; //is it a sccs dir? if ("cvs".equals(lowername) || "cvsroot".equals(lowername)) return false; } // is there a contexts config file if (_contexts!=null) { String context=name; if (!file.isDirectory()) { context=context.substring(0,context.length()-4); } if (new File(_contexts,context+".xml").exists() || new File(_contexts,context+".XML").exists() ) { return false; } } return true; } } /* ------------------------------------------------------------ */ public WebAppProvider() { super(new Filter()); _filter=(Filter)_filenameFilter; setScanInterval(0); } /* ------------------------------------------------------------ */ /** Get the extractWars. * @return the extractWars */ public boolean isExtractWars() { return _extractWars; } /* ------------------------------------------------------------ */ /** Set the extractWars. * @param extractWars the extractWars to set */ public void setExtractWars(boolean extractWars) { _extractWars = extractWars; } /* ------------------------------------------------------------ */ /** Get the parentLoaderPriority. * @return the parentLoaderPriority */ public boolean isParentLoaderPriority() { return _parentLoaderPriority; } /* ------------------------------------------------------------ */ /** Set the parentLoaderPriority. * @param parentLoaderPriority the parentLoaderPriority to set */ public void setParentLoaderPriority(boolean parentLoaderPriority) { _parentLoaderPriority = parentLoaderPriority; } /* ------------------------------------------------------------ */ /** Get the defaultsDescriptor. * @return the defaultsDescriptor */ public String getDefaultsDescriptor() { return _defaultsDescriptor; } /* ------------------------------------------------------------ */ /** Set the defaultsDescriptor. * @param defaultsDescriptor the defaultsDescriptor to set */ public void setDefaultsDescriptor(String defaultsDescriptor) { _defaultsDescriptor = defaultsDescriptor; } /* ------------------------------------------------------------ */ public String getContextXmlDir() { return _filter._contexts==null?null:_filter._contexts.toString(); } /* ------------------------------------------------------------ */ /** * Set the directory in which to look for context XML files. *

* If a webapp call "foo/" or "foo.war" is discovered in the monitored * directory, then the ContextXmlDir is examined to see if a foo.xml * file exists. If it does, then this deployer will not deploy the webapp * and the ContextProvider should be used to act on the foo.xml file. * @see ContextProvider * @param contextsDir */ public void setContextXmlDir(String contextsDir) { try { _filter._contexts=Resource.newResource(contextsDir).getFile(); } catch (MalformedURLException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } /* ------------------------------------------------------------ */ /** * @param configurations The configuration class names. */ public void setConfigurationClasses(String[] configurations) { _configurationClasses = configurations==null?null:(String[])configurations.clone(); } /* ------------------------------------------------------------ */ /** * */ public String[] getConfigurationClasses() { return _configurationClasses; } /** * Set the Work directory where unpacked WAR files are managed from. *

* Default is the same as the java.io.tmpdir System Property. * * @param directory the new work directory */ public void setTempDir(File directory) { _tempDirectory = directory; } /** * Get the user supplied Work Directory. * * @return the user supplied work directory (null if user has not set Temp Directory yet) */ public File getTempDir() { return _tempDirectory; } /* ------------------------------------------------------------ */ public ContextHandler createContextHandler(final App app) throws Exception { Resource resource = Resource.newResource(app.getOriginId()); File file = resource.getFile(); if (!resource.exists()) throw new IllegalStateException("App resouce does not exist "+resource); String context = file.getName(); if (file.isDirectory()) { // must be a directory } else if (FileID.isWebArchiveFile(file)) { // Context Path is the same as the archive. context = context.substring(0,context.length() - 4); } else { throw new IllegalStateException("unable to create ContextHandler for "+app); } // Ensure "/" is Not Trailing in context paths. if (context.endsWith("/") && context.length() > 0) { context = context.substring(0,context.length() - 1); } // Start building the webapplication WebAppContext wah = new WebAppContext(); wah.setDisplayName(context); // special case of archive (or dir) named "root" is / context if (context.equalsIgnoreCase("root")) { context = URIUtil.SLASH; } else if (context.toLowerCase().startsWith("root-")) { int dash=context.toLowerCase().indexOf('-'); String virtual = context.substring(dash+1); wah.setVirtualHosts(new String[]{virtual}); context = URIUtil.SLASH; } // Ensure "/" is Prepended to all context paths. if (context.charAt(0) != '/') { context = "/" + context; } wah.setContextPath(context); wah.setWar(file.getAbsolutePath()); if (_defaultsDescriptor != null) { wah.setDefaultsDescriptor(_defaultsDescriptor); } wah.setExtractWAR(_extractWars); wah.setParentLoaderPriority(_parentLoaderPriority); if (_configurationClasses != null) { wah.setConfigurationClasses(_configurationClasses); } if (_tempDirectory != null) { /* Since the Temp Dir is really a context base temp directory, * Lets set the Temp Directory in a way similar to how WebInfConfiguration does it, * instead of setting the * WebAppContext.setTempDirectory(File). * If we used .setTempDirectory(File) all webapps will wind up in the * same temp / work directory, overwriting each others work. */ wah.setAttribute(WebAppContext.BASETEMPDIR,_tempDirectory); } return wah; } } jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/util/000077500000000000000000000000001174773561500257025ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/util/FileID.java000066400000000000000000000043411174773561500276430ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.util; import java.io.File; /** * Simple, yet surprisingly common utility methods for identifying various file types commonly seen and worked with in a * deployment scenario. */ public class FileID { /** * Is the path a Web Archive? * * @param path * the path to test. * @return True if a .war or .jar or exploded web directory * @see FileID#isWebArchiveFile(File) */ public static boolean isWebArchive(File path) { if (path.isFile()) { String name = path.getName().toLowerCase(); return (name.endsWith(".war") || name.endsWith(".jar")); } File webInf = new File(path,"WEB-INF"); File webXml = new File(webInf,"web.xml"); return webXml.exists() && webXml.isFile(); } /** * Is the path a Web Archive File (not directory) * * @param path * the path to test. * @return True if a .war or .jar file. * @see FileID#isWebArchive(File) */ public static boolean isWebArchiveFile(File path) { if (!path.isFile()) { return false; } String name = path.getName().toLowerCase(); return (name.endsWith(".war") || name.endsWith(".jar")); } public static boolean isXmlFile(File path) { if (!path.isFile()) { return false; } String name = path.getName().toLowerCase(); return name.endsWith(".xml"); } } jetty8-8.1.3/jetty-deploy/src/main/javadoc/000077500000000000000000000000001174773561500205455ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/000077500000000000000000000000001174773561500213345ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/000077500000000000000000000000001174773561500227605ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/jetty/000077500000000000000000000000001174773561500241175ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/jetty/deploy/000077500000000000000000000000001174773561500254135ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/000077500000000000000000000000001174773561500272605ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/AppLifeCycle.png000066400000000000000000000470661174773561500323030ustar00rootroot00000000000000PNG  IHDRTA(WsBIT|d pHYs''MTtEXtSoftwarewww.inkscape.org< IDATxwxSe_R(@J{-(CY- F?DeLAP)Le{P(-#IH4}Փ$ysN4 !fgVHBB3*f" U!DB$T!0IBa&PL$ !HBB3*f" U!DB$T!0K<ˇ7z! !+Ӂ+V'O]xbŊY0*!x57'OsmN:eP:Ċ+裏X`gϞRJ|Gw^{3f _}/^F5Yl4M#>>8ߧz=P{t)z:883$EF`U%ԓ'ORR%z=֭cܿO>'㏙6mϟ7nmۖ͛70dϟ ٳg޽{zʕ+و#::0oBә$ 7K,8::Yf+4fU#GV]taܿSNwq@}{A4cbbti" d0NKEzuV~w@uJt:J(LB=vo~)͛7Ǹ:n84i?111.ZDGGAddhKfs~"##_Nggg\\\Lfɒ%` 566QFٳ={6ϟDFF̝;w>j䄗.\ <<Νۦidd$Ozɓ'*%LPfM@WZՐ(u:ƍc޽l߾(<==4i`:rH~'mFll,_zM6Iaaam33JhF $K߀X<~'Ȍ31YApp5!֭[jժ1g4MjժY"E׼ysϒ%KtԮ]kג?t|̓x]! &88Pak̙Sk:aSI͛71bg&44h<==ML0I&i̙B'_LL AAA|͛7\2s;]ǏMH(SÇܹs#CZ;w_lٲY:d=s`8;;[:4~.^7TV]tɰ^*U1ԉӜ9sǏ=~lڴɬLÇpBԩS|W[nDEE&'g}fu2Ce̘1) :?eGHU d˖-ZVJ׮]Y~=۷oa]Ŋ9qgΜTRTTzW^%""r)V> 6d<ŋ)Vݻw篿2iߟMҼys~7T=ʌ3ț7/:u/Pɞ={={6o͛7gʕܹ3 իZ. 5ڵ]ҵkWXjK&  PdI9Hoߞ… -[6jժe8P.\ƍ\vƍS^=6mJ…MNxZNW7J*Z۩\2]tB 4襧&$OM8q*Txܸqh?N%pvvfƍԬY]RhQ @\\!ԨQ6mPfMöm )T L2sxʖ-K.]R  b׮]&Z^z4k֌֭[u$'SݻɺNx4M… 'ONm6ԩcܩSԫW=zٳ4i9sd̙,\^z̕+W1/Icȑ3gܹ3#00zܹct}{Im[܋0l |iHhG=|0׮]DJlǏ7i?͞=;gȑ/_yܹnnnܺus ?~ CO33sN~?2ܐ0kJ`,%nc}޼ySLLJRJٞw s E*j׮믿nNK0NGR8{՝ աC޽K޽)\0?f̘1T^>I&ѹsgéUݻwO*UDnOɚ5+۷#D*Uڵki۶a^R 3ՋNC4ΝkDyw4 WWWO^gΝ&= z-V^M=utz:00A"Eٳ'/^ܰ]Z˟?? Hײu):t݆K?~۰Ņ˳sN5k+W(\0Gjժ=IP-Zc||||=z6mp] .Ltt4|t^ݻٽ{7-23g 5PPa8Lڵpuu޽{3p@.\Hr8y$?6&ƎԩS ~LȒ+00WZU>$lh/MoOff;Gs=\]][{ܿs*uZȖ-ECjʔ)ԪU=z:X_*3_~?~ZlIٲe6{yy~CCCׯr"gΜtDJ֬YMzsm8p*U JOwHȑ;-r4i҄Sn]ڔȓ'ժU+U1YR@====N<_3avj(ȟ? bț7oۉQ:k֬iLdBbŨT$S3KQ?>>P|Z֭KޠAʗ/oXM ț7I{vظq#sի|azj888PhQݻw ,Oiڴ).]à &sOM4PB]fgg;3׻鉗\:dM%_|~'OX454M#88CI"ٜS.Dl.N:y HUۦ4GMT!fĂDF.ߗ.]nݺѩS'HڝsE\ _?m"ct\?9es%Jn9888-[6gώ;ٲe+[I6JffO$fZEA$LF4Ln-!prriΫ# UMLL 111/+8::5kVtYfkI"Iqqqg2oF fɒ噄)gNPEMzM4d:yi^^^t:37d %H,67lJX/;;4i<1Ͼ*>>}_WXI"yt޵kPlfU 7ހͳ Sމ\XI"M)%4IBicxw1z ,7{wh/]޽NW?ؽah~~z=|Y3XԸ'MRqرа!i;vtkW8u*aPEص  EURZ֬Qqc`T~mzu(QWM s'A*qC>?O>y`@ &LVr0MwŒPz޺5\}]@>jُ?ܳJ#G&2BohLj: xH=QCc`5ڷWӿ1yz>aF˖/UJcF5]Fewkdɢtwܹ5/7;sFbj} 77|dkd˦jv( ??5ݨGXdd>l4߿WXPEAT鼄vRu 6Vۯ]S%ЬYs_my8|X@UA`q׮zo6)<\myGxzRi`C\T ŊA"=$!-@SJ$_p [6Ȟ89s˦._t\Ф ^oJ9sNNpx{03pj>(S71ݫPE5ov-h4P%MsNaFUJMp6ܼ)-\5k6t:}:|ؽZ$ژH DJ6la[#ٸq#˖-ሗjCnܸ;v$*lCl!)J«WѧEDVM3k,-Z/@TT筷ޢgϞ/\I\nܐc"odoO={x\d_P<͛+S9r͙33g_5kV F'2M7nL80u=tX6MMY- xbi/fo7o^jԨ[v?|ҡ$IV"b~ `ӦM^*ܹs|'ܺu0o̘1l?|؂Q.[,1~Ilؿ?&/\K-mj%/oqpp_~_\tq ,푄*D&PhQLµk)Q OaiC"t4jԈ<{Kdc*D&˒!IBa&PL̛P-+Lǃ/ܸ}N}62H8p T ~5}:fca 4JH~N+y&,VR5y2+g(H734iyBѢx#3U ̝k(L/CΜpӦPqupԭz=_NAУd˦**]8Kԗ':Z}yjPoooH|޿RUѣ 9rPڗNgvv8|XZ5ڮ]?;!Kƍн;ԯ W{6l ]5SccaR6mR۶mecm#GT rpXZw-] mڨc,:8ZߟХ $֓' ZU0oC]3ҹС0j8:¤ICJU+=<2i W38sFM|qywo5*ΜNK_~QϞUQ#`,:-y|Q2W *޿7uq?U-=ڸSd QjY|:WVOiIKȸ8-hhOw5G]jTn\fFj] {{'ˋS?kUh,^;v(]ڸ44W ؿ_M7i1dqE4QnnnQF\z^/ɓ5<<45Դ^mb|5j|{IxppJB$۵0-ÚQxte'Oj8:jkA8Rڏ&~^r˙39 )C`̼mN0.KbSUjPEɄeTCرN PXY@Dij9 (/xvv6Nt׫iꋐp%Gkhn깝liZ@0AYǫQQeQQc+1Q$,Oj7zPlx-V~7gy?/WN%vhє^=k-8YڥA{tǺeiŊZrOO ٸ1'Oߏ ᆱ]y}a26N\9@U`Nc1>eTM UHi31o ];(X7W;o^Ľ/ᡆ$5k%TTܪ78Ջjiaʞך> _jA=]JcƨaWkN@ VS%]&oUŷW 4~UWzc>,L]{P„dHH\b=^{yӉw1gyaa]6fz

[Wii[j:ā5I>%%=Y/cGӞŔ>UejKn_Ghƿj̜zw2]E}ThPPJB$G6aB/PPygwikQ鈡D巤s*ڥK0hn_Yanݳ=E6s& f̘1{ި!$44!{;{)>*,QRk֨SGΜ y%TH*Hx5jK׮] R"ݻG߾}:a}_)V 5sUډr>Ug".^| ZiByu~r)ʔ)c-8r#Gdz8N*PHRߥ 6m۷x)cf͚ŏ?Hܹ-Mje&O-bݺu5 >"VX͛Yv-."iBngeŋ ݰa.7oޤwUHӧʷ~kP2 )Zn KNNNZ .0qD F%2 ^ψ#puueԩ'St:NJӧ1 *)ݛڵk3tPKHB@G׮]ر#GXPtB>}ܹɔ 5iҤ K.,\‰o 2{ѧOON ,N%% \r\s!K#,… `INGh\a(R/>d Η/6lϏ.]СCMXÇ3yd֬Y1vvd&i]U<ɔsgȑ(P?tc/_Ί+puut8gx̝; B|'M[|96mbݺuLPmȖ-[Xf ˗/-UaNʓ'O6mCO i۶-GSNܹs3 >777IVJJ6ƍߟ3gJo߾nZƘZ1I6*$$___ @f,HziԨ/! Ն2x`T€Dwݻw +ڰ,Yxbͧ~jp2hzIݺu>|$ 5tL6};ЦMIȳu+mڴё-[мys&҄T3\]]Yv-{aΜ9'C4qкukz2HBϕpkMӘ3b)C:rN24.U{ a֬p##ahڴ;|OT0ΟWӁ0hԫ]z=|o>B*G[pC*YΛЪ1in M7>hW^kLc׮{7٩}q}矡X1ZQ~}hnRN}|ki 5M4>6Ԙ6Æik;wCp WWgsWW>3.7OD 5}Fj} 8tȸFja //8[7UJزƌj:_>+ƌ(T(韃i"PEwSϫšhQ4In]v}޸i*i^WWM۷CPl}cwJP%"ET9(ղzM<-sȰ)>=={` $V^,accՐMLG37o͛g=zwf(pߴCM琄*رSti#h^u۫^rTuhQۗ -NL xػw@J 66#Gw^ˁ-G.]\5)="#y^:tH" IB\v֭[si,>pW* $9s&W^嫯ђa4"U~776?i$JWnlѣi۶-۷'004 UVa4" iƂ ؽ{7sΥ@UU[t)c…X:D҆jnݺEtlڴIiҷo_HǎmՒZ|96mbܹN'pܹÀ5j 4t8jcܹ3OL3a;K#^AJ6gʕ̞=%KZ:afgҥK̝;,)H{RBAAAtޝ+W?K2Q>۷cǎܿje,X̙3Pʕ+ :O?ʕ+[:$ nj9///&L g7e2aaa 0-Z;X:tKWÙr*^5Sj;7KҺ;wd֬Y|gTkfZ1yd"##:uj è I2Z LŁӛ#\nVhbn|eB cԨQm6)@at:'NdtpekTJN(3KNYwBstW|Ɍ۷)S0qDիA]v+Vnݺ_&S>K9_@(V.22?~'\QlYV^ME)SaSVСCjՊ~K2/3gN~>}3#IBB111;o7[oY:$A3k,%""[8:' ?~-ZPV-.]N!ի K.ܼy;v駟rmKfӤ JhL</?s}!z,^~?ȑ#-͒{J(ի% ֭[SUׯ_nl$T+Q}Dtb0 9q[ԩS& B\!-HB|*Vӧ9~8cƌ'՜?ڲ(IBظ+2}t]cŊ2* XwB-< BY&˖-:yl޹gϦ륂u&+Y3ȑCW.$ ص ~!bC{=!ҁN.%L ›oB @PZmlْ\SMm 'nMݼ Nz Gk^8}8BdvQxQ"#矍_Al,m׸sVķ;Ty3T 玎Щ>~\NákWȕ χ8=~w{wͩSlU]4 >5R׭S Q_//6 T˗.U^=ؽ UtiSÔ)g 6ܹ f6lPAݺy,X8pnUMwìYO PFP8v ^oRT S7yjsԶ0p ӧch-XwvV۬Y|gl/jhghi|Ƒ#e!!kmqZW4F(]Zc6E4<=5VT~MEI?И4I=O壏4g4HAn43[oiZw{94/!C41i/cƲe%Jh.u9~<Bh´Ǐq萆k=g\ѣ:6ϝS׭׸pAo4\]5]S˶npsxm;5NXT[qhy4:vTܾ͚} gg5<<4Jc7ȒŘ+u`>WK>VQƗ_ܧn|@7n47NJcBQ#Hj޼& ''cLYj/k֨i??^xO# :;4QՇǏUQ}DUU[NÆy9syzT;l* w IDAT&UM'V7U AA k' jւU{&Yʗ/1`\^j HVpyV үe:jZM_Ea<*tb} u8qu5Tpare564濻89ڵq{.5,+UUɏsg+uK5[}av3g/^}T)T҉ aacԱ}_|yӟ0+:wV?T3^|Ӏ%Ԡ UȝhQ+8fZް-+E4Xzȡ $T ||\95jukv`Hm^x1Zc5K}y*VwU=rQha+Se^{Mt)SFKCM*8;Ä jNjcǗFNțWUᓣMON:P&d͚nat~' C^%0P PsGk ~M>TUǎUM *}lrtd}Rԡ-[rIK"H!IVܹ *PjU-"$Z |8z(ˋnݺk.i0$~X-͑jEƎkr("""pwwOٵ+xiӦq-,iPl$T+={vƏox÷~K5,1rHeq,MjeH…)S ۷oW^\ta .66}Rzu bpl$T+ԩSׯJMdP;t֍ niǡf@;w&迋Cxzz~zý{h߾Çe„ TV<)Z!Nṳ3k֬a߾}̙3ǂ֭[уYfI2M'P3;;;ΝK||<#GDo Vܹsߟ%KPD Ki[?#'z Wٳ'K,9WơC:u*k׮88P8+V;wnK#/Š+XbZ$ … 6ShQK#,l͚5ݻ QFP3@0a5SpA\a̙ݻw1cUgAPm@DD~~~tڕvY:>c<<<5jC$ڈxN6l >>SV-zmp2lf_| êl\TT=ze˖L$T3zhUFϞ=2׭]U K. 2-[Z:Tm̙3Yr%Ev=̙3)[OjΝ;Y`Et8"._СCYp!rG$U~VT)VZŐ!C8|p1FU$Z1)fҽ{wڶmK1~2~Yr%nnnfأH+P3xJR:th-\LlZU]qsl3i$jhҟ-5֓L6mĊaSZ5e8:2a ,D4+jtb檙GscΥG=?]\yhooĉ׳de,%qJJJ4PWWGww7GU. o>ԭjdxx?ӅBg*ر;wHˑkLOOglA222";;p#lڴ]v 른p&&&ɡm۶I xhoo?tGa)++####HBll,tvvRSSr" TWWr$D T &&#G)--U9ؽ{7 qaPJ RRRҥK.gј 顼f<O8]΢pm}GG555ƪ5%וIBB۷oBRRKZz244D__DGG4qL ㏻ݱ10/G yWW߸q#ǓˡCB޷OJLLd0k(,DX֯&ldJKC?7lz;y$FSSO/R T;/ p4LL06E8|8c>;~\0Y:u3g΄(M*sSza*;_~ ;N*z+TVKͰw/\bx>v:x);ol ^{^ʯ^ />8vu5?yy>ȱc=}ONJ+C#2\ߐi8~/#ҥ ?^dž4J`k 6yc'CRyßRS >k3{ >Æu --c ))?+&fje={'GY 5Zel^]l07jyyk Lwv 38Xnul̤!.e$%[%%Kv/\w /?c7>8}MN“Og;h .N"ι̽[nU^YYp劝=jk{OtCmкֲeQQY֬znZ+W^=dC! O27~Z[mx47úucccoa3IO/Lo bzapum(w?D, c!.oP¶Y}}g]wK'8EE] |nBr=6ccpa< dӓR2#zzs\z* CqD*"UD# TG""(PEDQ8@qD*"UD}}?]4tY@3p sN6%"8@qD*"UD# TG""(PEDQ8@qD*"UD# TGb4؄IENDB`jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/AppLifeCycle.svg000066400000000000000000000370221174773561500323050ustar00rootroot00000000000000 image/svg+xml G incoming_app command_deploy state_deployed Deploying Undeployed Undeploying Incoming WebApp Deployed App LifeCycle Starting Stopping Started DefaultAppLifeCycleBindings.png000066400000000000000000002001651174773561500351760ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/jetty/deploy/doc-filesPNG  IHDRSsBIT|d pHYsy;tEXtSoftwarewww.inkscape.org< IDATxwxU{M@ PҐ:(i"k)PQi *H @ @ an1;$$r+g@.puu7+Y7oĂ pQܺu ٳ'mVi(O@@ZlY$"z:jjTR㺬DKfjj R R)&sDDTd*''cǎm|3&OS_=+33=zk$~~~꾏޽{K .ѱc*$ISTTTF1v5VII JJJVZBR 3331*5."F&SQQQ&RO>7~b"ճgOpttE㠠 (8}4abb*V磠EEE%2~Ey Gɖ%,,,`ii \^MQyjd2uYUV8z(rrrp̝;GC@JJ_v x Zt)nܸT!--M<(&Smڴϝ;'~ܢE q.{tt8 QH·ұ"+//*JLX1{.>rppsL&8͚5EEEI <GZƢEʼÆ 3gΈN͛0a~g񵉉 LMM%U F9R3K.^B 2?VYȘJJJL$%% puu-jx2h+#=^^^1bbcg-͛7/YƍDׯG6mPTT///q>Lq͚5 Ro|?OF刨vЏd߽{B2vhDD5BNp1\~QQQXl8jT*rJXZZ|||RRR/K{e;vL6R-Z|8tODIާ_ssIa iM|qt:_'%48mp*Uaa!n޼7opqq}jU]VJzyyaŊxgĶXqo( D.]Rh?G8>} >ŋ!C̙3s hРr9j뿲`ccBؠ 999Zua̘1b,666ĉ'иq}DT4 n޼[nj HJJ6$,JéSо}{8998r<==Km?ڵ{gL6 ]t!CJɓ'Ѹqcy+TQd.'..T&M˒D j*(Ĺsl2lڴ pvvF~MիWÁ G$ PAA?mbcc,JÆ C.] srrPPP pjVׯԩSHNND /,^ڞWYedXp!/ISpB||g/%%%ER!Q,\ .|kjw"22 +QMQyzzJ~) qAOOOX[[?QF믿Nwww4o!!!rFH¦)))ŋѮ];k/_ ^I1i$8p͛7Ghh( j4i"Oggg}pdff"66Z֜GT">>%*`ҥ,GGGxyy!::/ $$$@Uѿ~KʢjP?pZlY%ϪN:w܁Jd.QɔS^LxW(ݻ7z-QYZh!aeeUqqqyGnڇΝ;tj,iܻw FǏJ틮]J?@||<ѰaC 0@G޽{qiI&1bMٳC۶m1djlݺ111ǸqРA5k֠q޽;`Ph۶-mۆ7nq;v,lmmt:v؁'O]voL2&$$A/UVܹsk011lKHddd#GK8qBVVZnaÆIEӧO#==K.۷wRɔuwwGxx8޽-[bԨQ61x`ԩS=zH~oU7F8xzzI&FԨi~DD5]VVVK ;;;wuV4iiii5kdZ^^&L]Lh N8!Yp! ;wĸqpѣGi&|G尴IJe˰~z|8y$5kHzS@hydd$mۆw}YYYFXXvU믿_ Looo|7X|9&$$ٸz*7`QQQh֬8bHZHHN:UǏ>J%/_s疊e޽hժ<<<3СC(**9z(6l؀3f@T k׮{'NVcΝXh~!==}6oϣ:ܼyo6vDDUFLd:/^q!Bu6 {A?3T*֭['~waĉ6l`ȑ6lV\3g}\ 6͛7+VѣkڵkS"::ZRAIIIo͛cz*6m$ܹoXuĈ5A?e/&&͚5Cll,`8p^xFDD`ҥVGСCvZIwelٲEk.,^Cg,dggرce&R SiPPp $<j $Ә[l \Q I ~yhZtIT*KGX)bҥKǏ HJJBRR/J'Y*>K?S|ϭ[޽{K$VަMKdU?:w<ދƢRQ#SС^vM Q #5mTNJ/=ݻpvvUV8}4Z=õ2JfffLB}||$vkשT*Sr^a M`s-,,p9\r&&&bRw-dddp-R랜tm޽hԨN>-`߾}}6˽)|}}%'^Ԇ"3g]&i| JD(vvv_srrzhT*% aggWBuqrrBQQ_.I!*OHHv܉\zU'h\|~~~ h{ 7hiiiig.]+W~ iZܸqTQ7dաADTU4/,kh6333+AmÇ;RԢE hZɔ>kcn09rDl+5<{k׮d9sΝD D||<yK IDEEAՊS [[[lݺ۷o<S,)rqedgg(H(R`iid:?2IԹsJ3cڵq!rϗ,qAiӐիWҥKhٲ%,X OD? iṏ́ 0n8L:U,w~uhZ 4۷G`` ,Xx4m1~x!2?s ????z3gΠk׮)&k^xaڴi;v,4il?"O0GFJJ ~wCh48pz ݾ}b߾}8{,ڶm pssÔ)S0rH`ƍ@߾}%feeaԩx饗p cРAFOMMM`L"R}!,, ܹs /({d*** _d:tL~dlݺUl۲eJJGDD{p5kV\.G`` a8%S-,,"n>װaC4o\|իWcʕXlrssѨQ#=Zxb8v3fH-גC ,?,\ѤIH111AHHddcҤIɓ'ٳgѣgũSM6())A``.bݺuؾ};n߾ kkk_j ڵC^^lقLt]we4m=\qnr劘Li[ƶmې`055\;i$`jc}U-Z`?"d\_())App0[nEpp8QFHNN\xbIW^yÆ Î;rJիAaa!lllđ/ooo|h4={XjoQy&ktL⥗^BV;J3ydxxx`? kwww4mڔ#RDToّ+VThh( V 333!%%*JRp/kܾ} sΉ):$SOII9s@OOO8;;ƍ{é ___$%%Ȑq888ۻTC"N&S٘={zѢEi#|sIR1\;m4XPHJY&_ ,mԨx\*Q,,,мysxyy!)) BTym۶A&?C cM*s VurppQU's{lrIٛ7oDZb2K.BIZ>ɔa@ZטzXZZy())Azz:Ґ)CСèrֶ~-\\\ޫsԵk$JJJPf_Ê~o333˗#??ЧOq!HVffxR/0>||WDT[r HKKCZZ#jkkk1ba "\25}tqg}T٫W0V{p7xo&bbb駟#:I2vZ76l: pwwZlcFHpqqk*DD$S=]|2<<<$}䭬L &t'N\P(zjqs\\8J7nܐ\ӫW/ܹVVVf*..FvvcEL&5lmm333cEDTթ۷kRxyyW^.iiipuuZx1b gϞxЧOHVΝ`8~85k{3ft"*EPQ&鐗'Iw2)JIdmmrDDPF*Jj&&&~hҴiW_ϟ?:B%zBHFhBr'~GDT9TEAVkZT֭,6"LMM'''((((/d2aaa XZZQa2iIt:O=TEDdHP# t: QPPP*QDuB$Jd2cGDTԊdʕ+Coƽ{77ǾHHV^ ~dZc?QMMLLTi&I&#*))AQQVVc6lRRYc eTFF|M_ IIII/f3B%%%aƍ8pnݺxxxs5j7n\>'Ocǎ͛K6%"*$KhP\\̪O &J,>F:{,6m@(a믿7--ML,,,вeKٳgTLFV1o<JΝ;waaa믑~k8}cz蓪>D&&&b"$ˡP($ǏWn3Z20J%B={ڠq`ظqP"66td2!jtσj+ݻѰaCk2L111yڈѓG% QQQm۶!22.\=zǏG^Э[7@~~>1޽{/B.y:t8fX M64~bbb`kk:`رMHj͛s܏O@@lٲ>|xbۃ?6mt:]tt߿>}t:.33S"1c#_lc: IDAT~{Ws~!]ƍˌg:NS:RdL+Wڶm[mڴ='ODT7}' 6; ""g}\|Y|8#Sz8p N:С>+WD-';UuP5k#C.]3gΈ /|'?{Fbb"_~3g&MWWWmt+ѺukDFFSLիѮ];1>qQab ^\r抉B[#FKӧOǸqe{"ڵks0tP@DDN*I:vXj PTdO?+]͛7vvvPT8q4`rQ᭷BNN`ҥ{GMDDDDDړ)ÄEe-V|jժd} 7?LTO?ŧ~ ^UNPqd2tv¹shp%Ba֭1~x?;wF,nmm-&v?~\|?~ $UQ)$,c0*T*ѪU+\ttxVq2+KOR=[ L۵kpy̛7OL.]*.6|]v}=*a~t:#U&SZ/U^ߨ(q\V${3gɓ˼~:_PP\صkakk+[XX[nGl3LV\[^~e9:)~Yej)~ k?6GDDDDDZ Pŋ똘,\PcwTYkl0! oB777 v¢EuÇ߹s{ƞ={pݻf͂X 0}?@-31Z~=vڅBdggc x{{ɩٵkZ~q|ǥ@"""""Z:2+h_~T={⭷BQQ\.GppaSǎ/ 7oJ%]:uС;vKdd$ P*kRK ?L>~'Nƍh^xh4<^  $$$ 55 6p-t: 6TDDDDDTud0 *>i9w.TaXAdGϞ=.^;wC ѣ%׬Z WGx&p:>R}:t;vHj4Gᬬw^ 8PltRRR`ee_/\"""""Z2~QDt:M, QJW)믿.V۴i#GҐBOOO8;;?Fbb"j5ѠA:Q}6g4o\2uU{'OLLDBB:$&Rcǎ}v...pqqyx ڊ{mqd*̛7+W_o˗/7bDDDDDDd L w///l&LDDDDDQ,ܾ}[&27t:PkVzYx̘1PXo\z׮]=0nܸJ}.FMK|geСC_K@\|[lVJGŎ;j7GDDDDDQJUVn:=99:t W %>Ul"""""jL2j* <* &L_@DP^pĉǺqq1]f͚=$zZZj55j&SSL)SHMMC%&&vvvgII n߾wnnnuUjݴН;wp-uΝaoo LL&Nnݺ7oĉaooxzz+Cxx8눉7t @H,,,vvvhڴ)pRѴiS4ixq1>ANN&M{{{xzzM6qҥ'_2ڦaaaׯ@T"<<ZGŋ sss۷ݺusqqAzz:ʕ+hڴK۷ann@dW^FkРRSSy,}₻wΝ;'djj [[[ܻwOr=z#m0c |>777ܹsVk){PTdzDDu7%""c0Ȕ?Z^z駟Ɯ9s wwwDEEI7o=6m @Ht4jwFxx8d2 33Gܾ}cǎFL&?deeaHKKc806mڈdž4 w'Obb{DDrss{);;;޽٘;wH>;++ aaag}{/ԈdJP r\l}6fϞ-0qO{^J۷oGѷo_\\\-Baa!`̘1xakk>}HZ&S0|lقcȑb%|ؾpB666xwT*K?\KKKÇK/aٲePThٲ%}QիQXX<]Vl߲e ʼptȰ}ȑb! }J%Zl ?cǎĥ߿ (?a+Xŋb{PPd2rrr$5 (  Xz-4lÇG~~>%@bbZ瞓TzKyF%ˣ_SSSt:\rEӸqc8++K7ot.k$իbߡCjhrJlٲ]vGi&_DDDDDTL&&VVV ToĤB&>ѡmۊ8W(WΝ+j9:: Z #b=Il+,,n´iʌ5-- r/oT*|DDDDDTԃZۧO{{{BR+%%%󜜜$#Me믿CڵkصkW8E){vF˗/ʹn/^LO/,))wݻI&?#ر#=þ}$oc֬Ye^ӺukJ&4ϟ^zXt)6l}-oյkW@||||x <Ť$+W@w%"ڄ#SDDTq6_|!$3怳30o~+`cXڴ.! 4OA O=%$pÇ Iü0epܴ)BB!99fׯK[ؽ^/<݅Dq(!۷DpC!C~HDDuG9{Vqu^7l|( ?۶ }ƏCo|5!9rr&N4F^{~_JXdf̜)$WskJǸ{7gBӦ Iܹ%@~rBz@qS>|SH(/dQh0EDDuG~"]R"$p萐T=>GzMK #Q-[ =t /YY@TT1P?Iad꯿&&+$OB۶mB  ´gc|<,LKΝ'RNݧ_ ium~uI_GeɓdRگS'a$J5a}R/}ݱcٯo*}-ܼ)$pcشݻQ{#̞-$_܀{$y볈N`2EDDBQz ]Dyi (ez8kWewsJ(޹s9~C?j%0!=hڕ[SṘ/""U8͏ڷFfSv =ԓݯ];T;wJoۥ uգ8 }}$ݿ}{ǏoNuO,-dsݺ׾Hc$":#SDD$pPwoa ,^ L,5zC  }WHF.,=µp !j텇ݺG%ijgvP.ݽF?hPQ#B!L3Խ;м0ORZ9?^8x0`a\P>ظQN8}:-T{p!jLH*$D(0{Lde~~J+~%=[[!!Oˁ!YTHf%$ܿ]9S80]KSJ/K3g #IzB uM pڵڵ hܸg0rǏ/}nX!\@ 7>]HBBDkⲟGDDLU\&_: Ҟ=wsg!ۺQ Xh 1L? >]zMLQab"z<{eOXOF""`2EDDSՖȨ{QDDDDDDdLU)""""" `2EDDDDDTL*Q-K"g0 ?+Lj_ 3>|mKKcF)7FD""2nKDT `׮]ؼy3ۇBS!qzME=}v4i;2N3vDDT }$ғ8{nȸ_x7ft!+GDTý;8t<==Krj5C^~]E:g\?< 1vhDK,-[e˖2+= >-€C{oOז#*,>`njQ]&(#:6GU7[;,LMM?ܜhPuW_}&M2v8TOd3N캽0W?8N$e\Ñ+`R jBO$SExh<1ބK~$cȿ_Oua6v܂`cD~}+)S;rss1|pbɒ%01l:ng fAZ V  y&ՒL=RtjRr?,:{/lG7vvꙃbe"L%%%:u*~zXZrD*br[xbps NDCEv2ȪU[p\)d2znv 1#]RZd fΜ}1*'wߡ{իRSS1719j"^i)6n6 fp17?\Z]#SL Caxt7K7cCu\AA&LBQd۷oG}-[UVtx& h3P=t%=ˏ,©ƿZY#S3bG{&RT+8Z:c@Kx֪a޽;:t5k0"4h֬Y_|0v8Tp;%`H(cBT3cNBZYeɔVDGg@TYcBuѯ_?,Z&ڵk}êUr_^ZaDd<8Y-ϫdRNyU#*L&CcΌ2v(T}\E57"""~z̜9ռ$E鸙fάLƥ01Ecf8Ttf<C&jD'f1vT`ԨQÇ/8vvv Cjj*F"cD̙HY5C!BC/8Y-ϪdlY}<W0}\E)~g駟ƽ{"g2"aTh4Xۮ1m/ĦM//eĈĀrJt4ܻ23jހL%hpHUoFS/ًr rS9lD^=Yӱo7YhhKNv ٱà9Szm~(\NZK.ؽ{7 ?#Gi4DFFSNbL>}jnebQ3ks O^DY:7G3ۤj/qdԆ@L~7[}XIU}s3D[mPs :FԩSѿÇcvf͚8uLHʱw_D ) P3~iW #FZ:`ƱO鐕;ncݘi 5 Sv*='p|왷 `/i*n]HƖ~õPU;w{Au;{~Q?F\0vX' _d=O(oHz <1tQ"BJ\2%pqCӘnl>s`+t6>3#8lwnýE# ;_}~ǢGy:$& ÖFbbu16O@աh;GQn!1"V\dߢ;l2STcã*?&M'NzBK~A(A:ҫ{ i?l$_ZPBFd ^ Y1|s.=b2JJow&6:œe~f^Zty'AZpS9lR.\Josz?],+/ASWfCZCX2lK|sᾂL]ߏծ4ڒCJ*N\ZQ)c 7Rq]P.'wȼΗ'+Fs+Ɋ`Ÿvc)OUDD_{6nܨʏREKK駟Ҷm[B~G 6 #Eſ[_s0~-+TVpf Å g8m5-]ѐjp}lyo=Pw;-e~۴>Xz`Cf>8;2'+}HOO{QS,$Ϟv [;fXg\ΞϷ48K֮)8Cynr8R]QHK]C߽l ~ns<_GHvmb'񉥇I KDɝ5aǛh6%s_*;6~CN-;xp.&ڼc:s&/G%aϐhJ叙~"þoL͘Gjt{r 9).TseEމ( ﹶq'+:VSE9̾6KCG]uB=|NvnoRm4͢c[F$:֍#?9<'W"uǛ04dw>̰™ߏ+=s;?{l}o=_*_MY__?]v~P)QP8o1~k;:mȉű_΁Ϸ5U4M3+ry?`dkBq^1á{q?WS\۸#+zү 6CFAm>rơ{PyٝR*J˙X9bOE3'xvo$?Kء! f& VϮLX9"? o)M O4\X/ Ѧ1m5UU|~[lOcوY9a)sC).Z~ R\r2M @뛦Eœ8^隸 gxЇsJb1!3*K+~h^aH%7'jrc t޻}~'u$gNB6Q!Z݇,|,VbW_քTPTUQ:e .YFeHOѣի%% o[n=#єUt%x_~z^X Ֆ7:|$&6or{KTϮ>dE׭m.o>kwEꉎ^&fTUTƍHH!ȉ vyRWXijѹ Y "Fp;-> TMth7'(U.ފVc`iPk/[Mi3#9H@׻GT5ŵ'~=B -kSNaH؈oɛJm_aHsEM] dףXcReSkXlHKNvfC[r귣Z_E9`he`mZj*TkhFsӐD co:ݳ4诱S3's(#/9iJ,IبJ]~j_evwD{:Z.Ʃ3MrRÒpk״!zchR{\ l06 oPFv/48iG};Y CHDUE}Uihba@󊉩HFğWpTztӖ_GHQN!^Qv ܚ*PB O{{{>cn޼ӧ?~<}ųkVsdRZD mtPRcێ)>r]8'.JY0ʊdDVnw?y js2eE26#cZTUTQSM{yJUĞimT9R9Y{E ֘cSt|f@ZD f h|%g>zmk[*$x9 d")Ck#n-\'vfݔTUoքskNէQaޏ˛;ۑ$+5M |%bS9gW^ct}מ3Ӂ+%2(+;.ajInRW_"xd[G-eY1v1WȹpnJ=N =o U;SVTF$Zhڝ_-eE2 Vlܘb1>~)C`.;EeylA4; J^+'T4̤05 63!J2*TPЮ];ڵk?ՇR ֍/Th&;./ρ2bGqbal}uд7:؛/h5Z[tKY2{x!}v)y15cXzX_|ݧfalxk%}>xtseB.Sxԉ(-k$Jyv/&ʄqk\.$ /(hIc*~=  CvBUYp׽hH5v/r}vnn_߿R`5u5:ޝ]nFM]M!&"ǨXzXsnܫ@GE*C]y=i'ot tfMWY1 9$vvWO+\/y[dś:6wC_-}m>87#?'z*JWv\j`OZ&-^lÍ#׹)7O#hpR;n zNK+7q"ƳT3nk8rn) {qe%CnwOvUί;M~J.//$.`ܕ=56%/%t΍6ۧ9i9[sĻ% , yapEm-]#w7WCB *Tjj8tecY^ mF{V-܋6c†W)ڨk3lK잽w_C]Ct$]=1ql}ǗɈƱ] e]/Ph`lg9'u*Տx}46O_ǂn_Ԙ$2v-._QU^nx ;8{B;?Ώ7!Ą0 >BР`%g/׌tx Jl}[P>!ZiAG[Zط}ݫx|3l+Ok^'n0'Gy*KsCdhk<YYJJuâ*‚oBY?>ϸשX8)R^\F~jjjj8*< hI}*e%bnGv\v +XmEfB)=P&JN-;U$dcnU {Sâ>WB~>v&O;vɓOߜ1UB?CqjLLSV$'޽pWZeBShThseL1m56>T$y$t uWI_1G`{]UM*7n۪P!1Q|Fl~O n?sNJbKaܝ|5]W*ߏ߾||o1}~=o;Ty22y;H4%|yQi8RWu;l"\%/%B}"gWL|V6TU.rrh1q㸵ӆ|#7!C RS]CW…BN-?Jd`Xr Y2=FTw!ՠ8}vQVXJ qmAtNǐEq^1?:fmA]Cₗ 05۴Zg6:OAs|[mnrF|?SD *IǏàAO   ]`hӦ> a~dU+iiЭ8°4$r?!:Z٭8-KPR{@`[/i%˃޽A&456omEbH%|}ݻ! IDAT* <=E3g.uT&&uaȞЫsyVVn"\Тj[}{1/;&{?fp℘gOU;wNCycGF/ڐp1Ç7bcE55U>:%g_W{TVTV>yc&::cKnblLʕ$%Z2҈;k[ BMu .Kk7\Zt971u4ç?R BVlgW":Fz D)'ok[R=B9*f:E׷{NUy%W_ ``s&MRÒǫ/UD EVtX[QV$#94> 7\H\q% ݊;Y\]}PPHFHs=T<3U[\)W9 z&; lď b98eĝjWZSoߌG/¥;/-ϡ{))8;C߬ e2V]L06Ӵ7oFq{|I&tR*+ђR]Y͒afLɦcQYuuã'5-M^\2qgb80/.[,5dϜmK40w'g eª)p~iF4ы'bhšG+e".r>:wԩ5Z#G`@>aWk'L{ 6o)ɓEb0 h 8}}8{6|u55b1v8NH95UWTsłij+aSU%vbQbY O@76lC9V'yiܽ;SwL&>۳fAf'@Py ~%l(>Mrs[N::x\׬F!0i /$?S15o.ǨQ`G0q"Ggscx#<r9llX 뷗Q^3<F^El}IH2nD`ק[0w`H8\.g﹓YC3' S үTP]go,\-)+sH%(ZIqnN-\(+)35< @G5rǡ3TWVSo(-G^SK={Rq vRVAMu KH Y:Nv4X>5j'F6TSH4%XyPxyI9,D\/QSSϞBSW12PN,9LFHr9q6N]EAmrnĀφbj&tC]t tIh7ł ȌJCV(3ty֜RVw?Ȋɤ#[6N[ͅ14To4n\GG/ibnT%2p0]-FN\f΢wSU^ɖ븼iWEnm~*e2zN'Wh"NĎ7Q[31bH9Lޅ:hzˆlIq1|m xMRR~/CzQyS-YR9p\*᝹jl.<>.?$% QB<(v}@ŏ> ꡡbby$16u"C^{`sxtw Z~]YkܡP( qn/sbg:as} :tsEaT7b mOa4bXF_CψAiiklYݼ"?ldJI]ZqT &DŽ ںDX x+F#W7Qh䄍=w?WqhN):L\=~߉C\x '^ lFG#O#;. RZj[s **5%lO@nB6V^xuS`HDZD |iά R'}۶ gOq,#Q OKK;#C^\̽]ԵUD:u&Q ǏѹskV94mh->dC6ڢeꮻtI^Eߚw*EG FرBT;+?U%%"W~ALd rLZHr|yVTl&%Djx2NTWRS]ŞՒs7qopD xd̜ͱ !16 b<#bd9cN`2=QTKJX/2.|f\|NWa}[.61 '浝ET5"R;"ʫPP]#6r ._Oïo ZzqX%ku3~A:ccoF!ђY;"mccvRU7c#Z~Эk@FT@YϽ' 8!gDHC+#sɊP0 Ԃo]tSD\ЂĝFo~=֟a'9A~5Bqq|{e/F^]B] єPV$袃ݏ5?βm.ddƩTUTxQ(5!}ܺse%s xo= j/TTpE ƌ^{T4/)aĉ155 h{qq9 r {S7N+W^+|/YY ~~B.Vȑu .04 j=^ _yqpƧ *.wmdL;XY{P6n|(>׮Kuk@xnެS]Ls=xzbb"jڍMc`?XcF䌖"'+22Ć^rxy_³0N^FBkKGTϬ<7ƴzU<;16"J"͜hI5%rW#z͇¥7#?%Shq:]ȎoGqjᢸgdKqnJrhhhbhcLXnBs02Rs\r@u9A1€2k[LM=WH Of5rʫȊI5mwK+7ή:|/PJ wksjj\.ɜcjT;l}nXz<7}f5559Cj9DSW ׶ȫkjڑ?EC@wbfG#r2.u{#[qL.1w;TUTۻg( ZLMRSȄS0w&cxk *dɊk}"fMq3Ү&FFFd͆DXKw+ڌˋ')bw5԰$͚v܊ɠȶX?~5XA>J2h ;!;Шl6N!'a\UP> ZQ܀ǵ;v ZJJė5]U=1@U= u>m5#`@3űDKPE"ڶN"P)Qбh91 `_X}i{A{/&xz||g._{B]eщ#GB(ATTU^k֬0 ߯;_w{ aK nXzx!-N~oTP!rl>3nDG"ݵSa  ȑ)S`hmi8"6jW.Xfg߿-ż0ilh$@ZNYK׻58WnBgg+I4%Ֆ*YY1UI.TG'۴>U%m0&JR5u548XoETЫR]#]:OQ04۽ТY1TxVոjhh~zzHHRR*#6ܬcGf2c{kJǨU+L ~(LŻ UiӠI.A6mJ{hj A 55p;Wxx}c>],>XaybP?DoP]h!~ nxJ5SB'>^k(+3'N5텚]-. _󒥥0޽EWcjTaH-\(B0g[o9I/7'l@1̚% O<*..b.7Oxzŋߟq6ئSm?K/ uF{_]X a)*%>Bf/jkt"#s֠PSbAѤ C`چyGԩ(5K N޸lY4Hxł%,Lχ}Q1jP]chDXܹ#$77!@l$D(VW?YA˅M"7AlIb|wW䚘P^~~OSfaPROA͉PPC"jrb ȣ--> yHΨ4/ VYFe5hkTSկ4zU(̕/߲^SV&vz}w++}A<0|0DEXl05~^TF^"6.,1{WR0>YcvϢanCyI9:??^JPSC>bwIf27D С ^!u}8{I drdIۜ?pf&ZDKJ#c&y/2 G%;.+.*sx>y |pn::|~6i) ù~04$()$xD.'E`t "OHrjjruͩ!l%*jkHGҥx,4GO OVzHMŅcȉFn-[NW#p$h$N-]^l['.qfN em~}hJHD[J8zcKT5*J ܠȰG㶗 nFL[!jhM8Ũ$ &~!ff"a+V$ @H7lIq>i?_~H]b*ׯt>xgP&=G'ܭZiq[\*}xNqfmeOF.EUE1Ǣ"7)/'5<7qJM$L fGCSB½dHꓴӁ22k)-)eɎ"*ANv+/b N|[w8mt ;.裑H4%x5O@xIə*/)үRZPUS˴nr/chm bk), *,$Jq80_T=k+#05,$P"Q E/|GI~1M GB!|,N{Z%{yYbU +!Sc BG(N^α!Xۨ&7155GM]5DG-%/)m3EAɖFCSª K11΄oBELwqk5Jldd'͉"=*JS?ݹq ֖3fǥBŝ Xb:C7;:%j^2D%%b!tCf?bjjjXzX K>6e71wdӻkɊMVLN-\ȈJ/SS]CQv!M`bAYq|DKJ~J.[k?^IqN!N-\(+VzN0PYV! Bv-l|g5r pU44%ƻ?v&ğe[+1s2/:B E? WK2&_·O N$]!Љ45r~ƳTWV#ՖRQZNv\55'q+6 c;)aIXzXSU@aV;$R tt3 c(/F%eL9F|?nko!v5G߃ew&Rxx5%dFgPQRo@*TX[?9Q '푺##1jiCк[&;; K˖-Yd U"˙>}:ϟg IDATկQWBO)_xtJYŹEJ%djIH`:lyo=M;{s'6nDFG#OVlM BFŽ'݃9UVCIVQ節s "ή>_ ZnOI]H&j%1dHG' , ī/6>vlzw ]})usWKBDސ#X7eY jRMd׶Gp #ۢJ=O<7ޔ+tڛ>e9 I S'sL8{.%)OSÓﴈ샜ȌJfٛ9[`@FT?NРx1C[*1v٫kŷ le%bxk:MNݱljZO&/F:o5ԩA.. -"_a@_Oű55TUExGUmIg>"|w(| *LL8eJ.]bԩ*JJ^~eٴiZO֛i!Qk)aI-rŪ5NhCa8< f.N) %֤hS1=QT>wJ)-"Y)MC#B/o+SÓ p$+& 7!~PSUMUY%-]1u2igoOaǢPSSS-ZrD<-//Ğ9X5y*"Ϗ1(<< #q v%r"MK_iۉIŇ'%, '[x!4v| ׶ۙ`jɭ\X.o NkelYy#ԫ)4G'/LUR$*M ayŪ5Www&v%\$efHna^KwkB^ 94C3gb2ne疮$&`a&6Ƥ^MVR :sWJ~ͽ c_GpPo͢EPUQhJ6F(EFdwL(uMM,ݭ12"u;ˎԢ odKq]K[1⸝G86sZyn3#;?L8C6sr^Lx{f 6ƶu%4n˖ʲJ*dw4צ 6TWalAD\_q}TU* ˴dwJ;3g ڌ툑u≢1{6amjIu8abA C.m}7nӦMSzm~\27\I3^&F8u5?>KԹ,w/ƪ+qm#_j긷$|W("1s2 @Gw^FC <:z!Ֆ̙Winsi9d2yǹ5ȼA׷{5HsמHg7_,ܬAv!jWQ_ %S  Аhp.MM\V68|A_&b[_;"E`iKTHwaQ\_ǿ,ibET {{-آ17FcݨI4{PAL\\1K9񁝽3;Ι۔ʩ4\{NgvƔ+&d)!^x)=?l~9uSjU_100`„ lڴ+@B^0Olx,~;Ƶ=ޤfIpM/;Bd`fx.9?OfZC+9j^x}%GR9r;8Iq/|s}~5C<)'W*OYae_N,?Bjs5RSzC.oaeq;82Ww]{eW{lSzх;%+WRJ4oޜ7$jƏϙ3gؿ?VY(xz?y-f`Pc<0O '59ZMtpIqIŦxBБBk_?cGZM'iX:VgpO) IW{ND?"%!\zEl3f*).8@zq,ȺqiX*m޿1%.:}R)۸]V?\O\|˾Z՟.e1$&e_xnɳh9]N꿄kG¹mx#ޜ勱M&R]u+ū;cbǒs93k)ZUJ03i$iܸ1۶mdɒoI(%%biiɦMd )QlOs-hQȒ*m^0[}%7DJb ǮŹv)aĎXd״-XwTv\q"֜$oadfLbL%땦쟵pP瞻 jb`}|l!je_SΣ" ,2u]LRl"J}r@V#*(ذr(́SB1|`PcjϹ6Kn$$o@;m8*ŽdY[](V;A\vIMYIș,*`Tؤ7GGt*U$&D_?Đu#Va_сDm88qaYNijh, Y{W }u6Ԫ+l]2I #/>{'=-]cbyNs öt{6:LNH :α ===jtCZJ~7Wt3[clnBjNJ<᱘T֧yG mݻ!wx#wT2>v!TlQ8㒈"#Ga^BkEmfQ aoPD.ԣG+F6mXjuuHBb]tAL2E<"=-?E-m۾`F)t"]h01X" 5>?tĮLQ/=E!K>_ͦfU==νSuE=z.RC >kgM!?kbhb@wMB*Q^~TlYN(TD-C7֏-Ҫ+^0Jd,viw?)go*veɌ{He(T0 `Pc5k X5vB".bi)JpOs59Fջ*k ^xuk^ٽ(dI}ݻ;#ow(җVCN"k4hЀ]v1l0l٢pӧ4mڔ]J"%>d M^yٗ&#[IZJ7\$%PՉ;XW<摷veku)W1g59IjT@0njS~UNSsLR;DBt<+z-†3\UuM&x5ghbc$Dꄃn!1L80oltyū;SG]Sӵ[~iOހ< ʣ|uD##c6]9Ř'-9+{Za^Ђ0ߧ˟^4(C=Ep՟;nB幾כЇO?ӷvZgeZ:*ɕG֩ uéVI.OHKM#%1")QZU(,0ʏ5tɑX\0kAo. ...;v;?ptBұcGON۶m8ii~F&^B9 UËTjUo?mgJ_E002 ."|6,﹐:c]4?'V3JI$ ZPƭV"59Tbb(^÷aI_HǪ5J$NԊ5#CO鵔 74 208^ꍩ)CPOG/fCL3 põcMVO,l=)6̘ӫڱ&5xQG/[K'xoW/5%_|NUz*Q8lf#:EK] ']JO]*\ʖiw^۰+S%gcN=88z*jtCzZ:KmRmi79K[Sй0NҔ qUC)B%m5ߕg/fCCɩTi[T_}7/Pӧ+W]N^\x*Dy8(WQ_#l hZxd tCC9jR{ tgW . \z|ߕO&csdLM277\↳XOŖU4-Z_z.zce$]VvvCVᇮ1d9veRv)9c^R ʰ\J-Mwlu$>ΚkkZǑ#4*_#WsMUvՙDM(IW˺ǡjq1 )VcC\;dQ123[9hN>s :+3K.쬱-]?t.΢OԨnq)U|ppc]6XסIIKau;NrZf\v7bnnDpaK6oLrtzNV;:s!i)9Gd|8}IdXUY;>L祾`u9fJ+;+~ɛ \kvJ[Cy3gΤcǎ4i҄ ]$r3qD8 jIPۏ?o&TrV<,^gjJ$'%r惱q,i wEp^VV_JO>}:͚5ڵ`f޼y,[#G`o/MM#: !xZkW,76 kKV*pUtÚ7oΆ իu8"QL0'N~uE\W#21gѺEGS˦G+o{6]vfaoA,5=MkHMJbjtTT2uTVXpD.Ba˖-:$XXP…[Wubbxq65?J}/Ӓj˩oUM;ǨRχɁF1ї =-Z#GsN&Mcƞ'..v’%KP+`mŊ>j:KB .駟|rׯpD6tQFŦM(_yԍ ؏hzC~g]$rv\]倳̪<%~$BחΝ;3qDwpD6qFf͚Ν;)Vy\:9wf1g:p,PK`o툁P*<.(_Er,-+*9$I"s4oޜ': ̟?m۶sNYCJd+\+Ħ`鄩C9H:g$&P֪խkܶ9]4.I"JNNfȐ!xb }\-ćM#3{V4iwaq-*qiqE *TpeE Q˦$SB}w?M6aan,F2n"cT )-B__C&5d>!;zI&M |?{Ξ/[D .]*B*@~={6-[ʕ+Gd05kF6mBL!b˖-AG!|2ad'..,gǎO>lڴI)!&$B\Ԕ-[FnHLLuH <97mرcٿ?*TadB!^$ɔBR*9sNf uH-;v 6p9.\ȯʑ#G(VB"3%܈#prriӦlڴҥK:ar IDAT$'O`ȑ4k֌;wpLMMuBI2%y@֭)Z(;wf4lP!WعsEۛX\"BdSO!WWWW_}uxIzz:SLv=7nÇe"!Ȇ$B<#G3c ]#^n:nܸi:J!VB9 >Kj u `H@@f=d8::.8!J)!z-]=Iu(yY\T*ZlСCiӦ M!kH2%yR Uׁ$[[u4,,yWUDCI&I+B L !DTJ -Z@|*֭S(T(yW+Cf0g;Z !b2Bw 'Lx6oD XH4٨}M!;B!_n0aB7FEcWVg]u9NV!ٞL !pll`rT BM(XPX>8wb"- ۷CPrA !BϞ>ApTs炻UΫW3m U2.k`xL{Ghbݳ"!$SB!>, ?e[PTZHIF@It܁a * mSZw7װ~=+ɓRU+8~w2g*+OeC1%Q{me\% ~ #FzۄB>JPVʶ֭@6 vRZ7VM2qqnLV-P RZB)L !`*%Qʟ_V8;+Aor|YӧŊ|z2>ń) $V&M ~9%}{|NN1=1K!D!P!pUZIu;vdg;r"#jزEvW٢D}p!c sC( \e<0k2~E tI9s6:6!L !x˖޽ʴJP*dud;VIjՂ}%8X7psU(LALRQ1cEXF2=Ν0gszzJZ˖J :(Ӭ߿ySY;/`Z(_^uCB!r=E7BK/w15U]9++Kҿ-dahQguHyc,ZH!xKO!r8Μ9'\x-B:2o{>_||<~),Z###]&5$B\ 2ӧOkYXXL+^\LSϘ1}yftB7n~BK*U+WRzW>l2lQ1yd&N^^^G!ĿdJ!r%Kc 4x߾}ٳoM6lݺAvZ]#$B\ˋO>=zh9;;$9Dٲe9~8֭cܸq:$!/dJ!rNʈ#?X`7F__uaaa[fϞ=T*ZnMTTCBI"~:GRq)*V@ڵ:u*uq]T*f͚E~pssG! !@fB\#--ٳgi&VXi ///\]]a ˳ΥKׯ?#m۶ʰBL !D.p]܈ٳFZșWѣG={6ӧOu8BI2%9Zft҅~YfallDիWK"%/^Ǐs BrrCB\O)!BCCܹ3vɓ2Wffflܸggg<<<uHBI2%ضmhԨݺucƍ(P@!`L8tBZ2fJ!H ={˱uH"}6ݻwgG!D#-SB۷]$lٲ?~u1n8tB*2%DLL cǎח~ GGG]$rtk]Ɔ uHB+H˔Bdԭ[*UpAIR5k ]$L !%$$0i$.]ի)UCܥKׯ? )tN$]!r===UƺȡӤD&G: èP`戉Cs1l0رcQ8BBBڵ+-Zou8" I al}1I &5=Ua ;S;\ѵX7>)3}GO ځWE.E]Z“15otӒ(eQ WjZW]s*YUuh"INNfڴi=zUVQB]$dFIdd$k֬!_|Ir/k(iBj8wƬ rM']Lb4a< @/YWgn?j:PA'PƶE {+ tȁ%FG@O"|΃0ux`:?qhύRRS]KV}NolLŧ3Ʒ,{2mhQ*C]%r`6^ZMDL(-mL`"B_`> f[ǩ̜9۷rJU ?Yx1u޲ Lh)?a9=qng;Sʎ>\!\q#V]3l6vӓit>{1Y)e 1m*ž̻;G!\֭[4hЀXΞ=+vطoǏgѢEG11t<W m$R"[92&0ӏRgKܘL_Oe1]#N|`SoLJDzz:?3ݻwgܹOKKM/^Ǐs BrrC9w7RҎV;y }jlڕedp!?X€:#5J|t% y<׍x]#r?ϟ^zI7233cƍ8;;AppC9ԍx:32}垌2,+$SQ)Q Ї.(pDբl{MwuC9ZfŴmۖiӦpBd*L<'ၗW>~P"Pfa4)JvjD>SKfLzM2u40fqru("ӣ}lxj," yxyyq9<<Z-c_dgew,;~HrJB['ufiwW>FZJZ֟T*j|%YŲe8u+3f 9*]%',9YrskO18cI?FYb'?z̅g Ͳ:bCBzQ_(˺g@>7gF}Va<Xc)A~kz-YYvdzz/-q b7ǮLQnOGoǷqSYV;Wu]P9^.OD@8t5-(ݨ ŇpZJgYlB!rkkkΝ?̉'ذa[l!<<___e2 tU3w:עNv)B(^ Q'W% [fY,ER\s %!vT2$&}^H1BV~.s]2ϜC])U4<8s75=bۤ 4GOt5m n5'U*bM'\pM2w܆5dJ!J;>|׳i&fΜ]o>?N`UĚ!Fb`X3:Ҕ#5)008OHKIP)[쬵HO")6 –$'pV*Q8S#=-JEaeYu'-u)hL-M145"AO@Jb Iq>cח,`3ƮLQ&i)i^{]rְ\LEģ0m%=%18@pWaQ(Ct+ذ)\6Su> ĘD+:`hyиXoa[(_wR\O|DA8h7{|= lK/[.er'p]>Ki9,IwcB/XblK/> KVJTP$hޯ%F>sbc ]٢~1Oaln (Q&aB_YglX &A'i\==WB!;ZlI˖-Y|9˖-cJj1z*ko赐gY&@rB[vN;067!5)ԤT mBŃS) ~d7x k.?ugazbbXqO})M 6,csz.@4eV^&&LAYu]gzOW^C=w-VO9/&Sf8L-M 6±Z,FvZg.n<˓[(dIY\[2˧ǨtՋ4vLȁؐld؆Q8V& ;eQt)i}֔ kɎr]2>TxL);/ d, S"b)Z6hb&2p܇ӫ< (T1&ise: MHILO255X~~dIvɠ?Gh^̓l5JMx Ǘᯑ7PN2a ̺S~9{8ayy=Đ tעr? %8 F&>4JSci8ăr IqIXY3b8ke5=~뻈!L/?}4'R+?-5fmsn݂@04šDuGO.^~E@?. ]3j(߿,- nބ 03ggpp;wFn\vOn߆i\ikxL' \R 0|l WXuū&rIqx.9#S(^ݙssfjG4v-Cq4:3l5Oscsb>9tꗦp+.Qs-]"Qy:/2U.?_^i ر~<8{5(QE|TlY;ƱO Uƴ |ʨUbb>Kshm' csRRIIdމZqidQTnJ(6]n~gVîi[tgTT+M*6R9/fCV?}&IZeu#X%𿻿`bi X'W7fcjeʪ3յkf%qki<9?-kKOP35f5#V2n;2չcfʢ2ono߈íy7ߍ{'o3Lά9NLǞqnZg$?pXZͲ󉏎gԞ _Aןp~L߮u Ĵk?B܇7cWZ$fRkWf?^7GAB,K~D~=+vGǵulA+92|>[iI=U *T6mOdIp|[A\l g.߇e˔/!Dw"TU@ǎдrW/r oa_غ{ڕaGo_#W3xvőQyLL敱q,@J])QVi5. bdfLqm006$$p]2Чn߆TP#S5$6V}#LiY2b7GcT\2ЧF:Y/SLv$s˂CYuXYS񓪨Uj 8 $_{" W'ZOEaKdet5~E ѵFf*iK( #77Au7q\2cYS+rd> MpP?hoP@NVS-MlŲ }͗mRFC=@6ո7cKcjeF_ivRdį%떦VwUѐ&狤oωeG72֘nsruG4„4Wtͷ%_z/HVUh>5wDrB ykRNVyj (hA_J׾[7Ç3ʤg֭R/9:tPZCa IDATN57`r119٫~ow(l4(vz*=jtCnu}­C9 FN|dmu~>e#N֚Z м污E%橲!iZ+Q+jm2f@c4#µ9.Y|a$$k S(Q?k/QPŎ ifO˹,3zZݜ^hOMNA猱b>yQ_(I dyZϩ yz/Xk7u@rY2.zq]qK[{>wck9)C Jg~?y1eˣhti QTP$ۿWyg^"S|_=Dz^SRv;/hzz]s!uOzZ&A{OТ*qDFhPђ2Ч[9޷a  2&lkE>М̞в$R/KK]Zl<<<2. {J lݪ~< uk ++[/mkknJwºu-Lb" ǎJZiw9Rb.]Zy>* WZ+Cڭk }RjUh\Src7Df(^͉ _}W_{lz=sv#~j] \r#xugz{y!Voy*W&SϙXRe*B 1e>Gov}?dmOqDRv_e^z҃*%v2Gc^'웹ˏdrjR ff_kl@+'W}m2\|gkK{.q>L 9# HKQE!Kʸ*WƽT>zTIZTbώj좵J"쵆i< ")} |3E)=-Gn`mn:A^w5L`f  :FO#7[_"oOx*C ^z_B4Ͷ[^Ԉذm]SaPϚrr `MyR$=޸v(Q^u*eO g@ћt>|, HMԔ+R( 4Ϛjk0}$Iy4﹘+om{GÆʝSOETIIP-vwFw[Jֿb/ NeLM߯@I>%XÜ9u|JR5m̜"jn8r2|H9?qB鶨V/ḋ6$x{У,_$V+.^*Y0db$bp$lڤsMKunڤL\sgJ˒c1Ly})=yRI21P9 l^y[Dv܂\W}`E}Ϟ:^}1)݉rFa\қ}K{gqcuGor5\l/Ӹ|5@14 eqߔV ZPe.l8C?< Z]HIЌ=~žn CCjtytۻY2HjWM,*Zo'N+jhVKJQ{Ldq~ri8 jrsJ<}_uq.#?9윿Ă{$mȐ-aޘpq=G}O.Ej+BOs`{GRozL[6CzU[?ݨڤgvi61g9dv|K;KT7[mG~{s3b*\^$9< 4jy5FJ$+ FTENMek{{Oҥj ٽWe&Pf峳SI*͙4I=vq:;P#Cݐ FAiJx_fmiBjN, ~}\>UUϜ=Of:j gRRѫlֿuwbcET55jJʂ5+gqZK`]:Nid;d>o!U=mڶzbbaLsί14̈́ Ys@g1`pr2sx_M<;EӮ6~7l6ozNQ7o&&|p&(9nvf6WF3f?3i.v2~ 7ʀ,n\{VWG15crTLuy&jкNz8TT痙:?+} ƻsYc s~⒩'/;=~be8UsАKX08ޞ6, fT̬sh=Gd8x8q.ӥAՈV~'Rnӷu)9xl NZ k]Y7}%;$+-*x93ۈ5N^AVZ&v#g`وol7 K{+/X:o_kNͷ7΄l sFՈś".(cQ:ǵ/SV;I^+_і,Tb#G~>oeS8/QPZ,#Fwjəf2֭?X ~4d}/АkFf_^3|S=_w*mpa[2wtTBCu (~.PύwLjFlD3<&N=eKi.̆ w(5irfgK/~D7_m_k/w= ;+Vվ^9Q τ1Dmj(Hb4d&;yP7FF.{w gfr14T#>/udJegݼY0SUn,XWu?/z\QJ T9u  B%&&] l|djB|VOU6o=gQ} z|._#J\ߚ=eX$SUtK7;*6@uzޮH3P`I?Ezx4H/ڀrffmN"-׋^~y[ݮQNl\c~E_sWy%S2cScm_Wz3oN#֎4EKmv~<Wdzq/GbǸVNOjT󘵣u;146fkY9|֎}C(ls4*05U;&5E?.MEP* 33MO?W%;{czÇUg}{%5[TΝ0m7W +lr}{Ӫs_ۃ_ɩZIaBMcm{Sc^xXQ?7΃s?}犾z֭X$y!ʳ'2aڬbԺleܹ;ΰX[pbb(JzBGgb~Y%5f@5ocUUȆFFToEr9xP3ajYTRܡujaV (׎WƎU{L٩y}~7wWǹK kk~ӭo*D0c:Gܕlb4{̮otݶ 㜜OZZ΂qkѢڴBTsBwO\ ?4=G ([Ӻ9"w۵RM j"oj5Z .Ąx;;zYC㬬BɓՍI *tI'_Jl|}U)*R#`*Gk ^_j_~JU|qvV-kք%K}{W!CՅ+/OB<~..j饗zHNVMc ǜ3GnkރԱ*c*̛: fnW=̄/ Ғ &&<52sf۲83+S!:MƂ^'*]-eJCrL E=B~ 7Άi |2>+012 xDWCאFT͜LR>JO&~BSR֥ *NV_Nnj|ejP5koU7C*I-\bdUbv޻_ZjVV7<DT#XR|.Diq fSvNJR<;J o]V̜f z>/n0婙+[Μf owkn‰9-k|#~7z[%2%RVafͷR;=4.8C~ϖ߽8k' _olvnv{v?GrA;H/e~BreP3hʕH e} : 1Ç3(*72RM6<{`nnX[?MNmC}SsՠZ{ 5]RVVe# WuT1xC%Rk֤ΡCFGSwZ +h^̙{:^mBp˯t5 f';MNentu1 126֪̈́_NYs38a%jz6dw;~ f& Y4JW jNVZ&;ڂ1Bx#՚zh..9 ̘-IiL^HOJgu1ns\2m&tz3oB]Y_lh65~ifBŦD]:߫S!>1SK34S!x=[Tm$-jMszq|Lי.jw}BZ|*#bۿ܌ύk{ݪ$Dij."΅դ5Zdpv%)&#۰Ñ * xi ZuHѨ=M͐!뫓HD]ĵV%O{vj=K7zׇ $&1j썹9?[H^ fl%12Y=߽_uKU8;?R:~_nƹ+/|> ƬKKqt!nĚNvzCٳh;fx6F_L: f;BfJ6ˌX6\ާK;t֎QN!96壿:7g}${s z6_^qfTkꍕ57N׺M֪5ة~&ʊ'nfjKHJjE:L:ۨ"5~up>Rin;/;aT|%SS棐Ƣ_2u%>ǞE9Q̬̩ӵ-GE,d9٥Ѓ+Im[t:5296V[wwWBQZ||TcHXyzD2S3 'VBNvn{-Uc` lv0#viɆ '\݅[qdgdZї100 ME[ =Lɝl\L,LGޮD] /'O;Jp"Άaj7{@>MڗݾW ;Bߏrqy~dgalnfN՜qL`l]88'8#104KD^g>ו(~ !yyfbbaz{D_mu1PWuA&deblj v>cD_i{f2S3~*Sߢބ 7T͔֜u D'vtN=&(G(4yK˒cTzR:Q"th4D^rSKSm \P07;shq des5JA(TٹD_YIY,p %/ow~`c4/G1LRn}SPfg5ćT&Tu"|6l6m01')*_#r$+Hj &5C{s5goF8tU~:)o>_P7CIJ?b3w5\Tzf6tW9t0|3OSloMDZγ8Vub-TmEbdhCCN@WWΝKƄB{gkt5r<?SW%i4f :r3jˑx6ѵ:r-kq3$}ģ'7i2PwAxW K0UmCS9_IKHcg'՚zn*vcX;Zy>J~Un7gkFZD_=W`o}ZAx6)9vOŐ=_AjMMFr:6`jafVf4М*l7"%9a'CN.9kJ{|cM_ImHBf5IN$Z4.046ħ]mR =̾wR߃\݅LwhyD%S!ǃڰ`ᩡ!9z"-jC}2PgCWLܶxVM&m|K;KVMXµr3 HOe{n Ʀl7B^Ҟ8y9yFb5yyjĥ:oeF.OfJ~?2DZ8y.jY/g6& .HzbUVeq bu#R3<@Bwo@pll|<|@ЭaR3IFƀ7cI.y! GHrl[_`dl~:MYѵ8_bٰV~ؠ^l߾,K4zsz"+@f5ZW e}ЯGi86mD&M9r$! !3Cc#ƬMz S*X / O.n1S-;L/ x#oL:LðvҭhBSm5Ҡ o:%U{fsiyrr\C#C~ ;218P B-K;8d`s:s>8z>NXNǭBĹp9Ʀ^늛o%nW(TCsi͌\5.y k'bn>]u)7ʤĩ)PUV֭\ڜK{kG,/G|X+ Z_0ϊ}4|Rt"v%12^Kyz5~vdl wϵ\\߾vUV#=) [ `x!>k-.8l/{k\[?3f$lu)Xl~l/fLeȢQ?}}~z9‘#G:u*cԨQn' IkjI&T^=~}RW;c> }]hcScjޗn  _Ĉg:y _a5 Q3evn;_F V:_{7;LHK&.(ëxmBzdA310Ɇ*Un?zK IOb5g0ڝp7cqPo)X9XgCh7sZB'|IiiiX{ooo-[x rss1b6;QRɲ2179;2t#l̬͙}f,IlRBO̔FɆ|5\y6mIOJǧznaWɞ>ǴcAyT[ݑ4ЌE}ڜa?kG:,>3+sjH? Wq(?+-~X9Xt{$;3~Yᵮ,|s 67^֠nφ,>K{k^0l]*hGk #99lK|Mݞ146&qIS1PL^KM7{iPv=SK3jĭЛhQΨڜ}ыMn? _}G,*XQ K;K^ʇ/ Q[XS̬V/"_Tpշ2#/'#?dɰ{ k'6WθqX`UTO>gϞwy_zz:nݺXhA_"vuJMg?}"щ7h#;pk7=IN;Xy? Eة,fP?]Ԝ0vm?1LJFEl^ࢢŒzz$'R] vESX<իcҤI8rsg}Ds $|=22}"oƲF+hLٚiSk婑Ù'9 mw(D*35f֮G!< 7TX7xSSS,Y¨Q8r䈞#ш}?I&;QԵGT }!9DFR .d CSBnI2XT/~+WfVfұTܺJ#C#SN͍q1`6lѣ?ʕ+tؑ9s0`}#ʠ K &>~B_gxΠdv:9w8)ĖMEECFFFo;Rŋ㉕AzĴi]vxzz>(%>f۶mXZZؼ-+$^G^,l#m~'e6ʷ?vo}S 'n뉛;fiM<Fí8n$ ]\2'8xbbbիÇgܸqGRRRӧڵcƌG<\㏈ \ILXz(I9I3d愻ѣR/LRTb)T={w8BQn$!3###.\?;w&!!A!ٳgڵ+ ,DJ!$SBQF̘1cҶm[BBBx 8pfZjpܑ2?!(c˄ Xr%w8 i&~m6l؀BrI)!(.\/ȼyҥO˗pB6n܈Br !x|}}پ};zƍ=Z!'g}Ɩ-[رc666G!5B2,%%ӠA>}#1FÌ3~:VL! !D' ( ?$::aÆD9ȑ#IJJbڵH !D)dJ!8###{|||ҥ I#www[ OB)Brdʕ|lذwwt< T"%e ,,bNHHW^ L8\A!nL !D9{n&Nի[nRK-2Q6@ `^獈gϞL>مB !DڵkC?pDΝcɒ%l߾M61a6mڄBQRBLNpqq /v-;$q;C^^ӧO'::ŋ}vB;0h4}![DggE/Bh(@*(mܹ~jp15j}ٙ3gH"%e !SʱR%xTTHhЭt 5k*=Pn.t wnU,MǏ#ޯk֬Y:ЩS'lBnn#BdJ!D<Μ@HH4zFMf5DDyˑX'O2gvv)TȚ)!+- ɓSǫWwUk4/CH}ܩCTlۦf,-aChF:5??ؾ]%o=z#?Pt)xݿko_k8zT͘9:B]3g|nkkСC7nk~BQ2L !(]*q:srr\J+V+WǍdA\y>ƌ/8Ǽy*!uK%_5/[,H&LEԱ*o AjUyF%..omۖ7@oqhذ!ƍcXYY=k !(ҀB!R@ Q|<1o_hZ%4*S\ ^x[ >L%?&&_V/l*2vvc{@@_}@LJ / |kWw #__Zټy: (B}fJ!D{ UN׹j0py{$%[.kkU~WLXHЪUA"tN0lܨdL)PI22=t]$BrHB<t)ڥڊ*2ޯ}M?T5dgrZ3%>f]''`ֶ-l`yyB<L !x U}Ӧ{'S['`nUcll<ssQ%jEYZ7%23n|!xjH2%Qm猌TDNVIҘ1*عS*=VɺVݺp.U~~j4 !x*Ț)!+5UGxQ%5vuHYY!ĪS'XN%//D[7%KT~ҝ)mUW`Pz9;\0>֮-ؗGUVQEhjf񠉜B$SB!J)x{v澾`kfy~P]Mnnsgk|S,|[[Dj.nGJW47u0|X5HNVKUK[$ х)H[*8EF=l5TJ*6nP%+kTeo_.H !($B#OdJ!/)B!BdJ!B!J@)!B!(IB!$B!BdJ!B!J@)!B!(IB!$B!BdJ!B!J@)!B!(IB!$B!BdJ!b} wB!JX!;pw O9sddS!+F#B!Bd0L!B!J@)!B!(IB!$B!BdJ!B!J@)!B!(IB!$B!BdJ!B!J@)!B!(IB!$B!BdJ!B!J@)!B!(IB!$B!BdJ!B!J@)!B!(IB!$B!B)LX 0IENDB`DefaultAppLifeCycleBindings.svg000066400000000000000000000770211174773561500352140ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/jetty/deploy/doc-files image/svg+xml G incoming_app command_deploy state_deployed Deploying Undeployed Undeploying Incoming WebApp Deployed Default App LifeCycle Bindings Starting Stopping Started StandardUndeployer Removes ContextsRemoves HandlersFrees Up Resources StandardStopper Disables Incoming Requests StandardStarter Allows Incoming Requests StandardDeployer Allocates ResourcesCreates ContextsCreates / Adds Handlers jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager.png000066400000000000000000000631661174773561500334150ustar00rootroot00000000000000PNG  IHDR{a1sBIT|d pHYs''MTtEXtSoftwarewww.inkscape.org< IDATxwX{bAX6,iS)&Dh]{#Vl@R0`n5<>gΜf9sFV!Z@G!$-!ZCB!IK!֐%Bki:!INt?;}f(De$IK tϿģ=q$''333̞8rMϟ;L)B֠ApvvsssLMM^:1{1g>3;LMM+Fǎر#/^t8BQ}۷hyݻwILL`ĉ;wDz_|ׄPNzѣG  iӦ̝;We 2vXڴiC>|8qqqҫW/BCC}ϼy W^`ԩ2uTϟO ܹs3l07n'|BQQҎZfܹ???t֭[>cǎG^^֭+Ӟ ?#))) 25kpU222V~~> "99=zp'55իWмys$L2 7n̐!CrM~mbcckkkeFzz:{:~8)))L>J}Y ϰ!33S9Ç( ח֭믿\___ny<<)_wtO~FXBTjO4ﯔ%%%)fj׮?[l@GGGXi*`l+W={ssseHѣJ*-kѢ7|CVVTJ7.s]pE$cnn^JϣPe[iۥ]tt$i=_;!m˔:j^>G sw<{'f&ry:Pgpg:NYX wi7qc/DE{줕N||>>Hqa!j> HGWJ5O8S8l6DaJQA>I'ڵ5j%׈ڴi6055AJ;EGGLqq1}ڵPK͚5hժ 6ѣԯ_+W)7n...ʶ҄TDbbbS^=T*J jԨm8w\vJAWWWAi]]] i޼r]L<T*zF=}bIin. GKѯfNT승DLmȍûQw,\Vc:Ñ4>KCꓛJqQ!gaԶ_Ia^$qO@teP GSOv2ԧ OӲdaoo=UVUfa۶m,^#Gt=iիW%K0k,rssԩ2'x$DČz}<Rp|tVMc^w٘I4}sv~0KWP*mB6lHÆ v}}}}F#4iԩS144O?-Wnbb?=7oEOOܬcǖy]NԩSlVTӇ>}<صkצve ,WW!#`lewΟ#+[OƳU2u-ݪ1bO1'}& GCtcF\ޱ]j>z A}3߻ ߰_!;6p*[rez^/ЊKDzʥM@=ݺZxj*͂'sĠôihݺS?!_q~J[6zYmi<[gXկ~}_ޙ_oޡ'7,&ly.ϖ(., fv}2F/~֝$7klU򳡹%60$/3oGHZjZY9gOfͰy|!* e<{ zyAȘLlՅ}G5K|`SJWچ|{6).*DGWOɯ1 GOU'( )ǎS&;dggӡCeɓ'gT*2"ٳڮH&"";;;Fp3Jwj)L>!;y9FV87@C/q4e߹?Q\X7ahi;:z׬ρo.h6f;J^VHv|!y!*H]%KJrr2zqƱj*RSSIMMSO?eʔ)@}`Ba?R00J6;bY2: QTvmU:yi܎9N+8nH31Vqez}ɧt &v4}c"%Tkӝ2qoWMxgH>`bJ ޥ'3k+ndeC6_CڃCeѢESPP3x8y$PPP>YYYpu6nիWϏ-ZPn]={p<==W+V 77(3鲲Xf .\ ==UҢE 100Pںy& IIItޝ"=c"""p  (YΝ;ѽ{w"##| B;GM㔥ZD3g($ZnMxx8|u]^*##~ӕJ,ӷo20k,.^ȝ;wޘJBRdey777̔֠ApppPeee% Bه[Ξ=/2 bҒ FFFڲj*GoħV~:>>>* w-sWpttTnTB* J*L,Xnݺ>sBCCٶm5jԠo߾riv +)1:|777lmmٳgAAA̛7[[[zmvΝ+Y1WY}נAt x"/^ʊ@ZlY&}Gll2Y̯ҵ ֭2Dhee͛7 חK.)Ê])=WJ&] !Ŀ?i"ׯСCiܸ17oJ>|K@uqqeXtEh???eB={6 ] >+11d]ƴipww֖{)3ydZqq1UV+s/}$e1mll8t;KMM%11wwwwfnnL0)=ի++ŗ&ҞBi~Hs-SvoooJ櫖͚521!<ܫcҪR ݛeHttttݝ-Z(uJ<$,,^zѭ[7y>>jwqU8p -[E=Ol?+,6{rAh׮ J82OGG`t)Y-%%EYYf@ɚ۶mc\xʻᆱ^7]iJVpvv&** YJ!?^x{{SF Ο?ϤIXt)\t KKKM(6My/..FD)dʻ3boe߾}ersscݺuӡ=gή^j{,窧uA۷VZt}}}M&Fdggckk˃kBh*i !Zv-}ȑ#$!v t !EQTTDxxC⩐%sҥK@ٛfxN(϶KII)scJϩp%iݾ}7j8"!$-!SvBGG 6 xeddA5prr"66{,S߅Vϡm۶ƞ={055%2223BI9TPP#G011֖(nܸȄx22<(sn,YDaTHOK!֐%BkH9'DB!IK!֐%sNDB!IK!֐%sNDB!IK!֐%BkH9'״DB4 0WQY9>~ZΌ}=ҳrl]eHtutx`G+mWwu ZJ]~|owa/dֺ}[3vPG68͚'a Am˃>I/@j]l?'úr>> ;+3 7G S]1w~dXg֋`ێ`Mz޴nP;)N^g᜼tAuY @VN,s7У?Fxk=8I):XSV3mnFڞXU{7K A w}2Q16x6:3c$R3{'/]`s`ȠA Ԅ[yGԘ~>eڛ}/(W{ȷ*]e w!~)S8v![4n;!nomLjy7iv!C;7eXM#r1{}#5ВؓRr$Zfj8z.~^ݯ=!-?7UkIMϦghݠ+v#S78{&~^U]M_3cCR152@_7e{Pj$IS^Wǝ]Q+P2 |UW^7[M֦XMJFbcijL@-r璐°.MRboֽ l771$#ÉB<IZBT%ۏ$oUn>ȷ (Ɲ{dfbgi΃| xNO"R?#}]g;+N%* D05[z,Ex>hcdpN68Z[?}/J $䚖M?s,~".]Og?n}ZZL`E[y7mG$Zy:R,vnʼ_i6m⭇9v!,qT#؟9|fnf5{Oc>BTdkAʔ7S+|dp -eݗlk @]/W\W`T7ڒ a_fh{Tm=Tvu}1uiͻ |!N6|0_T?]>}><ԤP|GONV՚BJN,\x~..]LxX4NoiLZB4xF䫏B!ÃBhАMt>'[K#r%Y6=]:xn󴄨@8::T*_/uEVX~PD%'=-!*Ж-[(,,ĉE$-!*Pxx8EEE,YDӡ\%D`߾}iΪ IDAT D$-!*ș3gHOO 55{i8"!$-!*ȲeHIIl޼Y $i QAv؁JА.]鐄zz@Qff&4hЀUr9N>ZB<i Qoߎ ~8uꔦCBI)?~x G&vA!*!Cʕ9::ҫW/ D#CzZB!$-!ZCB!IK!֐%BkHB5$i !Bh IZB!$-!4(33Jǎٺu+&Lm+!*Р5kpB/^Lff&`dd&&&$$$Ǖ+Wx뭷筷{{{Hg$DŒ%nݚ%KOVشiXXX ޽'Nge#Fйsgjժ AAAXXXhlx0///ƏϬY(7|aÆ1sL233r'''tuu)..~A !rMK Z`ɉ+V0tP͙={6;w`޽DEE= SSSrss;w.!!!J2y$IK 4h$==YDvZN:)WfϞ=曌1W_}{{{M6qԩ5{a``CH CCCڴiCϞ=' ;;;LLLڵ+4h(R|!AAAXYY=s]v%//~Sp-}ϟϮ]m̘1x$i !*777978v8.]JVV_ff& .իJYvv6ќ>}l8w/&&&bCDD6l넕$-!DӪU+"""qnnn޽{iݺ5gΜ9X[[ӣG%̙3F$իWӣGzUؿ?Ғ/͛7SXXHhh(ǏP\$i aDGGsEMRi}hѢDEEE`` ˖-ښ3gPTTÇ۷/]taر_(W^d]v%$$'flmm3f Fڵk<LB4hm۶%==mҭ[7zɺu4899Ʈ]:u*̜9{{{ 022"$$sss뇃Pall˗IHHW^JU666V+U\\}a~'j֬ݻ;w.7oV&i3vXGGG*B 2O]pAݨQ#aSʃޱc:66V)=zzꌌ u'O蟍 .Ǐ_,11Q}Yɓ'wU^gdd׮]>|H}uտ:%%EVէNR*O<^hz-[o޼lkٲ:::Z} <[$%rQ"##o9qD/^}ۓ@_~رg~R UTQ^,,,ٳͭ/={===:uT{*!IK *,,DOO`tuu;w.@k)dggcjjJjjA~o__g>btɓ'qrrth%И~Lj#Xx1CKTb<-!`ooυ PT3tPM%*1i !4f͚jlmmiҤ#$-!F 2###\]]ӓ $i !4]vؠR t8%(lmm155gϞGTrתU+tttpqqt({q~1D?P6o7/BQS]AYMQ +*RsMG!AV,_\D8B[7k /KQ't]Ut%tt MG!ABIXR%BkHB5$i !Z.\OԜ/Zu?S\T\:íG;ֱ",M$nnK!ēъq2Nzbv|0\_Kcځ6iRjInFc%i"_yi ^ƫ& Š38S#PEob]c[T*馴wzLT7q.lXo څ`U>Sw6|i8 -@&˷ά32*qp4ys"Ʀܽx+撛q{TĞ%!L읈ۺڽԦ];=vVfEVVNJ>dSenX{Ti]j;6^5tWPabcO*=wSbYXnAm! Ⱦ[Ey "?+$uq1jSohѢ#9iwY@_I:y}cSngNTva_#3> ~!YorS} z}<} &polYDžSãEǒT*~}-oLQPN,~?Z鿽 )P ;N]S}/@F IwY0~/~Dq4QU!>37abTo,k n:{:PPXG675'DѺu/4RfdmG^߿ToĬk㖜]5>>z V!Ejzp7>?IXzj&ڛ^k?'71W t{;o`jl惧Y8?}41VȪLjq!V'^Idpf|2;* kv3cnsh)gݾz1UӑԨK~FVIWt'#1W惧 ŕ{N+INI+#$4vG{,]Z|:27G>ũK02ԧwƼѷ=V&l?Ø++`Hf'CU|\ͯa`Ǧ|<;::*߂.'/qlbo]Aj&h𠩝.Kgs%yT*T)uPi÷\;kQTxƝ~ L0sr-{v>L4C]g.%׿~;'˶*G#*Vf8uݢϸL~ !ez?b k^_և!ROlbB2Dzl];ben9+wE)uE'0mN??`39wwo.~YkW9 xedd?`}p!f;Uf}0J9>ߪJ,C4cC4/s^Nj4 k}=u sJ&Bfd3uv:7K̲QTZG]=9q~;NJz}á݈^2B=NN^o}294Cvx͇N$IcҢMъMdkXDuI˧Ss|!/3-+)}JG\ޱ̛ \ #%,9w71çS;ǍNߗX'|C䦧~-#3> 3*xwCql]Eნ?mϷۋ\ݳUA^%f<.\Oa^.I׸PK<[Vf&d_PGU #N^ wNU{jksSzjHUygckkyү}v$Wzaކ}'+; VwZ{ǝ:^YѶQ-vFJ: sWoҿ[Qru`x2{Kewl:x;i A~eWwuEz1l-3 071bhe׃/0snT}'{.V!o_j5[ѭE}J%)%}@m:7x~hԒxx–wjzF8 Tf|*~ †p:L M6C}m43 !Y%?2sv ttY ڎ8Ĭ]CQMPk@pJ1v_jJy6PԢ?y vv{dk;j}o Wl)M|ԩ)::%[=]<]~Drm޾IM{05=\*ypN`(w췡Bꮎϖf^/Jٛ}6tMJ2GfƆnX%mze]Q|p#:4˕Cg.z1 >am[ CC ~6eb2m[s<N*u>A_^>iext/ Qʬ=kuGwo2e Mao)KFYgjtG.t]?fYrG{ U\6ǥaG!*Bn~_-BXԨsWruR),*؅x6weZ)WFU'"N^GoIDRrZ_D۷+U4{dĈܼ0/mx l>3Xnۜu{0:5)bմnX/!$>UF)K)jyVHJ !-RJdca9Я}#VˢxTu jWP6ᩴʦѽ|~eH,͌IVaZ*VYϡ_@ v, P_q`HNn}6.ww^Ȼ?t;ɞ)ۇum[1yRz G浯02ЧSJj]>O/CԦQM>¿̶`$l`=z1 soY0Iw\k^ϛ>-v,N(IF_z.s%[K3uj-~ ao%Xƞ#ޥZn=6Ls(@߸<J42?y(zR|+WTTVu~oX{tu0cX$steжq-jyp?'|l=|3cCe*;fԭFjU8x&Jŷo/L | /u`cQ5θ:(۫UqZ{l,. <G^AUf[YWUO_O _Jwq{kVw{{ר'vV񢠰ܴ.}4#NPboLPȀ:^XP]@_O z`cn k1zɸ]05;q5_ԄNMbma *vwRtJ'kCTyx,ȒAc˰?s *#5kpw"3߯ɶg C +J=<(De_W }sW?n$<ǐ y[@*\cxIOҒBh IZB!$-!ZCB!IK!֐%Bk}ZUEoY!/OglHϯ'%MG!*3kwi(? ÃB!$-!ZCB!IK!֐%BkHB5$i +,.WVPC*^QBMX<$i Q X|ZkO0y׍r~pXy}V~8MWh7 mg_r#=q7^y#IZBT8p% ۮ?NM,Wnadž?N&ώK6m&@OWŗ]=}q-S +bQ~:z;3@;/573?v,.ڻbiۯӹ K:Ү=V~Q1;/Ӯ5s&L*LH˔jT;̾tlLy Lx{9ujJ{U/Rs6MݶʶݱcpcGհp2.gP\&ߞw^.G$1=7 '~ſ@lF=C-e۝|:Adzi Jc bKԫbFC73-ȱr @SO ifFh][tT*Fe8RјV?FzEjƥ3$\*ߞTWp(>d-HOK ZcmNjd5bcR_/+9}1cM>>KiteƎ prJ.$p@ul?SlLdJV'dQқ;ɲwxEj\~+#C=:1P2yr&)kǭ|~EFJym̌L} k>@-'\?9ʼ>gHtM<,Xq.U XvpUU*j'>y9؝ǎ%:9C-'S, Uq~>&X̙G3%3, ]WRrq27P֟ÑRVޘ;Y{ _%D9ŵ{yy%3j9ӑ[JҺOJvvKVzVP29y5߶`ge, (VzXSO D eꒄZֈf8ye'pl?.ܺORFr=77%K>9!}r!*#Ё9aʟCjr%7Ut5ne332"?4#8+:u mi 99w+moLV o[PL e)!՘7o&r=-iy,<Ī唬$_BhpΞ4mߖٵ:Vb|)AzrI/հBδjjp#N`LPp? u`p^Zu-85M?7b.h[n۷UZe r9w0~m9k[۸_ʊ 101m !ĝhpgZ5IKJ%ȯ[ԊqK),qøq;S']d?X0a$r%EELו +?&35HN=:qܜ{*L#f(#f`dYy*ťe:X%euYzS^Q#h?Ҳ8@nANx43FR2ٕQ?oKسFMl&/|mۓSJr"nC<7MzV=Ц/>Ĕ6 <׳&@vzK~F_ϕ;ݵ8Jr)Ĥ7n_,\O#pO//C3{~5MAGoUMR3s1was~Bm#OFV^*T975 ȐXJɞOj]cQ?o'61|u ag> es^ O7Veբ۽lJqlF60w̜+ahdDsҶs*uiO+--!ly]8PZ\̚ۏL7^-h32ƀ+w`hfFf,KEż:ORz6}+7nsU 45Rk?/P9B~"Z{q.>g毤i&醥 .mv%bͼ:hȔ#3vcljUص[|CCAjQTX@IQ!&f3=7*MolgϕQX4B73obg4g^)L0#UJ)*dJRZ))ȣR4{ ܬ-077¢sss vsbhvQǿ3鋿Vmu#8Ck|,9'`om'zV*ϋZ3~l߂]xu2 Eд ?ʞrn: 7psezLy+1_g>X2 WX_X-վ܋ ɼ|#z :qYX3kL?BńH[cajaѸ7*_^ߵU|e([\'ƦdmZ kٳv Gu o丛}ޝ:Ʊ׮ģ_ƫ%=f s^+wRƉKxm8 +mSEyyrssIJJiz^^eeulZYݏt W3sq<ϻp9b\`C|D:k O~$lJ8Hi[)j |kbtnCf.|NN\rF-XUogh<ơ8.&$sVٷ]JbC|$ K.OhM#sLbjV"!9VR'FDU>Ld\"O_ɐGۢRx59X~Dİk m_IH*ŗ7O{BQ|j:I#:y4 -ㆱ042"WH>: ҆>-(*(ށxsοHO|5k̒ZcUc\YZ-U]^^UN/((@q*hԐiy>̍XkL{lo] JʨbQs-=e@^߷9l$Cϛ4ϿU 슯;94sagBށ{Tw\Z*Yy.°^x8Fy}7;E1w69` !-rf%;Ħ9tfs40oPk}\ղ5bR 0:Rwbq?4ٛMysw&}lP'wgnӮ[/6]L&+-[GJ=5J6LZR"V1pl՚O_ )[?z_Z>(T* N}U|]:@ay?f5hלYctSτ`myӲ.7zװidNfeajfkۼJ/'#'wC|{:X{elz^^mnޟ|Ҳ*MI;S硪㛝WV nM.߲2sT_/2r (.)khOMӊ7#cMTtl^rO̘1qH7FadMn;ٰ7"7fmcZ{:*,͌ D JEaBE?S'zV9IKV`UiFفc^bt҅8VZ_"""0445-J}h⣪jonۜ[me,5t{x}vSk;&촻F 4օ["o܃aum}\9p&ɋS7W)+bnC~an|R: ;+Kw }ճo}08$<ͺ)4#mTYLtt4۷oСCBU4uCzCǧpv a?H<ŒTLlȽ/[ZUqaz}h]޿/v1=EB}7Hh=D M$<@Zt$v;fd8mFS[tJ q W!X:cPOOO cǎriܸ1фNӦMo|lu=%MWӺ=zs4:爫:53&Mq'%#<p@7i1`$/G[QAWik?8'ώCy[hTzV^}8=#sK| ǧp*H<o;#uX0 y9%Ϩ:yP_uyTh "((8ƍGQY vE`` cǎeʼE@u0=+X5m' N r 2RJŹc7.fcX_:UC9$H9?~߈ 6⩯32l.28]}hqH>}_"|7nq#kbo%Fcwoj!OT_RoU*Z)Zc[`:ZX;I L]?/wBCC֭}W\EC]BNNgٲe4j ,-uIVTTP\\̇~+:&8 TacK+l}Zu1طl?[i7n:kIqB_}h/14cw> & Z'~h₍/V:G֧5r:Mk`Oz߉imGM{ڍݛ-Lڥ -LpmG ]fӦM?Ғҷo_B۫mQp|FNȻvkm;:= -qݙ6mӦM#33-[0i$f4ir! 8::ָ\v1nkPOnZ@w|8LNgVMEY)jCd_ڎ.Fqnܼ8i퍲Z2bZ7azYI'y>o}_6f<{ ԜV;!ns 0j9r_|.\LJCtGߵn`; .̆ZviӤٳBuUँ106a[i h1`%y7h_BZK:|Llh;|?N. !Wb}+_5&xOS*/F.e5CKwUw'lwڍStt4?#Ύ|W ;rG8 s4:p *On%uTn.QP}Ͼ6'Q|||1c)))τV aРAFp0(((`̜9lvJhh([)--5bԦSysLZ`ffСC:t(߿?K.Ghh(:tjr02V4ݸ:ťe?C`v_&Q v"$зEJf.>nsG,[cmm5fff8::NfrT xQVcQ}uݓ?1h4tޝuϜDFFi&-Z C gϞ: +cn><\t@Nk>>bMe^u qU}$'_#+*|Ԛ`bdHAQ f,d'.w(~ow`Jb׏#G:Z![vKxC~xZ-.]ԩS:u ___edd;'Ofʔ)T*!O ?/~Ʒ'ckeE_г} VnKZVve_RZa6aGs"_ }NtoΩ J1}~+1_g>X2 1he^a1cQtwW]LHW1MfԘYc,&ȸD| Sc}͊Tjj*jOOOڵkرc9<;v젴MԩSo\=(}xUZj8ȐJkԨ#F`D >;_n!15- Rg\r_Jrf;gAy.'_Fr-[rgez2???Ͳ~Epbk*mLl"eD_M\|~3c#zM]̀mh̅ɉ WQRVΨ 훝8ńd_WuM+*eϹKIzޜDAq ]idUILY$$g2rJ:\tg&1Wv,;2q<=%CmJw`9|f/JKK#""SNq 111 }u ƆYf1mڴ{royʩkrj^o]8p&6\8pF?ofۉ ~WmqYN]™ث`jlHĐ!CpppۤRn+ uΈIh 7iey_<}+Et 9+~ޚϷ쿣՗/KJ9ʺ[ױYuIDATi_Kߎ1w&T*OJx:ru9' fϘ8#02РR\TN]':rkӽ] 7uRzcu0,X`A}WBrW1hVWmo^/ (*)Ҍ°^wl厕)#v7$w ;+ rlťe,0{k =ߥR\}X[x`O';\͟B:yboMfN#;VE9Q-V+*hjJhքw'?cu?UFGםZ7 -n;ٰ7"7fmcZ{:*,͌ D JEaBE?S'V&}D9meCxW'FgPg_:>Wʏ2ҶvPUv+4skʁ3L^фJAIh4*,3_VϾCu+'x3{F.^I̘?K}Wޥd0oHJ֊5sE4 ZB<,Leɋ]N'>UxDT!=ZB!C.KaQߵ 2jN^ T3EP_5u@BK<\R.ܢP@E. !P -!!%B1$B(BŐBZB!C ;[w-ăĪk jIBK4\V.!D!B(BŐBZB!CBK!bHh !P Vw%+yPQ^ߵ JM ZB!C. !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBZB!CBK!bHh !P -!!%B1$B(BŐBlnbTIENDB`jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager.svg000066400000000000000000000514311174773561500334200ustar00rootroot00000000000000 image/svg+xml G incoming_app command_deploy state_deployed Deployment Management DeploymentManager AppProvider File System Jetty Server Handler StartStop WebApp AppLifeCycle Binding Binding Binding Binding WebApp DeploymentManager_Roles.png000066400000000000000000000526061174773561500344770ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/javadoc/org/eclipse/jetty/deploy/doc-filesPNG  IHDRD~sBIT|d pHYs''MTtEXtSoftwarewww.inkscape.org< IDATxgxڀlz${MD@DErQ!t*zIH#޳ɖ$,I [׵W63oymOj5"""H"" QDDADQDDADQDDADQDDADQDDʑw Q(I"uF d8`#RAwEP@$ @*Ji"FB525~8=-HSQL 0 DEi}5E`q `O>C!ZcK<#^YARBaa(&4vB 3hhcL. "QF;b,,LVɄAE %(^Ď`,|C If%dh iim. \6̘ŊTAqcQK5:FDA1jRB.ZфAN* ,ALI/PEϯ()2Fq""uBVPBQ3XTȉ76F{DDtBx~5g0 n(' c0I&7BDP 'a0IYi05 mϐE һQެ>rlEda<W~AE)lӫJY9/''ޒ\z`.@y&s2rh9㖖 l=ZࢢlW!KzU֘ٺjJlD6CSEns2~q7/[&܁qdN6؂N}5oj]7/:?3g֖&ANf<.H鬛|,W!;~KQj̹ϓx3&mInhD`+WNӜI|>8bO|Teno]wo_DsfcnDaRWEAko(VFOmͰ: C}T^=Te˫?} s{>ѯ~Gы dAcHK*Z.(o}ُU&sHroRgm#cէymNo\};KI!&,˘tcraP:WҘɍ itҼGOԷREXb`I]yUh+kǑYJ6IeQ*rR(%S<:MHwPW@PUMA^)NR H$-,*TՇV2D=?蔑uNSϠ O5fJ5ׄk/)VZDfjZwoj\WʍL|*arxeJMVjkAGz:97B{jق7bje6vOĥSɜ*[;Z1l|jiKL첆Gm5 NuE2Q:D|jRbՂdsx ѹxk:Ȣ94,,$p 1ȟ\8XOxU]Wg0.^6zU2)-B a'/DKle1rkRqvf䤖_c}-]f_'Z]|;[[I:yL3jikUZx.uӻ~ҫdt}^u\ZյE't[l0.$mPN-4ƊNI<.=""F?:X# H90#N \ WD"mQAk }q +0 \Nf?;~NtK{POdP={ CA^)}p}}Ea0JJJJj 5s)׌B %{$@e#hܙKϑ?cj͗\JƻvR_JFJM6,̟'|FJ!62]TJ&).;K<キVC\d6^~# ϫN J^I[2\=[RN= *q 7e'q9܊GVYͰF*Ц'-1ᣓ`Z*{(^`q ׌A+4]WI}#N,$ۗT5GwrbOGgI/Ѫr;rR\]Y{ 冢 @~N5x yue&Y6IqmziK$œ\۸1l|s\m,ap=0Ѐj坤%hYcfhJJDeVTAߑM { “Ru!Ӗym"G(Mڂq϶.pDLN<|퉸*y5 'W,)*(NWκuH?#]|43x" Jͦ5{n^v+ljXi@7K˯z|^zZڊ&R hs>{xsB^MT8h:o9љ 隭Ѳ;Oљ?D^o *Cۺѹ/N%T4 ӾĴw9} DVk(?ab5)#,:xOBtJgf~C= ~XQ} A|M 4oƯ3rRjy&=$ ͆U&ieJZdǣ5jS;22S8?؈lܼxtZ[l]-Ei":W֘J/&#&AN;"-16+k -wT$).R>vuq;MxJ|z T^DMyEA54kq>YEDL=0NjGN""FG&_oa/F]qeJbV+}. *}w)>LD"R3</OZx0 g^BOq R/8/1JYFx0W8{@kεa/q19$fo^v%)l&uED ővWPA.Hf=*JXDNHb4 XCL@?zI3U"2YXTTIr9'Td PdCWB. OŽfflP("BPم9dsð{BOݙ)7aJ)Na%@l9Nujn$X`G36X[MjP5 䤢 Rqtx םgnV)8 Qc#x!a j kj*oVOZPCÓu1q ^@XXrӧOwSDL( :pԩSS C)))E!vRR # C rK nP)++^ƍtޝn "!M6i#Fll$rL3(P+U;RKBV9ư/Ȭ ,/ָPEUˈcPP) ;r͎*`~h# H!%+Jaq GCRU{=<&D5P.aAa&dT_K`ɜ7d ]`Prv{R|IaS{4ՎNJ_Pp:+)8IzV`u&% ʊʪ0dDAYɽ„~4e ɐ^4/܈_"2. +՜f?LyK>~M1/j?6).ވb mNM`̌OuC-^Ôwą >n;aLW6>fPZ+?s.s΍x0:e6u͋fǑtx<͉ Y׿<}Oˁӗ1^ :mOsmo\ p1,RʪjT+5C{uf3eCJ*k[! aϽOLB2k(7Z?]ImxB*}tOk^<y)Ckdѳ=q$J܁?&9=13wqj0h%{QT,gŦ<=n(VжESy?ZуY|wOչ?w=V}~:=;7HL :!OWgKHoੱCe#^ ,ֺy]@?66ogi_b^qX[Y̑sW5PuHաU0W#nѫc^e ff`gpr!͚bme n.0CEPVdȴ4ǮEƒNO݂W#'ܛxȼeb܌ʼnşAvPJ"cxƓGƵXR3Ifh/D =zil?|&ӕf#e޼xZ6ac#66:ScX ~:]D.mKEWy{m+5o0^ktoߊtyBIHܮXEWl4vr]Tz ݐ@i>{s67 +ww]Z9KJg{TjIiZ5V2-&գ_)luOC¡5mޔsĕXj#3 ]Nۜ\8l_jNjKSZ`㜽R]br x N/-YŰ(^^sn`pFr i&Qq4zirkaCXeqpMN0~x_l0?-^CBJ:e "boc)1y@_dT*5FCXt<pW+c`F놼:}3e锼&: C-F |0q.ӳC>}h2 ¹—'&)-L[5x:zK KG߯b߻bԀZC(4^HqEd C`\*/Nz\&͚%_5݅W11h/b5LxSJZG[P+ɣES?~ul_Z ڵykUiݼcd@z>ͪw2spuFT͊9x{s9vfN(VzNF)(ɯS:|9n=}ݿh6s܂BY;P$F֒mH7aPY}y+U_UiB{k N_̕p *&Vms&KZ"ɫBwn`aS;YqO7Vmo3w %=+@6"D RNՃՈ[zM>a6W݄Af0 ݅u ?8׎ Av^!.Inr)NMvj_Q/}Ȟ㡤dd '.`\e妽c wN] `t{̹Z N_μ2^G͹љsk! 8d{erkL`Cxƽ5疬7>sdK Vnd•,Z~Om]^֏[; o<V4Y0¢Y0,āiOFv.!z*|]B "^zwާ3?O}9c}lYU[;W;P@Zfe 2E%r2spqr%U<' ; v+K@?jJ%}}nl/[S0`>SGR29zTA9Y/+7eޛIZs6si4 ɞ㡜Flb*+7a>("cm6`3_RPQ; o];kT!mظ-'n<9fYtmBs]@]3i~^/?=7Isrݙtgڷ Ǐ^荋c K+D'$¤QZ:o܈l^4/~̜<ޝ>a+U_4_IAQ ޜFfB_=GIL0ceAͷ1pZMFP^j\s~]MVg+8 8q&̻CW_C<04lY·0c7|CEfM =Y뵂=75r3߾r~t[8z m8s3\һ uA A=/ȬiHSk v /!?˙Gٱiٱzi&" <"li^2k»`Z#$-Ł@"Axd_Op7\^BQy`wES?Y^Ĉl#6̸bN6LAFtrCw`%"" "RxQ/ņ bݴ( wd IDAT D7n{;?h$äFH>rckDah,hK=PH۷_{p * (KpXE9s B&bY ;)%m C*ga3έhBnc HAy6Rr87мX;G3aC0^ViAK ipCñnp4^o/ *D Aa&@G.QDt<u! غ@~,00(JbdU< t v$&t͉>[1p{gB*^ӡ/ 6™F-RDmF 7Zq1" bߍZ!DD p}ъ30G 8}ʉ_)e0dBtsVÁo - SKu."bTpt `0$^QEDmP J '~5rr|oeq}YD6Q"k;+ ĉF''à vȻ}qV\!=YH%XZԃiI~]?a(ɇеze՗}aYvbǯ s5)N07[_^? ڎ7L> f+.vΪ2¿WRiv\5 \J 7U!Ә'{p1!6XTeJ5/ysjW锶PdDn$QPJ+o{tkSgr8x2<Ҋ-S8.M'c; 2{k x;dO?<` ,?@''\零T7{cPŖpV p;/-X{62F|)72n~ lY=ktz.p3:t&嗲H,ٛէnsV.vLO'!,˩쾞{3ۅNlf1ǡw Bwa(ʂ:g3 tm{vsJHΕDL^y Q͙7cQÿ|8F*ʊ Vn`3_gO 1/G+t֌w^K{ndP 699Ǘ[#gXM}KijnZBhn6bWkȶB`|A.|wb+9߉SYy2Asfj&ﳽ/ i¾nt&Ŝ4x=8ȴެד.*c.ڂƶbK]RQVjnH}'K ywmˏcY~Bw{+>BSFvQW]&6TŒ!|Z~)[/h`.HǿZ/ӎ'{i|&2[ Uj5_{##Wq`vx9ZQP3+/YX=S xmP ]ޠLŷ#zT&<54YCDE1! WbjWםK"9Wk#-͗tԤ`l0gK]9XxhjAHO*JWk\_.+XQ}e@SeO[y/T\dGк :8qy -* ^3{}fV;pK;|[ciuf2?S۳J)2~P3~|?-On%$f%8zWmTV)7tb.*m'܅eְ5I57{<"BElK)j n宙#\KtbJ?V neq1!B{-4=BK/{M*z{k ؐ]LN ,~ 滪JO#:} O{ҵK=rNQE+HpmZ, CaF"(|rOìTU'[f򸅴r\uzN*hY,j.!A>uOjnyT8XW^S*e*6>5ǪvOe6ffj(icג5s 5O,y}YeՎ~Zڻ綖r+R%gbsBX9TM*x5uosWNFgdS=*N6W{mxyBBY]}feQ|y1t|^u,AR\`i!a3q'w痲dlIRExJO%2'_nS;kuR H/eDgz} @$^DDj ;+ zcH'Iɓk=WM{ KůƌiBJs)VLNq;9mŔ~MVF1y% h C8/GkM}UR =p+u⩞MG^cw ä( 98 DѵI >>V 2%\O'1DK&J]'kj"!* 6= lCje0<ăS1لjQs+.υj0"ăjewC/}<]Dtj`ntlRCuג@&0'h3e 晻VC-?יi.רJ[`ο<rRk}BZ~)J ra6L[ub^OSwLNu{Zsf|'@xnDG~ YHĉ-4$e0nZw,<,8&V_z;l+[Sgz`-CRǙDU؟Cu-]?%OΈϐ[]Ppy% | p@\ĭ"YtNc=_ 394SJ'xQ0cHP6NjKXV?,$b3{#F˴^,O+z|uR.璜W_ 7z2nYRqQn$F:qYٲjb~6lэ>χսp-2)ˍ^*+O&pf&BO+_z~)8`6u>IyM0 lF''.cPʔjyHZ#[9),UReS>D3HE,1RB|v_ I/EPi@X t||ظN.PhTLUFfU;Ħ¬8Lz {zBF:sp|'$QeRզ hYi{`_|~p51ߜHJEC~٪sW\,r|moQOb5C͙Ps\,yb`Pnc ͍jb@o'ӱQU#[p )n7 a`޸콑Nnw!j+_gkr>uwJujك[bgIlf1ۮVK;ueϼr*ϑOO3W>!AX;(+L"~.ft]Ӎ#kymн.l`ەT.Vgu _gkmeZ zuI׹$]Ig eDR\d˫-4sMGoa1"ă٣c!PPqVt T?kh0P% Cֻ͙f#;4ъ}7 ajgy!XJ9}xe@S,-$ʕɕK8 m]hS]`P+wӻZ>JMbN Yex9Yh]QSk1έ=@8ʴVq^VLhGe1'v`J/7Y,軵z^{4.+aX7{K>ۚ1U C7LP†/|Q Wp2:˩V2{d(,mV_n_]DĨ'ݰŠ"DDtoPFX(!L) RÆ s ћ3I'1C&`;jf'"b0ݟ6(yh1`DDICIg\W1CnjZH Fİڸ/ZHqiRĘFRa:+{6U׽2_G,R>/Ds~Xyy4"6{'ԇbHbaJ (ɽw:ذG]:y dz"/2cή0X!L3<?K gLaq ʽnaڷ bsKV(8u){Ƞ^&m/ <& ?~=_}'9{5w'^:VZ/1_WF23Qg3G'BRx4g3op8LtB`og} | wkkkxt{e&S)!~76vbx߮:so~fՂ"=нg(+aYMq@Pz-fLEV#amyˆ6u, tâڶ{|N ^MnP ]O[U La ށZѷpY,߸=+qvgXt8|ܜML\a?N7G CVe-}'ļYӈOFTەl\MN!ixVa,,yF:Z18FLB2|)(*&*LPjfUqYsZxֱ1f0: }D^Aeb)v^ F0S$u & j^J%'. 61#TOiXevftYaa(ʺw#2mȬ/0W'?Lf}` FLfARZ&M /Lz~'ۚYGX̝;wnS :/&F̂B<<͞u{V:;"@ m[Đ^`S<@zwkHK4t-2-P@멕[u׹wޖ'FjD,Gyo SKJe $$܄'tc֚g/s#:N5yV*tn12̺2zJz#+NSҫmKڮQ0R G `y2 3T~]y1V ZfҬy|oڵxE +"&%:92a} $!%UҦYV89ƥhtoY-*.[<6WnRZp i,\ՙa)~ ⓸ޝqs9Tܖ6u@ 5jr wܜ),.I_ȯvWȴ#h, ڼBYY8?\ &V" ;ѷ+>$fj>nӾeFs*Y,{'%20`=e-3٪˹x#[SI *.Q"/e}zCN\΄7>s{#"6[qv1ojf6s~}psv$Ό)ԨuWLj.(JޝBpiov:؟^xW'. !!%&,{2Wg6:Fb3k+~s+zwf !vP-ov2{zVk)5n$X3^,(*Ζ;_XU $yS}8s%Wޠ&>OjMS'܃t΢/ni N:gKL <&A־^ޢmIFTE m#{;_@BךNG߯ɁNmп[{jW@bvXnUyK֐GBtP܂tˣ+.zyegCwMÉML/s%<ŏlɣqur?=q,o uf/\˓Gk8Vq5/J'FsMR¦}'X.."Q=KH 6=Ό?j>itlv!OPH$lS t0S3yX=3H#/ߴ&ڵE뇰f8| &#|Lrֿ[;R)2{}Ilb*~^gǑ!wUl3iR24,-et?5W'츴y >N\AώAx/x9q:} a`Ϥhpbwհ|JH}xjMqqt`}o{U= 6sDmF<a;agc%λع ^2 Р)P_I'B7僗,Ż 6+cOh`_13>g]\Fgs0quv,ނƈ閝 8{@mkǑZ/ w@ipevmBƢAYy_]o|F `8vQK70( uYXSp`>a@DA(L/ jd크â{8޴UT;ǘ +VԆ鄡(Reu""z!T~:baPC>؍9<8 16!u=6j""հk M^F¸EA1Ec>' sъ'!}ъ30^RNd>Fpa'Ajx?I& paHFGTßCÄ!/TPi(u_TrנEDJA(;G0i( }+˄zW9=~Sk֋S럸KPpE6<:dwb6HhP("/h]^G[ *E ( $ BVBI'$wr'C$w'眜33yܹww=E %?d;ش"Uzd|IWPЎ[*r1dkjٺGj8ذ7.hj=iYֶl5"&ZTZ7?q9S#qu:}2zl)Tx[0.Cz܆aNS=nyqxp֗r X9^|=8~*A~mqH=׫Aۚߝ K^䘡QMQ[V͵ƒ]5sșϐ{*B]QuB] ~]$}/^ˀЖۣVw} Jbf`y W[g_I~>…ڞ(+"tl O-.$@`@A 0o/\Ei$%";B&Un?H7sh3KpK) )-V]l-Lz}YE$R|<av-4o7z}-^vlۄvWwD ܿT v”ӯq VJytq̭ F<97Mp*,4~OJfѾ\.NZĦ>e21hh6 *܃YOD,9) a¨`Hlmx)X\"<ؕy:N%ޠPx*Cύ7+q 7=kLf pJIĭ .瑒YD/bx5=˛_3'G^+q*dribH*Us;UXAb9+1,ڧz_#96a ղU(3;}md۾dwUo1}e ޚ 9\jkxӼitƨSڊs{ q襌0H sW^^7w8R3c ow?:ug(יf-zaDh;9Kji#ncи4?ʌ*uϝ= V}ߋP?7)UgIw?9=>`(L ;R/KYs82ndKVdɪ3}R9IWn1_s5'kfOdjeoZ\¦ˡP geoc4~`ܡa@J\/wvgpsA#`:rXa f 9 <VV3x/#L7ȖfYODV+Йh$ȺY^_q\vl|w>>oan@\ vJaxa]v5.Hszocf5DTV鹔ZHo  n&2ZlCяm{9;==Šmy$0(C~Z:q^NvɵFy!xn0bPө.̜ܟu;.pXiY0x`BW`QH握zw|)F $O]q0 Y >:œ4?; 7gocXuuGH.HB4j lqr.)++q;شֶ]GiMc8F[YW`D_|osW@'DI image/svg+xml G incoming_app command_deploy state_deployed Deployment Manager Bind LifeCycle Use LifeCycle App LifeCycle App Provider Manage Provider Process App jetty8-8.1.3/jetty-deploy/src/main/javadoc/overview.html000066400000000000000000000003131174773561500232760ustar00rootroot00000000000000 Jetty DeploymentManager API Overview Short overview of the API. jetty8-8.1.3/jetty-deploy/src/main/resources/000077500000000000000000000000001174773561500211505ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/000077500000000000000000000000001174773561500217375ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/000077500000000000000000000000001174773561500233635ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/000077500000000000000000000000001174773561500245225ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/000077500000000000000000000000001174773561500260165ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/jmx/000077500000000000000000000000001174773561500266145ustar00rootroot00000000000000ContextDeployer-mbean.properties000066400000000000000000000011751174773561500350670ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/jmxContextDeployer: Deployer for runtime deploy/undeploy of webapps contexts: MObject: The ContextHandlerCollection to which the deployer deploys scanInterval: Object: The interval in seconds between scans of the deploy directory configurationDir: Object:RO: The deploy directory setConfigurationDir(java.lang.String):ACTION:Set the deploy directory setConfigurationDir(java.lang.String)[0]:dir:The directory setConfigurationDir(java.io.File):ACTION:Set the deploy directory setConfigurationDir(java.io.File)[0]:file:The directory configurationManager: MObject:Source of property values for property name resolution in deployed config file DeploymentManager-mbean.properties000066400000000000000000000011711174773561500353460ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/jmxDeploymentManager: Deployment Manager nodes:MBean: App LifeCycle Nodes apps:MBean: Deployed Apps contexts:MMBean: Deployed Contexts appProviders:MMBean: Application Providers getApps(java.lang.String):MBean:ACTION: List apps that are located at specified App LifeCycle node getApps(java.lang.String)[0]:nodeName: Name of the App LifeCycle node requestAppGoal(java.lang.String,java.lang.String):ACTION: Request the app to be moved to the specified App LifeCycle node requestAppGoal(java.lang.String,java.lang.String)[0]:appId:App identifier requestAppGoal(java.lang.String,java.lang.String)[1]:nodeName:Name of the App LifeCycle node WebAppDeployer-mbean.properties000066400000000000000000000023311174773561500346140ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/jmxWebAppDeployer: Deployer for startup deployment of webapps contexts: MObject: The ContextHandlerCollection to which the deployer deploys allowDuplicates: Object:RO: Whether or not duplicate deployments are allowed setAllowDuplicates(boolean):ACTION: Whether or not duplicate deployments are allowed setAllowDuplicates(boolean)[0]:allowDuplicates: True allows duplicate webapps to be deployed while false does not defaultsDescriptor: Object: The webdefault.xml descriptor to use for all webapps deployed by the deployer configurationClasses: Object: The set of configuration classes to apply to the deployment of each webapp webAppDir: Object: The directory where the webapps are to be found to deploy extract: Object:RO: Whether or not to extract war files on deployment setExtract(boolean):ACTION:Set whether or not to extract war files setExtract(boolean)[0]:extract: True will extract war files while false will not parentLoaderPriority: Object:RO: Whether to use j2se classloading order or servlet spec classloading order setParentLoaderPriority(boolean):ACTION: Set which classloading paradigm to use setParentLoaderPriority(boolean)[0]:parentPriorityClassLoading: True uses j2se classloading order while false uses servlet spec order jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/lifecycle-bindings.txt000066400000000000000000000000221174773561500323030ustar00rootroot00000000000000# Default Bindingsjetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/providers/000077500000000000000000000000001174773561500300335ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/providers/jmx/000077500000000000000000000000001174773561500306315ustar00rootroot00000000000000ContextProvider-mbean.properties000066400000000000000000000000731174773561500371070ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/providers/jmxContextProvider: Context AppProvider for Deployment managerScanningAppProvider-mbean.properties000066400000000000000000000003061174773561500376630ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/providers/jmxScanningAppProvider: Scanning AppProvider for Deployment manager monitoredDirName: The directory to monitor for new Apps scanInterval: The scan interval in seconds recursive: Look in subdirectories WebAppProvider-mbean.properties000066400000000000000000000006411174773561500366420ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/main/resources/org/eclipse/jetty/deploy/providers/jmxWebAppProvider: Web application AppProvider for Deployment manager extractWars: Extract WAR files to temporary directory parentLoaderPriority: ClassLoaders give priority to classes from parent loader defaultsDescriptor: The default descriptor applied before any web.xml contextXmlDir: The directory of context.xml files configurationClasses: The configuration classes to apply tempDir: The temporary directory to use jetty8-8.1.3/jetty-deploy/src/test/000077500000000000000000000000001174773561500171715ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/java/000077500000000000000000000000001174773561500201125ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/java/org/000077500000000000000000000000001174773561500207015ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/000077500000000000000000000000001174773561500223255ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500234645ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/000077500000000000000000000000001174773561500247605ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/AppLifeCyclePathCollector.java000066400000000000000000000043311174773561500326100ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.util.ArrayList; import java.util.List; import org.eclipse.jetty.deploy.graph.Node; import org.junit.Assert; /** * Binds to all lifecycle nodes, and tracks the order of the lifecycle nodes for testing purposes. */ public class AppLifeCyclePathCollector implements AppLifeCycle.Binding { List actualOrder = new ArrayList(); public void clear() { actualOrder.clear(); } public List getCapturedPath() { return actualOrder; } public String[] getBindingTargets() { return new String[] { "*" }; } public void processBinding(Node node, App app) throws Exception { actualOrder.add(node); } public void assertExpected(String msg, List expectedOrder) { if (expectedOrder.size() != actualOrder.size()) { System.out.println("/* Expected Path */"); for (String path : expectedOrder) { System.out.println(path); } System.out.println("/* Actual Path */"); for (Node path : actualOrder) { System.out.println(path.getName()); } Assert.assertEquals(msg + " / count",expectedOrder.size(),actualOrder.size()); } for (int i = 0, n = expectedOrder.size(); i < n; i++) { Assert.assertEquals(msg + "[" + i + "]",expectedOrder.get(i),actualOrder.get(i).getName()); } } } jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/AppLifeCycleTest.java000066400000000000000000000157021174773561500307700ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.jetty.deploy.graph.GraphOutputDot; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.deploy.graph.Path; import org.eclipse.jetty.toolchain.test.TestingDir; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; /** * Just an overly picky test case to validate the potential paths. */ public class AppLifeCycleTest { @Rule public TestingDir testdir = new TestingDir(); private void assertNoPath(String from, String to) { assertPath(from,to,new ArrayList()); } private void assertPath(AppLifeCycle lifecycle, String from, String to, List expected) { Node fromNode = lifecycle.getNodeByName(from); Node toNode = lifecycle.getNodeByName(to); Path actual = lifecycle.getPath(fromNode,toNode); String msg = "LifeCycle path from " + from + " to " + to; Assert.assertNotNull(msg + " should never be null",actual); if (expected.size() != actual.nodes()) { System.out.println(); System.out.printf("/* from '%s' -> '%s' */%n",from,to); System.out.println("/* Expected Path */"); for (String path : expected) { System.out.println(path); } System.out.println("/* Actual Path */"); for (Node path : actual.getNodes()) { System.out.println(path.getName()); } Assert.assertEquals(msg + " / count",expected.size(),actual.nodes()); } for (int i = 0, n = expected.size(); i < n; i++) { Assert.assertEquals(msg + "[" + i + "]",expected.get(i),actual.getNode(i).getName()); } } private void assertPath(String from, String to, List expected) { AppLifeCycle lifecycle = new AppLifeCycle(); assertPath(lifecycle,from,to,expected); } @Test public void testFindPath_Deployed_Deployed() { assertNoPath("deployed","deployed"); } @Test public void testFindPath_Deployed_Started() { List expected = new ArrayList(); expected.add("deployed"); expected.add("starting"); expected.add("started"); assertPath("deployed","started",expected); } @Test public void testFindPath_Deployed_Undeployed() { List expected = new ArrayList(); expected.add("deployed"); expected.add("undeploying"); expected.add("undeployed"); assertPath("deployed","undeployed",expected); } @Test public void testFindPath_Started_Deployed() { List expected = new ArrayList(); expected.add("started"); expected.add("stopping"); expected.add("deployed"); assertPath("started","deployed",expected); } @Test public void testFindPath_Started_Started() { assertNoPath("started","started"); } @Test public void testFindPath_Started_Undeployed() { List expected = new ArrayList(); expected.add("started"); expected.add("stopping"); expected.add("deployed"); expected.add("undeploying"); expected.add("undeployed"); assertPath("started","undeployed",expected); } @Test public void testFindPath_Undeployed_Deployed() { List expected = new ArrayList(); expected.add("undeployed"); expected.add("deploying"); expected.add("deployed"); assertPath("undeployed","deployed",expected); } @Test public void testFindPath_Undeployed_Started() { List expected = new ArrayList(); expected.add("undeployed"); expected.add("deploying"); expected.add("deployed"); expected.add("starting"); expected.add("started"); assertPath("undeployed","started",expected); } @Test public void testFindPath_Undeployed_Uavailable() { assertNoPath("undeployed","undeployed"); } /** * Request multiple lifecycle paths with a single lifecycle instance. Just to ensure that there is no state * maintained between {@link AppLifeCycle#getPath(Node, Node)} requests. * * @throws IOException */ @Test public void testFindPathMultiple() throws IOException { AppLifeCycle lifecycle = new AppLifeCycle(); List expected = new ArrayList(); File outputDir = testdir.getEmptyDir(); // Modify graph to add new 'staging' -> 'staged' between 'deployed' and 'started' GraphOutputDot.write(lifecycle,new File(outputDir,"multiple-1.dot")); // before change lifecycle.insertNode(lifecycle.getPath("deployed","started").getEdge(0),"staging"); GraphOutputDot.write(lifecycle,new File(outputDir,"multiple-2.dot")); // after first change lifecycle.insertNode(lifecycle.getPath("staging","started").getEdge(0),"staged"); GraphOutputDot.write(lifecycle,new File(outputDir,"multiple-3.dot")); // after second change // Deployed -> Deployed expected.clear(); assertPath(lifecycle,"deployed","deployed",expected); // Deployed -> Staged expected.clear(); expected.add("deployed"); expected.add("staging"); expected.add("staged"); assertPath(lifecycle,"deployed","staged",expected); // Staged -> Undeployed expected.clear(); expected.add("staged"); expected.add("starting"); expected.add("started"); expected.add("stopping"); expected.add("deployed"); expected.add("undeploying"); expected.add("undeployed"); assertPath(lifecycle,"staged","undeployed",expected); // Undeployed -> Started expected.clear(); expected.add("undeployed"); expected.add("deploying"); expected.add("deployed"); expected.add("staging"); expected.add("staged"); expected.add("starting"); expected.add("started"); assertPath(lifecycle,"undeployed","started",expected); } } DeploymentManagerLifeCyclePathTest.java000066400000000000000000000116461174773561500344240ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.List; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.toolchain.jmx.JmxServiceConnection; import org.junit.Test; public class DeploymentManagerLifeCyclePathTest { @Test public void testStateTransition_NewToDeployed() throws Exception { DeploymentManager depman = new DeploymentManager(); depman.setDefaultLifeCycleGoal(null); // no default AppLifeCyclePathCollector pathtracker = new AppLifeCyclePathCollector(); MockAppProvider mockProvider = new MockAppProvider(); depman.addLifeCycleBinding(pathtracker); depman.addAppProvider(mockProvider); depman.setContexts(new ContextHandlerCollection()); // Start DepMan depman.start(); // Trigger new App mockProvider.findWebapp("foo-webapp-1.war"); App app = depman.getAppByOriginId("mock-foo-webapp-1.war"); // Request Deploy of App depman.requestAppGoal(app,"deployed"); // Setup Expectations. List expected = new ArrayList(); // SHOULD NOT SEE THIS NODE VISITED - expected.add("undeployed"); expected.add("deploying"); expected.add("deployed"); pathtracker.assertExpected("Test StateTransition / New -> Deployed",expected); } @Test public void testStateTransition_Receive() throws Exception { DeploymentManager depman = new DeploymentManager(); depman.setDefaultLifeCycleGoal(null); // no default AppLifeCyclePathCollector pathtracker = new AppLifeCyclePathCollector(); MockAppProvider mockProvider = new MockAppProvider(); depman.addLifeCycleBinding(pathtracker); depman.addAppProvider(mockProvider); // Start DepMan depman.start(); // Trigger new App mockProvider.findWebapp("foo-webapp-1.war"); // Perform no goal request. // Setup Expectations. List expected = new ArrayList(); pathtracker.assertExpected("Test StateTransition / New only",expected); } @Test public void testStateTransition_DeployedToUndeployed() throws Exception { DeploymentManager depman = new DeploymentManager(); depman.setDefaultLifeCycleGoal(null); // no default AppLifeCyclePathCollector pathtracker = new AppLifeCyclePathCollector(); MockAppProvider mockProvider = new MockAppProvider(); // Setup JMX MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer()); mbContainer.start(); mbContainer.addBean(depman); depman.addLifeCycleBinding(pathtracker); depman.addAppProvider(mockProvider); depman.setContexts(new ContextHandlerCollection()); // Start DepMan depman.start(); // Trigger new App mockProvider.findWebapp("foo-webapp-1.war"); App app = depman.getAppByOriginId("mock-foo-webapp-1.war"); // Request Deploy of App depman.requestAppGoal(app,"deployed"); JmxServiceConnection jmxConnection = new JmxServiceConnection(); jmxConnection.connect(); MBeanServerConnection mbsConnection = jmxConnection.getConnection(); ObjectName dmObjName = new ObjectName("org.eclipse.jetty.deploy:type=deploymentmanager,id=0"); String[] params = new String[] {"mock-foo-webapp-1.war", "undeployed"}; String[] signature = new String[] {"java.lang.String", "java.lang.String"}; mbsConnection.invoke(dmObjName, "requestAppGoal", params, signature); // Setup Expectations. List expected = new ArrayList(); // SHOULD NOT SEE THIS NODE VISITED - expected.add("undeployed"); expected.add("deploying"); expected.add("deployed"); expected.add("undeploying"); expected.add("undeployed"); pathtracker.assertExpected("Test JMX StateTransition / Deployed -> Undeployed",expected); } } jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java000066400000000000000000000055011174773561500320770ustar00rootroot00000000000000package org.eclipse.jetty.deploy; import java.util.Collection; import java.util.Set; import org.eclipse.jetty.deploy.test.XmlConfiguredJetty; import org.eclipse.jetty.toolchain.test.TestingDir; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; public class DeploymentManagerTest { @Rule public TestingDir testdir = new TestingDir(); @Test public void testReceiveApp() throws Exception { DeploymentManager depman = new DeploymentManager(); depman.setDefaultLifeCycleGoal(null); // no default AppLifeCyclePathCollector pathtracker = new AppLifeCyclePathCollector(); MockAppProvider mockProvider = new MockAppProvider(); depman.addLifeCycleBinding(pathtracker); depman.addAppProvider(mockProvider); // Start DepMan depman.start(); // Trigger new App mockProvider.findWebapp("foo-webapp-1.war"); // Test app tracking Collection apps = depman.getApps(); Assert.assertNotNull("Should never be null",apps); Assert.assertEquals("Expected App Count",1,apps.size()); // Test app get App actual = depman.getAppByOriginId("mock-foo-webapp-1.war"); Assert.assertNotNull("Should have gotten app (by id)",actual); Assert.assertEquals("Should have gotten app (by id)","mock-foo-webapp-1.war",actual.getOriginId()); } @Test public void testBinding() { AppLifeCyclePathCollector pathtracker = new AppLifeCyclePathCollector(); DeploymentManager depman = new DeploymentManager(); depman.addLifeCycleBinding(pathtracker); Set allbindings = depman.getLifeCycle().getBindings(); Assert.assertNotNull("All Bindings should never be null",allbindings); Assert.assertEquals("All Bindings.size",1,allbindings.size()); Set deploybindings = depman.getLifeCycle().getBindings("deploying"); Assert.assertNotNull("'deploying' Bindings should not be null",deploybindings); Assert.assertEquals("'deploying' Bindings.size",1,deploybindings.size()); } @Test public void testXmlConfigured() throws Exception { XmlConfiguredJetty jetty = null; try { jetty = new XmlConfiguredJetty(testdir); jetty.addConfiguration("jetty.xml"); jetty.addConfiguration("jetty-deploymgr-contexts.xml"); // Should not throw an Exception jetty.load(); // Start it jetty.start(); } finally { if (jetty != null) { try { jetty.stop(); } catch (Exception ignore) { // ignore } } } } } jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/MockAppProvider.java000066400000000000000000000053151174773561500306740ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy; import java.io.File; import org.eclipse.jetty.deploy.util.FileID; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.WebAppContext; public class MockAppProvider extends AbstractLifeCycle implements AppProvider { private DeploymentManager deployMan; private File webappsDir; public void setDeploymentManager(DeploymentManager deploymentManager) { this.deployMan = deploymentManager; } @Override public void doStart() { this.webappsDir = MavenTestingUtils.getTestResourceDir("webapps"); } public void findWebapp(String name) { App app = new App(deployMan,this,"mock-" + name); this.deployMan.addApp(app); } public ContextHandler createContextHandler(App app) throws Exception { WebAppContext context = new WebAppContext(); File war = new File(webappsDir,app.getOriginId().substring(5)); context.setWar(Resource.newResource(Resource.toURL(war)).toString()); String path = war.getName(); if (FileID.isWebArchiveFile(war)) { // Context Path is the same as the archive. path = path.substring(0,path.length() - 4); } // special case of archive (or dir) named "root" is / context if (path.equalsIgnoreCase("root") || path.equalsIgnoreCase("root/")) path = URIUtil.SLASH; // Ensure "/" is Prepended to all context paths. if (path.charAt(0) != '/') path = "/" + path; // Ensure "/" is Not Trailing in context paths. if (path.endsWith("/") && path.length() > 0) path = path.substring(0,path.length() - 1); context.setContextPath(path); return context; } } jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/bindings/000077500000000000000000000000001174773561500265555ustar00rootroot00000000000000GlobalWebappConfigBindingTest.java000066400000000000000000000071131174773561500351630ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/bindings// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.bindings; import static org.hamcrest.Matchers.*; import java.io.File; import java.util.List; import org.eclipse.jetty.deploy.providers.ScanningAppProvider; import org.eclipse.jetty.deploy.test.XmlConfiguredJetty; import org.eclipse.jetty.toolchain.test.IO; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.PathAssert; import org.eclipse.jetty.toolchain.test.TestingDir; import org.eclipse.jetty.webapp.WebAppContext; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; /** * Tests {@link ScanningAppProvider} as it starts up for the first time. */ public class GlobalWebappConfigBindingTest { @Rule public TestingDir testdir = new TestingDir(); private static XmlConfiguredJetty jetty; @Before public void setupEnvironment() throws Exception { jetty = new XmlConfiguredJetty(testdir); jetty.addConfiguration("jetty.xml"); // Setup initial context jetty.copyContext("foo.xml","foo.xml"); jetty.copyWebapp("foo-webapp-1.war","foo.war"); } @After public void teardownEnvironment() throws Exception { // Stop jetty. jetty.stop(); } @Test public void testServerAndSystemClassesOverride() throws Exception { File srcXml = MavenTestingUtils.getTestResourceFile("context-binding-test-1.xml"); File destXml = new File(jetty.getJettyHome(),"context-binding-test-1.xml"); IO.copy(srcXml,destXml); PathAssert.assertFileExists("Context Binding XML",destXml); jetty.addConfiguration("binding-test-contexts-1.xml"); jetty.load(); jetty.start(); List contexts = jetty.getWebAppContexts(); Assert.assertThat("List of Contexts", contexts, hasSize(greaterThan(0))); WebAppContext context = contexts.get(0); Assert.assertNotNull("Context should not be null",context); String defaultClasses[] = context.getDefaultServerClasses(); String currentClasses[] = context.getServerClasses(); String addedClass = "org.eclipse.foo."; // What was added by the binding Assert.assertThat("Default Server Classes",addedClass,not(isIn(defaultClasses))); Assert.assertThat("Current Server Classes",addedClass,isIn(currentClasses)); // boolean jndiPackage = false; // this test overrides and we removed the jndi from the list so it // should test false // for (String entry : context.getSystemClasses()) // { // if ("org.eclipse.jetty.jndi.".equals(entry)) // { // jndiPackage = true; // } // } // // Assert.assertFalse(jndiPackage); } } jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/000077500000000000000000000000001174773561500260615ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/GraphTest.java000066400000000000000000000070671174773561500306370ustar00rootroot00000000000000package org.eclipse.jetty.deploy.graph; import junit.framework.Assert; import org.junit.Test; public class GraphTest { final Node nodeA = new Node("A"); final Node nodeB = new Node("B"); final Node nodeC = new Node("C"); final Node nodeD = new Node("D"); final Node nodeE = new Node("E"); @Test public void testPath() { Path path = new Path(); Assert.assertEquals(0,path.nodes()); Assert.assertEquals(null,path.firstNode()); Assert.assertEquals(null,path.lastNode()); path.add(new Edge(nodeA ,nodeB)); Assert.assertEquals(2,path.nodes()); Assert.assertEquals(nodeA,path.firstNode()); Assert.assertEquals(nodeB,path.lastNode()); path.add(new Edge(nodeB ,nodeC)); Assert.assertEquals(3,path.nodes()); Assert.assertEquals(nodeA,path.firstNode()); Assert.assertEquals(nodeC,path.lastNode()); } @Test public void testPoint() { Graph graph = new Graph(); graph.addNode(nodeA); Assert.assertEquals(1,graph.getNodes().size()); Assert.assertEquals(0,graph.getEdges().size()); Path path = graph.getPath(nodeA,nodeA); Assert.assertEquals(0,path.nodes()); } @Test public void testLine() { Graph graph = new Graph(); graph.addEdge(new Edge(nodeA,nodeB)); Assert.assertEquals(2,graph.getNodes().size()); Assert.assertEquals(1,graph.getEdges().size()); Path path = graph.getPath(nodeA,nodeB); Assert.assertEquals(2,path.nodes()); } @Test public void testTriangleDirected() { Graph graph = new Graph(); graph.addEdge(new Edge(nodeA,nodeB)); graph.addEdge(new Edge(nodeA,nodeC)); graph.addEdge(new Edge(nodeB,nodeC)); Assert.assertEquals(3,graph.getNodes().size()); Assert.assertEquals(3,graph.getEdges().size()); Path path = graph.getPath(nodeA,nodeB); Assert.assertEquals(2,path.nodes()); path = graph.getPath(nodeA,nodeC); Assert.assertEquals(2,path.nodes()); path = graph.getPath(nodeB,nodeC); Assert.assertEquals(2,path.nodes()); } @Test public void testSquareDirected() { Graph graph = new Graph(); graph.addEdge(new Edge(nodeA,nodeB)); graph.addEdge(new Edge(nodeB,nodeC)); graph.addEdge(new Edge(nodeA,nodeD)); graph.addEdge(new Edge(nodeD,nodeC)); Assert.assertEquals(4,graph.getNodes().size()); Assert.assertEquals(4,graph.getEdges().size()); Path path = graph.getPath(nodeA,nodeC); Assert.assertEquals(3,path.nodes()); path = graph.getPath(nodeC,nodeA); Assert.assertEquals(null,path); } @Test public void testSquareCyclic() { Graph graph = new Graph(); graph.addEdge(new Edge(nodeA,nodeB)); graph.addEdge(new Edge(nodeB,nodeC)); graph.addEdge(new Edge(nodeC,nodeD)); graph.addEdge(new Edge(nodeD,nodeA)); Assert.assertEquals(4,graph.getNodes().size()); Assert.assertEquals(4,graph.getEdges().size()); Path path = graph.getPath(nodeA,nodeB); Assert.assertEquals(2,path.nodes()); path = graph.getPath(nodeA,nodeC); Assert.assertEquals(3,path.nodes()); path = graph.getPath(nodeA,nodeD); Assert.assertEquals(4,path.nodes()); graph.addNode(nodeE); path = graph.getPath(nodeA,nodeE); Assert.assertEquals(null,path); } } jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/000077500000000000000000000000001174773561500267755ustar00rootroot00000000000000ScanningAppProviderRuntimeUpdatesTest.java000066400000000000000000000130371174773561500372330ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.deploy.providers; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jetty.deploy.AppProvider; import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.deploy.test.XmlConfiguredJetty; import org.eclipse.jetty.toolchain.test.OS; import org.eclipse.jetty.toolchain.test.TestingDir; import org.eclipse.jetty.util.Scanner; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.junit.After; import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.Test; /** * Similar in scope to {@link ScanningAppProviderStartupTest}, except is concerned with the modification of existing * deployed webapps due to incoming changes identified by the {@link ScanningAppProvider}. */ public class ScanningAppProviderRuntimeUpdatesTest { private static final Logger LOG = Log.getLogger(ScanningAppProviderRuntimeUpdatesTest.class); @Rule public TestingDir testdir = new TestingDir(); private static XmlConfiguredJetty jetty; private final AtomicInteger _scans = new AtomicInteger(); private int _providers; @Before public void setupEnvironment() throws Exception { jetty = new XmlConfiguredJetty(testdir); jetty.addConfiguration("jetty.xml"); jetty.addConfiguration("jetty-deploymgr-contexts.xml"); // Should not throw an Exception jetty.load(); // Start it jetty.start(); // monitor tick DeploymentManager dm = jetty.getServer().getBeans(DeploymentManager.class).get(0); for (AppProvider provider : dm.getAppProviders()) { if (provider instanceof ScanningAppProvider) { _providers++; ((ScanningAppProvider)provider).addScannerListener(new Scanner.ScanListener() { public void scan() { _scans.incrementAndGet(); } }); } } } @After public void teardownEnvironment() throws Exception { // Stop jetty. jetty.stop(); } public void waitForDirectoryScan() { int scan=_scans.get()+2*_providers; do { try { Thread.sleep(200); } catch(InterruptedException e) { LOG.warn(e); } } while(_scans.get() _xmlConfigurations; private Map _properties = new HashMap(); private Server _server; private int _serverPort; private String _scheme = HttpSchemes.HTTP; private File _jettyHome; public XmlConfiguredJetty(TestingDir testdir) throws IOException { _xmlConfigurations = new ArrayList(); Properties properties = new Properties(); String jettyHomeBase = testdir.getDir().getAbsolutePath(); // Ensure we have a new (pristene) directory to work with. int idx = 0; _jettyHome = new File(jettyHomeBase + "#" + idx); while (_jettyHome.exists()) { idx++; _jettyHome = new File(jettyHomeBase + "#" + idx); } deleteContents(_jettyHome); // Prepare Jetty.Home (Test) dir _jettyHome.mkdirs(); File logsDir = new File(_jettyHome,"logs"); logsDir.mkdirs(); File etcDir = new File(_jettyHome,"etc"); etcDir.mkdirs(); IO.copyFile(MavenTestingUtils.getTestResourceFile("etc/realm.properties"),new File(etcDir,"realm.properties")); IO.copyFile(MavenTestingUtils.getTestResourceFile("etc/webdefault.xml"),new File(etcDir,"webdefault.xml")); File contextsDir = new File(_jettyHome,"contexts"); if (contextsDir.exists()) { deleteContents(contextsDir); } contextsDir.mkdirs(); File webappsDir = new File(_jettyHome,"webapps"); if (webappsDir.exists()) { deleteContents(webappsDir); } webappsDir.mkdirs(); File tmpDir = new File(_jettyHome,"tmp"); if (tmpDir.exists()) { deleteContents(tmpDir); } tmpDir.mkdirs(); File workishDir = new File(_jettyHome,"workish"); if (workishDir.exists()) { deleteContents(workishDir); } workishDir.mkdirs(); // Setup properties System.setProperty("java.io.tmpdir",tmpDir.getAbsolutePath()); properties.setProperty("jetty.home",_jettyHome.getAbsolutePath()); System.setProperty("jetty.home",_jettyHome.getAbsolutePath()); properties.setProperty("test.basedir",MavenTestingUtils.getBasedir().getAbsolutePath()); properties.setProperty("test.resourcesdir",MavenTestingUtils.getTestResourcesDir().getAbsolutePath()); properties.setProperty("test.webapps",webappsDir.getAbsolutePath()); properties.setProperty("test.targetdir",MavenTestingUtils.getTargetDir().getAbsolutePath()); properties.setProperty("test.workdir",workishDir.getAbsolutePath()); // Write out configuration for use by ConfigurationManager. File testConfig = new File(_jettyHome, "xml-configured-jetty.properties"); FileOutputStream out = new FileOutputStream(testConfig); properties.store(out,"Generated by " + XmlConfiguredJetty.class.getName()); for (Object key:properties.keySet()) _properties.put(String.valueOf(key),String.valueOf(properties.get(key))); } public void addConfiguration(File xmlConfigFile) throws MalformedURLException { _xmlConfigurations.add(Resource.toURL(xmlConfigFile)); } public void addConfiguration(String testConfigName) throws MalformedURLException { addConfiguration(MavenTestingUtils.getTestResourceFile(testConfigName)); } public void addConfiguration(URL xmlConfig) { _xmlConfigurations.add(xmlConfig); } public void assertNoWebAppContexts() { List contexts = getWebAppContexts(); if (contexts.size() > 0) { for (WebAppContext context : contexts) { System.out.println("WebAppContext should not exist:\n" + context); } Assert.assertEquals("Contexts.size",0,contexts.size()); } } public String getResponse(String path) throws IOException { URI destUri = getServerURI().resolve(path); URL url = destUri.toURL(); URLConnection conn = url.openConnection(); InputStream in = null; try { in = conn.getInputStream(); return IO.toString(in); } finally { IO.close(in); } } public void assertResponseContains(String path, String needle) throws IOException { System.out.println("Issuing request to " + path); String content = getResponse(path); Assert.assertTrue("Content should contain <" + needle + ">, instead got <" + content + ">",content.contains(needle)); } public void assertWebAppContextsExists(String... expectedContextPaths) { List contexts = getWebAppContexts(); if (expectedContextPaths.length != contexts.size()) { System.out.println("## Expected Contexts"); for (String expected : expectedContextPaths) { System.out.println(expected); } System.out.println("## Actual Contexts"); for (WebAppContext context : contexts) { System.out.printf("%s ## %s%n",context.getContextPath(),context); } Assert.assertEquals("Contexts.size",expectedContextPaths.length,contexts.size()); } for (String expectedPath : expectedContextPaths) { boolean found = false; for (WebAppContext context : contexts) { if (context.getContextPath().equals(expectedPath)) { found = true; break; } } Assert.assertTrue("Did not find Expected Context Path " + expectedPath,found); } } public void copyContext(String srcName, String destName) throws IOException { System.out.printf("Copying Context: %s -> %s%n",srcName,destName); File srcDir = MavenTestingUtils.getTestResourceDir("contexts"); File destDir = new File(_jettyHome,"contexts"); File srcFile = new File(srcDir,srcName); File destFile = new File(destDir,destName); copyFile("Context",srcFile,destFile); } private void copyFile(String type, File srcFile, File destFile) throws IOException { PathAssert.assertFileExists(type + " File",srcFile); IO.copyFile(srcFile,destFile); PathAssert.assertFileExists(type + " File",destFile); System.out.printf("Copy %s: %s%n To %s: %s%n",type,srcFile,type,destFile); System.out.printf("Destination Exists: %s - %s%n",destFile.exists(),destFile); } public void copyWebapp(String srcName, String destName) throws IOException { System.out.printf("Copying Webapp: %s -> %s%n",srcName,destName); File srcDir = MavenTestingUtils.getTestResourceDir("webapps"); File destDir = new File(_jettyHome,"webapps"); File srcFile = new File(srcDir,srcName); File destFile = new File(destDir,destName); copyFile("Webapp",srcFile,destFile); } private void deleteContents(File dir) { System.out.printf("Delete (dir) %s/%n",dir); if (!dir.exists()) { return; } for (File file : dir.listFiles()) { // Safety measure. only recursively delete within target directory. if (file.isDirectory() && file.getAbsolutePath().contains("target" + File.separator)) { deleteContents(file); Assert.assertTrue("Delete failed: " + file.getAbsolutePath(),file.delete()); } else { System.out.printf("Delete (file) %s%n",file); Assert.assertTrue("Delete failed: " + file.getAbsolutePath(),file.delete()); } } } public DeploymentManager getActiveDeploymentManager() { return _server.getBean(DeploymentManager.class); } public File getJettyDir(String name) { return new File(_jettyHome,name); } public File getJettyHome() { return _jettyHome; } public String getScheme() { return _scheme; } public Server getServer() { return _server; } public int getServerPort() { return _serverPort; } public URI getServerURI() throws UnknownHostException { StringBuffer uri = new StringBuffer(); uri.append(this._scheme).append("://"); uri.append(InetAddress.getLocalHost().getHostAddress()); uri.append(":").append(this._serverPort); return URI.create(uri.toString()); } public List getWebAppContexts() { List contexts = new ArrayList(); HandlerCollection handlers = (HandlerCollection)_server.getHandler(); System.out.println(_server.dump()); Handler children[] = handlers.getChildHandlers(); for (Handler handler : children) { if (handler instanceof WebAppContext) { WebAppContext context = (WebAppContext)handler; contexts.add(context); } } return contexts; } public void load() throws Exception { XmlConfiguration last = null; Object[] obj = new Object[this._xmlConfigurations.size()]; // Configure everything for (int i = 0; i < this._xmlConfigurations.size(); i++) { URL configURL = this._xmlConfigurations.get(i); XmlConfiguration configuration = new XmlConfiguration(configURL); if (last != null) { configuration.getIdMap().putAll(last.getIdMap()); } configuration.getProperties().putAll(_properties); obj[i] = configuration.configure(); last = configuration; } // Test for Server Instance. Server foundServer = null; int serverCount = 0; for (int i = 0; i < this._xmlConfigurations.size(); i++) { if (obj[i] instanceof Server) { if (obj[i].equals(foundServer)) { // Identical server instance found break; } foundServer = (Server)obj[i]; serverCount++; } } if (serverCount <= 0) { throw new Exception("Load failed to configure a " + Server.class.getName()); } Assert.assertEquals("Server load count",1,serverCount); this._server = foundServer; this._server.setGracefulShutdown(10); } public void removeContext(String name) { File destDir = new File(_jettyHome,"contexts"); File contextFile = new File(destDir,name); if (contextFile.exists()) { Assert.assertTrue("Delete of Context file: " + contextFile.getAbsolutePath(),contextFile.delete()); } } public void setProperty(String key, String value) { _properties.put(key,value); } public void setScheme(String scheme) { this._scheme = scheme; } public void start() throws Exception { Assert.assertNotNull("Server should not be null (failed load?)",_server); _server.start(); // Find the active server port. this._serverPort = (-1); Connector connectors[] = _server.getConnectors(); for (int i = 0; i < connectors.length; i++) { Connector connector = connectors[i]; if (connector.getLocalPort() > 0) { this._serverPort = connector.getLocalPort(); break; } } Assert.assertTrue("Server Port is between 1 and 65535. Actually <" + _serverPort + ">",(1 <= this._serverPort) && (this._serverPort <= 65535)); // Uncomment to have server start and continue to run (without exiting) // System.out.printf("Listening to port %d%n",this.serverPort); // server.join(); } public void stop() throws Exception { _server.stop(); } } jetty8-8.1.3/jetty-deploy/src/test/resources/000077500000000000000000000000001174773561500212035ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/resources/binding-test-contexts-1.xml000066400000000000000000000052721174773561500263250ustar00rootroot00000000000000 -org.eclipse.jetty.continuation. -org.eclipse.jetty.jndi. -org.eclipse.jetty.plus.jaas. -org.eclipse.jetty.websocket. -org.eclipse.jetty.servlet.DefaultServlet org.eclipse.jetty. org.eclipse.foo. java. javax. org.xml. org.w3c. org.apache.commons.logging org.eclipse.jetty.continuation org.eclipse.jetty.plus.jaas. org.eclipse.jetty.websocket org.eclipse.jetty.servlet.DefaultServlet /context-binding-test-1.xml /contexts 1 /xml-configured-jetty.properties /webapps 1 /contexts jetty8-8.1.3/jetty-deploy/src/test/resources/context-binding-test-1.xml000066400000000000000000000020421174773561500261320ustar00rootroot00000000000000 org.eclipse.foo. jetty8-8.1.3/jetty-deploy/src/test/resources/contexts/000077500000000000000000000000001174773561500230525ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/resources/contexts/foo.xml000066400000000000000000000005561174773561500243650ustar00rootroot00000000000000 /foo /foo.war jetty8-8.1.3/jetty-deploy/src/test/resources/etc/000077500000000000000000000000001174773561500217565ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/resources/etc/realm.properties000066400000000000000000000013711174773561500251760ustar00rootroot00000000000000# # This file defines users passwords and roles for a HashUserRealm # # The format is # : [, ...] # # Passwords may be clear text, obfuscated or checksummed. The class # org.eclipse.util.Password should be used to generate obfuscated # passwords or password checksums # # If DIGEST Authentication is used, the password must be in a recoverable # format, either plain text or OBF:. # jetty: MD5:164c88b302622e17050af52c89945d44,user admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin other: OBF:1xmk1w261u9r1w1c1xmq,user plain: plain,user user: password,user # This entry is for digest auth. The credential is a MD5 hash of username:realmname:password digest: MD5:6e120743ad67abfbc385bc2bb754e297,user jetty8-8.1.3/jetty-deploy/src/test/resources/etc/webdefault.xml000066400000000000000000000570051174773561500246310ustar00rootroot00000000000000 Default web.xml file. This file is applied to a Web application before it's own WEB_INF/web.xml file default org.eclipse.jetty.servlet.DefaultServlet acceptRanges true dirAllowed true welcomeServlets false redirectWelcome false maxCacheSize 256000000 maxCachedFileSize 10000000 maxCachedFiles 1000 cacheType both gzip true useFileMappedBuffer true 0 default / jsp org.apache.jasper.servlet.JspServlet logVerbosityLevel DEBUG fork false xpoweredBy false 0 jsp *.jsp *.jspf *.jspx *.xsp *.JSP *.JSPF *.JSPX *.XSP 30 index.html index.htm index.jsp arISO-8859-6 beISO-8859-5 bgISO-8859-5 caISO-8859-1 csISO-8859-2 daISO-8859-1 deISO-8859-1 elISO-8859-7 enISO-8859-1 esISO-8859-1 etISO-8859-1 fiISO-8859-1 frISO-8859-1 hrISO-8859-2 huISO-8859-2 isISO-8859-1 itISO-8859-1 iwISO-8859-8 jaShift_JIS koEUC-KR ltISO-8859-2 lvISO-8859-2 mkISO-8859-5 nlISO-8859-1 noISO-8859-1 plISO-8859-2 ptISO-8859-1 roISO-8859-2 ruISO-8859-5 shISO-8859-5 skISO-8859-2 slISO-8859-2 sqISO-8859-2 srISO-8859-5 svISO-8859-1 trISO-8859-9 ukISO-8859-5 zhGB2312 zh_TWBig5 Disable TRACE / TRACE jetty8-8.1.3/jetty-deploy/src/test/resources/jetty-deploy-wars.xml000066400000000000000000000017301174773561500253310ustar00rootroot00000000000000 /webapps 1 /workish jetty8-8.1.3/jetty-deploy/src/test/resources/jetty-deploymgr-contexts.xml000066400000000000000000000030541174773561500267330ustar00rootroot00000000000000 /contexts 1 /xml-configured-jetty.properties /webapps 1 /contexts jetty8-8.1.3/jetty-deploy/src/test/resources/jetty.xml000066400000000000000000000150461174773561500230720ustar00rootroot00000000000000 10 200 0 300000 2 false 8443 20000 5000 Test Realm /etc/realm.properties 0 /logs/yyyy_mm_dd.request.log yyyy_MM_dd 90 true false false GMT true true true 1000 jetty8-8.1.3/jetty-deploy/src/test/resources/webapps/000077500000000000000000000000001174773561500226445ustar00rootroot00000000000000jetty8-8.1.3/jetty-deploy/src/test/resources/webapps/foo-webapp-1.war000066400000000000000000000100541174773561500255540ustar00rootroot00000000000000PK lS; META-INF/PK lS;Df}META-INF/MANIFEST.MFMLK-. K-*ϳR03r,J,K-BV+$xRKRSt* 3R|RxJ3sJYٙ]lfz@;xPK lS;WEB-INF/PK lS;WEB-INF/classes/PK lS;WEB-INF/classes/org/PK lS;WEB-INF/classes/org/eclipse/PK lS;"WEB-INF/classes/org/eclipse/jetty/PK lS;(WEB-INF/classes/org/eclipse/jetty/tests/PK lS;/WEB-INF/classes/org/eclipse/jetty/tests/webapp/PK %kS;j mWEB-INF/web.xmlSn0ﶁ BIP=Ѫ!7ـc[YC$<*iݍY`J#2bCNL*:"/OAXqZ9;,KV1Sx82@.N ҳ{pYbrK\cXj*Lk'S,L"\=M_V2|8؈+l˙VR>蟥}ÌdP+ ;R*VP`ʫL~)=#=6DlsxefL:*3%f٧WZ))N#ZňSrш4q\~mr+\r ע*RUDj~PK lS;META-INF/maven/PK lS;'META-INF/maven/org.eclipse.jetty.tests/PK lS;4META-INF/maven/org.eclipse.jetty.tests/foo-webapp-1/PK jS;`SJ7;META-INF/maven/org.eclipse.jetty.tests/foo-webapp-1/pom.xmlTMo0 Wh9m[IסC(~ɾN"3:Y2$I(qܬ. G'RcV8 (3:<*zv`DMPK lS;w7Fb{BMETA-INF/maven/org.eclipse.jetty.tests/foo-webapp-1/pom.properties OCgE vvp *on0[=0J#Po.}݂6Rv\| C+P;Pa6_Yc_mJ\PK lS; AMETA-INF/PK lS;Df}'META-INF/MANIFEST.MFPK lS;AWEB-INF/PK lS;AWEB-INF/classes/PK lS;AWEB-INF/classes/org/PK lS;AEWEB-INF/classes/org/eclipse/PK lS;"AWEB-INF/classes/org/eclipse/jetty/PK lS;(AWEB-INF/classes/org/eclipse/jetty/tests/PK lS;/AWEB-INF/classes/org/eclipse/jetty/tests/webapp/PK %kS;j mRWEB-INF/web.xmlPK lS;I8@WEB-INF/classes/org/eclipse/jetty/tests/webapp/InfoServlet.classPK lS;AbMETA-INF/maven/PK lS;'AMETA-INF/maven/org.eclipse.jetty.tests/PK lS;4AMETA-INF/maven/org.eclipse.jetty.tests/foo-webapp-1/PK jS;`SJ7;&META-INF/maven/org.eclipse.jetty.tests/foo-webapp-1/pom.xmlPK lS;w7Fb{BG META-INF/maven/org.eclipse.jetty.tests/foo-webapp-1/pom.propertiesPK" jetty8-8.1.3/jetty-deploy/src/test/resources/webapps/foo-webapp-2.war000066400000000000000000000100551174773561500255560ustar00rootroot00000000000000PK lS; META-INF/PK lS;Df}META-INF/MANIFEST.MFMLK-. K-*ϳR03r,J,K-BV+$xRKRSt* 3R|RxJ3sJYٙ]lfz@;xPK lS;WEB-INF/PK lS;WEB-INF/classes/PK lS;WEB-INF/classes/org/PK lS;WEB-INF/classes/org/eclipse/PK lS;"WEB-INF/classes/org/eclipse/jetty/PK lS;(WEB-INF/classes/org/eclipse/jetty/tests/PK lS;/WEB-INF/classes/org/eclipse/jetty/tests/webapp/PK lS;$6mWEB-INF/web.xmlSn0!RJU%$zU{CncGYC$<*iݍŴt5! $6Ufח'zO@AempRƹ|yYcXp8"@&2I ҳ{pgXb3K`Xp9f 6P/+F ><:{$-lLb_\52xe-"^wJGn ڛ]) T+tG +B6.ӂw qRߦ;zfhE. ^yY)`Rxu>3+hڿ*@ʓ@]V%bDmsYsxֱv3gѿ?9(LVj{]PK lS;p @WEB-INF/classes/org/eclipse/jetty/tests/webapp/InfoServlet.classSn@=7Ԥ!M);)Kfhy P jJxs!ƞx>B\/HH4|̹.3x\@<6qBs?lfnA(W=~\m^.N-G,{*"(G駄t1 dvݱ$#?6#;bYy}B!G)֧B@Z'/[!;v_HM8k&xKi퉗l4e΅d'l BmAuBO"F<@C=4u;T5Q iٖr LlmBa}=کƩʙ66 ?a5$9ts|tZ<^a[DϽE4yF<f$j`>p/\6`ױe^`Kٖ} %\f[(5cVQa0+ ~>;*ΐNu ٯ*FSgFYkW<\SUM'RPK lS;META-INF/maven/PK lS;'META-INF/maven/org.eclipse.jetty.tests/PK lS;4META-INF/maven/org.eclipse.jetty.tests/foo-webapp-2/PK kS; >;META-INF/maven/org.eclipse.jetty.tests/foo-webapp-2/pom.xmlTMo0 Wh9m[IaC(ې~ɾN"3:Y2$I(qܬ. G'RcV8 (3:4 #8Xgz8fܡ:Še4Ihǵ@2ub|%28zOnb9^6z> Ia9nge&G*!C>PV跍ye#lzhUH0QtDƵZ2ᢏ~<2q!w1k#*}51=XAv%8>4mhwXqw9%DωэSC%5>*zv`DMPK lS;H|BMETA-INF/maven/org.eclipse.jetty.tests/foo-webapp-2/pom.properties 1 НS@m@xͯbl v*nnԩ h3e;cB4qb[t_7SABC*fu/kM+PK lS; AMETA-INF/PK lS;Df}'META-INF/MANIFEST.MFPK lS;AWEB-INF/PK lS;AWEB-INF/classes/PK lS;AWEB-INF/classes/org/PK lS;AEWEB-INF/classes/org/eclipse/PK lS;"AWEB-INF/classes/org/eclipse/jetty/PK lS;(AWEB-INF/classes/org/eclipse/jetty/tests/PK lS;/AWEB-INF/classes/org/eclipse/jetty/tests/webapp/PK lS;$6mRWEB-INF/web.xmlPK lS;p @WEB-INF/classes/org/eclipse/jetty/tests/webapp/InfoServlet.classPK lS;AbMETA-INF/maven/PK lS;'AMETA-INF/maven/org.eclipse.jetty.tests/PK lS;4AMETA-INF/maven/org.eclipse.jetty.tests/foo-webapp-2/PK kS; >;&META-INF/maven/org.eclipse.jetty.tests/foo-webapp-2/pom.xmlPK lS;H|BG META-INF/maven/org.eclipse.jetty.tests/foo-webapp-2/pom.propertiesPK# jetty8-8.1.3/jetty-deploy/src/test/resources/webapps/foo-webapp-3.war000066400000000000000000000100551174773561500255570ustar00rootroot00000000000000PK lS; META-INF/PK lS;Df}META-INF/MANIFEST.MFMLK-. K-*ϳR03r,J,K-BV+$xRKRSt* 3R|RxJ3sJYٙ]lfz@;xPK lS;WEB-INF/PK lS;WEB-INF/classes/PK lS;WEB-INF/classes/org/PK lS;WEB-INF/classes/org/eclipse/PK lS;"WEB-INF/classes/org/eclipse/jetty/PK lS;(WEB-INF/classes/org/eclipse/jetty/tests/PK lS;/WEB-INF/classes/org/eclipse/jetty/tests/webapp/PK lS;SoQmWEB-INF/web.xmlSn0yBIP=Ѫ!,`V֐5 JcfggfwpZf*8@ XJ3} Ӹ5NJ:g'E3x/-dJNH/=;q %&5V9;xl~.ǬĴrB9*$Uc e%ӈѣ'r␍Ia**qZd^kQ[M$Nd[ qRwhSSXr34?h#AeY)`K{zw:כ[Yq!!oAmVbDIvܑ9@>B\/HH4|̹.3) j˸{ǃ6Q3P7 +H?P@v]'Ж=YrOSB2XVzʑӏCZCrN>Rs#[yRSeY-]ۗ-u/&{։5A%K6 @~LBZqw6`q:!' KJr g#ir`i!C}w S(bIZδlK9Z&6!lTTcL lx6 ?a5$9ts|tZ<^a[DϽE4yF<f$j`>p/\6`ױe^`Kٖ} %\f[(5cVQa0+ ~>;*ΐNu ٯ*FSgFYkW<\SUM'RPK lS;META-INF/maven/PK lS;'META-INF/maven/org.eclipse.jetty.tests/PK lS;4META-INF/maven/org.eclipse.jetty.tests/foo-webapp-3/PK kS;9;META-INF/maven/org.eclipse.jetty.tests/foo-webapp-3/pom.xmlTMo0 Wh9m[IaC(~ɾN"3:Y2$I(qܬ. G'RcV8 (3:<誼R  `fX1\im`2:Mhǵ@ "ub|%2/8zGnb9^6z> Ia9nga&.+!C>PV跍{ye#lzhUH0QtDƵZ2~<2q1w1k*}51[Av%8>4mhuX{pﷱ9%D/эƉԛF KHqk|3T$-6PK lS;y |BMETA-INF/maven/org.eclipse.jetty.tests/foo-webapp-3/pom.properties 1 НS@m@xͯbl v*nV:ue;cB4qb[t_7SABC*fu/kM+PK lS; AMETA-INF/PK lS;Df}'META-INF/MANIFEST.MFPK lS;AWEB-INF/PK lS;AWEB-INF/classes/PK lS;AWEB-INF/classes/org/PK lS;AEWEB-INF/classes/org/eclipse/PK lS;"AWEB-INF/classes/org/eclipse/jetty/PK lS;(AWEB-INF/classes/org/eclipse/jetty/tests/PK lS;/AWEB-INF/classes/org/eclipse/jetty/tests/webapp/PK lS;SoQmRWEB-INF/web.xmlPK lS;eJ@WEB-INF/classes/org/eclipse/jetty/tests/webapp/InfoServlet.classPK lS;AbMETA-INF/maven/PK lS;'AMETA-INF/maven/org.eclipse.jetty.tests/PK lS;4AMETA-INF/maven/org.eclipse.jetty.tests/foo-webapp-3/PK kS;9;&META-INF/maven/org.eclipse.jetty.tests/foo-webapp-3/pom.xmlPK lS;y |BG META-INF/maven/org.eclipse.jetty.tests/foo-webapp-3/pom.propertiesPK# jetty8-8.1.3/jetty-deploy/src/test/resources/webapps/logcommon.war000066400000000000000000001326071174773561500253620ustar00rootroot00000000000000PK l/; META-INF/PK l/;Df}META-INF/MANIFEST.MFMLK-. K-*ϳR03r,J,K-BV+$xRKRSt* 3R|RxJ3sJYٙ]lfz@;xPK l/;WEB-INF/PK l/; WEB-INF/lib/PK l/;WEB-INF/classes/PK l/;WEB-INF/classes/org/PK l/;WEB-INF/classes/org/eclipse/PK l/;"WEB-INF/classes/org/eclipse/jetty/PK l/;(WEB-INF/classes/org/eclipse/jetty/tests/PK l/;/WEB-INF/classes/org/eclipse/jetty/tests/webapp/PK Z9<4_6'WEB-INF/lib/commons-logging-api-1.1.jarpݒ-m۶m۶m۶mmm{wK}=W*Y3ƨZU  -LVTEVRN^`6!f5w Xl|ܐg ~+L0h'BQ*Nu%wa0uPiϹƲx% R9<V`>g"G^',o]/Z >X D64,=Z?"4bvUF}r_>*3;84RUKA-<Ϳ_FRXTNYeGKyk~ݩL,4(VRÎ,9 a 7'CMUj!6gO~*ֵ\?uRK֭rmÂ;[[gٸdW mVȅTw.m:{wgrzhGw_ow}Z?yep7X7+:Zn'AkG,ȶdYb-Rn~IpSmrEz?F.Ujϫ*Ƒz(|ږ=ބҪ35B@1[orX|)՝(Բ ^]!P hGW1+e9a8 6ܴƷlM$"ISH%!04Gkqapk,k:ڌ[jϻI~ / ǜ<:[I6:L_!Kt,C:% d4F<[r 5p}lB# (S/2&Ok}Γwb)zx^ h_`v,6hCRBk٫ք?Yˢh-:Hjt5aN$1[T;3?79r]o +|?ģr \SgPQ~j!.-Y(_B*\A?pN(h%hn%4͕mN)o; "z|eYALTN |V)6]^a-P3y|debÌL'UE2S $`v 3Dhr r|~M;VyG;p, 9aCS4 \(!_yw?p+5wrv Z%6D ~7`V 0Ro1 cq2\ <>3/N? |L Q`Pv£&-.!{A1hhE(rܐ3alx?)Z^7ƍ covxc,R kb 7Ϛ6h z8*`mqeH4-ШAy*'&BB-fc̞9Tg`'NAЪ`e%3U:KI?/[=ͯ4|?\?$:xo&8m gp6ҼS#jC>gP-k6QH<T 2 A";4c"mU~OK/5 拼"8friR(a(pɋ+K3!z8Rj絑2 f^o qI0F~ w<@ܨ5n_n6%{}qGZ?PvM4%ch3^5}1]K ,~d^5Ziel+"v a!RGf^ #=(UQSgXd) ıˁ+ .!rBi 1], K;il1G'"f{'moiӀ{ܾ|&Ld?#:Zs/8nW%(Z}R@;=OCBF3bO4FkGk8b0߱w<ڳazX6/ql>R8"֔؋H: ~ z"zygK)`S) r6^bHxqkFR)#?eFI]u ,x'kMͪ@ʱ݊Cp,qy+CeiyZﴍmv_qaG9:OF]9߯[!G!l`5+O1 VY [B{򸆉k6wkK/ lRnW30WSYq\JdH_f ڿl!e,9p8cfG]4$mRej[@&Z)20X)xد 1*#RԢ E\%eOR]1L虝/k1jQVQc~Z1RG.Lh^IƼlh (w9E KBF1CrN3%n :hc]b-d$Vʴ,7,}֋|]M((f1Cc{'Opl#FBe&.By]41)\̄(wJ sH 5V[X$F7_F]@%HRt@ pI 1I!O|dLjZ:! C: ny„/7 o Fڊv?s̍8U™^^IzPq@"2bRd5E}+櫒EPʖ`bgж3zKjw̯ AW65`Z24,f!I D:=b:s0"A [Wt\ ^7+Sn3FaQnV` -&aw+1 ] WFS8͞R_|W瀤.ԑ. BIP(8!*4kk+2(zGJEz2?Y_xsK%; ⸐IEz ݎT[ Sk3n#&bvp"%7_rZAs0eKeqXg)0h6;^`A+aL%}՛~0遾0g"^V?AIUgJ`PFD!2jJW.p,_˰Bߌgr7ųBΩw( ΁&H4R@MQD5o6]eB-RjY%>4pH <VafF1 /1Q\kfp"uVU2ח96e}Q_UG BZ Ubʌ[.  MMsKdw9N.s;~t?`cՌ'Ec=1=4T{xH;KĂ#'uUB+DGP!#6ʂ'!!kedI^X1c31Xh~4HE̲_jڇb/Ŵ6cV-ߛӿ|/;SktdGK/^{|x^OpQ=3:KXIaWBoV9lK%^q(X gM^)qy1w$FxG_7ࣁ70 琼A(kNK : ,f4KT=z``YfJ[45~c KΊULsH{({d\DE%!TJZ4 )H*1\ohC ᖤ_xɨ?!gDD!>qs ^uSQh$2RN5ҭt5RE j(&X2Q+TV"!nr.qÕ'˕'yř5Pk ˹ g|FMJ86^9Ƹ8T$ЪMΕ} ֺD9i_g(4Eu83qSqO0cXdSΥ"o' 1tM3;To]6z֤e ( ˪\Z fX7,5ߟYz ѥ͓0R7K8 C.N( Oͤ*;]VOm#y"A.vdFO? h;&4b.o-Ar .>Uz9ƆPo>(kw];=.-Q^ !U0bV+@rK>#=#l{z@MvI덹Íٞ]m/ԏ'3h@6 ~=q\l%qEVkgMq֮_q.:cj=\gKcpܮzYn.,Fx^_ BtoYBv0R[3o!8$ _^;{PJQ\xw6pv۽NW߷#ϡ޵ ϱ]MfCL"\ulNdW4{BJ1lRWͽwZ\"#%7c^#>mƸPA@Dm~ܓ$? %WǺw)t@6A`2J^iTZxc1s MAY^~"ήuCDjGMN9BSHp?!(S<Դmˈ/,7*Zd~JL!G3-ChiRA3 2B93)P)|Fsp!eH6[Cq򨕶g1pedXMlܒ{8DhXя'1ժM("&LQB{$eD\h8bq9cƍbo#s7)k%)8N-Lj ~ ī8Qsa|, |`s@k$cW[\<`c;>AE\ ȲTWD1_njO<,?Gi1 s5P!K̐29@28-!|K!%t2̮3 | ` =G2~vZwCY-HD9e a3̿R\8o8_-.Xb[ SKx6j`#ϮY`a׀ 04MD/r?HY9`C p{[0CJ8= ,ƲQu8$P»Cׂ,8w7g$DQӗWW6v++jkTU*ȕFu F!q/ *`WUt<{rCs}])hƵzղ,[KP{-]K=e y+ĀdѓMKLF 5yx Z~w6=|V_X gwa>->qiio9z`D{$aJV+*l/n.+l/,je ϥ-h.LUkQF)ZZ:d[Çi!-roڮ&u E1 #KIj/j9n9QPr"ѩuP mضŏZSqYGRL05{T3ܗG%Nt 49tm)4R ?T͝eq*jc?N8Ozsi: )':Ä$>&o"|h6e G+!WQUWZWThkʹQv%vfэl#b'4S=;`}WEРuAμ(\v|*Zj>b {z#eKyhzTY5#^VSh3%agzKt"$;lKȤ>*4PX]ndX??1#O$oGA[4q<@l3W"8kLjEV¸ !a͕4<-Ȥ|l_\Q}r5";'+K#2@ ~9q6q>^KQ`Y^Z -/8xeUeum"v}^qw/5Is 6`(V H捫R(n3FS9c3NԈ柆xQٸ/sL)zat"]vq#\^+NqUMԆ^!\©beT|jHmZ sbg2Tr'kU) b9ް9GJ H8b9G pMp eBUD 2LߣPPc9.Ir GC-C6llef+  BznL.R~bo1} }K1h3 -`2§(1,W*$y`Rs5, }) >,oTRnó~1KuAIcƌfnXV)-&31DBZR.tGYpO.ALj#XTf ,+hFB׍p/L~{ )m )jȔdeBP+g]݈Aϡ[*멚qV#!YZL[=_f̊}* Kn) x/_ 'h%=Qy";ҏ*v2զ ""?\PtDTr>PR/֭-ݱ}D̔19 2 j,o{L=4pLWIYl,F6w4~HZGF9KҐpU .#(Nꢩ?℣l O*QvC ZďGf WĹҸI>;B1DfJ !|xPlL/7 %vm{ 2Jkm: |k\"2ebǟ/[ZMs'&eĄcSEh?M ٚ ,j&3cd,9Cj7On&㬨GP7eOcoQz+QXIT ,Gp`C)7ȄQ6u0.ayGv\OáC h-,.,%lkm+}RJw!훧4ߨYc|.!oCAD?- o4[΀+~"Z|}?Hϕ{%3L~O Iw!3}yĜܶpugWVL%[<8X ;xY Ķ_=tQ &e5I:E- eeD!\d&2}h^|eC|5Hf19R"~zmlqFmہ︁snǴPcY :P2P1;#^Ck[ | [Gh8tA,m9 ruH`BA-QR5r&g/Au5zQ$ly׌N{o@w)&n/TH>@"h + >XZ +tNZ[\\wY9vfMs**'ۓ5"p%F/Lpa 4gnğ<xKO &2yrOVfJeu; Sa7!3)MU*uW?`s<¤Ue̡̧T>M3!7 LNT5>P?jBBQFd;lWpbQ6S6kSYrvW ~J,MFޡsT)'$;D5S.HQPөW/^K!SNVz"J@IZ[\im Uی.ݙsBWoG)ۍͥpI}9aUoL%nL nRGDN6I(DL AHO2RϰG@9jz,9 7hЌ:Ɵd q^t@ygʔ"YR/H<ՍJWȢI^NrTc,-w([ΆYb~gS̜uНkdȅC6ҾآM= Z%=GMF@S\#vnʀ>HS$T&H&L*i;9"0,T9@YcVĔ,X 41]<|LnݨDR EԖ3ϓjBn9áߋ>*52iմo >Ȗ`Ig-3a WV_ ٖ!/mu6tMCmƪP-.͎p[@oYN#%Țe ĨȜ K`#Q<ܰsu͐e)+*(h\#Y):Ekma>d..έ v?d8k,THl猴RYrS[R^.= o=Q$Dz†gt>D$RrrE )Z%g -e Nt=,"w LKrnZ΢^ECjfp+8NyS-և~FjWq;^8B0иu}r)0ᄎiqM R $`yIؐ|>0p傲TNE73+XX8".yƍ YZa`.,-2H/3fyT vƩ OP;Y<և`ڦ޻jjVm:G.AØ^{qvƔ4fz%n@NFd=^3)L(əTh6x'c-83TW,Uu%{֌xfJU>ɽ6]x#]0Z&ܠG0u{WKČ="C6.D~VeF"kZbZveπH-x/:|B#$(˶t۳'ܓ'[n/-]< FhzSyS)=S]"MiS74՝]Ԅ_{>ʐl9#WASJ07`{Aݖ>h7+7r =$~7`p~2)»s/^7pp~!XMt8;kށ7[7/n/c L$ٳ3ta"vM{!Fz;.F{4LlH~2hvݵʷ];}h/ =s^T>;na} Em@)z>TgQȕ(˖tj'g"UWHKZH|"iIx<X3[\hD9QҜzd@Y` dYQDAGϬaXHh뎕MP$@cx2H^Rb5~'+-%f.Io83 M۰$ׁZN}rNH']eӂcƐ`'Nc~A ◁XZoa-~F\:G;jzF7$[= A_+# W,C`a]25 \U8yNA9M͸9Nwm]YAj5ȈxAU{٦mIS)_%-E; tM׶m۶m۶m<׶m۶m۶ow3lҩʩ9u ublb8l]ر&?" b`{gCDnّ NUٹgžxa^qzAS *z:'*zk=J]Zժ=ܐc`'w2ojt yn^{my5+w M!buݓ.qݭġW#@fL bPj:7i*xoUmc+Მ;Gug'yG cOl- 6+|EWrulwdsxn/ϭ]u؋hq㾣< ש*&s44P0)xdIs}LHa/"w[(}|j?wD/b/P/~)g߰V+?HroX/w=k~}6/"Bľ$T„Fh vH$LcJ% Xѵ^XbyK3I_J]('*E%ȖQA4C7(Mm.gld.nNo9 S 9TPzջGY.1`ŁT1'Ey?vDpO=ëlFU(,50כN^j(5@HhV)"UJ7"^=-^務&53z7&ڰֆYjF&[3ܞ,JѶZ3 Eܧb,YLÀN< %P^/s .@L aʆէa0dSXw/ek4dws4 CBӌJm"491F_kY1D65<&0-d{YBI0{2RwJ'wz3 \X$%G鯏D8RZ_05br) ( h1Z(XxlQn`6+!Q@iK_T:59[-Ob7B_tA-Qmnϖh+3pţ+PNrم42e jey1h_ wSOh,9Skmx(˸e=s\*):G涎"t*1 M8KK$&vAZh^W@<*ׄ#1OOy{m o 0[ Roӭ~0#mCKZg_97{gX Z>"e+Xg gV@6;:$SB&3"s >Am7g-sw6Zlkf"'t<퉧5EO_Ȯͫ"GoRzQ'%2g6$;wDF],RUPwF|߄s=̢8Q$T")=6e^?Y#+.w39S87n03" ORlesO0cHuv1F"9ʰ!G]<1|0Fx``% cb?@q|+42}Y0t}0wb?u'=-J [@1geM͌~Ou0gXeLҒ((9Cń&4Rو  YM̼/("#j-RjIP@L4y^N+T~z>= zdgwBr(9EvG*US8jS=Ft .G! XS_TZ2Fpۚ>R^g##EȑU;}عht$w#m#} , e,F ӚhC^S?"]&#s";ԪЀ-__j|)\Ͼպ0(r@[MA;\ݫ~}B&#5h=zqLݾW=iKŊ$NFhU~)iX[`G)D;3\Nik8Fĉs~dEm$moz[M.ɋ9qD4- Ф7Ը:BhC ȦXb5m#1> n||F{i g;Yg4͐/*6@~6ﭬE˧laL3$5Gx^~W ,FuDa\?# ~Y4LjO`.K` Lhũ&lSiJ4I - ^_Z'g>i[>v(8Ymg(=%Nc;|'T=bz$ʑw.maɎہl!g}A͌Gʗ4E0Xp55tI8~"j#1s,D)+kr<rr=CP~QJ6BI6%j]3sTc4Q+PZN`?+'7[jl~6?tdXY,[=LnfOVM/U;u<.#?!+θG 5P'] Ƚ69ߴ %O&N_{C< p?a`Ү"6oy'C%ktPSw#?Kxv C_jF 5Ve=7l & ۷dsdN dJhCꌊ`[m;٠q)9qgszVj !S"nAӱW=C4~((#Jufv t;=wIш/<i%F zǤ])@3XL]]Agi`?M>`x-eb57u?&UV[e^?8n2 )o^RX!_asMpD жr0@ =h2.wpgbDwpth狌iǘc!g=! Hi0/)91př2ZcOկg*T&1ZFb{ˆ̙SMWSmp$4ܕ8g >$yݸe|yJ]mHSB(6Pa*0p|es]b4,=Uhd;3KٜWl[/[@zdh21QCa8R_L>OKe^+nK!vgYhVtQ,z^RF,9ke%:6~yj! ҵ"SS*TL;ȺO%R.f<X''g\~QE)4ocەUA8Ɋ8i(0~m}`NJ\l$?^Y*J%F cƛE*lmԩKŠe&!J-X dvڄi-P= 8WISdGWƍ8'AuEBfĠ+fT~{m")1p#1jS1)@|C6#E=FjCP~HAk4˔ Cl47Wڈ7+|SYF.6U,m6sYHn#M&;^nʄVePOV9 ܕ>vi3۶M#g+ =fml67޸O դ(}%2e {IjNmJOeY܈8DlFRC; /<./^>YQYWtnےv*9& oDK=D~aw>h335 _t(&`ٖ4VtJWb3|'qm@U[Y^nGxh>)bh*QW0ƀ`HD~=5=D1[qP2alliD.臱[3穲s3{M1k{ہU5120*m{;1!ddpmavWǶXȯ;/xZhwٲl= ~aBvuE'G@"q52(ҢUzA +V`qDNmr}@"Q"Vw0QEM!p行*ܢA4AYU$ZKM!JJQ(uHY04F69ucK~7mevOnAk{hIӼcd.4EM],铑 YFk&  Ah^bLvF}J[ghjggTHKKmKjU_ʍḻ,CVWmV :|0ǡ.Ezqkl+|ؒkv n &cj(cS K%R-݊cVٹGnޒcY;0X޹GS,ʃ.nőG\ۅؗ0ۅ1ׯΘĘؘwIl##n;_Q_ّ:k bUnnhU K:nBm3?I 8 B'5G=B(yB9p+.C^SlzBInr,w2="4N9L9 @Wr~~Ӓ3a޳9'X2c,ok'Kv u~~G9?ڐ}!ADBOD e]97EK'HO-95OMdBfŘlQ1fF,iF b,8- iLҘ,X8,vڧB{߲'ӓV;MBO|ջiCN4®t٫]Czq:x:9㎐t! CM SIJ%̒c-Iӝ^09Hu l#UE 41u;ظE (E1jϑTHOr1橑b9D m(~UAwhHoE¶$ԏ09 lD+egxd 'ލ-W `Ŷ.%†lNPA""ʓ7%B#dz `4F|ePS{,9P=@'@a&wboI:,lk ^5a&& Ѳ`ߌQHB|i6V+$7)ۢe_k&Uynp0&K>CL56r"@憱'+[Ijn~#EniF?0),=CEA}=ҼTŶܫ mH![Tn+8*[,3N3WAją&QܶAwiLħv[e)6F*DLg´sLaaʝc}fEuP\2vԆ렍}#hȰ(hXCPJãjfn %Yq^vkQ3M::[^w^LȬ|fI~}\t_]+?:<+k2 ,CTPѹPV3U;%RzNYsy E*gdW3F!ckJCR[,\DŃ&9CEy(o[:!GLbo4*ס)8k ǹo߲7Pt<ȿv|=t8SP^ieYy["m\`yhzB1LҒB5O>V8y(8Ґ 'N/"Ad5.og7@ox ]dr*55iث.=Ef|Ȱ\/bRd2rh@i l=/)fYu7l" C[vAK'h'|訄-LtI /vkNMlG]T번&j!lʵSYYJSm5tH\jo䄭ZJ/#k"dh$[v!j5S\m 4H2ߩ^}{ɫm5ؑakl`,5O}c/~T6 4m?r(g1N*H϶mg008aJ~@sUG kZ,w|hKdOؖ6ga5ո-w좶D_]?.džڳKs͗q|¬,,cv {z <7$ԭs~Ѱv?_rbcM4Qco`#h!mY` 6^$;v]DmIc4 'h Ѝݿre $!)[!g -h "uͭ @RH)*zmMxj:.=kT"˕ݙd#DA\>EDY-B h=nſpS}$kRwXк  ATHzSPz7~bJ R&_F/[7p4W28A! #&qVL 6{kI=Mښ .9+Ћ("V}:Y\ҵ55ͻY;Wy_D|i7~AdfXovZ}RO^Z]޾sV9Kk*vV3|@TmvaTA|N%ˈa5zx3)l-1:\=T.2ĺ-bczDY3L~Bȕ'3dz-(٠}2sN7M2aMdS-uerZ 'gf?,~$ZWQ;phucq}S`1.it7%0e۵XSR&dg`SalbA$dL54w]p7Jb;c}30b֕GpA0AS%grQB۽F7ʼnvD/*42,.ՐHH@KRۃF3 ۞G֯P>yR'2_`J{*^e1Lk\8 )u8c)c*|JS5VW!ioKv_!,2D0#kz-X9yP EP q4 M0S]-\M9T-A|Yyc]&;= Dr"A)f7epϜ>6G-޻9~݉msebXT+bqnmCPe&kb@Ja)45d?"pڼU!ʒչi\)r_"3' _kK{ʹzOxߛ߿m1ftARHǹ2Xhjk)iنo#]σKL^@%!1seʡE0RZ\&2t$w6ЉF's(Ծ~dPJhvM^K6[5f <4*Hc_摙Qzfذ=7#I"@|1rRj]JOSfu%!'% ^E񣙳g)N4#Hh {{%")TѯI ̤)m"jT2bD`N!*{ϏM6yU7;*ߛ#s6EvZ!P֧3tkA;r K틨ѳpV/ lOe\Fw^ XG&rL SED^hM7iD瑮*eJ$Bb"tiKx&vYPpG*;hBl_䝭{'zÐ;kJ젮InAW8KLhF.s9pbVLnVrVɳs ёF{iwc5u )Ec0ut)<u)5 ||*T{!X3+~pMTl?ԓii{f)0 ϣqX H;  vvc ֵy|3?> ysrj抂J"Iۡoa$'{<֎u|.7"2uŲ_9=!drDІi0Y_0#ZY6P *e_3)=_W~TCnsۡ[Ķ]VdN]W`A$]%eQBĞCjZF76>[GաZVu;8raȊZ|R`nz]7[2'$grʣ,3Խcm߰_U~ll= 5O`'ksWy~ؕί`v~㽦S _fq) 5r*jh)BퟤUIz5ZULz-zӲQc6*HJZ+/[kMq-M~U-RN1[UT-j[9k@ CR\C&^' E 1,SNTFꩢd; ;c_zL[B ܱגAe4!E@F!_?X+8Jn 2`YVh/(21* I0b

l^灱!4qK{HI'|"Ma& z>b>k}пt#^:2ĻZa탤M%1C OC-.86+?KVt+(8 ˗ͣ!ZrJzi]ca%(N;,$k#; traKM00wmíO!7.MFi!{M>r˔H:q&7yKK*AHEF%"-:* ܂y0t+R9Xk>H#U `=\.#>熣CzLuž /PĭAG!r cR {>nJ̍"`+EV` V/o07en TjdXKIG 4a5ZxҘ@`= ɡ_Q_f,z4pRZ58@._-H' yr[f1&uw&ɒÌuL0(;}GHNl \犃b..WBѽ+^j3bcTƩw}(ɰs(,V3#3!Q饵2;+6g hrVī;Tz8GaPxb\Tz儛r,W 7nIIFюjq]sٮwn.xP[jAo+}[|PюB7z+5>gCVA(& C21C3uPIXR' < 83 ZK$ Brn2 Vj_п >׾bH yq wF'lfc+)-=K'~1"".'Jc:pR_d|#d i-mȤ, _EvOX[Ky/ꚰ6pCK4$ks?жo~b Oyhn('^~?D? .?(wjl8i>^P"X]A ["Itpuw$$ɚά8Ǣ1VW.%֏e;n39@% )'ߒgz'll>5ha *ˋj@0[+d xM# bh`)QMZ".r.J6v\aV(#69ؐg(:aaf0g vJB{T |b 2^'|T 5 xxG;s쉟^ZR gEإ',{PxM0mA)E6M͍Zfߝ,d<ٵ|ΌmVE}駘&]HqbKg΂,0f3=@}`@5Y/O]X>"fN7ziסs@cˉGC^mĀ2${;jjڊ-.seی,KR,s0rSY  ?{ww57`>hFj=Z$?o[T,٧0VVpJ՝!S=z%|AϛBO?q~DVv56irȔ0MUxY 8K߂s&%tѻLpxHL*q*[wvpJ0w$ߘ;i N1 ROE{.l4Uvņ.v48MlN[E`}tk ct̸+Hse;Dc0=h&] }HSuFsO=BqMVB!>@D^_U1M-Z\='$C R(_OPGFo/1OP_$vdzwӐړQؘʋoOb=%w֦Ċ^ī=B ,d3~'Q@ovF~鶧twN:&?hm?Y?r ?\K*w4!)ʶ#_vj)!Nިv`/l&l$"KDUI.RTԏ0^sϾ8&QlӜ~ XEQB[.GÊ f-pͲhVyW{8)[a "ﶉE+/_!'qcu676z Y5˦,W vfj2 ^̔MDѣUE ƶn !S>U\8X8"f ̓ XX^q94!b:_n4y;һ亗 tٖ9H0# }aT\h*p xx*ِųvjƄ12W0VnC5YOiIiAdfI8H  I<Hy !QɑOM@XhݸEl.AX^kZovu~ No@0y~:}M3SߓJI$ƈgX6+~v`c([?V7:0.j,q Š[u)ŬYm\ RUm;MRW(uHImRȶ.Vzw?/zu-H*ϰu;?.}:eѧ, ?,>3y)dyU$=*ffi _<;< 4g!'UsBG|$y^x}6C3 E6Nէ-%禞bZ榜rZY䥝|&\%"m]^&Y+[[,IreԘn:}1_+pw[-zl a?#}e}Rͧ?ב[>C}ͩK^HyΜ%uQ;c=c}.ړ_[Pq]Rw LzMwM"]Ls _̉[̒NVlQjJLq%zN0h&W@$Czi0HCg1_ԑf‹} ? A4.7p6읹j\LpCsA>MP>ȧ&^gw" :: aUnZRLLkE{:MSUWY"(=AςKQ>l3Mi߱ ˽ۤ 9 +5N{Ia!{1`(r, Ŋ6A*Bkyf3 CHFjB,;!j(f@2p Qw$U@ Khd=tŔa2Zam%8S_[Vjjk-0Uv6.GpeTXc_RSkkͥdU_iE*-D*mmlARᴔ5]"imiIʢ"KhVgcLtX9b99YE"aw+(OUFni4k`i0!Tu0yκ5{>;HoBQ+Bŀf5&əiWR O4CX=0yC 逕l=2\sSEx#@f#jų@*f4nFQJm/N-h\HU*adP-Y2C`is`A\*l$ǡHZ!%kYL, Pv$"\8,#t2 22mV.,|I72"PA-gA؎g}rNdr 5a1byd#TupB4QYei%YpJ| <"hK;Д{"ۍ"哬ISYLJWFZrĘ TٲY5=;3 Y4NBT ċqALD*MRU*Dj=UGњoZQrFJN}ѩ+15$V꿕vQq%[n 8 .[p 4Cp Cp! /ν_&w:OQZUwծ[L0:=OoU@oT%j wX͟$,kFȀinMϪ@XFVKkuoyaMa3Yg:om RBB$wH_Y>WΏ(O9aշ9`bSD=uOw6v20âfUUO$%}YUy )kQzH׻X܀%k,;[( A :>KVGT:UY,wc,9pLI?jYyBq4gڡ0x'hOy!|op #Ĭ04%ђ{b,T<434J^GC/Ex^2/'mS"L:2&ExXoN8t K^Q:N wԠ\!3^܂+s \C}*3&U#tf-q!JA0ʤy bh+q^Yn})p8hML~O2$A/<|`UE _2.I)];LJ+* mNsD-LIA{%9>mb 7':0yt|ní!'22K { tH}gHwr}Ts97C/#EՆlc;aaVw#*+<(F5dsM(JB?OOJT߹&(O9Q14PG8_)͢։=t޷ݟZ55 ffqoO,o@WWd0灂U(/bHUN3: sxm|&üDHuZlDI 㸛vEYX. #ʩD]q*tt<|> Jm{ ʌı([%jl칏![\Còc,̽zRm~(ҷĻA7CŨJ3g_A,ڄ|ri>2OʅAH +v/ .qI.ͯ: R6ge,&5W!˹%ʗ7` Ft>),Rʋq*;bn_* p-VL⥋ݲ sҨ7߰{cZW`O?e,蜌f?Եΰ ۳8m -de]Bn:+n3"-A9-@P'Cr@4+X6{|@u96JZ]/u8v1ÅЊɰ5e|/oQ-+)ﴴg5]{ )jP/SR`c]5vЦ!Յ_6^!Iu9%N4|@[~@91JQ Rlܹ6Z[nCҰŵJyrǼW^&sTݣηZy[~q=6ɘCQgx]a 6`UƩM)9s.71eq`AZ1^t Z#crx4 `Ċa=ՌBgW,Y-9'H]Pb%|q ʔnpo*lϔsߓ QrWoCS͋^Id|>D .H6#0SP_pBh R掆Fcg͠:;bm ѫ B·\zhll :.}/whx?W*b>߈7Hvnٻ-թ%Ͳ,DIzzJ v|=ifgf7X! N '7}(8ׄnJ8{5s|v'-(_:fTUƼvi}IRa#'߼)Ϫ"99L%! : L~M^Cd燪łg_aB6ǂk7D0GaE5+;%Hu͟s$۪Pe&dNF%0vûF NxGOHC |7CN.ۖb.K4K<:6S5!*)%k(Z/aϝN%g\ڴjP-!Hi#t*IG_ߢ~gIu`\c(PJ"[$@!VI6< >ێ0Wk%t`6fa?pG'=_+ *v{TB3: 8~V%gŎcS_U^ uK`ְ$j˓ _\,\(|3dhy%p`U:!a-4&WU&|O}LG8s2+8 1/wkS036v@-ܾopg].Q3:|:g}%mkphX&ë8}ej*km͹0cݣ1keŭg\5B Lh)4Q(2|]bX[T.1?{L_x2ƧNu~4H;'Y5DJOQd6fMHi9_8VcJ vM^FE__/])`Q.}ý8|,^~XNBئ3H.A-dW] LhLUfhT VeVVj ړ+ͪ}V&H(fá{[ӷCh K:%ddCFN!y't*[XLX8޲Aʹ.R\JNE_G"e 0faJ詈VUXQ)z>7͔zV9`zb1oB]ɷUMJFPy2je(oٟcwz=zp/qL͗:+="[Qrro  +f6vrՃB7.IB0}׮ lٺxHZhZB{ @ж4ݗhߓfX2vKʳnMR`~QB " G2h6kG#5|{sY(9z0 \c_L598ZҫKZE S|Լ Kz@q>OBJz$D`{wb){Be.N5XD.5,PXː}dOHKk ՏbKȺ!n(_@*)SS(N7Ly2y r "c:Gnۯ],_~U=󒭎JN-t^߬Ϧ>j*K׻RPq%o GKy~Ng,:{ݹ2Ɖẖ΀dB<}XjcQ}e䇪.>Tn$'^q_ 0&F~e>V5߰cX8]BRԨ'},a/T*ĠUV^1>=I4>m\ נ ?+6xߕt; );~/'1 vüzصxݨ^iiɰW7Ҙ̀uE աDڦ'FiPM]Bk ^-CikcDZ7/@w;F^X%P\<8|FGw8NǷy]{">k[&Rб/rpZZLlfg:aJp1 ecL[W)eC`}r=E|CǍn>Pr#47҄0&0|ϔ;Y>DrQl{qal+E%@"anG{`^c'-MaOLXEp riž, yMG&֧E2`#tTL8;\%ڛ1]6fo?NHA# Ɖ/;Di^bKw"Z&^Z|۽i'|di}kDU7﵊DؒRㅧd,L|a>¿>lA 'NhφJ{TQ 2WxO.YzBC}ଟnFg=IfĶk{m2ĞU ε OX嵞ٿ4܅] R;LՄ}Ji(l\Iq1ljjAK&Q^K.J9)rϽ%#4#uNYYʂudܰk_5~_z= }JQ0.`yK}0hI֊D!v0Ҧ0[+ҶWZP'70VN!Y:y۲ FM31 0@+wR.Rj3ruOak'\MR~@dj(CId5L>mLBbTÔVs=qfia+EOu9Nqtv80X V+)Eբ]ZG,chu&UR 7^K)4`%ڼIm$cGqE\xLlJ<'Jy~g($<:A]JH_`/1ݩN(WՖ33 cQHm̅/x68eTa6(؉Kh*"x*'aу ymuf4 Rb¬oDal3K& 1D( Ԅfnjl+3ǚlڹhW o>59}@ďRA -8SiN= D\~f4gX3C'ݒr2OФRfStWs&JcNWKhjE]f4Rvg-ު߾?aܱPLnjUSyzptQ*%T{qMI( 3Xgpb5 kUeǭx=i9 qזor(BNy<0ǓYXD0]7PT;]o4 tK]yܟD'+nC{ {QGG:@yqU&i ~;:10TK_?VQWQexLZB9i1qqfGDŽ?J?_ ((` ?_] w?@/K4?4x&Пm~KiA-l㳋Vo7ruKt~(~|B oD1kS[{CG1?q6rMgo:J@ctGH$c4_E96t:IU4ǟTD`a*'ܨ7?ct_EsPqb5 0ާ??F'Zl*/CBk8cϫ|o~ӆģ$/Vp7xr)=y)3z?)Iea~h)ǜJPK Mt(;bMp7WEB-INF/web.xmlSn0ﶁ JUJDL#ljIx$--G`ZA*3!!DYLHb2=6WB69/˒,+>Gm6֐J Zi" ȝd5,RJ`n=8b cFc|E+ݴh|aߘMx^+̵S#S:K'uif:;*A;Е@B{@B*x/umj +ն -v99i8F/\ƭӱN}\ͼq}%NˏD_03 h5o׈[۝Su;'Z(6n|i>PK l/;oLyCWEB-INF/classes/org/eclipse/jetty/tests/webapp/LoggingServlet.classUrD?"QTB uH)!ILR峬9y^bx(=Yd\ډgw{۽ݽ_';8;>.>>qobgfoiUu_T064Gb$L@Ema[WQEE8e2J֑8n("m$ b|RXx}z\綔dY @E~PZW]pDrwpܑɁ8R'(JÒ)^ĩtCWT86˶LNBkfدe?uӱk!51M6dlp$G`R͕qnmȓ\8)rJcS{4]E}=pOD"{FÔWRyb?'Լh3,n ק|"WKړaSxZ%Cjs_ꖙ'wkf=iڬO1ki ;ZLu] 4i$Qg=Ex Yd-bxN\Wo yD8ぅ3< +J_PG)̆Dt \-B_&3Fx'y!C26+5]@0B%Ύ澯^|K^+N^ { >]H3 1`vf j}D9@& 7?PK l/;META-INF/maven/PK l/;'META-INF/maven/org.eclipse.jetty.tests/PK l/;DMETA-INF/maven/org.eclipse.jetty.tests/dummy-webapp-logging-commons/PK Mt(;APKMETA-INF/maven/org.eclipse.jetty.tests/dummy-webapp-logging-commons/pom.xmlTn0+XڃD;Mnp)̔~},+j0]gKFgL *hH *y:~_~ > A&ȀR2}㚩bE-G~ʊ|>s.%C4$!Yn!VfayB\e(d̂L4`yYńd+ о q!j .Eaܖ+)8 9zpqDK'l7oZ DŪkb.XqȬocm1t݆PWJTB$Bxnl&;)q*C痳Eաن*= P./4U7梔ysDމatش n7W{!ΈؾhL]X@ƲV11>9WYg^܌<:ݍI(CFƞ rjUI4p܃Ђ&3mŚqaRf>ŠE U pt3cQg!"vfѪ#$gd2!3ȭfRkvvu7w%kzLJa.o1tRH/eySGm|{5'T>PBꢾEMWZqQm˖l|Y飴IC}hkP@xs/RmS=>=tmi0+cf3sZ JWxY+|tM#}ym&0*a_T>=}mػP?PK l/;fRMETA-INF/maven/org.eclipse.jetty.tests/dummy-webapp-logging-commons/pom.properties K 0}N1uB?Ѕ+uQ "͇dZ_uEI0UjG醮&3;0exh|\^T̤:d. ̔NdzYw c[0z×\PK l/; AMETA-INF/PK l/;Df}'META-INF/MANIFEST.MFPK l/;AWEB-INF/PK l/; AWEB-INF/lib/PK l/;AWEB-INF/classes/PK l/;A=WEB-INF/classes/org/PK l/;AoWEB-INF/classes/org/eclipse/PK l/;"AWEB-INF/classes/org/eclipse/jetty/PK l/;(AWEB-INF/classes/org/eclipse/jetty/tests/PK l/;/A/WEB-INF/classes/org/eclipse/jetty/tests/webapp/PK Z9<4_6'|WEB-INF/lib/commons-logging-api-1.1.jarPK Mt(;bMp7 WEB-INF/web.xmlPK l/;oLyCWEB-INF/classes/org/eclipse/jetty/tests/webapp/LoggingServlet.classPK l/;AMETA-INF/maven/PK l/;'AĪMETA-INF/maven/org.eclipse.jetty.tests/PK l/;DA META-INF/maven/org.eclipse.jetty.tests/dummy-webapp-logging-commons/PK Mt(;APKkMETA-INF/maven/org.eclipse.jetty.tests/dummy-webapp-logging-commons/pom.xmlPK l/;fRĮMETA-INF/maven/org.eclipse.jetty.tests/dummy-webapp-logging-commons/pom.propertiesPKjetty8-8.1.3/jetty-distribution/000077500000000000000000000000001174773561500166465ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/pom.xml000066400000000000000000000442771174773561500202010ustar00rootroot00000000000000 4.0.0 org.eclipse.jetty jetty-project 8.1.3.v20120416 jetty-distribution Jetty :: Distribution Assemblies pom target/distribution org.apache.maven.plugins maven-resources-plugin copy-base-assembly-tree generate-resources copy-resources false true ${assembly-directory} ${basedir}/src/main/resources org.apache.maven.plugins maven-antrun-plugin generate-resources run org.apache.maven.plugins maven-remote-resources-plugin generate-resources process org.eclipse.jetty.toolchain:jetty-artifact-remote-resources:1.0 org.eclipse.jetty.toolchain:jetty-distribution-remote-resources:1.1 ${assembly-directory} maven-dependency-plugin copy generate-resources copy org.eclipse.jetty jetty-project ${project.version} version txt true ${assembly-directory}/ VERSION.txt org.eclipse.jetty test-jetty-webapp ${project.version} war true ** ${assembly-directory}/webapps test.war org.eclipse.jetty jetty-start ${project.version} jar true ** ${assembly-directory} start.jar copy-lib-deps generate-resources copy-dependencies org.eclipse.jetty org.eclipse.jetty.orbit,org.eclipse.jetty.spdy jetty-all,jetty-start,jetty-monitor,jetty-jsp jar ${assembly-directory}/lib copy-orbit-servlet-api-deps generate-resources copy org.eclipse.jetty.orbit javax.servlet ${orbit-servlet-api-version} true ${assembly-directory}/lib servlet-api-3.0.jar copy-orbit-lib-annotations-deps generate-resources copy-dependencies org.eclipse.jetty.orbit javax.annotation,org.objectweb.asm jar ${assembly-directory}/lib/annotations copy-orbit-lib-jta-deps generate-resources copy-dependencies org.eclipse.jetty.orbit javax.transaction jar ${assembly-directory}/lib/jta copy-orbit-lib-jndi-deps generate-resources copy-dependencies org.eclipse.jetty.orbit javax.mail.glassfish,javax.activation jar ${assembly-directory}/lib/jndi copy-orbit-lib-jsp-deps generate-resources copy-dependencies org.eclipse.jetty.orbit com.sun.el,javax.el,javax.servlet.jsp,javax.servlet.jsp.jstl,org.apache.jasper.glassfish,org.apache.taglibs.standard.glassfish,org.eclipse.jdt.core jar ${assembly-directory}/lib/jsp unpack-config-deps generate-resources unpack-dependencies org.eclipse.jetty config false META-INF/** ${assembly-directory} copy-lib-monitor-deps generate-resources copy-dependencies org.eclipse.jetty jetty-monitor jar true ${assembly-directory}/lib/monitor unpack-javadoc generate-resources unpack-dependencies org.eclipse.jetty.aggregate jetty-all javadoc true ${assembly-directory}/javadoc org.apache.maven.plugins maven-assembly-plugin src/main/assembly/jetty-assembly.xml gnu false package single org.apache.maven.plugins maven-pmd-plugin true org.codehaus.mojo findbugs-maven-plugin true org.eclipse.jetty.orbit javax.annotation org.eclipse.jetty.orbit org.objectweb.asm org.eclipse.jetty.orbit javax.activation org.eclipse.jetty.orbit javax.mail.glassfish org.eclipse.jetty.orbit javax.transaction org.eclipse.jetty.orbit javax.security.auth.message org.eclipse.jetty jetty-jsp ${project.version} org.eclipse.jetty jetty-deploy ${project.version} org.eclipse.jetty jetty-rewrite ${project.version} org.eclipse.jetty jetty-ajp ${project.version} org.eclipse.jetty jetty-annotations ${project.version} org.eclipse.jetty test-jetty-webapp war ${project.version} org.eclipse.jetty jetty-jmx ${project.version} org.eclipse.jetty jetty-jndi ${project.version} org.eclipse.jetty jetty-plus ${project.version} org.eclipse.jetty jetty-client ${project.version} org.eclipse.jetty jetty-continuation ${project.version} org.eclipse.jetty jetty-start ${project.version} org.eclipse.jetty jetty-policy ${project.version} org.eclipse.jetty jetty-servlets ${project.version} org.eclipse.jetty jetty-monitor ${project.version} org.eclipse.jetty jetty-websocket ${project.version} org.eclipse.jetty jetty-overlay-deployer ${project.version} org.eclipse.jetty.aggregate jetty-all javadoc jar ${project.version} JDK7-plus-modules [1.7,) maven-dependency-plugin copy-lib-spdy-deps process-resources copy-dependencies org.eclipse.jetty.spdy jar ${assembly-directory}/lib/spdy copy-spdy process-resources copy org.eclipse.jetty.spdy spdy-jetty-http-webapp ${project.version} war true ** ${assembly-directory}/webapps spdy.war unpack-spdy process-resources unpack-dependencies org.eclipse.jetty.spdy config false META-INF/** ${assembly-directory} org.eclipse.jetty.spdy spdy-core ${project.version} org.eclipse.jetty.spdy spdy-jetty ${project.version} org.eclipse.jetty.spdy spdy-jetty-http ${project.version} org.eclipse.jetty.spdy spdy-jetty-http-webapp ${project.version} war jetty8-8.1.3/jetty-distribution/src/000077500000000000000000000000001174773561500174355ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/000077500000000000000000000000001174773561500203615ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/assembly/000077500000000000000000000000001174773561500222005ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/assembly/jetty-assembly.xml000066400000000000000000000007041174773561500256770ustar00rootroot00000000000000 assembly tar.gz zip ${assembly-directory} ** **/META-INF/** *-config.jar jetty8-8.1.3/jetty-distribution/src/main/assembly/jetty-src.xml000066400000000000000000000005651174773561500246540ustar00rootroot00000000000000 src zip ${basedir}/../ **/** **/target/** jetty8-8.1.3/jetty-distribution/src/main/assembly/site-component.xml000066400000000000000000000007451174773561500256740ustar00rootroot00000000000000 site-component jar ${basedir}/target/dist-src jetty-distribution-${version}-site-component target/site/** README** VERSION** LICENSES/** jetty8-8.1.3/jetty-distribution/src/main/resources/000077500000000000000000000000001174773561500223735ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/README.txt000066400000000000000000000027221174773561500240740ustar00rootroot00000000000000 JETTY ===== The Jetty project is a 100% Java HTTP Server, HTTP Client and Servlet Container. The Jetty @ eclipse project is based on the Jetty project at codehaus http://jetty.codehaus.org Ongoing development is now at the eclipse foundation http://www.eclipse.org/jetty/ Jetty @ eclipse is open source and is dual licensed using the apache 2.0 and eclipse public license 1.0. You may choose either license when distributing jetty. BUILDING JETTY ============== Jetty uses maven 2 as its build system. Maven will fetch the dependancies, build the server and assemble a runnable version: mvn install RUNNING JETTY ============= The run directory is either the top-level of a binary release or jetty-distribution/target/assembly-prep directory when built from source. To run with the default options: java -jar start.jar To see the available options and the default arguments provided by the start.ini file: java -jar start.jar --help To run with extra configuration file(s) appended, eg SSL java -jar start.jar etc/jetty-ssl.xml To run with properties java -jar start.jar jetty.port=8081 To run with extra configuration file(s) prepended, eg logging & jmx java -jar start.jar --pre=etc/jetty-logging.xml --pre=etc/jetty-jmx.xml To run without the args from start.ini java -jar start.jar --ini OPTIONS=Server,websocket etc/jetty.xml etc/jetty-deploy.xml etc/jetty-ssl.xml to list the know OPTIONS: java -jar start.jar --list-options jetty8-8.1.3/jetty-distribution/src/main/resources/bin/000077500000000000000000000000001174773561500231435ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/bin/README.jetty-cygwin.txt.txt000066400000000000000000000006451174773561500301200ustar00rootroot00000000000000Before running jetty-cygwin.sh on cygwin, define the JAVA_HOME and JETTY_HOME first. $ export JAVA_HOME=/path/to/jvm $ export JETTY_HOME=/path/to/jetty Examples: $ export JAVA_HOME=/usr/bin/jvm So assuming you installed cygwin on C:\cygwin, the jvm needs to be in C:\cygwin\usr\bin\jvm $ export JETTY_HOME=/usr/share/jetty6 So assuming you installed cygwin on C:\cygwin, jetty needs to be in C:\cygwin\usr\share\jetty6jetty8-8.1.3/jetty-distribution/src/main/resources/bin/jetty-cygwin.sh000077500000000000000000000435771174773561500261570ustar00rootroot00000000000000#!/bin/bash # # Startup script for jetty under *nix systems (it works under NT/cygwin too). # To get the service to restart correctly on reboot, uncomment below (3 lines): # ======================== # chkconfig: 3 99 99 # description: Jetty 8 webserver # processname: jetty # ======================== # Configuration files # # /etc/default/jetty # If it exists, this is read at the start of script. It may perform any # sequence of shell commands, like setting relevant environment variables. # # $HOME/.jettyrc # If it exists, this is read at the start of script. It may perform any # sequence of shell commands, like setting relevant environment variables. # # /etc/jetty.conf # If found, and no configurations were given on the command line, # the file will be used as this script's configuration. # Each line in the file may contain: # - A comment denoted by the pound (#) sign as first non-blank character. # - The path to a regular file, which will be passed to jetty as a # config.xml file. # - The path to a directory. Each *.xml file in the directory will be # passed to jetty as a config.xml file. # # The files will be checked for existence before being passed to jetty. # # $JETTY_HOME/etc/jetty.xml # If found, used as this script's configuration file, but only if # /etc/jetty.conf was not present. See above. # # Configuration variables # # JAVA_HOME # Home of Java installation. # # JAVA # Command to invoke Java. If not set, $JAVA_HOME/bin/java will be # used. # # JAVA_OPTIONS # Extra options to pass to the JVM # # JETTY_HOME # Where Jetty is installed. If not set, the script will try go # guess it by first looking at the invocation path for the script, # and then by looking in standard locations as $HOME/opt/jetty # and /opt/jetty. The java system property "jetty.home" will be # set to this value for use by configure.xml files, f.e.: # # /webapps/jetty.war # # JETTY_PORT # Override the default port for Jetty servers. If not set then the # default value in the xml configuration file will be used. The java # system property "jetty.port" will be set to this value for use in # configure.xml files. For example, the following idiom is widely # used in the demo config files to respect this property in Listener # configuration elements: # # # # Note: that the config file could ignore this property simply by saying: # # 8080 # # JETTY_RUN # Where the jetty.pid file should be stored. It defaults to the # first available of /var/run, /usr/var/run, and /tmp if not set. # # JETTY_PID # The Jetty PID file, defaults to $JETTY_RUN/jetty.pid # # JETTY_ARGS # The default arguments to pass to jetty. # # JETTY_USER # if set, then used as a username to run the server as # usage() { echo "Usage: $0 {start|stop|run|restart|check|supervise} [ CONFIGS ... ] " exit 1 } [ $# -gt 0 ] || usage ################################################## # Some utility functions ################################################## findDirectory() { OP=$1 shift for L in $* ; do [ $OP $L ] || continue echo $L break done } running() { [ -f $1 ] || return 1 PID=$(cat $1) ps -p $PID >/dev/null 2>/dev/null || return 1 return 0 } ################################################## # Get the action & configs ################################################## ACTION=$1 shift ARGS="$*" CONFIGS="" NO_START=0 ################################################## # See if there's a default configuration file ################################################## if [ -f /etc/default/jetty8 ] ; then . /etc/default/jetty8 elif [ -f /etc/default/jetty ] ; then . /etc/default/jetty fi ################################################## # See if there's a user-specific configuration file ################################################## if [ -f $HOME/.jettyrc ] ; then . $HOME/.jettyrc fi ################################################## # Set tmp if not already set. ################################################## if [ -z "$TMP" ] then TMP=/tmp fi ################################################## # Jetty's hallmark ################################################## JETTY_INSTALL_TRACE_FILE="etc/jetty.xml" TMPJ=$TMP/j$$ ################################################## # Try to determine JETTY_HOME if not set ################################################## if [ -z "$JETTY_HOME" ] then JETTY_HOME_1=`dirname "$0"` JETTY_HOME_1=`dirname "$JETTY_HOME_1"` if [ -f "${JETTY_HOME_1}/${JETTY_INSTALL_TRACE_FILE}" ] ; then JETTY_HOME=${JETTY_HOME_1} fi fi ################################################## # if no JETTY_HOME, search likely locations. ################################################## if [ "$JETTY_HOME" = "" ] ; then STANDARD_LOCATIONS=" \ /usr/share \ /usr/share/java \ $HOME \ $HOME/src \ ${HOME}/opt/ \ /opt \ /java \ /usr/local \ /usr/local/share \ /usr/local/share/java \ /home \ " JETTY_DIR_NAMES=" \ jetty-8 \ jetty8 \ jetty-8.* \ jetty \ Jetty-8 \ Jetty8 \ Jetty-8.* \ Jetty \ " JETTY_HOME= for L in $STANDARD_LOCATIONS do for N in $JETTY_DIR_NAMES do if [ -d $L/$N ] && [ -f "$L/${N}/${JETTY_INSTALL_TRACE_FILE}" ] ; then JETTY_HOME="$L/$N" fi done [ ! -z "$JETTY_HOME" ] && break done fi ################################################## # No JETTY_HOME yet? We're out of luck! ################################################## if [ -z "$JETTY_HOME" ] ; then echo "** ERROR: JETTY_HOME not set, you need to set it or install in a standard location" exit 1 fi cd $JETTY_HOME JETTY_HOME=`pwd` ##################################################### # Check that jetty is where we think it is ##################################################### if [ ! -r $JETTY_HOME/$JETTY_INSTALL_TRACE_FILE ] then echo "** ERROR: Oops! Jetty doesn't appear to be installed in $JETTY_HOME" echo "** ERROR: $JETTY_HOME/$JETTY_INSTALL_TRACE_FILE is not readable!" exit 1 fi ########################################################### # Get the list of config.xml files from the command line. ########################################################### if [ ! -z "$ARGS" ] then for A in $ARGS do if [ -f $A ] then CONF="$A" elif [ -f $JETTY_HOME/etc/$A ] then CONF="$JETTY_HOME/etc/$A" elif [ -f ${A}.xml ] then CONF="${A}.xml" elif [ -f $JETTY_HOME/etc/${A}.xml ] then CONF="$JETTY_HOME/etc/${A}.xml" else echo "** ERROR: Cannot find configuration '$A' specified in the command line." exit 1 fi if [ ! -r $CONF ] then echo "** ERROR: Cannot read configuration '$A' specified in the command line." exit 1 fi CONFIGS="$CONFIGS $CONF" done fi ################################################## # Try to find this script's configuration file, # but only if no configurations were given on the # command line. ################################################## if [ -z "$JETTY_CONF" ] then if [ -f /etc/jetty.conf ] then JETTY_CONF=/etc/jetty.conf elif [ -f "${JETTY_HOME}/etc/jetty.conf" ] then JETTY_CONF="${JETTY_HOME}/etc/jetty.conf" fi fi ################################################## # Read the configuration file if one exists ################################################## CONFIG_LINES= if [ -z "$CONFIGS" ] && [ -f "$JETTY_CONF" ] && [ -r "$JETTY_CONF" ] then CONFIG_LINES=`cat $JETTY_CONF | grep -v "^[:space:]*#" | tr "\n" " "` fi ################################################## # Get the list of config.xml files from jetty.conf ################################################## if [ ! -z "${CONFIG_LINES}" ] then for CONF in ${CONFIG_LINES} do if [ ! -r "$CONF" ] then echo "** WARNING: Cannot read '$CONF' specified in '$JETTY_CONF'" elif [ -f "$CONF" ] then # assume it's a configure.xml file CONFIGS="$CONFIGS $CONF" elif [ -d "$CONF" ] then # assume it's a directory with configure.xml files # for example: /etc/jetty.d/ # sort the files before adding them to the list of CONFIGS XML_FILES=`ls ${CONF}/*.xml | sort | tr "\n" " "` for FILE in ${XML_FILES} do if [ -r "$FILE" ] && [ -f "$FILE" ] then CONFIGS="$CONFIGS $FILE" else echo "** WARNING: Cannot read '$FILE' specified in '$JETTY_CONF'" fi done else echo "** WARNING: Don''t know what to do with '$CONF' specified in '$JETTY_CONF'" fi done fi ##################################################### # Run the standard server if there's nothing else to run ##################################################### if [ -z "$CONFIGS" ] then CONFIGS="${JETTY_HOME}/etc/jetty-logging.xml ${JETTY_HOME}/etc/jetty.xml" fi ##################################################### # Find a location for the pid file ##################################################### if [ -z "$JETTY_RUN" ] then JETTY_RUN=`findDirectory -w /var/run /usr/var/run /tmp` fi ##################################################### # Find a PID for the pid file ##################################################### if [ -z "$JETTY_PID" ] then JETTY_PID="$JETTY_RUN/jetty.pid" fi ################################################## # Check for JAVA_HOME ################################################## if [ -z "$JAVA_HOME" ] then # If a java runtime is not defined, search the following # directories for a JVM and sort by version. Use the highest # version number. # Java search path JAVA_LOCATIONS="\ /usr/java \ /usr/bin \ /usr/local/bin \ /usr/local/java \ /usr/local/jdk \ /usr/local/jre \ /usr/lib/jvm \ /opt/java \ /opt/jdk \ /opt/jre \ " JAVA_NAMES="java jdk jre" for N in $JAVA_NAMES ; do for L in $JAVA_LOCATIONS ; do [ -d $L ] || continue find $L -name "$N" ! -type d | grep -v threads | while read J ; do [ -x $J ] || continue VERSION=`eval $J -version 2>&1` [ $? = 0 ] || continue VERSION=`expr "$VERSION" : '.*"\(1.[0-9\.]*\)["_]'` [ "$VERSION" = "" ] && continue expr $VERSION \< 1.2 >/dev/null && continue echo $VERSION:$J done done done | sort | tail -1 > $TMPJ JAVA=`cat $TMPJ | cut -d: -f2` JVERSION=`cat $TMPJ | cut -d: -f1` JAVA_HOME=`dirname $JAVA` while [ ! -z "$JAVA_HOME" -a "$JAVA_HOME" != "/" -a ! -f "$JAVA_HOME/lib/tools.jar" ] ; do JAVA_HOME=`dirname $JAVA_HOME` done [ "$JAVA_HOME" = "" ] && JAVA_HOME= echo "Found JAVA=$JAVA in JAVA_HOME=$JAVA_HOME" fi ################################################## # Determine which JVM of version >1.2 # Try to use JAVA_HOME ################################################## if [ "$JAVA" = "" -a "$JAVA_HOME" != "" ] then if [ ! -z "$JAVACMD" ] then JAVA="$JAVACMD" else [ -x $JAVA_HOME/bin/jre -a ! -d $JAVA_HOME/bin/jre ] && JAVA=$JAVA_HOME/bin/jre [ -x $JAVA_HOME/bin/java -a ! -d $JAVA_HOME/bin/java ] && JAVA=$JAVA_HOME/bin/java fi fi if [ "$JAVA" = "" ] then echo "Cannot find a JRE or JDK. Please set JAVA_HOME to a >=1.2 JRE" 2>&2 exit 1 fi JAVA_VERSION=`expr "$($JAVA -version 2>&1 | head -1)" : '.*1\.\([0-9]\)'` ##################################################### # See if JETTY_PORT is defined ##################################################### if [ "$JETTY_PORT" != "" ] then JAVA_OPTIONS="$JAVA_OPTIONS -Djetty.port=$JETTY_PORT" fi ##################################################### # See if JETTY_LOGS is defined ##################################################### if [ "$JETTY_LOGS" != "" ] then JAVA_OPTIONS="$JAVA_OPTIONS -Djetty.logs=$JETTY_LOGS" fi ##################################################### # Are we running on Windows? Could be, with Cygwin/NT. ##################################################### case "`uname`" in CYGWIN*) PATH_SEPARATOR=";";; *) PATH_SEPARATOR=":";; esac ##################################################### # Add jetty properties to Java VM options. ##################################################### JAVA_OPTIONS="$JAVA_OPTIONS -Djetty.home=$JETTY_HOME -Djava.io.tmpdir=$TMP" [ -f $JETTY_HOME/etc/start.config ] && JAVA_OPTIONS="-DSTART=$JETTY_HOME/etc/start.config $JAVA_OPTIONS" ##################################################### # This is how the Jetty server will be started ##################################################### JETTY_START=$JETTY_HOME/start.jar [ ! -f $JETTY_START ] && JETTY_START=$JETTY_HOME/lib/start.jar case "`uname`" in CYGWIN*) JETTY_START="`cygpath -w $JETTY_START`" echo $JETTY_START CONFIGS="`cygpath -w $CONFIGS`" echo $CONFIGS ;; esac RUN_ARGS="$JAVA_OPTIONS -jar $JETTY_START $JETTY_ARGS $CONFIGS" RUN_CMD="$JAVA $RUN_ARGS" ##################################################### # Comment these out after you're happy with what # the script is doing. ##################################################### #echo "JETTY_HOME = $JETTY_HOME" #echo "JETTY_CONF = $JETTY_CONF" #echo "JETTY_RUN = $JETTY_RUN" #echo "JETTY_PID = $JETTY_PID" #echo "JETTY_ARGS = $JETTY_ARGS" #echo "CONFIGS = $CONFIGS" #echo "JAVA_OPTIONS = $JAVA_OPTIONS" #echo "JAVA = $JAVA" ################################################## # Do the action ################################################## case "$ACTION" in start) echo -n "Starting Jetty: " if [ "$NO_START" = "1" ]; then echo "Not starting jetty - NO_START=1 in /etc/default/jetty8"; exit 0; fi if [ "$START_STOP_DAEMON" = "1" ] && type start-stop-daemon > /dev/null 2>&1 then [ x$JETTY_USER = x ] && JETTY_USER=$(whoami) [ $UID = 0 ] && CH_USER="-c $JETTY_USER" if start-stop-daemon -S -p$JETTY_PID $CH_USER -d $JETTY_HOME -b -m -a $JAVA -- $RUN_ARGS then sleep 1 if running $JETTY_PID then echo OK else echo FAILED fi fi else if [ -f $JETTY_PID ] then if running $JETTY_PID then echo "Already Running!!" exit 1 else # dead pid file - remove rm -f $JETTY_PID fi fi if [ x$JETTY_USER != x ] then touch $JETTY_PID chown $JETTY_USER $JETTY_PID su - $JETTY_USER -c " $RUN_CMD & PID=\$! disown \$PID echo \$PID > $JETTY_PID" else $RUN_CMD & PID=$! disown $PID echo $PID > $JETTY_PID fi echo "STARTED Jetty `date`" fi ;; stop) echo -n "Stopping Jetty: " if [ "$START_STOP_DAEMON" = "1" ] && type start-stop-daemon > /dev/null 2>&1; then start-stop-daemon -K -p $JETTY_PID -d $JETTY_HOME -a $JAVA -s HUP sleep 1 if running $JETTY_PID then sleep 3 if running $JETTY_PID then sleep 30 if running $JETTY_PID then start-stop-daemon -K -p $JETTY_PID -d $JETTY_HOME -a $JAVA -s KILL fi fi fi rm -f $JETTY_PID echo OK else PID=`cat $JETTY_PID 2>/dev/null` TIMEOUT=30 while running $JETTY_PID && [ $TIMEOUT -gt 0 ] do kill $PID 2>/dev/null sleep 1 let TIMEOUT=$TIMEOUT-1 done [ $TIMEOUT -gt 0 ] || kill -9 $PID 2>/dev/null rm -f $JETTY_PID echo OK fi ;; restart) JETTY_SH=$0 if [ ! -f $JETTY_SH ]; then if [ ! -f $JETTY_HOME/bin/jetty.sh ]; then echo "$JETTY_HOME/bin/jetty.sh does not exist." exit 1 fi JETTY_SH=$JETTY_HOME/bin/jetty.sh fi $JETTY_SH stop $* sleep 5 $JETTY_SH start $* ;; supervise) # # Under control of daemontools supervise monitor which # handles restarts and shutdowns via the svc program. # exec $RUN_CMD ;; run|demo) echo "Running Jetty: " if [ -f $JETTY_PID ] then if running $JETTY_PID then echo "Already Running!!" exit 1 else # dead pid file - remove rm -f $JETTY_PID fi fi exec $RUN_CMD ;; check) echo "Checking arguments to Jetty: " echo "JETTY_HOME = $JETTY_HOME" echo "JETTY_CONF = $JETTY_CONF" echo "JETTY_RUN = $JETTY_RUN" echo "JETTY_PID = $JETTY_PID" echo "JETTY_PORT = $JETTY_PORT" echo "JETTY_LOGS = $JETTY_LOGS" echo "CONFIGS = $CONFIGS" echo "JAVA_OPTIONS = $JAVA_OPTIONS" echo "JAVA = $JAVA" echo "CLASSPATH = $CLASSPATH" echo "RUN_CMD = $RUN_CMD" echo if [ -f $JETTY_RUN/jetty.pid ] then echo "Jetty running pid="`cat $JETTY_RUN/jetty.pid` exit 0 fi exit 1 ;; *) usage ;; esac exit 0 jetty8-8.1.3/jetty-distribution/src/main/resources/bin/jetty-xinetd.sh000077500000000000000000000004221174773561500261300ustar00rootroot00000000000000#!/bin/bash # look for JETTY_HOME if [ -z "$JETTY_HOME" ] then JETTY_HOME_1=`dirname "$0"` JETTY_HOME_1=`dirname "$JETTY_HOME_1"` JETTY_HOME=${JETTY_HOME_1} fi cd $JETTY_HOME exec /usr/bin/java -Djetty.port=8088 -jar start.jar etc/jetty.xml etc/jetty-xinetd.xml jetty8-8.1.3/jetty-distribution/src/main/resources/bin/jetty.sh000077500000000000000000000341701174773561500246460ustar00rootroot00000000000000#!/usr/bin/env bash # # Startup script for jetty under *nix systems (it works under NT/cygwin too). # To get the service to restart correctly on reboot, uncomment below (3 lines): # ======================== # chkconfig: 3 99 99 # description: Jetty 8 webserver # processname: jetty # ======================== # Configuration files # # /etc/default/jetty # If it exists, this is read at the start of script. It may perform any # sequence of shell commands, like setting relevant environment variables. # # $HOME/.jettyrc # If it exists, this is read at the start of script. It may perform any # sequence of shell commands, like setting relevant environment variables. # # /etc/jetty.conf # If found, and no configurations were given on the command line, # the file will be used as this script's configuration. # Each line in the file may contain: # - A comment denoted by the pound (#) sign as first non-blank character. # - The path to a regular file, which will be passed to jetty as a # config.xml file. # - The path to a directory. Each *.xml file in the directory will be # passed to jetty as a config.xml file. # # The files will be checked for existence before being passed to jetty. # # $JETTY_HOME/etc/jetty.xml # If found, used as this script's configuration file, but only if # /etc/jetty.conf was not present. See above. # # Configuration variables # # JAVA # Command to invoke Java. If not set, java (from the PATH) will be used. # # JAVA_OPTIONS # Extra options to pass to the JVM # # JETTY_HOME # Where Jetty is installed. If not set, the script will try go # guess it by first looking at the invocation path for the script, # and then by looking in standard locations as $HOME/opt/jetty # and /opt/jetty. The java system property "jetty.home" will be # set to this value for use by configure.xml files, f.e.: # # /webapps/jetty.war # # JETTY_PORT # Override the default port for Jetty servers. If not set then the # default value in the xml configuration file will be used. The java # system property "jetty.port" will be set to this value for use in # configure.xml files. For example, the following idiom is widely # used in the demo config files to respect this property in Listener # configuration elements: # # # # Note: that the config file could ignore this property simply by saying: # # 8080 # # JETTY_RUN # Where the jetty.pid file should be stored. It defaults to the # first available of /var/run, /usr/var/run, and /tmp if not set. # # JETTY_PID # The Jetty PID file, defaults to $JETTY_RUN/jetty.pid # # JETTY_ARGS # The default arguments to pass to jetty. # # JETTY_USER # if set, then used as a username to run the server as # usage() { echo "Usage: ${0##*/} [-d] {start|stop|run|restart|check|supervise} [ CONFIGS ... ] " exit 1 } [ $# -gt 0 ] || usage ################################################## # Some utility functions ################################################## findDirectory() { local L OP=$1 shift for L in "$@"; do [ "$OP" "$L" ] || continue printf %s "$L" break done } running() { local PID=$(cat "$1" 2>/dev/null) || return 1 kill -0 "$PID" 2>/dev/null } readConfig() { (( DEBUG )) && echo "Reading $1.." source "$1" } ################################################## # Get the action & configs ################################################## CONFIGS=() NO_START=0 DEBUG=0 while [[ $1 = -* ]]; do case $1 in -d) DEBUG=1 ;; esac shift done ACTION=$1 shift ################################################## # Read any configuration files ################################################## for CONFIG in /etc/default/jetty{,8} $HOME/.jettyrc; do if [ -f "$CONFIG" ] ; then readConfig "$CONFIG" fi done ################################################## # Set tmp if not already set. ################################################## TMPDIR=${TMPDIR:-/tmp} ################################################## # Jetty's hallmark ################################################## JETTY_INSTALL_TRACE_FILE="etc/jetty.xml" ################################################## # Try to determine JETTY_HOME if not set ################################################## if [ -z "$JETTY_HOME" ] then JETTY_SH=$0 case "$JETTY_SH" in /*) ;; ./*) ;; *) JETTY_SH=./$JETTY_SH ;; esac JETTY_HOME=${JETTY_SH%/*/*} if [ ! -f "${JETTY_SH%/*/*}/$JETTY_INSTALL_TRACE_FILE" ] then JETTY_HOME= fi fi ################################################## # if no JETTY_HOME, search likely locations. ################################################## if [ -z "$JETTY_HOME" ] ; then STANDARD_LOCATIONS=( "/usr/share" "/usr/share/java" "${HOME}" "${HOME}/src" "${HOME}/opt" "/opt" "/java" "/usr/local" "/usr/local/share" "/usr/local/share/java" "/home" ) JETTY_DIR_NAMES=( "jetty-8" "jetty8" "jetty-8.*" "jetty" "Jetty-8" "Jetty8" "Jetty-8.*" "Jetty" ) for L in "${STANDARD_LOCATIONS[@]}" do for N in "${JETTY_DIR_NAMES[@]}" do POSSIBLE_JETTY_HOME=("$L/"$N) if [ ! -d "$POSSIBLE_JETTY_HOME" ] then # Not a directory. skip. unset POSSIBLE_JETTY_HOME elif [ ! -f "$POSSIBLE_JETTY_HOME/$JETTY_INSTALL_TRACE_FILE" ] then # Trace file not found. skip. unset POSSIBLE_JETTY_HOME else # Good hit, Use it JETTY_HOME=$POSSIBLE_JETTY_HOME # Break out of JETTY_DIR_NAMES loop break fi done if [ -n "$POSSIBLE_JETTY_HOME" ] then # We have found our JETTY_HOME # Break out of STANDARD_LOCATIONS loop break fi done fi ################################################## # No JETTY_HOME yet? We're out of luck! ################################################## if [ -z "$JETTY_HOME" ]; then echo "** ERROR: JETTY_HOME not set, you need to set it or install in a standard location" exit 1 fi cd "$JETTY_HOME" JETTY_HOME=$PWD ##################################################### # Check that jetty is where we think it is ##################################################### if [ ! -r "$JETTY_HOME/$JETTY_INSTALL_TRACE_FILE" ] then echo "** ERROR: Oops! Jetty doesn't appear to be installed in $JETTY_HOME" echo "** ERROR: $JETTY_HOME/$JETTY_INSTALL_TRACE_FILE is not readable!" exit 1 fi ################################################## # Try to find this script's configuration file, # but only if no configurations were given on the # command line. ################################################## if [ -z "$JETTY_CONF" ] then if [ -f /etc/jetty.conf ] then JETTY_CONF=/etc/jetty.conf elif [ -f "$JETTY_HOME/etc/jetty.conf" ] then JETTY_CONF=$JETTY_HOME/etc/jetty.conf fi fi ################################################## # Get the list of config.xml files from jetty.conf ################################################## if [ -z "$CONFIGS" ] && [ -f "$JETTY_CONF" ] && [ -r "$JETTY_CONF" ] then while read -r CONF do if expr "$CONF" : '#' >/dev/null ; then continue fi if [ -d "$CONF" ] then # assume it's a directory with configure.xml files # for example: /etc/jetty.d/ # sort the files before adding them to the list of CONFIGS for XMLFILE in "$CONF/"*.xml do if [ -r "$XMLFILE" ] && [ -f "$XMLFILE" ] then CONFIGS+=("$XMLFILE") else echo "** WARNING: Cannot read '$XMLFILE' specified in '$JETTY_CONF'" fi done else # assume it's a command line parameter (let start.jar deal with its validity) CONFIGS+=("$CONF") fi done < "$JETTY_CONF" fi ##################################################### # Find a location for the pid file ##################################################### if [ -z "$JETTY_RUN" ] then JETTY_RUN=$(findDirectory -w /var/run /usr/var/run /tmp) fi ##################################################### # Find a PID for the pid file ##################################################### if [ -z "$JETTY_PID" ] then JETTY_PID="$JETTY_RUN/jetty.pid" fi ################################################## # Setup JAVA if unset ################################################## if [ -z "$JAVA" ] then JAVA=$(which java) fi if [ -z "$JAVA" ] then echo "Cannot find a Java JDK. Please set either set JAVA or put java (>=1.5) in your PATH." 2>&2 exit 1 fi ##################################################### # See if JETTY_PORT is defined ##################################################### if [ "$JETTY_PORT" ] then JAVA_OPTIONS+=("-Djetty.port=$JETTY_PORT") fi ##################################################### # See if JETTY_LOGS is defined ##################################################### if [ "$JETTY_LOGS" ] then JAVA_OPTIONS+=("-Djetty.logs=$JETTY_LOGS") fi ##################################################### # Are we running on Windows? Could be, with Cygwin/NT. ##################################################### case "`uname`" in CYGWIN*) PATH_SEPARATOR=";";; *) PATH_SEPARATOR=":";; esac ##################################################### # Add jetty properties to Java VM options. ##################################################### JAVA_OPTIONS+=("-Djetty.home=$JETTY_HOME" "-Djava.io.tmpdir=$TMPDIR") [ -f "$JETTY_HOME/etc/start.config" ] && JAVA_OPTIONS=("-DSTART=$JETTY_HOME/etc/start.config" "${JAVA_OPTIONS[@]}") ##################################################### # This is how the Jetty server will be started ##################################################### JETTY_START=$JETTY_HOME/start.jar [ ! -f "$JETTY_START" ] && JETTY_START=$JETTY_HOME/lib/start.jar START_INI=$(dirname $JETTY_START)/start.ini [ -r "$START_INI" ] || START_INI="" RUN_ARGS=(${JAVA_OPTIONS[@]} -jar "$JETTY_START" $JETTY_ARGS "${CONFIGS[@]}") RUN_CMD=("$JAVA" ${RUN_ARGS[@]}) ##################################################### # Comment these out after you're happy with what # the script is doing. ##################################################### if (( DEBUG )) then echo "JETTY_HOME = $JETTY_HOME" echo "JETTY_CONF = $JETTY_CONF" echo "JETTY_RUN = $JETTY_RUN" echo "JETTY_PID = $JETTY_PID" echo "JETTY_ARGS = $JETTY_ARGS" echo "CONFIGS = ${CONFIGS[*]}" echo "JAVA_OPTIONS = ${JAVA_OPTIONS[*]}" echo "JAVA = $JAVA" echo "RUN_CMD = ${RUN_CMD}" fi ################################################## # Do the action ################################################## case "$ACTION" in start) echo -n "Starting Jetty: " if (( NO_START )); then echo "Not starting jetty - NO_START=1"; exit fi if type start-stop-daemon > /dev/null 2>&1 then unset CH_USER if [ -n "$JETTY_USER" ] then CH_USER="-c$JETTY_USER" fi if start-stop-daemon -S -p"$JETTY_PID" $CH_USER -d"$JETTY_HOME" -b -m -a "$JAVA" -- "${RUN_ARGS[@]}" --daemon then sleep 1 if running "$JETTY_PID" then echo "OK" else echo "FAILED" fi fi else if [ -f "$JETTY_PID" ] then if running $JETTY_PID then echo "Already Running!" exit 1 else # dead pid file - remove rm -f "$JETTY_PID" fi fi if [ "$JETTY_USER" ] then touch "$JETTY_PID" chown "$JETTY_USER" "$JETTY_PID" # FIXME: Broken solution: wordsplitting, pathname expansion, arbitrary command execution, etc. su - "$JETTY_USER" -c " exec ${RUN_CMD[*]} --daemon & disown \$! echo \$! > '$JETTY_PID'" else "${RUN_CMD[@]}" & disown $! echo $! > "$JETTY_PID" fi echo "STARTED Jetty `date`" fi ;; stop) echo -n "Stopping Jetty: " if type start-stop-daemon > /dev/null 2>&1; then start-stop-daemon -K -p"$JETTY_PID" -d"$JETTY_HOME" -a "$JAVA" -s HUP TIMEOUT=30 while running "$JETTY_PID"; do if (( TIMEOUT-- == 0 )); then start-stop-daemon -K -p"$JETTY_PID" -d"$JETTY_HOME" -a "$JAVA" -s KILL fi sleep 1 done rm -f "$JETTY_PID" echo OK else PID=$(cat "$JETTY_PID" 2>/dev/null) kill "$PID" 2>/dev/null TIMEOUT=30 while running $JETTY_PID; do if (( TIMEOUT-- == 0 )); then kill -KILL "$PID" 2>/dev/null fi sleep 1 done rm -f "$JETTY_PID" echo OK fi ;; restart) JETTY_SH=$0 if [ ! -f $JETTY_SH ]; then if [ ! -f $JETTY_HOME/bin/jetty.sh ]; then echo "$JETTY_HOME/bin/jetty.sh does not exist." exit 1 fi JETTY_SH=$JETTY_HOME/bin/jetty.sh fi "$JETTY_SH" stop "$@" "$JETTY_SH" start "$@" ;; supervise) # # Under control of daemontools supervise monitor which # handles restarts and shutdowns via the svc program. # exec "${RUN_CMD[@]}" ;; run|demo) echo "Running Jetty: " if [ -f "$JETTY_PID" ] then if running "$JETTY_PID" then echo "Already Running!" exit 1 else # dead pid file - remove rm -f "$JETTY_PID" fi fi exec "${RUN_CMD[@]}" ;; check) echo "Checking arguments to Jetty: " echo "JETTY_HOME = $JETTY_HOME" echo "JETTY_CONF = $JETTY_CONF" echo "JETTY_RUN = $JETTY_RUN" echo "JETTY_PID = $JETTY_PID" echo "JETTY_PORT = $JETTY_PORT" echo "JETTY_LOGS = $JETTY_LOGS" echo "START_INI = $START_INI" echo "CONFIGS = ${CONFIGS[*]}" echo "JAVA_OPTIONS = ${JAVA_OPTIONS[*]}" echo "JAVA = $JAVA" echo "CLASSPATH = $CLASSPATH" echo "RUN_CMD = ${RUN_CMD[*]}" echo if [ -f "$JETTY_PID" ] then echo "Jetty running pid=$(< "$JETTY_PID")" exit 0 fi exit 1 ;; *) usage ;; esac exit 0 jetty8-8.1.3/jetty-distribution/src/main/resources/contexts-available/000077500000000000000000000000001174773561500261605ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/contexts-available/README.TXT000066400000000000000000000001741174773561500275200ustar00rootroot00000000000000 This directory contains example contexts that may be deployed by moving/copying/linking them to the ../contexts directory. jetty8-8.1.3/jetty-distribution/src/main/resources/contexts-available/resources.xml000066400000000000000000000016321174773561500307160ustar00rootroot00000000000000 Configure javadoc.xml /resources /resources/ index.html max-age=3600,public jetty8-8.1.3/jetty-distribution/src/main/resources/contexts/000077500000000000000000000000001174773561500242425ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/contexts/README.TXT000066400000000000000000000011721174773561500256010ustar00rootroot00000000000000 This directory is scanned by the ContextDeployer instance configured by the standard $JETTY_HOME/etc/jetty.xml configuration. It should contain XmlConfiguration files that describe individual contexts to be deployed to the server. This directory is scanned for additions, removals and updates for hot deployment. Frequenty the context configuration files here will reference war files or directories from $JETTY_HOME/webapps. Care must be taken to avoid a WebAppDeployer deploying duplicates of such webapplications. The directory ../contexts-available contains more example contexts that may be deployed by being copied here. jetty8-8.1.3/jetty-distribution/src/main/resources/contexts/javadoc.xml000066400000000000000000000016211174773561500263730ustar00rootroot00000000000000 Configure javadoc.xml /javadoc /javadoc/ index.html max-age=3600,public jetty8-8.1.3/jetty-distribution/src/main/resources/etc/000077500000000000000000000000001174773561500231465ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/etc/jetty.conf000066400000000000000000000011031174773561500251470ustar00rootroot00000000000000# ======================================================== # jetty.conf Configuration for jetty.sh script # -------------------------------------------------------- # This file is used by the jetty.sh script to provide # extra configuration arguments for the start.jar command # created by that script. # # Each line in this file becomes an arguement to start.jar # unless this file contains an --ini option, then these # arguments will be in addition to those found in the # start.ini file # ======================================================= --pre=etc/jetty-logging.xml jetty8-8.1.3/jetty-distribution/src/main/resources/lib/000077500000000000000000000000001174773561500231415ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/lib/ext/000077500000000000000000000000001174773561500237415ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/lib/ext/.donotdelete000066400000000000000000000000001174773561500262360ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/logs/000077500000000000000000000000001174773561500233375ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/logs/.donotdelete000066400000000000000000000000001174773561500256340ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/resources/000077500000000000000000000000001174773561500244055ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/resources/log4j.properties000066400000000000000000000004411174773561500275410ustar00rootroot00000000000000 # This is not needed by Jetty - but it helps with many web apps. log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n jetty8-8.1.3/jetty-distribution/src/main/resources/start.ini000066400000000000000000000043451174773561500242370ustar00rootroot00000000000000#=========================================================== # Jetty start.jar arguments # Each line of this file is prepended to the command line # arguments # of a call to: # java -jar start.jar [arg...] #=========================================================== #=========================================================== # If the arguements in this file include JVM arguments # (eg -Xmx512m) or JVM System properties (eg com.sun.???), # then these will not take affect unless the --exec # parameter is included or if the output from --dry-run # is executed like: # eval $(java -jar start.jar --dry-run) # # Below are some recommended options for Sun's JRE #----------------------------------------------------------- # --exec # -Dorg.apache.jasper.compiler.disablejsr199=true # -Dcom.sun.management.jmxremote # -Dorg.eclipse.jetty.util.log.IGNORED=true # -Dorg.eclipse.jetty.LEVEL=DEBUG # -Dorg.eclipse.jetty.util.log.stderr.SOURCE=true # -Xmx2000m # -Xmn512m # -verbose:gc # -XX:+PrintGCDateStamps # -XX:+PrintGCTimeStamps # -XX:+PrintGCDetails # -XX:+PrintTenuringDistribution # -XX:+PrintCommandLineFlags # -XX:+DisableExplicitGC # -XX:+UseConcMarkSweepGC # -XX:ParallelCMSThreads=2 # -XX:+CMSClassUnloadingEnabled # -XX:+UseCMSCompactAtFullCollection # -XX:CMSInitiatingOccupancyFraction=80 #----------------------------------------------------------- #=========================================================== # Start classpath OPTIONS. # These control what classes are on the classpath # for a full listing do # java -jar start.jar --list-options #----------------------------------------------------------- OPTIONS=Server,jsp,jmx,resources,websocket,ext,plus,annotations #----------------------------------------------------------- #=========================================================== # Configuration files. # For a full list of available configuration files do # java -jar start.jar --help #----------------------------------------------------------- #etc/jetty-jmx.xml etc/jetty.xml etc/jetty-annotations.xml # etc/jetty-ssl.xml # etc/jetty-requestlog.xml etc/jetty-deploy.xml #etc/jetty-overlay.xml etc/jetty-webapps.xml etc/jetty-contexts.xml etc/jetty-testrealm.xml #=========================================================== jetty8-8.1.3/jetty-distribution/src/main/resources/webapps/000077500000000000000000000000001174773561500240345ustar00rootroot00000000000000jetty8-8.1.3/jetty-distribution/src/main/resources/webapps/.donotdelete000066400000000000000000000000001174773561500263310ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/000077500000000000000000000000001174773561500156775ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/pom.xml000066400000000000000000000043541174773561500172220ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 jetty-http-spi Jetty :: Http Service Provider Interface ${project.groupId}.http.spi junit junit test com.sun.net.httpserver http 20070405 provided org.eclipse.jetty jetty-server ${project.version} provided org.apache.felix maven-bundle-plugin true manifest org.apache.maven.plugins maven-jar-plugin artifact-jar jar ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.http.spi.* jetty8-8.1.3/jetty-http-spi/src/000077500000000000000000000000001174773561500164665ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/000077500000000000000000000000001174773561500174125ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/java/000077500000000000000000000000001174773561500203335ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/java/org/000077500000000000000000000000001174773561500211225ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/000077500000000000000000000000001174773561500225465ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500237055ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/000077500000000000000000000000001174773561500246645ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/000077500000000000000000000000001174773561500254575ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/HttpSpiContextHandler.java000066400000000000000000000120301174773561500325540ustar00rootroot00000000000000package org.eclipse.jetty.http.spi; //======================================================================== //Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html //The Apache License v2.0 is available at //http://www.opensource.org/licenses/apache2.0.php //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.io.IOException; import java.io.PrintWriter; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.ContextHandler; import com.sun.net.httpserver.Authenticator; import com.sun.net.httpserver.Authenticator.Result; import com.sun.net.httpserver.BasicAuthenticator; import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpPrincipal; /** * Jetty handler that bridges requests to {@link HttpHandler}. */ public class HttpSpiContextHandler extends ContextHandler { private HttpContext _httpContext; private HttpHandler _httpHandler; public HttpSpiContextHandler(HttpContext httpContext, HttpHandler httpHandler) { this._httpContext = httpContext; this._httpHandler = httpHandler; } @Override public void doScope(String target, Request baseRequest, HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { if (!target.startsWith(getContextPath())) { return; } HttpExchange jettyHttpExchange; if (baseRequest.isSecure()) { jettyHttpExchange = new JettyHttpsExchange(_httpContext,req,resp); } else { jettyHttpExchange = new JettyHttpExchange(_httpContext,req,resp); } // TODO: add filters processing try { Authenticator auth = _httpContext.getAuthenticator(); if (auth != null) { handleAuthentication(resp,jettyHttpExchange,auth); } else { _httpHandler.handle(jettyHttpExchange); } } catch (Exception ex) { PrintWriter writer = new PrintWriter(jettyHttpExchange.getResponseBody()); resp.setStatus(500); writer.println("

HTTP ERROR: 500

"); writer.println("
INTERNAL_SERVER_ERROR
"); writer.println("

RequestURI=" + req.getRequestURI() + "

"); writer.println("
");
            ex.printStackTrace(writer);
            writer.println("
"); writer.println("

Powered by jetty://

"); writer.close(); } finally { baseRequest.setHandled(true); } } private void handleAuthentication(HttpServletResponse resp, HttpExchange httpExchange, Authenticator auth) throws IOException { Result result = auth.authenticate(httpExchange); if (result instanceof Authenticator.Failure) { int rc = ((Authenticator.Failure)result).getResponseCode(); for (Map.Entry> header : httpExchange.getResponseHeaders().entrySet()) { for (String value : header.getValue()) resp.addHeader(header.getKey(),value); } resp.sendError(rc); } else if (result instanceof Authenticator.Retry) { int rc = ((Authenticator.Retry)result).getResponseCode(); for (Map.Entry> header : httpExchange.getResponseHeaders().entrySet()) { for (String value : header.getValue()) resp.addHeader(header.getKey(),value); } resp.setStatus(rc); resp.flushBuffer(); } else if (result instanceof Authenticator.Success) { HttpPrincipal principal = ((Authenticator.Success)result).getPrincipal(); ((JettyExchange)httpExchange).setPrincipal(principal); _httpHandler.handle(httpExchange); } } public HttpHandler getHttpHandler() { return _httpHandler; } public void setHttpHandler(HttpHandler handler) { this._httpHandler = handler; } } jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyExchange.java000066400000000000000000000020071174773561500310630ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http.spi; import com.sun.net.httpserver.HttpPrincipal; /* ------------------------------------------------------------ */ /** */ public interface JettyExchange { HttpPrincipal getPrincipal(); void setPrincipal(HttpPrincipal principal); }jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpContext.java000066400000000000000000000054761174773561500316420ustar00rootroot00000000000000package org.eclipse.jetty.http.spi; //======================================================================== //Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html //The Apache License v2.0 is available at //http://www.opensource.org/licenses/apache2.0.php //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.sun.net.httpserver.Authenticator; import com.sun.net.httpserver.Filter; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; /** * Jetty implementation of {@link com.sun.net.httpserver.HttpContext} */ public class JettyHttpContext extends com.sun.net.httpserver.HttpContext { private HttpSpiContextHandler _jettyContextHandler; private HttpServer _server; private Map _attributes = new HashMap(); private List _filters = new ArrayList(); private Authenticator _authenticator; protected JettyHttpContext(HttpServer server, String path, HttpHandler handler) { this._server = server; _jettyContextHandler = new HttpSpiContextHandler(this, handler); _jettyContextHandler.setContextPath(path); } protected HttpSpiContextHandler getJettyContextHandler() { return _jettyContextHandler; } @Override public HttpHandler getHandler() { return _jettyContextHandler.getHttpHandler(); } @Override public void setHandler(HttpHandler h) { _jettyContextHandler.setHttpHandler(h); } @Override public String getPath() { return _jettyContextHandler.getContextPath(); } @Override public HttpServer getServer() { return _server; } @Override public Map getAttributes() { return _attributes; } @Override public List getFilters() { return _filters; } @Override public Authenticator setAuthenticator(Authenticator auth) { Authenticator previous = _authenticator; _authenticator = auth; return previous; } @Override public Authenticator getAuthenticator() { return _authenticator; } } jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpExchange.java000066400000000000000000000163061174773561500317320ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http.spi; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.URI; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpPrincipal; /* ------------------------------------------------------------ */ /** */ public class JettyHttpExchange extends HttpExchange implements JettyExchange { private JettyHttpExchangeDelegate _delegate; public JettyHttpExchange(HttpContext jaxWsContext, HttpServletRequest req, HttpServletResponse resp) { super(); _delegate = new JettyHttpExchangeDelegate(jaxWsContext,req,resp); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#hashCode() */ @Override public int hashCode() { return _delegate.hashCode(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getRequestHeaders() */ @Override public Headers getRequestHeaders() { return _delegate.getRequestHeaders(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getResponseHeaders() */ @Override public Headers getResponseHeaders() { return _delegate.getResponseHeaders(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getRequestURI() */ @Override public URI getRequestURI() { return _delegate.getRequestURI(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getRequestMethod() */ @Override public String getRequestMethod() { return _delegate.getRequestMethod(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getHttpContext() */ @Override public HttpContext getHttpContext() { return _delegate.getHttpContext(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#close() */ @Override public void close() { _delegate.close(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { return _delegate.equals(obj); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getRequestBody() */ @Override public InputStream getRequestBody() { return _delegate.getRequestBody(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getResponseBody() */ @Override public OutputStream getResponseBody() { return _delegate.getResponseBody(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#sendResponseHeaders(int, long) */ @Override public void sendResponseHeaders(int rCode, long responseLength) throws IOException { _delegate.sendResponseHeaders(rCode,responseLength); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getRemoteAddress() */ @Override public InetSocketAddress getRemoteAddress() { return _delegate.getRemoteAddress(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getResponseCode() */ @Override public int getResponseCode() { return _delegate.getResponseCode(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getLocalAddress() */ @Override public InetSocketAddress getLocalAddress() { return _delegate.getLocalAddress(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getProtocol() */ @Override public String getProtocol() { return _delegate.getProtocol(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getAttribute(java.lang.String) */ @Override public Object getAttribute(String name) { return _delegate.getAttribute(name); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#setAttribute(java.lang.String, java.lang.Object) */ @Override public void setAttribute(String name, Object value) { _delegate.setAttribute(name,value); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#setStreams(java.io.InputStream, java.io.OutputStream) */ @Override public void setStreams(InputStream i, OutputStream o) { _delegate.setStreams(i,o); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#getPrincipal() */ @Override public HttpPrincipal getPrincipal() { return _delegate.getPrincipal(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#setPrincipal(com.sun.net.httpserver.HttpPrincipal) */ public void setPrincipal(HttpPrincipal principal) { _delegate.setPrincipal(principal); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.spi.JettyExchange#toString() */ @Override public String toString() { return _delegate.toString(); } } jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpExchangeDelegate.java000066400000000000000000000131531174773561500333620ustar00rootroot00000000000000package org.eclipse.jetty.http.spi; //======================================================================== //Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html //The Apache License v2.0 is available at //http://www.opensource.org/licenses/apache2.0.php //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; import java.util.Enumeration; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpPrincipal; /** * Jetty implementation of {@link com.sun.net.httpserver.HttpExchange} */ public class JettyHttpExchangeDelegate extends HttpExchange { private HttpContext _httpContext; private HttpServletRequest _req; private HttpServletResponse _resp; private Headers _responseHeaders = new Headers(); private int _responseCode = 0; private InputStream _is; private OutputStream _os; private HttpPrincipal _httpPrincipal; JettyHttpExchangeDelegate(HttpContext jaxWsContext, HttpServletRequest req, HttpServletResponse resp) { this._httpContext = jaxWsContext; this._req = req; this._resp = resp; try { this._is = req.getInputStream(); this._os = resp.getOutputStream(); } catch (IOException ex) { throw new RuntimeException(ex); } } @Override public Headers getRequestHeaders() { Headers headers = new Headers(); Enumeration en = _req.getHeaderNames(); while (en.hasMoreElements()) { String name = (String)en.nextElement(); Enumeration en2 = _req.getHeaders(name); while (en2.hasMoreElements()) { String value = (String)en2.nextElement(); headers.add(name,value); } } return headers; } @Override public Headers getResponseHeaders() { return _responseHeaders; } @Override public URI getRequestURI() { try { String uriAsString = _req.getRequestURI(); if (_req.getQueryString() != null) { uriAsString += "?" + _req.getQueryString(); } return new URI(uriAsString); } catch (URISyntaxException ex) { throw new RuntimeException(ex); } } @Override public String getRequestMethod() { return _req.getMethod(); } @Override public HttpContext getHttpContext() { return _httpContext; } @Override public void close() { try { _resp.getOutputStream().close(); } catch (IOException ex) { throw new RuntimeException(ex); } } @Override public InputStream getRequestBody() { return _is; } @Override public OutputStream getResponseBody() { return _os; } @Override public void sendResponseHeaders(int rCode, long responseLength) throws IOException { this._responseCode = rCode; for (Map.Entry> stringListEntry : _responseHeaders.entrySet()) { String name = stringListEntry.getKey(); List values = stringListEntry.getValue(); for (String value : values) { _resp.setHeader(name,value); } } if (responseLength > 0) { _resp.setHeader("content-length","" + responseLength); } _resp.setStatus(rCode); } @Override public InetSocketAddress getRemoteAddress() { return new InetSocketAddress(_req.getRemoteAddr(),_req.getRemotePort()); } @Override public int getResponseCode() { return _responseCode; } @Override public InetSocketAddress getLocalAddress() { return new InetSocketAddress(_req.getLocalAddr(),_req.getLocalPort()); } @Override public String getProtocol() { return _req.getProtocol(); } @Override public Object getAttribute(String name) { return _req.getAttribute(name); } @Override public void setAttribute(String name, Object value) { _req.setAttribute(name,value); } @Override public void setStreams(InputStream i, OutputStream o) { _is = i; _os = o; } @Override public HttpPrincipal getPrincipal() { return _httpPrincipal; } public void setPrincipal(HttpPrincipal principal) { this._httpPrincipal = principal; } } jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServer.java000066400000000000000000000202331174773561500314500ustar00rootroot00000000000000package org.eclipse.jetty.http.spi; //======================================================================== //Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html //The Apache License v2.0 is available at //http://www.opensource.org/licenses/apache2.0.php //You may elect to redistribute this code under either of these licenses. //======================================================================== import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpHandler; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import java.io.IOException; import java.net.InetSocketAddress; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; /** * Jetty implementation of {@link com.sun.net.httpserver.HttpServer}. */ public class JettyHttpServer extends com.sun.net.httpserver.HttpServer { private static final Logger LOG = Log.getLogger(JettyHttpServer.class); private Server _server; private boolean _serverShared; private InetSocketAddress _addr; private ThreadPoolExecutor _executor; private Map _contexts = new HashMap(); private Map _connectors = new HashMap(); public JettyHttpServer(Server server, boolean shared) { this._server = server; this._serverShared = shared; } @Override public void bind(InetSocketAddress addr, int backlog) throws IOException { // check if there is already a connector listening Connector[] connectors = _server.getConnectors(); if (connectors != null) { for (Connector connector : connectors) { if (connector.getPort() == addr.getPort()) { if (LOG.isDebugEnabled()) LOG.debug("server already bound to port " + addr.getPort() + ", no need to rebind"); return; } } } if (_serverShared) throw new IOException("jetty server is not bound to port " + addr.getPort()); this._addr = addr; if (LOG.isDebugEnabled()) LOG.debug("binding server to port " + addr.getPort()); SelectChannelConnector connector = new SelectChannelConnector(); connector.setAcceptors(1); connector.setPort(addr.getPort()); connector.setHost(addr.getHostName()); _server.addConnector(connector); _connectors.put(addr.getHostName() + addr.getPort(), connector); } @Override public InetSocketAddress getAddress() { return _addr; } @Override public void start() { if (_serverShared) return; try { _server.start(); } catch (Exception ex) { throw new RuntimeException(ex); } } @Override public void setExecutor(Executor executor) { if (executor == null) throw new IllegalArgumentException("missing required 'executor' argument"); if (!(executor instanceof ThreadPoolExecutor)) throw new IllegalArgumentException("only java.util.concurrent.ThreadPoolExecutor instances are allowed, got: " + executor.getClass().getName()); if (LOG.isDebugEnabled()) LOG.debug("using ThreadPoolExecutor for server thread pool"); this._executor = (ThreadPoolExecutor) executor; _server.setThreadPool(new ThreadPoolExecutorAdapter(_executor)); } @Override public Executor getExecutor() { return _executor; } @Override public void stop(int delay) { cleanUpContexts(); cleanUpConnectors(); if (_serverShared) return; try { _server.stop(); } catch (Exception ex) { throw new RuntimeException(ex); } } private void cleanUpContexts() { for (Map.Entry stringJettyHttpContextEntry : _contexts.entrySet()) { JettyHttpContext context = stringJettyHttpContextEntry.getValue(); _server.removeBean(context.getJettyContextHandler()); } _contexts.clear(); } private void cleanUpConnectors() { for (Map.Entry stringConnectorEntry : _connectors.entrySet()) { Connector connector = stringConnectorEntry.getValue(); try { connector.stop(); } catch (Exception ex) { LOG.warn(ex); } _server.removeConnector(connector); } _connectors.clear(); } @Override public HttpContext createContext(String path, HttpHandler httpHandler) { checkIfContextIsFree(path); JettyHttpContext context = new JettyHttpContext(this, path, httpHandler); HttpSpiContextHandler jettyContextHandler = context.getJettyContextHandler(); ContextHandlerCollection chc = findContextHandlerCollection(_server.getHandlers()); if (chc == null) throw new RuntimeException("could not find ContextHandlerCollection, you must configure one"); chc.addHandler(jettyContextHandler); _contexts.put(path, context); return context; } private ContextHandlerCollection findContextHandlerCollection(Handler[] handlers) { if (handlers == null) return null; for (Handler handler : handlers) { if (handler instanceof ContextHandlerCollection) { return (ContextHandlerCollection) handler; } if (handler instanceof HandlerCollection) { HandlerCollection hc = (HandlerCollection) handler; ContextHandlerCollection chc = findContextHandlerCollection(hc.getHandlers()); if (chc != null) return chc; } } return null; } private void checkIfContextIsFree(String path) { Handler serverHandler = _server.getHandler(); if (serverHandler instanceof ContextHandler) { ContextHandler ctx = (ContextHandler) serverHandler; if (ctx.getContextPath().equals(path)) throw new RuntimeException("another context already bound to path " + path); } Handler[] handlers = _server.getHandlers(); if (handlers == null) return; for (Handler handler : handlers) { if (handler instanceof ContextHandler) { ContextHandler ctx = (ContextHandler) handler; if (ctx.getContextPath().equals(path)) throw new RuntimeException("another context already bound to path " + path); } } } @Override public HttpContext createContext(String path) { return createContext(path, null); } @Override public void removeContext(String path) throws IllegalArgumentException { JettyHttpContext context = _contexts.remove(path); if (context == null) return; _server.removeBean(context.getJettyContextHandler()); } @Override public void removeContext(HttpContext context) { removeContext(context.getPath()); } } jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServerProvider.java000066400000000000000000000047311174773561500331700ustar00rootroot00000000000000package org.eclipse.jetty.http.spi; //======================================================================== //Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html //The Apache License v2.0 is available at //http://www.opensource.org/licenses/apache2.0.php //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.io.IOException; import java.net.InetSocketAddress; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import com.sun.net.httpserver.HttpServer; import com.sun.net.httpserver.HttpsServer; import com.sun.net.httpserver.spi.HttpServerProvider; /** * Jetty implementation of Java HTTP Server SPI */ public class JettyHttpServerProvider extends HttpServerProvider { private static Server _server; public static void setServer(Server server) { _server = server; } @Override public HttpServer createHttpServer(InetSocketAddress addr, int backlog) throws IOException { Server server = _server; boolean shared = true; if (server == null) { server = new Server(); HandlerCollection handlerCollection = new HandlerCollection(); handlerCollection.setHandlers(new Handler[] {new ContextHandlerCollection(), new DefaultHandler()}); server.setHandler(handlerCollection); shared = false; } JettyHttpServer jettyHttpServer = new JettyHttpServer(server, shared); jettyHttpServer.bind(addr, backlog); return jettyHttpServer; } @Override public HttpsServer createHttpsServer(InetSocketAddress addr, int backlog) throws IOException { throw new UnsupportedOperationException(); } } jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpsExchange.java000066400000000000000000000101721174773561500321100ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http.spi; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.URI; import javax.net.ssl.SSLSession; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpPrincipal; import com.sun.net.httpserver.HttpsExchange; /* ------------------------------------------------------------ */ /** */ public class JettyHttpsExchange extends HttpsExchange implements JettyExchange { private JettyHttpExchangeDelegate _delegate; public JettyHttpsExchange(HttpContext jaxWsContext, HttpServletRequest req, HttpServletResponse resp) { super(); _delegate = new JettyHttpExchangeDelegate(jaxWsContext,req,resp); } @Override public int hashCode() { return _delegate.hashCode(); } @Override public Headers getRequestHeaders() { return _delegate.getRequestHeaders(); } @Override public Headers getResponseHeaders() { return _delegate.getResponseHeaders(); } @Override public URI getRequestURI() { return _delegate.getRequestURI(); } @Override public String getRequestMethod() { return _delegate.getRequestMethod(); } @Override public HttpContext getHttpContext() { return _delegate.getHttpContext(); } @Override public void close() { _delegate.close(); } @Override public boolean equals(Object obj) { return _delegate.equals(obj); } @Override public InputStream getRequestBody() { return _delegate.getRequestBody(); } @Override public OutputStream getResponseBody() { return _delegate.getResponseBody(); } @Override public void sendResponseHeaders(int rCode, long responseLength) throws IOException { _delegate.sendResponseHeaders(rCode,responseLength); } @Override public InetSocketAddress getRemoteAddress() { return _delegate.getRemoteAddress(); } @Override public int getResponseCode() { return _delegate.getResponseCode(); } @Override public InetSocketAddress getLocalAddress() { return _delegate.getLocalAddress(); } @Override public String getProtocol() { return _delegate.getProtocol(); } @Override public Object getAttribute(String name) { return _delegate.getAttribute(name); } @Override public void setAttribute(String name, Object value) { _delegate.setAttribute(name,value); } @Override public void setStreams(InputStream i, OutputStream o) { _delegate.setStreams(i,o); } @Override public HttpPrincipal getPrincipal() { return _delegate.getPrincipal(); } public void setPrincipal(HttpPrincipal principal) { _delegate.setPrincipal(principal); } @Override public String toString() { return _delegate.toString(); } /* ------------------------------------------------------------ */ /** * @see com.sun.net.httpserver.HttpsExchange#getSSLSession() */ @Override public SSLSession getSSLSession() { return null; } } jetty8-8.1.3/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/ThreadPoolExecutorAdapter.java000066400000000000000000000060101174773561500334000ustar00rootroot00000000000000package org.eclipse.jetty.http.spi; //======================================================================== //Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html //The Apache License v2.0 is available at //http://www.opensource.org/licenses/apache2.0.php //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.ThreadPool; /** * Jetty {@link ThreadPool} that bridges requests to a {@link ThreadPoolExecutor}. */ public class ThreadPoolExecutorAdapter extends AbstractLifeCycle implements ThreadPool { private static final Logger LOG = Log.getLogger(ThreadPoolExecutorAdapter.class); private ThreadPoolExecutor executor; public ThreadPoolExecutorAdapter(ThreadPoolExecutor executor) { this.executor = executor; } public boolean dispatch(Runnable job) { try { executor.execute(job); return true; } catch(RejectedExecutionException e) { LOG.warn(e); return false; } } public int getIdleThreads() { return executor.getPoolSize()-executor.getActiveCount(); } public int getThreads() { return executor.getPoolSize(); } public boolean isLowOnThreads() { return executor.getActiveCount()>=executor.getMaximumPoolSize(); } public void join() throws InterruptedException { executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); } public boolean isFailed() { return false; } public boolean isRunning() { return !executor.isTerminated() && !executor.isTerminating(); } public boolean isStarted() { return !executor.isTerminated() && !executor.isTerminating(); } public boolean isStarting() { return false; } public boolean isStopped() { return executor.isTerminated(); } public boolean isStopping() { return executor.isTerminating(); } protected void doStart() throws Exception { if (executor.isTerminated() || executor.isTerminating() || executor.isShutdown()) throw new IllegalStateException("Cannot restart"); } protected void doStop() throws Exception { executor.shutdown(); if (!executor.awaitTermination(60, TimeUnit.SECONDS)) executor.shutdownNow(); } } jetty8-8.1.3/jetty-http-spi/src/main/resources/000077500000000000000000000000001174773561500214245ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/resources/META-INF/000077500000000000000000000000001174773561500225645ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/resources/META-INF/services/000077500000000000000000000000001174773561500244075ustar00rootroot00000000000000com.sun.net.httpserver.spi.HttpServerProvider000066400000000000000000000000631174773561500352400ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/main/resources/META-INF/servicesorg.eclipse.jetty.http.spi.JettyHttpServerProvider jetty8-8.1.3/jetty-http-spi/src/test/000077500000000000000000000000001174773561500174455ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/test/java/000077500000000000000000000000001174773561500203665ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/test/java/org/000077500000000000000000000000001174773561500211555ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/test/java/org/eclipse/000077500000000000000000000000001174773561500226015ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500237405ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/test/java/org/eclipse/jetty/http/000077500000000000000000000000001174773561500247175ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/000077500000000000000000000000001174773561500255125ustar00rootroot00000000000000jetty8-8.1.3/jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/TestSPIServer.java000066400000000000000000000043271174773561500310450ustar00rootroot00000000000000package org.eclipse.jetty.http.spi; import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; import java.util.Iterator; import java.util.List; import java.util.Set; import com.sun.net.httpserver.BasicAuthenticator; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; public class TestSPIServer { public static void main(String[] args) throws Exception { String host="localhost"; int port = 8080; HttpServer server = new JettyHttpServerProvider().createHttpServer(new InetSocketAddress(host, port), 10); server.start(); final HttpContext httpContext = server.createContext("/", new HttpHandler() { public void handle(HttpExchange exchange) throws IOException { Headers responseHeaders = exchange.getResponseHeaders(); responseHeaders.set("Content-Type","text/plain"); exchange.sendResponseHeaders(200,0); OutputStream responseBody = exchange.getResponseBody(); Headers requestHeaders = exchange.getRequestHeaders(); Set keySet = requestHeaders.keySet(); Iterator iter = keySet.iterator(); while (iter.hasNext()) { String key = iter.next(); List values = requestHeaders.get(key); String s = key + " = " + values.toString() + "\n"; responseBody.write(s.getBytes()); } responseBody.close(); } }); httpContext.setAuthenticator(new BasicAuthenticator("Test") { @Override public boolean checkCredentials(String username, String password) { if ("username".equals(username) && password.equals("password")) return true; return false; } }); Thread.sleep(10000000); } } jetty8-8.1.3/jetty-http/000077500000000000000000000000001174773561500151065ustar00rootroot00000000000000jetty8-8.1.3/jetty-http/pom.xml000066400000000000000000000050461174773561500164300ustar00rootroot00000000000000 jetty-project org.eclipse.jetty 8.1.3.v20120416 4.0.0 jetty-http Jetty :: Http Utility ${project.groupId}.http org.eclipse.jetty jetty-io ${project.version} org.eclipse.jetty.orbit javax.servlet provided junit junit test org.apache.felix maven-bundle-plugin true manifest javax.servlet.*;version="2.6.0",javax.net.*,* org.apache.maven.plugins maven-jar-plugin artifact-jar jar test-jar test-jar ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.http.* jetty8-8.1.3/jetty-http/src/000077500000000000000000000000001174773561500156755ustar00rootroot00000000000000jetty8-8.1.3/jetty-http/src/main/000077500000000000000000000000001174773561500166215ustar00rootroot00000000000000jetty8-8.1.3/jetty-http/src/main/java/000077500000000000000000000000001174773561500175425ustar00rootroot00000000000000jetty8-8.1.3/jetty-http/src/main/java/org/000077500000000000000000000000001174773561500203315ustar00rootroot00000000000000jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/000077500000000000000000000000001174773561500217555ustar00rootroot00000000000000jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500231145ustar00rootroot00000000000000jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/000077500000000000000000000000001174773561500240735ustar00rootroot00000000000000jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java000066400000000000000000000366101174773561500303560ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.io.IOException; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.View; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ /** * Abstract Generator. Builds HTTP Messages. * * Currently this class uses a system parameter "jetty.direct.writers" to control * two optional writer to byte conversions. buffer.writers=true will probably be * faster, but will consume more memory. This option is just for testing and tuning. * */ public abstract class AbstractGenerator implements Generator { private static final Logger LOG = Log.getLogger(AbstractGenerator.class); // states public final static int STATE_HEADER = 0; public final static int STATE_CONTENT = 2; public final static int STATE_FLUSHING = 3; public final static int STATE_END = 4; public static final byte[] NO_BYTES = {}; // data protected final Buffers _buffers; // source of buffers protected final EndPoint _endp; protected int _state = STATE_HEADER; protected int _status = 0; protected int _version = HttpVersions.HTTP_1_1_ORDINAL; protected Buffer _reason; protected Buffer _method; protected String _uri; protected long _contentWritten = 0; protected long _contentLength = HttpTokens.UNKNOWN_CONTENT; protected boolean _last = false; protected boolean _head = false; protected boolean _noContent = false; protected Boolean _persistent = null; protected Buffer _header; // Buffer for HTTP header (and maybe small _content) protected Buffer _buffer; // Buffer for copy of passed _content protected Buffer _content; // Buffer passed to addContent protected Buffer _date; private boolean _sendServerVersion; /* ------------------------------------------------------------------------------- */ /** * Constructor. * * @param buffers buffer pool * @param io the end point */ public AbstractGenerator(Buffers buffers, EndPoint io) { this._buffers = buffers; this._endp = io; } /* ------------------------------------------------------------------------------- */ public abstract boolean isRequest(); /* ------------------------------------------------------------------------------- */ public abstract boolean isResponse(); /* ------------------------------------------------------------------------------- */ public boolean isOpen() { return _endp.isOpen(); } /* ------------------------------------------------------------------------------- */ public void reset() { _state = STATE_HEADER; _status = 0; _version = HttpVersions.HTTP_1_1_ORDINAL; _reason = null; _last = false; _head = false; _noContent=false; _persistent = null; _contentWritten = 0; _contentLength = HttpTokens.UNKNOWN_CONTENT; _date = null; _content = null; _method=null; } /* ------------------------------------------------------------------------------- */ public void returnBuffers() { if (_buffer!=null && _buffer.length()==0) { _buffers.returnBuffer(_buffer); _buffer=null; } if (_header!=null && _header.length()==0) { _buffers.returnBuffer(_header); _header=null; } } /* ------------------------------------------------------------------------------- */ public void resetBuffer() { if(_state>=STATE_FLUSHING) throw new IllegalStateException("Flushed"); _last = false; _persistent=null; _contentWritten = 0; _contentLength = HttpTokens.UNKNOWN_CONTENT; _content=null; if (_buffer!=null) _buffer.clear(); } /* ------------------------------------------------------------ */ /** * @return Returns the contentBufferSize. */ public int getContentBufferSize() { if (_buffer==null) _buffer=_buffers.getBuffer(); return _buffer.capacity(); } /* ------------------------------------------------------------ */ /** * @param contentBufferSize The contentBufferSize to set. */ public void increaseContentBufferSize(int contentBufferSize) { if (_buffer==null) _buffer=_buffers.getBuffer(); if (contentBufferSize > _buffer.capacity()) { Buffer nb = _buffers.getBuffer(contentBufferSize); nb.put(_buffer); _buffers.returnBuffer(_buffer); _buffer = nb; } } /* ------------------------------------------------------------ */ public Buffer getUncheckedBuffer() { return _buffer; } /* ------------------------------------------------------------ */ public boolean getSendServerVersion () { return _sendServerVersion; } /* ------------------------------------------------------------ */ public void setSendServerVersion (boolean sendServerVersion) { _sendServerVersion = sendServerVersion; } /* ------------------------------------------------------------ */ public int getState() { return _state; } /* ------------------------------------------------------------ */ public boolean isState(int state) { return _state == state; } /* ------------------------------------------------------------ */ public boolean isComplete() { return _state == STATE_END; } /* ------------------------------------------------------------ */ public boolean isIdle() { return _state == STATE_HEADER && _method==null && _status==0; } /* ------------------------------------------------------------ */ public boolean isCommitted() { return _state != STATE_HEADER; } /* ------------------------------------------------------------ */ /** * @return Returns the head. */ public boolean isHead() { return _head; } /* ------------------------------------------------------------ */ public void setContentLength(long value) { if (value<0) _contentLength=HttpTokens.UNKNOWN_CONTENT; else _contentLength=value; } /* ------------------------------------------------------------ */ /** * @param head The head to set. */ public void setHead(boolean head) { _head = head; } /* ------------------------------------------------------------ */ /** * @return false if the connection should be closed after a request has been read, * true if it should be used for additional requests. */ public boolean isPersistent() { return _persistent!=null ?_persistent.booleanValue() :(isRequest()?true:_version>HttpVersions.HTTP_1_0_ORDINAL); } /* ------------------------------------------------------------ */ public void setPersistent(boolean persistent) { _persistent=persistent; } /* ------------------------------------------------------------ */ /** * @param version The version of the client the response is being sent to (NB. Not the version * in the response, which is the version of the server). */ public void setVersion(int version) { if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START "+_state); _version = version; if (_version==HttpVersions.HTTP_0_9_ORDINAL && _method!=null) _noContent=true; } /* ------------------------------------------------------------ */ public int getVersion() { return _version; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.Generator#setDate(org.eclipse.jetty.io.Buffer) */ public void setDate(Buffer timeStampBuffer) { _date=timeStampBuffer; } /* ------------------------------------------------------------ */ /** */ public void setRequest(String method, String uri) { if (method==null || HttpMethods.GET.equals(method) ) _method=HttpMethods.GET_BUFFER; else _method=HttpMethods.CACHE.lookup(method); _uri=uri; if (_version==HttpVersions.HTTP_0_9_ORDINAL) _noContent=true; } /* ------------------------------------------------------------ */ /** * @param status The status code to send. * @param reason the status message to send. */ public void setResponse(int status, String reason) { if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START"); _method=null; _status = status; if (reason!=null) { int len=reason.length(); // TODO don't hard code if (len>1024) len=1024; _reason=new ByteArrayBuffer(len); for (int i=0;i0; } /* ------------------------------------------------------------ */ public boolean isWritten() { return _contentWritten>0; } /* ------------------------------------------------------------ */ public boolean isAllContentWritten() { return _contentLength>=0 && _contentWritten>=_contentLength; } /* ------------------------------------------------------------ */ public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException; /* ------------------------------------------------------------ */ /** * Complete the message. * * @throws IOException */ public void complete() throws IOException { if (_state == STATE_HEADER) { throw new IllegalStateException("State==HEADER"); } if (_contentLength >= 0 && _contentLength != _contentWritten && !_head) { if (LOG.isDebugEnabled()) LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength); _persistent = false; } } /* ------------------------------------------------------------ */ public abstract int flushBuffer() throws IOException; /* ------------------------------------------------------------ */ public void flush(long maxIdleTime) throws IOException { // block until everything is flushed long now=System.currentTimeMillis(); long end=now+maxIdleTime; Buffer content = _content; Buffer buffer = _buffer; if (content!=null && content.length()>0 || buffer!=null && buffer.length()>0 || isBufferFull()) { flushBuffer(); while (now0 ||buffer!=null && buffer.length()>0) && _endp.isOpen()&& !_endp.isOutputShutdown()) { blockForOutput(end-now); now=System.currentTimeMillis(); } } } /* ------------------------------------------------------------ */ /** * Utility method to send an error response. If the builder is not committed, this call is * equivalent to a setResponse, addContent and complete call. * * @param code The error code * @param reason The error reason * @param content Contents of the error page * @param close True if the connection should be closed * @throws IOException if there is a problem flushing the response */ public void sendError(int code, String reason, String content, boolean close) throws IOException { if (close) _persistent=false; if (isCommitted()) { LOG.debug("sendError on committed: {} {}",code,reason); } else { LOG.debug("sendError: {} {}",code,reason); setResponse(code, reason); if (content != null) { completeHeader(null, false); addContent(new View(new ByteArrayBuffer(content)), Generator.LAST); } else { completeHeader(null, true); } complete(); } } /* ------------------------------------------------------------ */ /** * @return Returns the contentWritten. */ public long getContentWritten() { return _contentWritten; } /* ------------------------------------------------------------ */ public void blockForOutput(long maxIdleTime) throws IOException { if (_endp.isBlocking()) { try { flushBuffer(); } catch(IOException e) { _endp.close(); throw e; } } else { if (!_endp.blockWritable(maxIdleTime)) { _endp.close(); throw new EofException("timeout"); } flushBuffer(); } } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/EncodedHttpURI.java000066400000000000000000000114041174773561500275170ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.io.UnsupportedEncodingException; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.UrlEncoded; import org.eclipse.jetty.util.Utf8StringBuffer; public class EncodedHttpURI extends HttpURI { private final String _encoding; public EncodedHttpURI(String encoding) { super(); _encoding = encoding; } @Override public String getScheme() { if (_scheme==_authority) return null; int l=_authority-_scheme; if (l==5 && _raw[_scheme]=='h' && _raw[_scheme+1]=='t' && _raw[_scheme+2]=='t' && _raw[_scheme+3]=='p' ) return HttpSchemes.HTTP; if (l==6 && _raw[_scheme]=='h' && _raw[_scheme+1]=='t' && _raw[_scheme+2]=='t' && _raw[_scheme+3]=='p' && _raw[_scheme+4]=='s' ) return HttpSchemes.HTTPS; return StringUtil.toString(_raw,_scheme,_authority-_scheme-1,_encoding); } @Override public String getAuthority() { if (_authority==_path) return null; return StringUtil.toString(_raw,_authority,_path-_authority,_encoding); } @Override public String getHost() { if (_host==_port) return null; return StringUtil.toString(_raw,_host,_port-_host,_encoding); } @Override public int getPort() { if (_port==_path) return -1; return TypeUtil.parseInt(_raw, _port+1, _path-_port-1,10); } @Override public String getPath() { if (_path==_param) return null; return StringUtil.toString(_raw,_path,_param-_path,_encoding); } @Override public String getDecodedPath() { if (_path==_param) return null; return URIUtil.decodePath(_raw,_path,_param-_path); } @Override public String getPathAndParam() { if (_path==_query) return null; return StringUtil.toString(_raw,_path,_query-_path,_encoding); } @Override public String getCompletePath() { if (_path==_end) return null; return StringUtil.toString(_raw,_path,_end-_path,_encoding); } @Override public String getParam() { if (_param==_query) return null; return StringUtil.toString(_raw,_param+1,_query-_param-1,_encoding); } @Override public String getQuery() { if (_query==_fragment) return null; return StringUtil.toString(_raw,_query+1,_fragment-_query-1,_encoding); } @Override public boolean hasQuery() { return (_fragment>_query); } @Override public String getFragment() { if (_fragment==_end) return null; return StringUtil.toString(_raw,_fragment+1,_end-_fragment-1,_encoding); } @Override public void decodeQueryTo(MultiMap parameters) { if (_query==_fragment) return; UrlEncoded.decodeTo(StringUtil.toString(_raw,_query+1,_fragment-_query-1,_encoding),parameters,_encoding); } @Override public void decodeQueryTo(MultiMap parameters, String encoding) throws UnsupportedEncodingException { if (_query==_fragment) return; if (encoding==null) encoding=_encoding; UrlEncoded.decodeTo(StringUtil.toString(_raw,_query+1,_fragment-_query-1,encoding),parameters,encoding); } @Override public String toString() { if (_rawString==null) _rawString= StringUtil.toString(_raw,_scheme,_end-_scheme,_encoding); return _rawString; } public void writeTo(Utf8StringBuffer buf) { buf.getStringBuffer().append(toString()); } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/Generator.java000066400000000000000000000053711174773561500266720ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.io.IOException; import org.eclipse.jetty.io.Buffer; public interface Generator { public static final boolean LAST=true; public static final boolean MORE=false; /* ------------------------------------------------------------ */ /** * Add content. * * @param content * @param last * @throws IllegalArgumentException if content is {@link Buffer#isImmutable immutable}. * @throws IllegalStateException If the request is not expecting any more content, * or if the buffers are full and cannot be flushed. * @throws IOException if there is a problem flushing the buffers. */ void addContent(Buffer content, boolean last) throws IOException; /* ------------------------------------------------------------ */ /** * Add content. * * @param b byte * @return true if the buffers are full * @throws IOException */ boolean addContent(byte b) throws IOException; void complete() throws IOException; void completeHeader(HttpFields responseFields, boolean last) throws IOException; int flushBuffer() throws IOException; int getContentBufferSize(); long getContentWritten(); boolean isWritten(); boolean isAllContentWritten(); void increaseContentBufferSize(int size); boolean isBufferFull(); boolean isCommitted(); boolean isComplete(); boolean isPersistent(); void reset(); void resetBuffer(); void returnBuffers(); void sendError(int code, String reason, String content, boolean close) throws IOException; void setHead(boolean head); void setRequest(String method, String uri); void setResponse(int status, String reason); void setSendServerVersion(boolean sendServerVersion); void setVersion(int version); boolean isIdle(); void setContentLength(long length); void setPersistent(boolean persistent); void setDate(Buffer timeStampBuffer); } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpBuffers.java000066400000000000000000000054401174773561500271750ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.BuffersFactory; import org.eclipse.jetty.util.component.AbstractLifeCycle; /* ------------------------------------------------------------ */ /** Abstract Buffer pool. */ public interface HttpBuffers { /** * @return the requestBufferSize */ public int getRequestBufferSize(); /** * @param requestBufferSize the requestBufferSize to set */ public void setRequestBufferSize(int requestBufferSize); /** * @return the requestHeaderSize */ public int getRequestHeaderSize(); /** * @param requestHeaderSize the requestHeaderSize to set */ public void setRequestHeaderSize(int requestHeaderSize); /** * @return the responseBufferSize */ public int getResponseBufferSize(); /** * @param responseBufferSize the responseBufferSize to set */ public void setResponseBufferSize(int responseBufferSize); /** * @return the responseHeaderSize */ public int getResponseHeaderSize(); /** * @param responseHeaderSize the responseHeaderSize to set */ public void setResponseHeaderSize(int responseHeaderSize); /** * @return the requestBufferType */ public Buffers.Type getRequestBufferType(); /** * @return the requestHeaderType */ public Buffers.Type getRequestHeaderType(); /** * @return the responseBufferType */ public Buffers.Type getResponseBufferType(); /** * @return the responseHeaderType */ public Buffers.Type getResponseHeaderType(); /** * @param requestBuffers the requestBuffers to set */ public void setRequestBuffers(Buffers requestBuffers); /** * @param responseBuffers the responseBuffers to set */ public void setResponseBuffers(Buffers responseBuffers); public Buffers getRequestBuffers(); public Buffers getResponseBuffers(); public void setMaxBuffers(int maxBuffers); public int getMaxBuffers(); } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpBuffersImpl.java000066400000000000000000000136231174773561500300210ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.BuffersFactory; import org.eclipse.jetty.util.component.AbstractLifeCycle; /* ------------------------------------------------------------ */ /** Abstract Buffer pool. * simple unbounded pool of buffers for header, request and response sizes. * */ public class HttpBuffersImpl extends AbstractLifeCycle implements HttpBuffers { private int _requestBufferSize=16*1024; private int _requestHeaderSize=6*1024; private int _responseBufferSize=32*1024; private int _responseHeaderSize=6*1024; private int _maxBuffers=1024; private Buffers.Type _requestBufferType=Buffers.Type.BYTE_ARRAY; private Buffers.Type _requestHeaderType=Buffers.Type.BYTE_ARRAY; private Buffers.Type _responseBufferType=Buffers.Type.BYTE_ARRAY; private Buffers.Type _responseHeaderType=Buffers.Type.BYTE_ARRAY; private Buffers _requestBuffers; private Buffers _responseBuffers; public HttpBuffersImpl() { super(); } /** * @return the requestBufferSize */ public int getRequestBufferSize() { return _requestBufferSize; } /** * @param requestBufferSize the requestBufferSize to set */ public void setRequestBufferSize(int requestBufferSize) { _requestBufferSize = requestBufferSize; } /** * @return the requestHeaderSize */ public int getRequestHeaderSize() { return _requestHeaderSize; } /** * @param requestHeaderSize the requestHeaderSize to set */ public void setRequestHeaderSize(int requestHeaderSize) { _requestHeaderSize = requestHeaderSize; } /** * @return the responseBufferSize */ public int getResponseBufferSize() { return _responseBufferSize; } /** * @param responseBufferSize the responseBufferSize to set */ public void setResponseBufferSize(int responseBufferSize) { _responseBufferSize = responseBufferSize; } /** * @return the responseHeaderSize */ public int getResponseHeaderSize() { return _responseHeaderSize; } /** * @param responseHeaderSize the responseHeaderSize to set */ public void setResponseHeaderSize(int responseHeaderSize) { _responseHeaderSize = responseHeaderSize; } /** * @return the requestBufferType */ public Buffers.Type getRequestBufferType() { return _requestBufferType; } /** * @param requestBufferType the requestBufferType to set */ public void setRequestBufferType(Buffers.Type requestBufferType) { _requestBufferType = requestBufferType; } /** * @return the requestHeaderType */ public Buffers.Type getRequestHeaderType() { return _requestHeaderType; } /** * @param requestHeaderType the requestHeaderType to set */ public void setRequestHeaderType(Buffers.Type requestHeaderType) { _requestHeaderType = requestHeaderType; } /** * @return the responseBufferType */ public Buffers.Type getResponseBufferType() { return _responseBufferType; } /** * @param responseBufferType the responseBufferType to set */ public void setResponseBufferType(Buffers.Type responseBufferType) { _responseBufferType = responseBufferType; } /** * @return the responseHeaderType */ public Buffers.Type getResponseHeaderType() { return _responseHeaderType; } /** * @param responseHeaderType the responseHeaderType to set */ public void setResponseHeaderType(Buffers.Type responseHeaderType) { _responseHeaderType = responseHeaderType; } /** * @param requestBuffers the requestBuffers to set */ public void setRequestBuffers(Buffers requestBuffers) { _requestBuffers = requestBuffers; } /** * @param responseBuffers the responseBuffers to set */ public void setResponseBuffers(Buffers responseBuffers) { _responseBuffers = responseBuffers; } @Override protected void doStart() throws Exception { _requestBuffers=BuffersFactory.newBuffers(_requestHeaderType,_requestHeaderSize,_requestBufferType,_requestBufferSize,_requestBufferType,getMaxBuffers()); _responseBuffers=BuffersFactory.newBuffers(_responseHeaderType,_responseHeaderSize,_responseBufferType,_responseBufferSize,_responseBufferType,getMaxBuffers()); super.doStart(); } @Override protected void doStop() throws Exception { _requestBuffers=null; _responseBuffers=null; } public Buffers getRequestBuffers() { return _requestBuffers; } public Buffers getResponseBuffers() { return _responseBuffers; } public void setMaxBuffers(int maxBuffers) { _maxBuffers = maxBuffers; } public int getMaxBuffers() { return _maxBuffers; } public String toString() { return _requestBuffers+"/"+_responseBuffers; } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpContent.java000066400000000000000000000110431174773561500272070ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.io.IOException; import java.io.InputStream; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; /* ------------------------------------------------------------ */ /** HttpContent. * * */ public interface HttpContent { Buffer getContentType(); Buffer getLastModified(); Buffer getIndirectBuffer(); Buffer getDirectBuffer(); Resource getResource(); long getContentLength(); InputStream getInputStream() throws IOException; void release(); /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ public class ResourceAsHttpContent implements HttpContent { private static final Logger LOG = Log.getLogger(ResourceAsHttpContent.class); final Resource _resource; final Buffer _mimeType; final int _maxBuffer; public ResourceAsHttpContent(final Resource resource, final Buffer mimeType) { _resource=resource; _mimeType=mimeType; _maxBuffer=-1; } public ResourceAsHttpContent(final Resource resource, final Buffer mimeType, int maxBuffer) { _resource=resource; _mimeType=mimeType; _maxBuffer=maxBuffer; } /* ------------------------------------------------------------ */ public Buffer getContentType() { return _mimeType; } /* ------------------------------------------------------------ */ public Buffer getLastModified() { return null; } /* ------------------------------------------------------------ */ public Buffer getDirectBuffer() { return null; } /* ------------------------------------------------------------ */ public Buffer getIndirectBuffer() { InputStream inputStream = null; try { if (_resource.length() <= 0 || _maxBuffer < _resource.length()) return null; ByteArrayBuffer buffer = new ByteArrayBuffer((int)_resource.length()); inputStream = _resource.getInputStream(); buffer.readFrom(inputStream,(int)_resource.length()); return buffer; } catch (IOException e) { throw new RuntimeException(e); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { LOG.warn("Couldn't close inputStream. Possible file handle leak",e); } } } } /* ------------------------------------------------------------ */ public long getContentLength() { return _resource.length(); } /* ------------------------------------------------------------ */ public InputStream getInputStream() throws IOException { return _resource.getInputStream(); } /* ------------------------------------------------------------ */ public Resource getResource() { return _resource; } /* ------------------------------------------------------------ */ public void release() { _resource.release(); } } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpCookie.java000066400000000000000000000117231174773561500270130ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; public class HttpCookie { private final String _name; private final String _value; private final String _comment; private final String _domain; private final int _maxAge; private final String _path; private final boolean _secure; private final int _version; private final boolean _httpOnly; /* ------------------------------------------------------------ */ public HttpCookie(String name, String value) { super(); _name = name; _value = value; _comment = null; _domain = null; _httpOnly = false; _maxAge = -1; _path = null; _secure = false; _version = 0; } /* ------------------------------------------------------------ */ public HttpCookie(String name, String value, String domain, String path) { super(); _name = name; _value = value; _comment = null; _domain = domain; _httpOnly = false; _maxAge = -1; _path = path; _secure = false; _version = 0; } /* ------------------------------------------------------------ */ public HttpCookie(String name, String value, int maxAge) { super(); _name = name; _value = value; _comment = null; _domain = null; _httpOnly = false; _maxAge = maxAge; _path = null; _secure = false; _version = 0; } /* ------------------------------------------------------------ */ public HttpCookie(String name, String value, String domain, String path, int maxAge, boolean httpOnly, boolean secure) { super(); _comment = null; _domain = domain; _httpOnly = httpOnly; _maxAge = maxAge; _name = name; _path = path; _secure = secure; _value = value; _version = 0; } /* ------------------------------------------------------------ */ public HttpCookie(String name, String value, String domain, String path, int maxAge, boolean httpOnly, boolean secure, String comment, int version) { super(); _comment = comment; _domain = domain; _httpOnly = httpOnly; _maxAge = maxAge; _name = name; _path = path; _secure = secure; _value = value; _version = version; } /* ------------------------------------------------------------ */ /** Get the name. * @return the name */ public String getName() { return _name; } /* ------------------------------------------------------------ */ /** Get the value. * @return the value */ public String getValue() { return _value; } /* ------------------------------------------------------------ */ /** Get the comment. * @return the comment */ public String getComment() { return _comment; } /* ------------------------------------------------------------ */ /** Get the domain. * @return the domain */ public String getDomain() { return _domain; } /* ------------------------------------------------------------ */ /** Get the maxAge. * @return the maxAge */ public int getMaxAge() { return _maxAge; } /* ------------------------------------------------------------ */ /** Get the path. * @return the path */ public String getPath() { return _path; } /* ------------------------------------------------------------ */ /** Get the secure. * @return the secure */ public boolean isSecure() { return _secure; } /* ------------------------------------------------------------ */ /** Get the version. * @return the version */ public int getVersion() { return _version; } /* ------------------------------------------------------------ */ /** Get the isHttpOnly. * @return the isHttpOnly */ public boolean isHttpOnly() { return _httpOnly; } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpException.java000066400000000000000000000046731174773561500275460ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.io.IOException; public class HttpException extends IOException { int _status; String _reason; /* ------------------------------------------------------------ */ public HttpException(int status) { _status=status; _reason=null; } /* ------------------------------------------------------------ */ public HttpException(int status,String reason) { _status=status; _reason=reason; } /* ------------------------------------------------------------ */ public HttpException(int status,String reason, Throwable rootCause) { _status=status; _reason=reason; initCause(rootCause); } /* ------------------------------------------------------------ */ /** * @return Returns the reason. */ public String getReason() { return _reason; } /* ------------------------------------------------------------ */ /** * @param reason The reason to set. */ public void setReason(String reason) { _reason = reason; } /* ------------------------------------------------------------ */ /** * @return Returns the status. */ public int getStatus() { return _status; } /* ------------------------------------------------------------ */ /** * @param status The status to set. */ public void setStatus(int status) { _status = status; } /* ------------------------------------------------------------ */ @Override public String toString() { return ("HttpException("+_status+","+_reason+","+super.getCause()+")"); } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java000066400000000000000000001262441174773561500270150ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Collection; import java.util.Date; import java.util.Enumeration; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; import java.util.StringTokenizer; import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache; import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.io.BufferDateCache; import org.eclipse.jetty.io.BufferUtil; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.util.LazyList; import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.StringMap; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ /** * HTTP Fields. A collection of HTTP header and or Trailer fields. * *

This class is not synchronized as it is expected that modifications will only be performed by a * single thread. * * */ public class HttpFields { private static final Logger LOG = Log.getLogger(HttpFields.class); /* ------------------------------------------------------------ */ public static final String __COOKIE_DELIM="\"\\\n\r\t\f\b%+ ;="; public static final TimeZone __GMT = TimeZone.getTimeZone("GMT"); public static final BufferDateCache __dateCache = new BufferDateCache("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); /* -------------------------------------------------------------- */ static { __GMT.setID("GMT"); __dateCache.setTimeZone(__GMT); } /* ------------------------------------------------------------ */ public final static String __separators = ", \t"; /* ------------------------------------------------------------ */ private static final String[] DAYS = { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; private static final String[] MONTHS = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan"}; /* ------------------------------------------------------------ */ private static class DateGenerator { private final StringBuilder buf = new StringBuilder(32); private final GregorianCalendar gc = new GregorianCalendar(__GMT); /** * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'" */ public String formatDate(long date) { buf.setLength(0); gc.setTimeInMillis(date); int day_of_week = gc.get(Calendar.DAY_OF_WEEK); int day_of_month = gc.get(Calendar.DAY_OF_MONTH); int month = gc.get(Calendar.MONTH); int year = gc.get(Calendar.YEAR); int century = year / 100; year = year % 100; int hours = gc.get(Calendar.HOUR_OF_DAY); int minutes = gc.get(Calendar.MINUTE); int seconds = gc.get(Calendar.SECOND); buf.append(DAYS[day_of_week]); buf.append(','); buf.append(' '); StringUtil.append2digits(buf, day_of_month); buf.append(' '); buf.append(MONTHS[month]); buf.append(' '); StringUtil.append2digits(buf, century); StringUtil.append2digits(buf, year); buf.append(' '); StringUtil.append2digits(buf, hours); buf.append(':'); StringUtil.append2digits(buf, minutes); buf.append(':'); StringUtil.append2digits(buf, seconds); buf.append(" GMT"); return buf.toString(); } /* ------------------------------------------------------------ */ /** * Format "EEE, dd-MMM-yy HH:mm:ss 'GMT'" for cookies */ public void formatCookieDate(StringBuilder buf, long date) { gc.setTimeInMillis(date); int day_of_week = gc.get(Calendar.DAY_OF_WEEK); int day_of_month = gc.get(Calendar.DAY_OF_MONTH); int month = gc.get(Calendar.MONTH); int year = gc.get(Calendar.YEAR); year = year % 10000; int epoch = (int) ((date / 1000) % (60 * 60 * 24)); int seconds = epoch % 60; epoch = epoch / 60; int minutes = epoch % 60; int hours = epoch / 60; buf.append(DAYS[day_of_week]); buf.append(','); buf.append(' '); StringUtil.append2digits(buf, day_of_month); buf.append('-'); buf.append(MONTHS[month]); buf.append('-'); StringUtil.append2digits(buf, year/100); StringUtil.append2digits(buf, year%100); buf.append(' '); StringUtil.append2digits(buf, hours); buf.append(':'); StringUtil.append2digits(buf, minutes); buf.append(':'); StringUtil.append2digits(buf, seconds); buf.append(" GMT"); } } /* ------------------------------------------------------------ */ private static final ThreadLocal __dateGenerator =new ThreadLocal() { @Override protected DateGenerator initialValue() { return new DateGenerator(); } }; /* ------------------------------------------------------------ */ /** * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'" */ public static String formatDate(long date) { return __dateGenerator.get().formatDate(date); } /* ------------------------------------------------------------ */ /** * Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies */ public static void formatCookieDate(StringBuilder buf, long date) { __dateGenerator.get().formatCookieDate(buf,date); } /* ------------------------------------------------------------ */ /** * Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies */ public static String formatCookieDate(long date) { StringBuilder buf = new StringBuilder(28); formatCookieDate(buf, date); return buf.toString(); } /* ------------------------------------------------------------ */ private final static String __dateReceiveFmt[] = { "EEE, dd MMM yyyy HH:mm:ss zzz", "EEE, dd-MMM-yy HH:mm:ss", "EEE MMM dd HH:mm:ss yyyy", "EEE, dd MMM yyyy HH:mm:ss", "EEE dd MMM yyyy HH:mm:ss zzz", "EEE dd MMM yyyy HH:mm:ss", "EEE MMM dd yyyy HH:mm:ss zzz", "EEE MMM dd yyyy HH:mm:ss", "EEE MMM-dd-yyyy HH:mm:ss zzz", "EEE MMM-dd-yyyy HH:mm:ss", "dd MMM yyyy HH:mm:ss zzz", "dd MMM yyyy HH:mm:ss", "dd-MMM-yy HH:mm:ss zzz", "dd-MMM-yy HH:mm:ss", "MMM dd HH:mm:ss yyyy zzz", "MMM dd HH:mm:ss yyyy", "EEE MMM dd HH:mm:ss yyyy zzz", "EEE, MMM dd HH:mm:ss yyyy zzz", "EEE, MMM dd HH:mm:ss yyyy", "EEE, dd-MMM-yy HH:mm:ss zzz", "EEE dd-MMM-yy HH:mm:ss zzz", "EEE dd-MMM-yy HH:mm:ss", }; /* ------------------------------------------------------------ */ private static class DateParser { final SimpleDateFormat _dateReceive[]= new SimpleDateFormat[__dateReceiveFmt.length]; long parse(final String dateVal) { for (int i = 0; i < _dateReceive.length; i++) { if (_dateReceive[i] == null) { _dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US); _dateReceive[i].setTimeZone(__GMT); } try { Date date = (Date) _dateReceive[i].parseObject(dateVal); return date.getTime(); } catch (java.lang.Exception e) { // LOG.ignore(e); } } if (dateVal.endsWith(" GMT")) { final String val = dateVal.substring(0, dateVal.length() - 4); for (int i = 0; i < _dateReceive.length; i++) { try { Date date = (Date) _dateReceive[i].parseObject(val); return date.getTime(); } catch (java.lang.Exception e) { // LOG.ignore(e); } } } return -1; } } /* ------------------------------------------------------------ */ public static long parseDate(String date) { return __dateParser.get().parse(date); } /* ------------------------------------------------------------ */ private static final ThreadLocal __dateParser =new ThreadLocal() { @Override protected DateParser initialValue() { return new DateParser(); } }; /* -------------------------------------------------------------- */ public final static String __01Jan1970=formatDate(0); public final static Buffer __01Jan1970_BUFFER=new ByteArrayBuffer(__01Jan1970); public final static String __01Jan1970_COOKIE = formatCookieDate(0).trim(); /* -------------------------------------------------------------- */ private final ArrayList _fields = new ArrayList(20); private final HashMap _names = new HashMap(32); /* ------------------------------------------------------------ */ /** * Constructor. */ public HttpFields() { } // TODO externalize this cache so it can be configurable private static ConcurrentMap __cache = new ConcurrentHashMap(); private static int __cacheSize = Integer.getInteger("org.eclipse.jetty.http.HttpFields.CACHE",2000); /* -------------------------------------------------------------- */ private Buffer convertValue(String value) { Buffer buffer = __cache.get(value); if (buffer!=null) return buffer; try { buffer = new ByteArrayBuffer(value,StringUtil.__ISO_8859_1); if (__cacheSize>0) { if (__cache.size()>__cacheSize) __cache.clear(); Buffer b=__cache.putIfAbsent(value,buffer); if (b!=null) buffer=b; } return buffer; } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } /* -------------------------------------------------------------- */ /** * Get Collection of header names. */ public Collection getFieldNamesCollection() { final List list = new ArrayList(_fields.size()); for (Field f : _fields) { if (f!=null) list.add(BufferUtil.to8859_1_String(f._name)); } return list; } /* -------------------------------------------------------------- */ /** * Get enumeration of header _names. Returns an enumeration of strings representing the header * _names for this request. */ public Enumeration getFieldNames() { final Enumeration buffers = Collections.enumeration(_names.keySet()); return new Enumeration() { public String nextElement() { return buffers.nextElement().toString(); } public boolean hasMoreElements() { return buffers.hasMoreElements(); } }; } /* ------------------------------------------------------------ */ public int size() { return _fields.size(); } /* ------------------------------------------------------------ */ /** * Get a Field by index. * @return A Field value or null if the Field value has not been set * */ public Field getField(int i) { return _fields.get(i); } /* ------------------------------------------------------------ */ private Field getField(String name) { return _names.get(HttpHeaders.CACHE.lookup(name)); } /* ------------------------------------------------------------ */ private Field getField(Buffer name) { return _names.get(HttpHeaders.CACHE.lookup(name)); } /* ------------------------------------------------------------ */ public boolean containsKey(Buffer name) { return _names.containsKey(HttpHeaders.CACHE.lookup(name)); } /* ------------------------------------------------------------ */ public boolean containsKey(String name) { return _names.containsKey(HttpHeaders.CACHE.lookup(name)); } /* -------------------------------------------------------------- */ /** * @return the value of a field, or null if not found. For multiple fields of the same name, * only the first is returned. * @param name the case-insensitive field name */ public String getStringField(String name) { Field field = getField(name); return field==null?null:field.getValue(); } /* -------------------------------------------------------------- */ /** * @return the value of a field, or null if not found. For multiple fields of the same name, * only the first is returned. * @param name the case-insensitive field name */ public String getStringField(Buffer name) { Field field = getField(name); return field==null?null:field.getValue(); } /* -------------------------------------------------------------- */ /** * @return the value of a field, or null if not found. For multiple fields of the same name, * only the first is returned. * @param name the case-insensitive field name */ public Buffer get(Buffer name) { Field field = getField(name); return field==null?null:field._value; } /* -------------------------------------------------------------- */ /** * Get multi headers * * @return Enumeration of the values, or null if no such header. * @param name the case-insensitive field name */ public Collection getValuesCollection(String name) { Field field = getField(name); if (field==null) return null; final List list = new ArrayList(); while(field!=null) { list.add(field.getValue()); field=field._next; } return list; } /* -------------------------------------------------------------- */ /** * Get multi headers * * @return Enumeration of the values * @param name the case-insensitive field name */ public Enumeration getValues(String name) { final Field field = getField(name); if (field == null) { List empty=Collections.emptyList(); return Collections.enumeration(empty); } return new Enumeration() { Field f = field; public boolean hasMoreElements() { return f != null; } public String nextElement() throws NoSuchElementException { if (f == null) throw new NoSuchElementException(); Field n = f; f = f._next; return n.getValue(); } }; } /* -------------------------------------------------------------- */ /** * Get multi headers * * @return Enumeration of the value Strings * @param name the case-insensitive field name */ public Enumeration getValues(Buffer name) { final Field field = getField(name); if (field == null) { List empty=Collections.emptyList(); return Collections.enumeration(empty); } return new Enumeration() { Field f = field; public boolean hasMoreElements() { return f != null; } public String nextElement() throws NoSuchElementException { if (f == null) throw new NoSuchElementException(); Field n = f; f = f._next; return n.getValue(); } }; } /* -------------------------------------------------------------- */ /** * Get multi field values with separator. The multiple values can be represented as separate * headers of the same name, or by a single header using the separator(s), or a combination of * both. Separators may be quoted. * * @param name the case-insensitive field name * @param separators String of separators. * @return Enumeration of the values, or null if no such header. */ public Enumeration getValues(String name, final String separators) { final Enumeration e = getValues(name); if (e == null) return null; return new Enumeration() { QuotedStringTokenizer tok = null; public boolean hasMoreElements() { if (tok != null && tok.hasMoreElements()) return true; while (e.hasMoreElements()) { String value = e.nextElement(); tok = new QuotedStringTokenizer(value, separators, false, false); if (tok.hasMoreElements()) return true; } tok = null; return false; } public String nextElement() throws NoSuchElementException { if (!hasMoreElements()) throw new NoSuchElementException(); String next = (String) tok.nextElement(); if (next != null) next = next.trim(); return next; } }; } /* -------------------------------------------------------------- */ /** * Set a field. * * @param name the name of the field * @param value the value of the field. If null the field is cleared. */ public void put(String name, String value) { if (value==null) remove(name); else { Buffer n = HttpHeaders.CACHE.lookup(name); Buffer v = convertValue(value); put(n, v); } } /* -------------------------------------------------------------- */ /** * Set a field. * * @param name the name of the field * @param value the value of the field. If null the field is cleared. */ public void put(Buffer name, String value) { Buffer n = HttpHeaders.CACHE.lookup(name); Buffer v = convertValue(value); put(n, v); } /* -------------------------------------------------------------- */ /** * Set a field. * * @param name the name of the field * @param value the value of the field. If null the field is cleared. */ public void put(Buffer name, Buffer value) { remove(name); if (value == null) return; if (!(name instanceof BufferCache.CachedBuffer)) name = HttpHeaders.CACHE.lookup(name); if (!(value instanceof CachedBuffer)) value= HttpHeaderValues.CACHE.lookup(value).asImmutableBuffer(); // new value; Field field = new Field(name, value); _fields.add(field); _names.put(name, field); } /* -------------------------------------------------------------- */ /** * Set a field. * * @param name the name of the field * @param list the List value of the field. If null the field is cleared. */ public void put(String name, List list) { if (list == null || list.size() == 0) { remove(name); return; } Buffer n = HttpHeaders.CACHE.lookup(name); Object v = list.get(0); if (v != null) put(n, HttpHeaderValues.CACHE.lookup(v.toString())); else remove(n); if (list.size() > 1) { java.util.Iterator iter = list.iterator(); iter.next(); while (iter.hasNext()) { v = iter.next(); if (v != null) put(n, HttpHeaderValues.CACHE.lookup(v.toString())); } } } /* -------------------------------------------------------------- */ /** * Add to or set a field. If the field is allowed to have multiple values, add will add multiple * headers of the same name. * * @param name the name of the field * @param value the value of the field. * @exception IllegalArgumentException If the name is a single valued field and already has a * value. */ public void add(String name, String value) throws IllegalArgumentException { if (value==null) return; Buffer n = HttpHeaders.CACHE.lookup(name); Buffer v = convertValue(value); add(n, v); } /* -------------------------------------------------------------- */ /** * Add to or set a field. If the field is allowed to have multiple values, add will add multiple * headers of the same name. * * @param name the name of the field * @param value the value of the field. * @exception IllegalArgumentException If the name is a single valued field and already has a * value. */ public void add(Buffer name, Buffer value) throws IllegalArgumentException { if (value == null) throw new IllegalArgumentException("null value"); if (!(name instanceof CachedBuffer)) name = HttpHeaders.CACHE.lookup(name); name=name.asImmutableBuffer(); if (!(value instanceof CachedBuffer) && HttpHeaderValues.hasKnownValues(HttpHeaders.CACHE.getOrdinal(name))) value= HttpHeaderValues.CACHE.lookup(value); value=value.asImmutableBuffer(); Field field = _names.get(name); Field last = null; while (field != null) { last = field; field = field._next; } // create the field field = new Field(name, value); _fields.add(field); // look for chain to add too if (last != null) last._next = field; else _names.put(name, field); } /* ------------------------------------------------------------ */ /** * Remove a field. * * @param name */ public void remove(String name) { remove(HttpHeaders.CACHE.lookup(name)); } /* ------------------------------------------------------------ */ /** * Remove a field. * * @param name */ public void remove(Buffer name) { if (!(name instanceof BufferCache.CachedBuffer)) name = HttpHeaders.CACHE.lookup(name); Field field = _names.remove(name); while (field != null) { _fields.remove(field); field = field._next; } } /* -------------------------------------------------------------- */ /** * Get a header as an long value. Returns the value of an integer field or -1 if not found. The * case of the field name is ignored. * * @param name the case-insensitive field name * @exception NumberFormatException If bad long found */ public long getLongField(String name) throws NumberFormatException { Field field = getField(name); return field==null?-1L:field.getLongValue(); } /* -------------------------------------------------------------- */ /** * Get a header as an long value. Returns the value of an integer field or -1 if not found. The * case of the field name is ignored. * * @param name the case-insensitive field name * @exception NumberFormatException If bad long found */ public long getLongField(Buffer name) throws NumberFormatException { Field field = getField(name); return field==null?-1L:field.getLongValue(); } /* -------------------------------------------------------------- */ /** * Get a header as a date value. Returns the value of a date field, or -1 if not found. The case * of the field name is ignored. * * @param name the case-insensitive field name */ public long getDateField(String name) { Field field = getField(name); if (field == null) return -1; String val = valueParameters(BufferUtil.to8859_1_String(field._value), null); if (val == null) return -1; final long date = __dateParser.get().parse(val); if (date==-1) throw new IllegalArgumentException("Cannot convert date: " + val); return date; } /* -------------------------------------------------------------- */ /** * Sets the value of an long field. * * @param name the field name * @param value the field long value */ public void putLongField(Buffer name, long value) { Buffer v = BufferUtil.toBuffer(value); put(name, v); } /* -------------------------------------------------------------- */ /** * Sets the value of an long field. * * @param name the field name * @param value the field long value */ public void putLongField(String name, long value) { Buffer n = HttpHeaders.CACHE.lookup(name); Buffer v = BufferUtil.toBuffer(value); put(n, v); } /* -------------------------------------------------------------- */ /** * Sets the value of an long field. * * @param name the field name * @param value the field long value */ public void addLongField(String name, long value) { Buffer n = HttpHeaders.CACHE.lookup(name); Buffer v = BufferUtil.toBuffer(value); add(n, v); } /* -------------------------------------------------------------- */ /** * Sets the value of an long field. * * @param name the field name * @param value the field long value */ public void addLongField(Buffer name, long value) { Buffer v = BufferUtil.toBuffer(value); add(name, v); } /* -------------------------------------------------------------- */ /** * Sets the value of a date field. * * @param name the field name * @param date the field date value */ public void putDateField(Buffer name, long date) { String d=formatDate(date); Buffer v = new ByteArrayBuffer(d); put(name, v); } /* -------------------------------------------------------------- */ /** * Sets the value of a date field. * * @param name the field name * @param date the field date value */ public void putDateField(String name, long date) { Buffer n = HttpHeaders.CACHE.lookup(name); putDateField(n,date); } /* -------------------------------------------------------------- */ /** * Sets the value of a date field. * * @param name the field name * @param date the field date value */ public void addDateField(String name, long date) { String d=formatDate(date); Buffer n = HttpHeaders.CACHE.lookup(name); Buffer v = new ByteArrayBuffer(d); add(n, v); } /* ------------------------------------------------------------ */ /** * Format a set cookie value * * @param cookie The cookie. */ public void addSetCookie(HttpCookie cookie) { addSetCookie( cookie.getName(), cookie.getValue(), cookie.getDomain(), cookie.getPath(), cookie.getMaxAge(), cookie.getComment(), cookie.isSecure(), cookie.isHttpOnly(), cookie.getVersion()); } /** * Format a set cookie value * * @param name the name * @param value the value * @param domain the domain * @param path the path * @param maxAge the maximum age * @param comment the comment (only present on versions > 0) * @param isSecure true if secure cookie * @param isHttpOnly true if for http only * @param version version of cookie logic to use (0 == default behavior) */ public void addSetCookie( final String name, final String value, final String domain, final String path, final long maxAge, final String comment, final boolean isSecure, final boolean isHttpOnly, int version) { String delim=__COOKIE_DELIM; // Check arguments if (name == null || name.length() == 0) throw new IllegalArgumentException("Bad cookie name"); // Format value and params StringBuilder buf = new StringBuilder(128); String name_value_params; QuotedStringTokenizer.quoteIfNeeded(buf, name, delim); buf.append('='); String start=buf.toString(); if (value != null && value.length() > 0) QuotedStringTokenizer.quoteIfNeeded(buf, value, delim); if (comment != null && comment.length() > 0) { buf.append(";Comment="); QuotedStringTokenizer.quoteIfNeeded(buf, comment, delim); } if (path != null && path.length() > 0) { buf.append(";Path="); if (path.trim().startsWith("\"")) buf.append(path); else QuotedStringTokenizer.quoteIfNeeded(buf,path,delim); } if (domain != null && domain.length() > 0) { buf.append(";Domain="); QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(),delim); } if (maxAge >= 0) { // Always add the expires param as some browsers still don't handle max-age buf.append(";Expires="); if (maxAge == 0) buf.append(__01Jan1970_COOKIE); else formatCookieDate(buf, System.currentTimeMillis() + 1000L * maxAge); if (version >0) { buf.append(";Max-Age="); buf.append(maxAge); } } if (isSecure) buf.append(";Secure"); if (isHttpOnly) buf.append(";HttpOnly"); name_value_params = buf.toString(); // remove existing set-cookie of same name Field field = getField(HttpHeaders.SET_COOKIE); Field last=null; while (field!=null) { if (field._value!=null && field._value.toString().startsWith(start)) { _fields.remove(field); if (last==null) _names.put(HttpHeaders.SET_COOKIE_BUFFER,field._next); else last._next=field._next; break; } last=field; field=field._next; } add(HttpHeaders.SET_COOKIE_BUFFER, new ByteArrayBuffer(name_value_params)); // Expire responses with set-cookie headers so they do not get cached. put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER); } /* -------------------------------------------------------------- */ public void putTo(Buffer buffer) throws IOException { for (int i = 0; i < _fields.size(); i++) { Field field = _fields.get(i); if (field != null) field.putTo(buffer); } BufferUtil.putCRLF(buffer); } /* -------------------------------------------------------------- */ public String toString() { try { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < _fields.size(); i++) { Field field = (Field) _fields.get(i); if (field != null) { String tmp = field.getName(); if (tmp != null) buffer.append(tmp); buffer.append(": "); tmp = field.getValue(); if (tmp != null) buffer.append(tmp); buffer.append("\r\n"); } } buffer.append("\r\n"); return buffer.toString(); } catch (Exception e) { LOG.warn(e); return e.toString(); } } /* ------------------------------------------------------------ */ /** * Clear the header. */ public void clear() { _fields.clear(); _names.clear(); } /* ------------------------------------------------------------ */ /** * Add fields from another HttpFields instance. Single valued fields are replaced, while all * others are added. * * @param fields */ public void add(HttpFields fields) { if (fields == null) return; Enumeration e = fields.getFieldNames(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); Enumeration values = fields.getValues(name); while (values.hasMoreElements()) add(name, (String) values.nextElement()); } } /* ------------------------------------------------------------ */ /** * Get field value parameters. Some field values can have parameters. This method separates the * value from the parameters and optionally populates a map with the parameters. For example: * *

     * 
     * FieldName : Value ; param1=val1 ; param2=val2
     * 
     * 
* * @param value The Field value, possibly with parameteres. * @param parameters A map to populate with the parameters, or null * @return The value. */ public static String valueParameters(String value, Map parameters) { if (value == null) return null; int i = value.indexOf(';'); if (i < 0) return value; if (parameters == null) return value.substring(0, i).trim(); StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true); while (tok1.hasMoreTokens()) { String token = tok1.nextToken(); StringTokenizer tok2 = new QuotedStringTokenizer(token, "= "); if (tok2.hasMoreTokens()) { String paramName = tok2.nextToken(); String paramVal = null; if (tok2.hasMoreTokens()) paramVal = tok2.nextToken(); parameters.put(paramName, paramVal); } } return value.substring(0, i).trim(); } /* ------------------------------------------------------------ */ private static final Float __one = new Float("1.0"); private static final Float __zero = new Float("0.0"); private static final StringMap __qualities = new StringMap(); static { __qualities.put(null, __one); __qualities.put("1.0", __one); __qualities.put("1", __one); __qualities.put("0.9", new Float("0.9")); __qualities.put("0.8", new Float("0.8")); __qualities.put("0.7", new Float("0.7")); __qualities.put("0.66", new Float("0.66")); __qualities.put("0.6", new Float("0.6")); __qualities.put("0.5", new Float("0.5")); __qualities.put("0.4", new Float("0.4")); __qualities.put("0.33", new Float("0.33")); __qualities.put("0.3", new Float("0.3")); __qualities.put("0.2", new Float("0.2")); __qualities.put("0.1", new Float("0.1")); __qualities.put("0", __zero); __qualities.put("0.0", __zero); } /* ------------------------------------------------------------ */ public static Float getQuality(String value) { if (value == null) return __zero; int qe = value.indexOf(";"); if (qe++ < 0 || qe == value.length()) return __one; if (value.charAt(qe++) == 'q') { qe++; Map.Entry entry = __qualities.getEntry(value, qe, value.length() - qe); if (entry != null) return (Float) entry.getValue(); } HashMap params = new HashMap(3); valueParameters(value, params); String qs = (String) params.get("q"); Float q = (Float) __qualities.get(qs); if (q == null) { try { q = new Float(qs); } catch (Exception e) { q = __one; } } return q; } /* ------------------------------------------------------------ */ /** * List values in quality order. * * @param e Enumeration of values with quality parameters * @return values in quality order. */ public static List qualityList(Enumeration e) { if (e == null || !e.hasMoreElements()) return Collections.EMPTY_LIST; Object list = null; Object qual = null; // Assume list will be well ordered and just add nonzero while (e.hasMoreElements()) { String v = e.nextElement().toString(); Float q = getQuality(v); if (q.floatValue() >= 0.001) { list = LazyList.add(list, v); qual = LazyList.add(qual, q); } } List vl = LazyList.getList(list, false); if (vl.size() < 2) return vl; List ql = LazyList.getList(qual, false); // sort list with swaps Float last = __zero; for (int i = vl.size(); i-- > 0;) { Float q = (Float) ql.get(i); if (last.compareTo(q) > 0) { Object tmp = vl.get(i); vl.set(i, vl.get(i + 1)); vl.set(i + 1, tmp); ql.set(i, ql.get(i + 1)); ql.set(i + 1, q); last = __zero; i = vl.size(); continue; } last = q; } ql.clear(); return vl; } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ public static final class Field { private Buffer _name; private Buffer _value; private Field _next; /* ------------------------------------------------------------ */ private Field(Buffer name, Buffer value) { _name = name; _value = value; _next = null; } /* ------------------------------------------------------------ */ public void putTo(Buffer buffer) throws IOException { int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1; if (o>=0) buffer.put(_name); else { int s=_name.getIndex(); int e=_name.putIndex(); while (s=0) buffer.put(_value); else { int s=_value.getIndex(); int e=_value.putIndex(); while (s") + "]"); } } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java000066400000000000000000001222411174773561500275260ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.io.IOException; import java.io.InterruptedIOException; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.io.BufferUtil; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ /** * HttpGenerator. Builds HTTP Messages. * * * */ public class HttpGenerator extends AbstractGenerator { private static final Logger LOG = Log.getLogger(HttpGenerator.class); // Build cache of response lines for status private static class Status { Buffer _reason; Buffer _schemeCode; Buffer _responseLine; } private static final Status[] __status = new Status[HttpStatus.MAX_CODE+1]; static { int versionLength=HttpVersions.HTTP_1_1_BUFFER.length(); for (int i=0;i<__status.length;i++) { HttpStatus.Code code = HttpStatus.getCode(i); if (code==null) continue; String reason=code.getMessage(); byte[] bytes=new byte[versionLength+5+reason.length()+2]; HttpVersions.HTTP_1_1_BUFFER.peek(0,bytes, 0, versionLength); bytes[versionLength+0]=' '; bytes[versionLength+1]=(byte)('0'+i/100); bytes[versionLength+2]=(byte)('0'+(i%100)/10); bytes[versionLength+3]=(byte)('0'+(i%10)); bytes[versionLength+4]=' '; for (int j=0;jcontent is {@link Buffer#isImmutable immutable}. * @throws IllegalStateException If the request is not expecting any more content, * or if the buffers are full and cannot be flushed. * @throws IOException if there is a problem flushing the buffers. */ public void addContent(Buffer content, boolean last) throws IOException { if (_noContent) throw new IllegalStateException("NO CONTENT"); if (_last || _state==STATE_END) { LOG.warn("Ignoring extra content {}",content); content.clear(); return; } _last = last; // Handle any unfinished business? if (_content!=null && _content.length()>0 || _bufferChunked) { if (_endp.isOutputShutdown()) throw new EofException(); flushBuffer(); if (_content != null && _content.length()>0) { if (_bufferChunked) { Buffer nc=_buffers.getBuffer(_content.length()+CHUNK_SPACE+content.length()); nc.put(_content); nc.put(HttpTokens.CRLF); BufferUtil.putHexInt(nc, content.length()); nc.put(HttpTokens.CRLF); nc.put(content); content=nc; } else { Buffer nc=_buffers.getBuffer(_content.length()+content.length()); nc.put(_content); nc.put(content); content=nc; } } } _content = content; _contentWritten += content.length(); // Handle the _content if (_head) { content.clear(); _content=null; } else if (_endp != null && (_buffer==null || _buffer.length()==0) && _content.length() > 0 && (_last || isCommitted() && _content.length()>1024)) { _bypass = true; } else if (!_bufferChunked) { // Yes - so we better check we have a buffer if (_buffer == null) _buffer = _buffers.getBuffer(); // Copy _content to buffer; int len=_buffer.put(_content); _content.skip(len); if (_content.length() == 0) _content = null; } } /* ------------------------------------------------------------ */ /** * send complete response. * * @param response */ public void sendResponse(Buffer response) throws IOException { if (_noContent || _state!=STATE_HEADER || _content!=null && _content.length()>0 || _bufferChunked || _head ) throw new IllegalStateException(); _last = true; _content = response; _bypass = true; _state = STATE_FLUSHING; // TODO this is not exactly right, but should do. _contentLength =_contentWritten = response.length(); } /* ------------------------------------------------------------ */ /** * Add content. * * @param b byte * @return true if the buffers are full * @throws IOException */ public boolean addContent(byte b) throws IOException { if (_noContent) throw new IllegalStateException("NO CONTENT"); if (_last || _state==STATE_END) { LOG.warn("Ignoring extra content {}",Byte.valueOf(b)); return false; } // Handle any unfinished business? if (_content != null && _content.length()>0 || _bufferChunked) { flushBuffer(); if (_content != null && _content.length()>0 || _bufferChunked) throw new IllegalStateException("FULL"); } _contentWritten++; // Handle the _content if (_head) return false; // we better check we have a buffer if (_buffer == null) _buffer = _buffers.getBuffer(); // Copy _content to buffer; _buffer.put(b); return _buffer.space()<=(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0); } /* ------------------------------------------------------------ */ /** Prepare buffer for unchecked writes. * Prepare the generator buffer to receive unchecked writes * @return the available space in the buffer. * @throws IOException */ @Override public int prepareUncheckedAddContent() throws IOException { if (_noContent) return -1; if (_last || _state==STATE_END) return -1; // Handle any unfinished business? Buffer content = _content; if (content != null && content.length()>0 || _bufferChunked) { flushBuffer(); if (content != null && content.length()>0 || _bufferChunked) throw new IllegalStateException("FULL"); } // we better check we have a buffer if (_buffer == null) _buffer = _buffers.getBuffer(); _contentWritten-=_buffer.length(); // Handle the _content if (_head) return Integer.MAX_VALUE; return _buffer.space()-(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0); } /* ------------------------------------------------------------ */ @Override public boolean isBufferFull() { // Should we flush the buffers? return super.isBufferFull() || _bufferChunked || _bypass || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE); } /* ------------------------------------------------------------ */ public void send1xx(int code) throws IOException { if (_state != STATE_HEADER) return; if (code<100||code>199) throw new IllegalArgumentException("!1xx"); Status status=__status[code]; if (status==null) throw new IllegalArgumentException(code+"?"); // get a header buffer if (_header == null) _header = _buffers.getHeader(); _header.put(status._responseLine); _header.put(HttpTokens.CRLF); try { // nasty semi busy flush! while(_header.length()>0) { int len = _endp.flush(_header); if (len<0) throw new EofException(); if (len==0) Thread.sleep(100); } } catch(InterruptedException e) { LOG.debug(e); throw new InterruptedIOException(e.toString()); } } /* ------------------------------------------------------------ */ @Override public boolean isRequest() { return _method!=null; } /* ------------------------------------------------------------ */ @Override public boolean isResponse() { return _method==null; } /* ------------------------------------------------------------ */ @Override public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException { if (_state != STATE_HEADER) return; // handle a reset if (isResponse() && _status==0) throw new EofException(); if (_last && !allContentAdded) throw new IllegalStateException("last?"); _last = _last | allContentAdded; // get a header buffer if (_header == null) _header = _buffers.getHeader(); boolean has_server = false; try { if (isRequest()) { _persistent=true; if (_version == HttpVersions.HTTP_0_9_ORDINAL) { _contentLength = HttpTokens.NO_CONTENT; _header.put(_method); _header.put((byte)' '); _header.put(_uri.getBytes("UTF-8")); // TODO check _header.put(HttpTokens.CRLF); _state = STATE_FLUSHING; _noContent=true; return; } else { _header.put(_method); _header.put((byte)' '); _header.put(_uri.getBytes("UTF-8")); // TODO check _header.put((byte)' '); _header.put(_version==HttpVersions.HTTP_1_0_ORDINAL?HttpVersions.HTTP_1_0_BUFFER:HttpVersions.HTTP_1_1_BUFFER); _header.put(HttpTokens.CRLF); } } else { // Responses if (_version == HttpVersions.HTTP_0_9_ORDINAL) { _persistent = false; _contentLength = HttpTokens.EOF_CONTENT; _state = STATE_CONTENT; return; } else { if (_persistent==null) _persistent= (_version > HttpVersions.HTTP_1_0_ORDINAL); // add response line Status status = _status<__status.length?__status[_status]:null; if (status==null) { _header.put(HttpVersions.HTTP_1_1_BUFFER); _header.put((byte) ' '); _header.put((byte) ('0' + _status / 100)); _header.put((byte) ('0' + (_status % 100) / 10)); _header.put((byte) ('0' + (_status % 10))); _header.put((byte) ' '); if (_reason==null) { _header.put((byte) ('0' + _status / 100)); _header.put((byte) ('0' + (_status % 100) / 10)); _header.put((byte) ('0' + (_status % 10))); } else _header.put(_reason); _header.put(HttpTokens.CRLF); } else { if (_reason==null) _header.put(status._responseLine); else { _header.put(status._schemeCode); _header.put(_reason); _header.put(HttpTokens.CRLF); } } if (_status<200 && _status>=100 ) { _noContent=true; _content=null; if (_buffer!=null) _buffer.clear(); // end the header. if (_status!=101 ) { _header.put(HttpTokens.CRLF); _state = STATE_CONTENT; return; } } else if (_status==204 || _status==304) { _noContent=true; _content=null; if (_buffer!=null) _buffer.clear(); } } } // Add headers if (_status>=200 && _date!=null) { _header.put(HttpHeaders.DATE_BUFFER); _header.put((byte)':'); _header.put((byte)' '); _header.put(_date); _header.put(CRLF); } // key field values HttpFields.Field content_length = null; HttpFields.Field transfer_encoding = null; boolean keep_alive = false; boolean close=false; boolean content_type=false; StringBuilder connection = null; if (fields != null) { int s=fields.size(); for (int f=0;f0 || content_type ) && !_noContent) { // known length but not actually set. _header.put(HttpHeaders.CONTENT_LENGTH_BUFFER); _header.put(HttpTokens.COLON); _header.put((byte) ' '); BufferUtil.putDecLong(_header, _contentLength); _header.put(HttpTokens.CRLF); } } else { // No idea, so we must assume that a body is coming _contentLength = (!_persistent || _version < HttpVersions.HTTP_1_1_ORDINAL ) ? HttpTokens.EOF_CONTENT : HttpTokens.CHUNKED_CONTENT; if (isRequest() && _contentLength==HttpTokens.EOF_CONTENT) { _contentLength=HttpTokens.NO_CONTENT; _noContent=true; } } break; case HttpTokens.NO_CONTENT: if (content_length == null && isResponse() && _status >= 200 && _status != 204 && _status != 304) _header.put(CONTENT_LENGTH_0); break; case HttpTokens.EOF_CONTENT: _persistent = isRequest(); break; case HttpTokens.CHUNKED_CONTENT: break; default: // TODO - maybe allow forced chunking by setting te ??? break; } // Add transfer_encoding if needed if (_contentLength == HttpTokens.CHUNKED_CONTENT) { // try to use user supplied encoding as it may have other values. if (transfer_encoding != null && HttpHeaderValues.CHUNKED_ORDINAL != transfer_encoding.getValueOrdinal()) { String c = transfer_encoding.getValue(); if (c.endsWith(HttpHeaderValues.CHUNKED)) transfer_encoding.putTo(_header); else throw new IllegalArgumentException("BAD TE"); } else _header.put(TRANSFER_ENCODING_CHUNKED); } // Handle connection if need be if (_contentLength==HttpTokens.EOF_CONTENT) { keep_alive=false; _persistent=false; } if (isResponse()) { if (!_persistent && (close || _version > HttpVersions.HTTP_1_0_ORDINAL)) { _header.put(CONNECTION_CLOSE); if (connection!=null) { _header.setPutIndex(_header.putIndex()-2); _header.put((byte)','); _header.put(connection.toString().getBytes()); _header.put(CRLF); } } else if (keep_alive) { _header.put(CONNECTION_KEEP_ALIVE); if (connection!=null) { _header.setPutIndex(_header.putIndex()-2); _header.put((byte)','); _header.put(connection.toString().getBytes()); _header.put(CRLF); } } else if (connection!=null) { _header.put(CONNECTION_); _header.put(connection.toString().getBytes()); _header.put(CRLF); } } if (!has_server && _status>199 && getSendServerVersion()) _header.put(SERVER); // end the header. _header.put(HttpTokens.CRLF); _state = STATE_CONTENT; } catch(ArrayIndexOutOfBoundsException e) { throw new RuntimeException("Header>"+_header.capacity(),e); } } /* ------------------------------------------------------------ */ /** * Complete the message. * * @throws IOException */ @Override public void complete() throws IOException { if (_state == STATE_END) return; super.complete(); if (_state < STATE_FLUSHING) { _state = STATE_FLUSHING; if (_contentLength == HttpTokens.CHUNKED_CONTENT) _needEOC = true; } flushBuffer(); } /* ------------------------------------------------------------ */ @Override public int flushBuffer() throws IOException { try { if (_state == STATE_HEADER) throw new IllegalStateException("State==HEADER"); prepareBuffers(); if (_endp == null) { if (_needCRLF && _buffer!=null) _buffer.put(HttpTokens.CRLF); if (_needEOC && _buffer!=null && !_head) _buffer.put(LAST_CHUNK); _needCRLF=false; _needEOC=false; return 0; } int total= 0; int len = -1; int to_flush = flushMask(); int last_flush; do { last_flush=to_flush; switch (to_flush) { case 7: throw new IllegalStateException(); // should never happen! case 6: len = _endp.flush(_header, _buffer, null); break; case 5: len = _endp.flush(_header, _content, null); break; case 4: len = _endp.flush(_header); break; case 3: len = _endp.flush(_buffer, _content, null); break; case 2: len = _endp.flush(_buffer); break; case 1: len = _endp.flush(_content); break; case 0: { len=0; // Nothing more we can write now. if (_header != null) _header.clear(); _bypass = false; _bufferChunked = false; if (_buffer != null) { _buffer.clear(); if (_contentLength == HttpTokens.CHUNKED_CONTENT) { // reserve some space for the chunk header _buffer.setPutIndex(CHUNK_SPACE); _buffer.setGetIndex(CHUNK_SPACE); // Special case handling for small left over buffer from // an addContent that caused a buffer flush. if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING) { _buffer.put(_content); _content.clear(); _content=null; } } } // Are we completely finished for now? if (!_needCRLF && !_needEOC && (_content==null || _content.length()==0)) { if (_state == STATE_FLUSHING) _state = STATE_END; if (_state==STATE_END && _persistent != null && !_persistent && _status!=100 && _method==null) _endp.shutdownOutput(); } else // Try to prepare more to write. prepareBuffers(); } } if (len > 0) total+=len; to_flush = flushMask(); } // loop while progress is being made (OR we have prepared some buffers that might make progress) while (len>0 || (to_flush!=0 && last_flush==0)); return total; } catch (IOException e) { LOG.ignore(e); throw (e instanceof EofException) ? e:new EofException(e); } } /* ------------------------------------------------------------ */ private int flushMask() { return ((_header != null && _header.length() > 0)?4:0) | ((_buffer != null && _buffer.length() > 0)?2:0) | ((_bypass && _content != null && _content.length() > 0)?1:0); } /* ------------------------------------------------------------ */ private void prepareBuffers() { // if we are not flushing an existing chunk if (!_bufferChunked) { // Refill buffer if possible if (!_bypass && _content != null && _content.length() > 0 && _buffer != null && _buffer.space() > 0) { int len = _buffer.put(_content); _content.skip(len); if (_content.length() == 0) _content = null; } // Chunk buffer if need be if (_contentLength == HttpTokens.CHUNKED_CONTENT) { if (_bypass && (_buffer==null||_buffer.length()==0) && _content!=null) { // this is a bypass write int size = _content.length(); _bufferChunked = true; if (_header == null) _header = _buffers.getHeader(); // if we need CRLF add this to header if (_needCRLF) { if (_header.length() > 0) throw new IllegalStateException("EOC"); _header.put(HttpTokens.CRLF); _needCRLF = false; } // Add the chunk size to the header BufferUtil.putHexInt(_header, size); _header.put(HttpTokens.CRLF); // Need a CRLF after the content _needCRLF=true; } else if (_buffer!=null) { int size = _buffer.length(); if (size > 0) { // Prepare a chunk! _bufferChunked = true; // Did we leave space at the start of the buffer. //noinspection ConstantConditions if (_buffer.getIndex() == CHUNK_SPACE) { // Oh yes, goodie! let's use it then! _buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2); _buffer.setGetIndex(_buffer.getIndex() - 2); BufferUtil.prependHexInt(_buffer, size); if (_needCRLF) { _buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2); _buffer.setGetIndex(_buffer.getIndex() - 2); _needCRLF = false; } } else { // No space so lets use a header buffer. if (_header == null) _header = _buffers.getHeader(); if (_needCRLF) { if (_header.length() > 0) throw new IllegalStateException("EOC"); _header.put(HttpTokens.CRLF); _needCRLF = false; } BufferUtil.putHexInt(_header, size); _header.put(HttpTokens.CRLF); } // Add end chunk trailer. if (_buffer.space() >= 2) _buffer.put(HttpTokens.CRLF); else _needCRLF = true; } } // If we need EOC and everything written if (_needEOC && (_content == null || _content.length() == 0)) { if (_needCRLF) { if (_buffer == null && _header.space() >= 2) { _header.put(HttpTokens.CRLF); _needCRLF = false; } else if (_buffer!=null && _buffer.space() >= 2) { _buffer.put(HttpTokens.CRLF); _needCRLF = false; } } if (!_needCRLF && _needEOC) { if (_buffer == null && _header.space() >= LAST_CHUNK.length) { if (!_head) { _header.put(LAST_CHUNK); _bufferChunked=true; } _needEOC = false; } else if (_buffer!=null && _buffer.space() >= LAST_CHUNK.length) { if (!_head) { _buffer.put(LAST_CHUNK); _bufferChunked=true; } _needEOC = false; } } } } } if (_content != null && _content.length() == 0) _content = null; } public int getBytesBuffered() { return(_header==null?0:_header.length())+ (_buffer==null?0:_buffer.length())+ (_content==null?0:_content.length()); } public boolean isEmpty() { return (_header==null||_header.length()==0) && (_buffer==null||_buffer.length()==0) && (_content==null||_content.length()==0); } @Override public String toString() { return String.format("%s{s=%d,h=%d,b=%d,c=%d}", getClass().getSimpleName(), _state, _header == null ? -1 : _header.length(), _buffer == null ? -1 : _buffer.length(), _content == null ? -1 : _content.length()); } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeaderValues.java000066400000000000000000000057461174773561500301620ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache; import org.eclipse.jetty.io.ByteArrayBuffer; /** * Cached HTTP Header values. * This class caches the conversion of common HTTP Header values to and from {@link ByteArrayBuffer} instances. * The resource "/org/eclipse/jetty/useragents" is checked for a list of common user agents, so that repeated * creation of strings for these agents can be avoided. * * */ public class HttpHeaderValues extends BufferCache { public final static String CLOSE="close", CHUNKED="chunked", GZIP="gzip", IDENTITY="identity", KEEP_ALIVE="keep-alive", CONTINUE="100-continue", PROCESSING="102-processing", TE="TE", BYTES="bytes", NO_CACHE="no-cache", UPGRADE="Upgrade"; public final static int CLOSE_ORDINAL=1, CHUNKED_ORDINAL=2, GZIP_ORDINAL=3, IDENTITY_ORDINAL=4, KEEP_ALIVE_ORDINAL=5, CONTINUE_ORDINAL=6, PROCESSING_ORDINAL=7, TE_ORDINAL=8, BYTES_ORDINAL=9, NO_CACHE_ORDINAL=10, UPGRADE_ORDINAL=11; public final static HttpHeaderValues CACHE= new HttpHeaderValues(); public final static Buffer CLOSE_BUFFER=CACHE.add(CLOSE,CLOSE_ORDINAL), CHUNKED_BUFFER=CACHE.add(CHUNKED,CHUNKED_ORDINAL), GZIP_BUFFER=CACHE.add(GZIP,GZIP_ORDINAL), IDENTITY_BUFFER=CACHE.add(IDENTITY,IDENTITY_ORDINAL), KEEP_ALIVE_BUFFER=CACHE.add(KEEP_ALIVE,KEEP_ALIVE_ORDINAL), CONTINUE_BUFFER=CACHE.add(CONTINUE, CONTINUE_ORDINAL), PROCESSING_BUFFER=CACHE.add(PROCESSING, PROCESSING_ORDINAL), TE_BUFFER=CACHE.add(TE,TE_ORDINAL), BYTES_BUFFER=CACHE.add(BYTES,BYTES_ORDINAL), NO_CACHE_BUFFER=CACHE.add(NO_CACHE,NO_CACHE_ORDINAL), UPGRADE_BUFFER=CACHE.add(UPGRADE,UPGRADE_ORDINAL); public static boolean hasKnownValues(int httpHeaderOrdinal) { switch(httpHeaderOrdinal) { case HttpHeaders.CONNECTION_ORDINAL: case HttpHeaders.TRANSFER_ENCODING_ORDINAL: case HttpHeaders.CONTENT_ENCODING_ORDINAL: return true; } return false; } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpHeaders.java000066400000000000000000000237721174773561500271640ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache; /* ------------------------------------------------------------------------------- */ /** */ public class HttpHeaders extends BufferCache { /* ------------------------------------------------------------ */ /** General Fields. */ public final static String CONNECTION= "Connection", CACHE_CONTROL= "Cache-Control", DATE= "Date", PRAGMA= "Pragma", PROXY_CONNECTION = "Proxy-Connection", TRAILER= "Trailer", TRANSFER_ENCODING= "Transfer-Encoding", UPGRADE= "Upgrade", VIA= "Via", WARNING= "Warning", NEGOTIATE= "Negotiate"; /* ------------------------------------------------------------ */ /** Entity Fields. */ public final static String ALLOW= "Allow", CONTENT_ENCODING= "Content-Encoding", CONTENT_LANGUAGE= "Content-Language", CONTENT_LENGTH= "Content-Length", CONTENT_LOCATION= "Content-Location", CONTENT_MD5= "Content-MD5", CONTENT_RANGE= "Content-Range", CONTENT_TYPE= "Content-Type", EXPIRES= "Expires", LAST_MODIFIED= "Last-Modified"; /* ------------------------------------------------------------ */ /** Request Fields. */ public final static String ACCEPT= "Accept", ACCEPT_CHARSET= "Accept-Charset", ACCEPT_ENCODING= "Accept-Encoding", ACCEPT_LANGUAGE= "Accept-Language", AUTHORIZATION= "Authorization", EXPECT= "Expect", FORWARDED= "Forwarded", FROM= "From", HOST= "Host", IF_MATCH= "If-Match", IF_MODIFIED_SINCE= "If-Modified-Since", IF_NONE_MATCH= "If-None-Match", IF_RANGE= "If-Range", IF_UNMODIFIED_SINCE= "If-Unmodified-Since", KEEP_ALIVE= "Keep-Alive", MAX_FORWARDS= "Max-Forwards", PROXY_AUTHORIZATION= "Proxy-Authorization", RANGE= "Range", REQUEST_RANGE= "Request-Range", REFERER= "Referer", TE= "TE", USER_AGENT= "User-Agent", X_FORWARDED_FOR= "X-Forwarded-For", X_FORWARDED_PROTO= "X-Forwarded-Proto", X_FORWARDED_SERVER= "X-Forwarded-Server", X_FORWARDED_HOST= "X-Forwarded-Host"; /* ------------------------------------------------------------ */ /** Response Fields. */ public final static String ACCEPT_RANGES= "Accept-Ranges", AGE= "Age", ETAG= "ETag", LOCATION= "Location", PROXY_AUTHENTICATE= "Proxy-Authenticate", RETRY_AFTER= "Retry-After", SERVER= "Server", SERVLET_ENGINE= "Servlet-Engine", VARY= "Vary", WWW_AUTHENTICATE= "WWW-Authenticate"; /* ------------------------------------------------------------ */ /** Other Fields. */ public final static String COOKIE= "Cookie", SET_COOKIE= "Set-Cookie", SET_COOKIE2= "Set-Cookie2", MIME_VERSION= "MIME-Version", IDENTITY= "identity"; public final static int CONNECTION_ORDINAL= 1, DATE_ORDINAL= 2, PRAGMA_ORDINAL= 3, TRAILER_ORDINAL= 4, TRANSFER_ENCODING_ORDINAL= 5, UPGRADE_ORDINAL= 6, VIA_ORDINAL= 7, WARNING_ORDINAL= 8, ALLOW_ORDINAL= 9, CONTENT_ENCODING_ORDINAL= 10, CONTENT_LANGUAGE_ORDINAL= 11, CONTENT_LENGTH_ORDINAL= 12, CONTENT_LOCATION_ORDINAL= 13, CONTENT_MD5_ORDINAL= 14, CONTENT_RANGE_ORDINAL= 15, CONTENT_TYPE_ORDINAL= 16, EXPIRES_ORDINAL= 17, LAST_MODIFIED_ORDINAL= 18, ACCEPT_ORDINAL= 19, ACCEPT_CHARSET_ORDINAL= 20, ACCEPT_ENCODING_ORDINAL= 21, ACCEPT_LANGUAGE_ORDINAL= 22, AUTHORIZATION_ORDINAL= 23, EXPECT_ORDINAL= 24, FORWARDED_ORDINAL= 25, FROM_ORDINAL= 26, HOST_ORDINAL= 27, IF_MATCH_ORDINAL= 28, IF_MODIFIED_SINCE_ORDINAL= 29, IF_NONE_MATCH_ORDINAL= 30, IF_RANGE_ORDINAL= 31, IF_UNMODIFIED_SINCE_ORDINAL= 32, KEEP_ALIVE_ORDINAL= 33, MAX_FORWARDS_ORDINAL= 34, PROXY_AUTHORIZATION_ORDINAL= 35, RANGE_ORDINAL= 36, REQUEST_RANGE_ORDINAL= 37, REFERER_ORDINAL= 38, TE_ORDINAL= 39, USER_AGENT_ORDINAL= 40, X_FORWARDED_FOR_ORDINAL= 41, ACCEPT_RANGES_ORDINAL= 42, AGE_ORDINAL= 43, ETAG_ORDINAL= 44, LOCATION_ORDINAL= 45, PROXY_AUTHENTICATE_ORDINAL= 46, RETRY_AFTER_ORDINAL= 47, SERVER_ORDINAL= 48, SERVLET_ENGINE_ORDINAL= 49, VARY_ORDINAL= 50, WWW_AUTHENTICATE_ORDINAL= 51, COOKIE_ORDINAL= 52, SET_COOKIE_ORDINAL= 53, SET_COOKIE2_ORDINAL= 54, MIME_VERSION_ORDINAL= 55, IDENTITY_ORDINAL= 56, CACHE_CONTROL_ORDINAL=57, PROXY_CONNECTION_ORDINAL=58, X_FORWARDED_PROTO_ORDINAL=59, X_FORWARDED_SERVER_ORDINAL=60, X_FORWARDED_HOST_ORDINAL=61; public final static HttpHeaders CACHE= new HttpHeaders(); public final static Buffer HOST_BUFFER=CACHE.add(HOST,HOST_ORDINAL), ACCEPT_BUFFER=CACHE.add(ACCEPT,ACCEPT_ORDINAL), ACCEPT_CHARSET_BUFFER=CACHE.add(ACCEPT_CHARSET,ACCEPT_CHARSET_ORDINAL), ACCEPT_ENCODING_BUFFER=CACHE.add(ACCEPT_ENCODING,ACCEPT_ENCODING_ORDINAL), ACCEPT_LANGUAGE_BUFFER=CACHE.add(ACCEPT_LANGUAGE,ACCEPT_LANGUAGE_ORDINAL), CONTENT_LENGTH_BUFFER=CACHE.add(CONTENT_LENGTH,CONTENT_LENGTH_ORDINAL), CONNECTION_BUFFER=CACHE.add(CONNECTION,CONNECTION_ORDINAL), CACHE_CONTROL_BUFFER=CACHE.add(CACHE_CONTROL,CACHE_CONTROL_ORDINAL), DATE_BUFFER=CACHE.add(DATE,DATE_ORDINAL), PRAGMA_BUFFER=CACHE.add(PRAGMA,PRAGMA_ORDINAL), TRAILER_BUFFER=CACHE.add(TRAILER,TRAILER_ORDINAL), TRANSFER_ENCODING_BUFFER=CACHE.add(TRANSFER_ENCODING,TRANSFER_ENCODING_ORDINAL), UPGRADE_BUFFER=CACHE.add(UPGRADE,UPGRADE_ORDINAL), VIA_BUFFER=CACHE.add(VIA,VIA_ORDINAL), WARNING_BUFFER=CACHE.add(WARNING,WARNING_ORDINAL), ALLOW_BUFFER=CACHE.add(ALLOW,ALLOW_ORDINAL), CONTENT_ENCODING_BUFFER=CACHE.add(CONTENT_ENCODING,CONTENT_ENCODING_ORDINAL), CONTENT_LANGUAGE_BUFFER=CACHE.add(CONTENT_LANGUAGE,CONTENT_LANGUAGE_ORDINAL), CONTENT_LOCATION_BUFFER=CACHE.add(CONTENT_LOCATION,CONTENT_LOCATION_ORDINAL), CONTENT_MD5_BUFFER=CACHE.add(CONTENT_MD5,CONTENT_MD5_ORDINAL), CONTENT_RANGE_BUFFER=CACHE.add(CONTENT_RANGE,CONTENT_RANGE_ORDINAL), CONTENT_TYPE_BUFFER=CACHE.add(CONTENT_TYPE,CONTENT_TYPE_ORDINAL), EXPIRES_BUFFER=CACHE.add(EXPIRES,EXPIRES_ORDINAL), LAST_MODIFIED_BUFFER=CACHE.add(LAST_MODIFIED,LAST_MODIFIED_ORDINAL), AUTHORIZATION_BUFFER=CACHE.add(AUTHORIZATION,AUTHORIZATION_ORDINAL), EXPECT_BUFFER=CACHE.add(EXPECT,EXPECT_ORDINAL), FORWARDED_BUFFER=CACHE.add(FORWARDED,FORWARDED_ORDINAL), FROM_BUFFER=CACHE.add(FROM,FROM_ORDINAL), IF_MATCH_BUFFER=CACHE.add(IF_MATCH,IF_MATCH_ORDINAL), IF_MODIFIED_SINCE_BUFFER=CACHE.add(IF_MODIFIED_SINCE,IF_MODIFIED_SINCE_ORDINAL), IF_NONE_MATCH_BUFFER=CACHE.add(IF_NONE_MATCH,IF_NONE_MATCH_ORDINAL), IF_RANGE_BUFFER=CACHE.add(IF_RANGE,IF_RANGE_ORDINAL), IF_UNMODIFIED_SINCE_BUFFER=CACHE.add(IF_UNMODIFIED_SINCE,IF_UNMODIFIED_SINCE_ORDINAL), KEEP_ALIVE_BUFFER=CACHE.add(KEEP_ALIVE,KEEP_ALIVE_ORDINAL), MAX_FORWARDS_BUFFER=CACHE.add(MAX_FORWARDS,MAX_FORWARDS_ORDINAL), PROXY_AUTHORIZATION_BUFFER=CACHE.add(PROXY_AUTHORIZATION,PROXY_AUTHORIZATION_ORDINAL), RANGE_BUFFER=CACHE.add(RANGE,RANGE_ORDINAL), REQUEST_RANGE_BUFFER=CACHE.add(REQUEST_RANGE,REQUEST_RANGE_ORDINAL), REFERER_BUFFER=CACHE.add(REFERER,REFERER_ORDINAL), TE_BUFFER=CACHE.add(TE,TE_ORDINAL), USER_AGENT_BUFFER=CACHE.add(USER_AGENT,USER_AGENT_ORDINAL), X_FORWARDED_FOR_BUFFER=CACHE.add(X_FORWARDED_FOR,X_FORWARDED_FOR_ORDINAL), X_FORWARDED_PROTO_BUFFER=CACHE.add(X_FORWARDED_PROTO,X_FORWARDED_PROTO_ORDINAL), X_FORWARDED_SERVER_BUFFER=CACHE.add(X_FORWARDED_SERVER,X_FORWARDED_SERVER_ORDINAL), X_FORWARDED_HOST_BUFFER=CACHE.add(X_FORWARDED_HOST,X_FORWARDED_HOST_ORDINAL), ACCEPT_RANGES_BUFFER=CACHE.add(ACCEPT_RANGES,ACCEPT_RANGES_ORDINAL), AGE_BUFFER=CACHE.add(AGE,AGE_ORDINAL), ETAG_BUFFER=CACHE.add(ETAG,ETAG_ORDINAL), LOCATION_BUFFER=CACHE.add(LOCATION,LOCATION_ORDINAL), PROXY_AUTHENTICATE_BUFFER=CACHE.add(PROXY_AUTHENTICATE,PROXY_AUTHENTICATE_ORDINAL), RETRY_AFTER_BUFFER=CACHE.add(RETRY_AFTER,RETRY_AFTER_ORDINAL), SERVER_BUFFER=CACHE.add(SERVER,SERVER_ORDINAL), SERVLET_ENGINE_BUFFER=CACHE.add(SERVLET_ENGINE,SERVLET_ENGINE_ORDINAL), VARY_BUFFER=CACHE.add(VARY,VARY_ORDINAL), WWW_AUTHENTICATE_BUFFER=CACHE.add(WWW_AUTHENTICATE,WWW_AUTHENTICATE_ORDINAL), COOKIE_BUFFER=CACHE.add(COOKIE,COOKIE_ORDINAL), SET_COOKIE_BUFFER=CACHE.add(SET_COOKIE,SET_COOKIE_ORDINAL), SET_COOKIE2_BUFFER=CACHE.add(SET_COOKIE2,SET_COOKIE2_ORDINAL), MIME_VERSION_BUFFER=CACHE.add(MIME_VERSION,MIME_VERSION_ORDINAL), IDENTITY_BUFFER=CACHE.add(IDENTITY,IDENTITY_ORDINAL), PROXY_CONNECTION_BUFFER=CACHE.add(PROXY_CONNECTION,PROXY_CONNECTION_ORDINAL); } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpMethods.java000066400000000000000000000040271174773561500272040ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache; /* ------------------------------------------------------------------------------- */ /** * * */ public class HttpMethods { public final static String GET= "GET", POST= "POST", HEAD= "HEAD", PUT= "PUT", OPTIONS= "OPTIONS", DELETE= "DELETE", TRACE= "TRACE", CONNECT= "CONNECT", MOVE= "MOVE"; public final static int GET_ORDINAL= 1, POST_ORDINAL= 2, HEAD_ORDINAL= 3, PUT_ORDINAL= 4, OPTIONS_ORDINAL= 5, DELETE_ORDINAL= 6, TRACE_ORDINAL= 7, CONNECT_ORDINAL= 8, MOVE_ORDINAL= 9; public final static BufferCache CACHE= new BufferCache(); public final static Buffer GET_BUFFER= CACHE.add(GET, GET_ORDINAL), POST_BUFFER= CACHE.add(POST, POST_ORDINAL), HEAD_BUFFER= CACHE.add(HEAD, HEAD_ORDINAL), PUT_BUFFER= CACHE.add(PUT, PUT_ORDINAL), OPTIONS_BUFFER= CACHE.add(OPTIONS, OPTIONS_ORDINAL), DELETE_BUFFER= CACHE.add(DELETE, DELETE_ORDINAL), TRACE_BUFFER= CACHE.add(TRACE, TRACE_ORDINAL), CONNECT_BUFFER= CACHE.add(CONNECT, CONNECT_ORDINAL), MOVE_BUFFER= CACHE.add(MOVE, MOVE_ORDINAL); } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java000066400000000000000000001436311174773561500270420ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.io.IOException; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.io.BufferUtil; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.View; import org.eclipse.jetty.io.bio.StreamEndPoint; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public class HttpParser implements Parser { private static final Logger LOG = Log.getLogger(HttpParser.class); // States public static final int STATE_START=-14; public static final int STATE_FIELD0=-13; public static final int STATE_SPACE1=-12; public static final int STATE_STATUS=-11; public static final int STATE_URI=-10; public static final int STATE_SPACE2=-9; public static final int STATE_END0=-8; public static final int STATE_END1=-7; public static final int STATE_FIELD2=-6; public static final int STATE_HEADER=-5; public static final int STATE_HEADER_NAME=-4; public static final int STATE_HEADER_IN_NAME=-3; public static final int STATE_HEADER_VALUE=-2; public static final int STATE_HEADER_IN_VALUE=-1; public static final int STATE_END=0; public static final int STATE_EOF_CONTENT=1; public static final int STATE_CONTENT=2; public static final int STATE_CHUNKED_CONTENT=3; public static final int STATE_CHUNK_SIZE=4; public static final int STATE_CHUNK_PARAMS=5; public static final int STATE_CHUNK=6; public static final int STATE_SEEKING_EOF=7; private final EventHandler _handler; private final Buffers _buffers; // source of buffers private final EndPoint _endp; private Buffer _header; // Buffer for header data (and small _content) private Buffer _body; // Buffer for large content private Buffer _buffer; // The current buffer in use (either _header or _content) private CachedBuffer _cached; private final View.CaseInsensitive _tok0; // Saved token: header name, request method or response version private final View.CaseInsensitive _tok1; // Saved token: header value, request URI or response code private String _multiLineValue; private int _responseStatus; // If >0 then we are parsing a response private boolean _forceContentBuffer; private boolean _persistent; /* ------------------------------------------------------------------------------- */ protected final View _contentView=new View(); // View of the content in the buffer for {@link Input} protected int _state=STATE_START; protected byte _eol; protected int _length; protected long _contentLength; protected long _contentPosition; protected int _chunkLength; protected int _chunkPosition; private boolean _headResponse; /* ------------------------------------------------------------------------------- */ /** * Constructor. */ public HttpParser(Buffer buffer, EventHandler handler) { _endp=null; _buffers=null; _header=buffer; _buffer=buffer; _handler=handler; _tok0=new View.CaseInsensitive(_header); _tok1=new View.CaseInsensitive(_header); } /* ------------------------------------------------------------------------------- */ /** * Constructor. * @param buffers the buffers to use * @param endp the endpoint * @param handler the even handler */ public HttpParser(Buffers buffers, EndPoint endp, EventHandler handler) { _buffers=buffers; _endp=endp; _handler=handler; _tok0=new View.CaseInsensitive(); _tok1=new View.CaseInsensitive(); } /* ------------------------------------------------------------------------------- */ public long getContentLength() { return _contentLength; } /* ------------------------------------------------------------ */ public long getContentRead() { return _contentPosition; } /* ------------------------------------------------------------ */ /** Set if a HEAD response is expected * @param head */ public void setHeadResponse(boolean head) { _headResponse=head; } /* ------------------------------------------------------------------------------- */ public int getState() { return _state; } /* ------------------------------------------------------------------------------- */ public boolean inContentState() { return _state > 0; } /* ------------------------------------------------------------------------------- */ public boolean inHeaderState() { return _state < 0; } /* ------------------------------------------------------------------------------- */ public boolean isChunking() { return _contentLength==HttpTokens.CHUNKED_CONTENT; } /* ------------------------------------------------------------ */ public boolean isIdle() { return isState(STATE_START); } /* ------------------------------------------------------------ */ public boolean isComplete() { return isState(STATE_END); } /* ------------------------------------------------------------ */ public boolean isMoreInBuffer() throws IOException { return ( _header!=null && _header.hasContent() || _body!=null && _body.hasContent()); } /* ------------------------------------------------------------------------------- */ public boolean isState(int state) { return _state == state; } /* ------------------------------------------------------------------------------- */ public boolean isPersistent() { return _persistent; } /* ------------------------------------------------------------------------------- */ public void setPersistent(boolean persistent) { _persistent = persistent; if (!_persistent &&(_state==STATE_END || _state==STATE_START)) _state=STATE_SEEKING_EOF; } /* ------------------------------------------------------------------------------- */ /** * Parse until {@link #STATE_END END} state. * If the parser is already in the END state, then it is {@link #reset reset} and re-parsed. * @throws IllegalStateException If the buffers have already been partially parsed. */ public void parse() throws IOException { if (_state==STATE_END) reset(); if (_state!=STATE_START) throw new IllegalStateException("!START"); // continue parsing while (_state != STATE_END) if (parseNext()<0) return; } /* ------------------------------------------------------------------------------- */ /** * Parse until END state. * This method will parse any remaining content in the current buffer. It does not care about the * {@link #getState current state} of the parser. * @see #parse * @see #parseNext */ public boolean parseAvailable() throws IOException { boolean progress=parseNext()>0; // continue parsing while (!isComplete() && _buffer!=null && _buffer.length()>0) { progress |= parseNext()>0; } return progress; } /* ------------------------------------------------------------------------------- */ /** * Parse until next Event. * @return an indication of progress <0 EOF, 0 no progress, >0 progress. */ public int parseNext() throws IOException { try { int progress=0; if (_state == STATE_END) return 0; if (_buffer==null) _buffer=getHeaderBuffer(); if (_state == STATE_CONTENT && _contentPosition == _contentLength) { _state=STATE_END; _handler.messageComplete(_contentPosition); return 1; } int length=_buffer.length(); // Fill buffer if we can if (length == 0) { int filled=-1; IOException ex=null; try { filled=fill(); LOG.debug("filled {}/{}",filled,_buffer.length()); } catch(IOException e) { LOG.debug(this.toString(),e); ex=e; } if (filled > 0 ) progress++; else if (filled < 0 ) { _persistent=false; // do we have content to deliver? if (_state>STATE_END) { if (_buffer.length()>0 && !_headResponse) { Buffer chunk=_buffer.get(_buffer.length()); _contentPosition += chunk.length(); _contentView.update(chunk); _handler.content(chunk); // May recurse here } } // was this unexpected? switch(_state) { case STATE_END: case STATE_SEEKING_EOF: _state=STATE_END; break; case STATE_EOF_CONTENT: _state=STATE_END; _handler.messageComplete(_contentPosition); break; default: _state=STATE_END; if (!_headResponse) _handler.earlyEOF(); _handler.messageComplete(_contentPosition); } if (ex!=null) throw ex; if (!isComplete() && !isIdle()) throw new EofException(); return -1; } length=_buffer.length(); } // Handle header states byte ch; byte[] array=_buffer.array(); int last=_state; while (_state0) { if (last!=_state) { progress++; last=_state; } ch=_buffer.get(); if (_eol == HttpTokens.CARRIAGE_RETURN && ch == HttpTokens.LINE_FEED) { _eol=HttpTokens.LINE_FEED; continue; } _eol=0; switch (_state) { case STATE_START: _contentLength=HttpTokens.UNKNOWN_CONTENT; _cached=null; if (ch > HttpTokens.SPACE || ch<0) { _buffer.mark(); _state=STATE_FIELD0; } break; case STATE_FIELD0: if (ch == HttpTokens.SPACE) { _tok0.update(_buffer.markIndex(), _buffer.getIndex() - 1); _responseStatus=HttpVersions.CACHE.get(_tok0)==null?-1:0; _state=STATE_SPACE1; continue; } else if (ch < HttpTokens.SPACE && ch>=0) { throw new HttpException(HttpStatus.BAD_REQUEST_400); } break; case STATE_SPACE1: if (ch > HttpTokens.SPACE || ch<0) { _buffer.mark(); if (_responseStatus>=0) { _state=STATE_STATUS; _responseStatus=ch-'0'; } else _state=STATE_URI; } else if (ch < HttpTokens.SPACE) { throw new HttpException(HttpStatus.BAD_REQUEST_400); } break; case STATE_STATUS: if (ch == HttpTokens.SPACE) { _tok1.update(_buffer.markIndex(), _buffer.getIndex() - 1); _state=STATE_SPACE2; continue; } else if (ch>='0' && ch<='9') { _responseStatus=_responseStatus*10+(ch-'0'); continue; } else if (ch < HttpTokens.SPACE && ch>=0) { _handler.startResponse(HttpMethods.CACHE.lookup(_tok0), _responseStatus, null); _eol=ch; _state=STATE_HEADER; _tok0.setPutIndex(_tok0.getIndex()); _tok1.setPutIndex(_tok1.getIndex()); _multiLineValue=null; continue; } // not a digit, so must be a URI _state=STATE_URI; _responseStatus=-1; break; case STATE_URI: if (ch == HttpTokens.SPACE) { _tok1.update(_buffer.markIndex(), _buffer.getIndex() - 1); _state=STATE_SPACE2; continue; } else if (ch < HttpTokens.SPACE && ch>=0) { // HTTP/0.9 _handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _buffer.sliceFromMark(), null); _persistent=false; _state=STATE_SEEKING_EOF; _handler.headerComplete(); _handler.messageComplete(_contentPosition); return 1; } break; case STATE_SPACE2: if (ch > HttpTokens.SPACE || ch<0) { _buffer.mark(); _state=STATE_FIELD2; } else if (ch < HttpTokens.SPACE) { if (_responseStatus>0) { _handler.startResponse(HttpMethods.CACHE.lookup(_tok0), _responseStatus, null); _eol=ch; _state=STATE_HEADER; _tok0.setPutIndex(_tok0.getIndex()); _tok1.setPutIndex(_tok1.getIndex()); _multiLineValue=null; } else { // HTTP/0.9 _handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _tok1, null); _persistent=false; _state=STATE_SEEKING_EOF; _handler.headerComplete(); _handler.messageComplete(_contentPosition); return 1; } } break; case STATE_FIELD2: if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) { Buffer version; if (_responseStatus>0) _handler.startResponse(version=HttpVersions.CACHE.lookup(_tok0), _responseStatus,_buffer.sliceFromMark()); else _handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _tok1, version=HttpVersions.CACHE.lookup(_buffer.sliceFromMark())); _eol=ch; _persistent=HttpVersions.CACHE.getOrdinal(version)>=HttpVersions.HTTP_1_1_ORDINAL; _state=STATE_HEADER; _tok0.setPutIndex(_tok0.getIndex()); _tok1.setPutIndex(_tok1.getIndex()); _multiLineValue=null; continue; } break; case STATE_HEADER: switch(ch) { case HttpTokens.COLON: case HttpTokens.SPACE: case HttpTokens.TAB: { // header value without name - continuation? _length=-1; _state=STATE_HEADER_VALUE; break; } default: { // handler last header if any if (_cached!=null || _tok0.length() > 0 || _tok1.length() > 0 || _multiLineValue != null) { Buffer header=_cached!=null?_cached:HttpHeaders.CACHE.lookup(_tok0); _cached=null; Buffer value=_multiLineValue == null ? _tok1 : new ByteArrayBuffer(_multiLineValue); int ho=HttpHeaders.CACHE.getOrdinal(header); if (ho >= 0) { int vo; switch (ho) { case HttpHeaders.CONTENT_LENGTH_ORDINAL: if (_contentLength != HttpTokens.CHUNKED_CONTENT && _responseStatus!=304 && _responseStatus!=204 && (_responseStatus<100 || _responseStatus>=200)) { try { _contentLength=BufferUtil.toLong(value); } catch(NumberFormatException e) { LOG.ignore(e); throw new HttpException(HttpStatus.BAD_REQUEST_400); } if (_contentLength <= 0) _contentLength=HttpTokens.NO_CONTENT; } break; case HttpHeaders.TRANSFER_ENCODING_ORDINAL: value=HttpHeaderValues.CACHE.lookup(value); vo=HttpHeaderValues.CACHE.getOrdinal(value); if (HttpHeaderValues.CHUNKED_ORDINAL == vo) _contentLength=HttpTokens.CHUNKED_CONTENT; else { String c=value.toString(StringUtil.__ISO_8859_1); if (c.endsWith(HttpHeaderValues.CHUNKED)) _contentLength=HttpTokens.CHUNKED_CONTENT; else if (c.indexOf(HttpHeaderValues.CHUNKED) >= 0) throw new HttpException(400,null); } break; case HttpHeaders.CONNECTION_ORDINAL: switch(HttpHeaderValues.CACHE.getOrdinal(value)) { case HttpHeaderValues.CLOSE_ORDINAL: _persistent=false; break; case HttpHeaderValues.KEEP_ALIVE_ORDINAL: _persistent=true; break; case -1: // No match, may be multi valued { for (String v : value.toString().split(",")) { switch(HttpHeaderValues.CACHE.getOrdinal(v.trim())) { case HttpHeaderValues.CLOSE_ORDINAL: _persistent=false; break; case HttpHeaderValues.KEEP_ALIVE_ORDINAL: _persistent=true; break; } } break; } } } } _handler.parsedHeader(header, value); _tok0.setPutIndex(_tok0.getIndex()); _tok1.setPutIndex(_tok1.getIndex()); _multiLineValue=null; } _buffer.setMarkIndex(-1); // now handle ch if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) { // work out the _content demarcation if (_contentLength == HttpTokens.UNKNOWN_CONTENT) { if (_responseStatus == 0 // request || _responseStatus == 304 // not-modified response || _responseStatus == 204 // no-content response || _responseStatus < 200) // 1xx response _contentLength=HttpTokens.NO_CONTENT; else _contentLength=HttpTokens.EOF_CONTENT; } _contentPosition=0; _eol=ch; if (_eol==HttpTokens.CARRIAGE_RETURN && _buffer.hasContent() && _buffer.peek()==HttpTokens.LINE_FEED) _eol=_buffer.get(); // We convert _contentLength to an int for this switch statement because // we don't care about the amount of data available just whether there is some. switch (_contentLength > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) _contentLength) { case HttpTokens.EOF_CONTENT: _state=STATE_EOF_CONTENT; _handler.headerComplete(); // May recurse here ! break; case HttpTokens.CHUNKED_CONTENT: _state=STATE_CHUNKED_CONTENT; _handler.headerComplete(); // May recurse here ! break; case HttpTokens.NO_CONTENT: _handler.headerComplete(); _state=_persistent||(_responseStatus>=100&&_responseStatus<200)?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentPosition); return 1; default: _state=STATE_CONTENT; _handler.headerComplete(); // May recurse here ! break; } return 1; } else { // New header _length=1; _buffer.mark(); _state=STATE_HEADER_NAME; // try cached name! if (array!=null) { _cached=HttpHeaders.CACHE.getBest(array, _buffer.markIndex(), length+1); if (_cached!=null) { _length=_cached.length(); _buffer.setGetIndex(_buffer.markIndex()+_length); length=_buffer.length(); } } } } } break; case STATE_HEADER_NAME: switch(ch) { case HttpTokens.CARRIAGE_RETURN: case HttpTokens.LINE_FEED: if (_length > 0) _tok0.update(_buffer.markIndex(), _buffer.markIndex() + _length); _eol=ch; _state=STATE_HEADER; break; case HttpTokens.COLON: if (_length > 0 && _cached==null) _tok0.update(_buffer.markIndex(), _buffer.markIndex() + _length); _length=-1; _state=STATE_HEADER_VALUE; break; case HttpTokens.SPACE: case HttpTokens.TAB: break; default: { _cached=null; if (_length == -1) _buffer.mark(); _length=_buffer.getIndex() - _buffer.markIndex(); _state=STATE_HEADER_IN_NAME; } } break; case STATE_HEADER_IN_NAME: switch(ch) { case HttpTokens.CARRIAGE_RETURN: case HttpTokens.LINE_FEED: if (_length > 0) _tok0.update(_buffer.markIndex(), _buffer.markIndex() + _length); _eol=ch; _state=STATE_HEADER; break; case HttpTokens.COLON: if (_length > 0 && _cached==null) _tok0.update(_buffer.markIndex(), _buffer.markIndex() + _length); _length=-1; _state=STATE_HEADER_VALUE; break; case HttpTokens.SPACE: case HttpTokens.TAB: _state=STATE_HEADER_NAME; break; default: { _cached=null; _length++; } } break; case STATE_HEADER_VALUE: switch(ch) { case HttpTokens.CARRIAGE_RETURN: case HttpTokens.LINE_FEED: if (_length > 0) { if (_tok1.length() == 0) _tok1.update(_buffer.markIndex(), _buffer.markIndex() + _length); else { // Continuation line! if (_multiLineValue == null) _multiLineValue=_tok1.toString(StringUtil.__ISO_8859_1); _tok1.update(_buffer.markIndex(), _buffer.markIndex() + _length); _multiLineValue += " " + _tok1.toString(StringUtil.__ISO_8859_1); } } _eol=ch; _state=STATE_HEADER; break; case HttpTokens.SPACE: case HttpTokens.TAB: break; default: { if (_length == -1) _buffer.mark(); _length=_buffer.getIndex() - _buffer.markIndex(); _state=STATE_HEADER_IN_VALUE; } } break; case STATE_HEADER_IN_VALUE: switch(ch) { case HttpTokens.CARRIAGE_RETURN: case HttpTokens.LINE_FEED: if (_length > 0) { if (_tok1.length() == 0) _tok1.update(_buffer.markIndex(), _buffer.markIndex() + _length); else { // Continuation line! if (_multiLineValue == null) _multiLineValue=_tok1.toString(StringUtil.__ISO_8859_1); _tok1.update(_buffer.markIndex(), _buffer.markIndex() + _length); _multiLineValue += " " + _tok1.toString(StringUtil.__ISO_8859_1); } } _eol=ch; _state=STATE_HEADER; break; case HttpTokens.SPACE: case HttpTokens.TAB: _state=STATE_HEADER_VALUE; break; default: _length++; } break; } } // end of HEADER states loop // ========================== // Handle HEAD response if (_responseStatus>0 && _headResponse) { _state=_persistent||(_responseStatus>=100&&_responseStatus<200)?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentLength); } // ========================== // Handle _content length=_buffer.length(); Buffer chunk; last=_state; while (_state > STATE_END && length > 0) { if (last!=_state) { progress++; last=_state; } if (_eol == HttpTokens.CARRIAGE_RETURN && _buffer.peek() == HttpTokens.LINE_FEED) { _eol=_buffer.get(); length=_buffer.length(); continue; } _eol=0; switch (_state) { case STATE_EOF_CONTENT: chunk=_buffer.get(_buffer.length()); _contentPosition += chunk.length(); _contentView.update(chunk); _handler.content(chunk); // May recurse here // TODO adjust the _buffer to keep unconsumed content return 1; case STATE_CONTENT: { long remaining=_contentLength - _contentPosition; if (remaining == 0) { _state=_persistent?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentPosition); return 1; } if (length > remaining) { // We can cast reamining to an int as we know that it is smaller than // or equal to length which is already an int. length=(int)remaining; } chunk=_buffer.get(length); _contentPosition += chunk.length(); _contentView.update(chunk); _handler.content(chunk); // May recurse here if(_contentPosition == _contentLength) { _state=_persistent?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentPosition); } // TODO adjust the _buffer to keep unconsumed content return 1; } case STATE_CHUNKED_CONTENT: { ch=_buffer.peek(); if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) _eol=_buffer.get(); else if (ch <= HttpTokens.SPACE) _buffer.get(); else { _chunkLength=0; _chunkPosition=0; _state=STATE_CHUNK_SIZE; } break; } case STATE_CHUNK_SIZE: { ch=_buffer.get(); if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) { _eol=ch; if (_chunkLength == 0) { if (_eol==HttpTokens.CARRIAGE_RETURN && _buffer.hasContent() && _buffer.peek()==HttpTokens.LINE_FEED) _eol=_buffer.get(); _state=_persistent?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentPosition); return 1; } else _state=STATE_CHUNK; } else if (ch <= HttpTokens.SPACE || ch == HttpTokens.SEMI_COLON) _state=STATE_CHUNK_PARAMS; else if (ch >= '0' && ch <= '9') _chunkLength=_chunkLength * 16 + (ch - '0'); else if (ch >= 'a' && ch <= 'f') _chunkLength=_chunkLength * 16 + (10 + ch - 'a'); else if (ch >= 'A' && ch <= 'F') _chunkLength=_chunkLength * 16 + (10 + ch - 'A'); else throw new IOException("bad chunk char: " + ch); break; } case STATE_CHUNK_PARAMS: { ch=_buffer.get(); if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) { _eol=ch; if (_chunkLength == 0) { if (_eol==HttpTokens.CARRIAGE_RETURN && _buffer.hasContent() && _buffer.peek()==HttpTokens.LINE_FEED) _eol=_buffer.get(); _state=_persistent?STATE_END:STATE_SEEKING_EOF; _handler.messageComplete(_contentPosition); return 1; } else _state=STATE_CHUNK; } break; } case STATE_CHUNK: { int remaining=_chunkLength - _chunkPosition; if (remaining == 0) { _state=STATE_CHUNKED_CONTENT; break; } else if (length > remaining) length=remaining; chunk=_buffer.get(length); _contentPosition += chunk.length(); _chunkPosition += chunk.length(); _contentView.update(chunk); _handler.content(chunk); // May recurse here // TODO adjust the _buffer to keep unconsumed content return 1; } case STATE_SEEKING_EOF: { // Close if there is more data than CRLF if (_buffer.length()>2) { _state=STATE_END; _endp.close(); } else { // or if the data is not white space while (_buffer.length()>0) if (!Character.isWhitespace(_buffer.get())) { _state=STATE_END; _endp.close(); _buffer.clear(); } } _buffer.clear(); break; } } length=_buffer.length(); } return progress; } catch(HttpException e) { _persistent=false; _state=STATE_SEEKING_EOF; throw e; } } /* ------------------------------------------------------------------------------- */ /** fill the buffers from the endpoint * */ protected int fill() throws IOException { // Do we have a buffer? if (_buffer==null) _buffer=getHeaderBuffer(); // Is there unconsumed content in body buffer if (_state>STATE_END && _buffer==_header && _header!=null && !_header.hasContent() && _body!=null && _body.hasContent()) { _buffer=_body; return _buffer.length(); } // Shall we switch to a body buffer? if (_buffer==_header && _state>STATE_END && _header.length()==0 && (_forceContentBuffer || (_contentLength-_contentPosition)>_header.capacity()) && (_body!=null||_buffers!=null)) { if (_body==null) _body=_buffers.getBuffer(); _buffer=_body; } // Do we have somewhere to fill from? if (_endp != null ) { // Shall we compact the body? if (_buffer==_body || _state>STATE_END) { _buffer.compact(); } // Are we full? if (_buffer.space() == 0) { LOG.warn("Full {}",_buffer.toDetailString()); throw new HttpException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413, "FULL "+(_buffer==_body?"body":"head")); } try { int filled = _endp.fill(_buffer); return filled; } catch(IOException e) { LOG.debug(e); throw (e instanceof EofException) ? e:new EofException(e); } } return -1; } /* ------------------------------------------------------------------------------- */ public void reset() { // reset state _contentView.setGetIndex(_contentView.putIndex()); _state=_persistent?STATE_START:(_endp.isInputShutdown()?STATE_END:STATE_SEEKING_EOF); _contentLength=HttpTokens.UNKNOWN_CONTENT; _contentPosition=0; _length=0; _responseStatus=0; // Consume LF if CRLF if (_eol == HttpTokens.CARRIAGE_RETURN && _buffer!=null && _buffer.hasContent() && _buffer.peek() == HttpTokens.LINE_FEED) _eol=_buffer.get(); if (_body!=null && _body.hasContent()) { // There is content in the body after the end of the request. // This is probably a pipelined header of the next request, so we need to // copy it to the header buffer. if (_header==null) getHeaderBuffer(); else { _header.setMarkIndex(-1); _header.compact(); } int take=_header.space(); if (take>_body.length()) take=_body.length(); _body.peek(_body.getIndex(),take); _body.skip(_header.put(_body.peek(_body.getIndex(),take))); } if (_header!=null) { _header.setMarkIndex(-1); _header.compact(); } if (_body!=null) _body.setMarkIndex(-1); _buffer=_header; returnBuffers(); } /* ------------------------------------------------------------------------------- */ public void returnBuffers() { if (_body!=null && !_body.hasContent() && _body.markIndex()==-1 && _buffers!=null) { if (_buffer==_body) _buffer=_header; if (_buffers!=null) _buffers.returnBuffer(_body); _body=null; } if (_header!=null && !_header.hasContent() && _header.markIndex()==-1 && _buffers!=null) { if (_buffer==_header) _buffer=null; _buffers.returnBuffer(_header); _header=null; } } /* ------------------------------------------------------------------------------- */ public void setState(int state) { this._state=state; _contentLength=HttpTokens.UNKNOWN_CONTENT; } /* ------------------------------------------------------------------------------- */ public String toString(Buffer buf) { return "state=" + _state + " length=" + _length + " buf=" + buf.hashCode(); } /* ------------------------------------------------------------------------------- */ @Override public String toString() { return String.format("%s{s=%d,l=%d,c=%d}", getClass().getSimpleName(), _state, _length, _contentLength); } /* ------------------------------------------------------------ */ public Buffer getHeaderBuffer() { if (_header == null) { _header=_buffers.getHeader(); _tok0.update(_header); _tok1.update(_header); } return _header; } /* ------------------------------------------------------------ */ public Buffer getBodyBuffer() { return _body; } /* ------------------------------------------------------------ */ /** * @param force True if a new buffer will be forced to be used for content and the header buffer will not be used. */ public void setForceContentBuffer(boolean force) { _forceContentBuffer=force; } /* ------------------------------------------------------------ */ public Buffer blockForContent(long maxIdleTime) throws IOException { if (_contentView.length()>0) return _contentView; if (getState() <= STATE_END || isState(STATE_SEEKING_EOF)) return null; try { parseNext(); // parse until some progress is made (or IOException thrown for timeout) while(_contentView.length() == 0 && !(isState(HttpParser.STATE_END)||isState(HttpParser.STATE_SEEKING_EOF)) && _endp!=null && _endp.isOpen()) { if (!_endp.isBlocking()) { if (parseNext()>0) continue; if (!_endp.blockReadable(maxIdleTime)) { _endp.close(); throw new EofException("timeout"); } } parseNext(); } } catch(IOException e) { // TODO is this needed? _endp.close(); throw e; } return _contentView.length()>0?_contentView:null; } /* ------------------------------------------------------------ */ /* (non-Javadoc) * @see java.io.InputStream#available() */ public int available() throws IOException { if (_contentView!=null && _contentView.length()>0) return _contentView.length(); if (_endp.isBlocking()) { if (_state>0 && _endp instanceof StreamEndPoint) return ((StreamEndPoint)_endp).getInputStream().available()>0?1:0; return 0; } parseNext(); return _contentView==null?0:_contentView.length(); } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ public static abstract class EventHandler { public abstract void content(Buffer ref) throws IOException; public void headerComplete() throws IOException { } public void messageComplete(long contentLength) throws IOException { } /** * This is the method called by parser when a HTTP Header name and value is found */ public void parsedHeader(Buffer name, Buffer value) throws IOException { } /** * This is the method called by parser when the HTTP request line is parsed */ public abstract void startRequest(Buffer method, Buffer url, Buffer version) throws IOException; /** * This is the method called by parser when the HTTP request line is parsed */ public abstract void startResponse(Buffer version, int status, Buffer reason) throws IOException; public void earlyEOF() {} } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpSchemes.java000066400000000000000000000022751174773561500271730ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ByteArrayBuffer; /* ------------------------------------------------------------------------------- */ /** * * */ public class HttpSchemes { public final static String HTTP ="http", HTTPS="https"; public final static Buffer HTTP_BUFFER = new ByteArrayBuffer(HTTP), HTTPS_BUFFER = new ByteArrayBuffer(HTTPS); } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpStatus.java000066400000000000000000001002451174773561500270630ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; /** *

* HttpStatusCode enum class, for status codes based on various HTTP RFCs. (see * table below) *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
EnumCodeMessage * RFC 1945 - HTTP/1.0 * RFC 2616 - HTTP/1.1 * RFC 2518 - WEBDAV
Informational - 1xx{@link #isInformational(int)}
{@link #CONTINUE_100}100Continue  * Sec. 10.1.1 
{@link #SWITCHING_PROTOCOLS_101}101Switching Protocols  * Sec. 10.1.2 
{@link #PROCESSING_102}102Processing   * Sec. 10.1
Success - 2xx{@link #isSuccess(int)}
{@link #OK_200}200OK * Sec. 9.2 * Sec. 10.2.1 
{@link #CREATED_201}201Created * Sec. 9.2 * Sec. 10.2.2 
{@link #ACCEPTED_202}202Accepted * Sec. 9.2 * Sec. 10.2.3 
{@link #NON_AUTHORITATIVE_INFORMATION_203}203Non Authoritative Information  * Sec. 10.2.4 
{@link #NO_CONTENT_204}204No Content * Sec. 9.2 * Sec. 10.2.5 
{@link #RESET_CONTENT_205}205Reset Content  * Sec. 10.2.6 
{@link #PARTIAL_CONTENT_206}206Partial Content  * Sec. 10.2.7 
{@link #MULTI_STATUS_207}207Multi-Status   * Sec. 10.2
 207Partial Update OK  * draft/01 
Redirection - 3xx{@link #isRedirection(int)}
{@link #MULTIPLE_CHOICES_300}300Multiple Choices * Sec. 9.3 * Sec. 10.3.1 
{@link #MOVED_PERMANENTLY_301}301Moved Permanently * Sec. 9.3 * Sec. 10.3.2 
{@link #MOVED_TEMPORARILY_302}302Moved Temporarily * Sec. 9.3(now "302 Found") 
{@link #FOUND_302}302Found(was "302 Moved Temporarily") * Sec. 10.3.3 
{@link #SEE_OTHER_303}303See Other  * Sec. 10.3.4 
{@link #NOT_MODIFIED_304}304Not Modified * Sec. 9.3 * Sec. 10.3.5 
{@link #USE_PROXY_305}305Use Proxy  * Sec. 10.3.6 
 306(Unused)  * Sec. 10.3.7 
{@link #TEMPORARY_REDIRECT_307}307Temporary Redirect  * Sec. 10.3.8 
Client Error - 4xx{@link #isClientError(int)}
{@link #BAD_REQUEST_400}400Bad Request * Sec. 9.4 * Sec. 10.4.1 
{@link #UNAUTHORIZED_401}401Unauthorized * Sec. 9.4 * Sec. 10.4.2 
{@link #PAYMENT_REQUIRED_402}402Payment Required * Sec. 9.4 * Sec. 10.4.3 
{@link #FORBIDDEN_403}403Forbidden * Sec. 9.4 * Sec. 10.4.4 
{@link #NOT_FOUND_404}404Not Found * Sec. 9.4 * Sec. 10.4.5 
{@link #METHOD_NOT_ALLOWED_405}405Method Not Allowed  * Sec. 10.4.6 
{@link #NOT_ACCEPTABLE_406}406Not Acceptable  * Sec. 10.4.7 
{@link #PROXY_AUTHENTICATION_REQUIRED_407}407Proxy Authentication Required  * Sec. 10.4.8 
{@link #REQUEST_TIMEOUT_408}408Request Timeout  * Sec. 10.4.9 
{@link #CONFLICT_409}409Conflict  * Sec. 10.4.10 *  
{@link #GONE_410}410Gone  * Sec. 10.4.11 *  
{@link #LENGTH_REQUIRED_411}411Length Required  * Sec. 10.4.12 *  
{@link #PRECONDITION_FAILED_412}412Precondition Failed  * Sec. 10.4.13 *  
{@link #REQUEST_ENTITY_TOO_LARGE_413}413Request Entity Too Large  * Sec. 10.4.14 *  
{@link #REQUEST_URI_TOO_LONG_414}414Request-URI Too Long  * Sec. 10.4.15 *  
{@link #UNSUPPORTED_MEDIA_TYPE_415}415Unsupported Media Type  * Sec. 10.4.16 *  
{@link #REQUESTED_RANGE_NOT_SATISFIABLE_416}416Requested Range Not Satisfiable  * Sec. 10.4.17 *  
{@link #EXPECTATION_FAILED_417}417Expectation Failed  * Sec. 10.4.18 *  
 418Reauthentication Required  * draft/01 
 418Unprocessable Entity   * draft/05
 419Proxy Reauthentication Required  * draft/01 
 419Insufficient Space on Resource   * draft/05
 420Method Failure   * draft/05
 421(Unused)   
{@link #UNPROCESSABLE_ENTITY_422}422Unprocessable Entity   * Sec. 10.3
{@link #LOCKED_423}423Locked   * Sec. 10.4
{@link #FAILED_DEPENDENCY_424}424Failed Dependency   * Sec. 10.5
Server Error - 5xx{@link #isServerError(int)}
{@link #INTERNAL_SERVER_ERROR_500}500Internal Server Error * Sec. 9.5 * Sec. 10.5.1 
{@link #NOT_IMPLEMENTED_501}501Not Implemented * Sec. 9.5 * Sec. 10.5.2 
{@link #BAD_GATEWAY_502}502Bad Gateway * Sec. 9.5 * Sec. 10.5.3 
{@link #SERVICE_UNAVAILABLE_503}503Service Unavailable * Sec. 9.5 * Sec. 10.5.4 
{@link #GATEWAY_TIMEOUT_504}504Gateway Timeout  * Sec. 10.5.5 
{@link #HTTP_VERSION_NOT_SUPPORTED_505}505HTTP Version Not Supported  * Sec. 10.5.6 
 506(Unused)   
{@link #INSUFFICIENT_STORAGE_507}507Insufficient Storage   * Sec. 10.6
* * @version $Id$ */ public class HttpStatus { public final static int CONTINUE_100 = 100; public final static int SWITCHING_PROTOCOLS_101 = 101; public final static int PROCESSING_102 = 102; public final static int OK_200 = 200; public final static int CREATED_201 = 201; public final static int ACCEPTED_202 = 202; public final static int NON_AUTHORITATIVE_INFORMATION_203 = 203; public final static int NO_CONTENT_204 = 204; public final static int RESET_CONTENT_205 = 205; public final static int PARTIAL_CONTENT_206 = 206; public final static int MULTI_STATUS_207 = 207; public final static int MULTIPLE_CHOICES_300 = 300; public final static int MOVED_PERMANENTLY_301 = 301; public final static int MOVED_TEMPORARILY_302 = 302; public final static int FOUND_302 = 302; public final static int SEE_OTHER_303 = 303; public final static int NOT_MODIFIED_304 = 304; public final static int USE_PROXY_305 = 305; public final static int TEMPORARY_REDIRECT_307 = 307; public final static int BAD_REQUEST_400 = 400; public final static int UNAUTHORIZED_401 = 401; public final static int PAYMENT_REQUIRED_402 = 402; public final static int FORBIDDEN_403 = 403; public final static int NOT_FOUND_404 = 404; public final static int METHOD_NOT_ALLOWED_405 = 405; public final static int NOT_ACCEPTABLE_406 = 406; public final static int PROXY_AUTHENTICATION_REQUIRED_407 = 407; public final static int REQUEST_TIMEOUT_408 = 408; public final static int CONFLICT_409 = 409; public final static int GONE_410 = 410; public final static int LENGTH_REQUIRED_411 = 411; public final static int PRECONDITION_FAILED_412 = 412; public final static int REQUEST_ENTITY_TOO_LARGE_413 = 413; public final static int REQUEST_URI_TOO_LONG_414 = 414; public final static int UNSUPPORTED_MEDIA_TYPE_415 = 415; public final static int REQUESTED_RANGE_NOT_SATISFIABLE_416 = 416; public final static int EXPECTATION_FAILED_417 = 417; public final static int UNPROCESSABLE_ENTITY_422 = 422; public final static int LOCKED_423 = 423; public final static int FAILED_DEPENDENCY_424 = 424; public final static int INTERNAL_SERVER_ERROR_500 = 500; public final static int NOT_IMPLEMENTED_501 = 501; public final static int BAD_GATEWAY_502 = 502; public final static int SERVICE_UNAVAILABLE_503 = 503; public final static int GATEWAY_TIMEOUT_504 = 504; public final static int HTTP_VERSION_NOT_SUPPORTED_505 = 505; public final static int INSUFFICIENT_STORAGE_507 = 507; public static final int MAX_CODE = 507; private static final Code[] codeMap = new Code[MAX_CODE+1]; static { for (Code code : Code.values()) { codeMap[code._code] = code; } } public enum Code { /* * -------------------------------------------------------------------- * Informational messages in 1xx series. As defined by ... RFC 1945 - * HTTP/1.0 RFC 2616 - HTTP/1.1 RFC 2518 - WebDAV */ /** 100 Continue */ CONTINUE(CONTINUE_100, "Continue"), /** 101 Switching Protocols */ SWITCHING_PROTOCOLS(SWITCHING_PROTOCOLS_101, "Switching Protocols"), /** 102 Processing */ PROCESSING(PROCESSING_102, "Processing"), /* * -------------------------------------------------------------------- * Success messages in 2xx series. As defined by ... RFC 1945 - HTTP/1.0 * RFC 2616 - HTTP/1.1 RFC 2518 - WebDAV */ /** 200 OK */ OK(OK_200, "OK"), /** 201 Created */ CREATED(CREATED_201, "Created"), /** 202 Accepted */ ACCEPTED(ACCEPTED_202, "Accepted"), /** 203 Non Authoritative Information */ NON_AUTHORITATIVE_INFORMATION(NON_AUTHORITATIVE_INFORMATION_203, "Non Authoritative Information"), /** 204 No Content */ NO_CONTENT(NO_CONTENT_204, "No Content"), /** 205 Reset Content */ RESET_CONTENT(RESET_CONTENT_205, "Reset Content"), /** 206 Partial Content */ PARTIAL_CONTENT(PARTIAL_CONTENT_206, "Partial Content"), /** 207 Multi-Status */ MULTI_STATUS(MULTI_STATUS_207, "Multi-Status"), /* * -------------------------------------------------------------------- * Redirection messages in 3xx series. As defined by ... RFC 1945 - * HTTP/1.0 RFC 2616 - HTTP/1.1 */ /** 300 Mutliple Choices */ MULTIPLE_CHOICES(MULTIPLE_CHOICES_300, "Multiple Choices"), /** 301 Moved Permanently */ MOVED_PERMANENTLY(MOVED_PERMANENTLY_301, "Moved Permanently"), /** 302 Moved Temporarily */ MOVED_TEMPORARILY(MOVED_TEMPORARILY_302, "Moved Temporarily"), /** 302 Found */ FOUND(FOUND_302, "Found"), /** 303 See Other */ SEE_OTHER(SEE_OTHER_303, "See Other"), /** 304 Not Modified */ NOT_MODIFIED(NOT_MODIFIED_304, "Not Modified"), /** 305 Use Proxy */ USE_PROXY(USE_PROXY_305, "Use Proxy"), /** 307 Temporary Redirect */ TEMPORARY_REDIRECT(TEMPORARY_REDIRECT_307, "Temporary Redirect"), /* * -------------------------------------------------------------------- * Client Error messages in 4xx series. As defined by ... RFC 1945 - * HTTP/1.0 RFC 2616 - HTTP/1.1 RFC 2518 - WebDAV */ /** 400 Bad Request */ BAD_REQUEST(BAD_REQUEST_400, "Bad Request"), /** 401 Unauthorized */ UNAUTHORIZED(UNAUTHORIZED_401, "Unauthorized"), /** 402 Payment Required */ PAYMENT_REQUIRED(PAYMENT_REQUIRED_402, "Payment Required"), /** 403 Forbidden */ FORBIDDEN(FORBIDDEN_403, "Forbidden"), /** 404 Not Found */ NOT_FOUND(NOT_FOUND_404, "Not Found"), /** 405 Method Not Allowed */ METHOD_NOT_ALLOWED(METHOD_NOT_ALLOWED_405, "Method Not Allowed"), /** 406 Not Acceptable */ NOT_ACCEPTABLE(NOT_ACCEPTABLE_406, "Not Acceptable"), /** 407 Proxy Authentication Required */ PROXY_AUTHENTICATION_REQUIRED(PROXY_AUTHENTICATION_REQUIRED_407, "Proxy Authentication Required"), /** 408 Request Timeout */ REQUEST_TIMEOUT(REQUEST_TIMEOUT_408, "Request Timeout"), /** 409 Conflict */ CONFLICT(CONFLICT_409, "Conflict"), /** 410 Gone */ GONE(GONE_410, "Gone"), /** 411 Length Required */ LENGTH_REQUIRED(LENGTH_REQUIRED_411, "Length Required"), /** 412 Precondition Failed */ PRECONDITION_FAILED(PRECONDITION_FAILED_412, "Precondition Failed"), /** 413 Request Entity Too Large */ REQUEST_ENTITY_TOO_LARGE(REQUEST_ENTITY_TOO_LARGE_413, "Request Entity Too Large"), /** 414 Request-URI Too Long */ REQUEST_URI_TOO_LONG(REQUEST_URI_TOO_LONG_414, "Request-URI Too Long"), /** 415 Unsupported Media Type */ UNSUPPORTED_MEDIA_TYPE(UNSUPPORTED_MEDIA_TYPE_415, "Unsupported Media Type"), /** 416 Requested Range Not Satisfiable */ REQUESTED_RANGE_NOT_SATISFIABLE(REQUESTED_RANGE_NOT_SATISFIABLE_416, "Requested Range Not Satisfiable"), /** 417 Expectation Failed */ EXPECTATION_FAILED(EXPECTATION_FAILED_417, "Expectation Failed"), /** 422 Unprocessable Entity */ UNPROCESSABLE_ENTITY(UNPROCESSABLE_ENTITY_422, "Unprocessable Entity"), /** 423 Locked */ LOCKED(LOCKED_423, "Locked"), /** 424 Failed Dependency */ FAILED_DEPENDENCY(FAILED_DEPENDENCY_424, "Failed Dependency"), /* * -------------------------------------------------------------------- * Server Error messages in 5xx series. As defined by ... RFC 1945 - * HTTP/1.0 RFC 2616 - HTTP/1.1 RFC 2518 - WebDAV */ /** 500 Server Error */ INTERNAL_SERVER_ERROR(INTERNAL_SERVER_ERROR_500, "Server Error"), /** 501 Not Implemented */ NOT_IMPLEMENTED(NOT_IMPLEMENTED_501, "Not Implemented"), /** 502 Bad Gateway */ BAD_GATEWAY(BAD_GATEWAY_502, "Bad Gateway"), /** 503 Service Unavailable */ SERVICE_UNAVAILABLE(SERVICE_UNAVAILABLE_503, "Service Unavailable"), /** 504 Gateway Timeout */ GATEWAY_TIMEOUT(GATEWAY_TIMEOUT_504, "Gateway Timeout"), /** 505 HTTP Version Not Supported */ HTTP_VERSION_NOT_SUPPORTED(HTTP_VERSION_NOT_SUPPORTED_505, "HTTP Version Not Supported"), /** 507 Insufficient Storage */ INSUFFICIENT_STORAGE(INSUFFICIENT_STORAGE_507, "Insufficient Storage"); private final int _code; private final String _message; private Code(int code, String message) { this._code = code; _message=message; } public int getCode() { return _code; } public String getMessage() { return _message; } public boolean equals(int code) { return (this._code == code); } @Override public String toString() { return String.format("[%03d %s]",this._code,this.getMessage()); } /** * Simple test against an code to determine if it falls into the * Informational message category as defined in the RFC 1945 - HTTP/1.0, * and RFC 2616 - * HTTP/1.1. * * @return true if within range of codes that belongs to * Informational messages. */ public boolean isInformational() { return HttpStatus.isInformational(this._code); } /** * Simple test against an code to determine if it falls into the * Success message category as defined in the RFC 1945 - HTTP/1.0, * and RFC 2616 - * HTTP/1.1. * * @return true if within range of codes that belongs to * Success messages. */ public boolean isSuccess() { return HttpStatus.isSuccess(this._code); } /** * Simple test against an code to determine if it falls into the * Redirection message category as defined in the RFC 1945 - HTTP/1.0, * and RFC 2616 - * HTTP/1.1. * * @return true if within range of codes that belongs to * Redirection messages. */ public boolean isRedirection() { return HttpStatus.isRedirection(this._code); } /** * Simple test against an code to determine if it falls into the * Client Error message category as defined in the RFC 1945 - HTTP/1.0, * and RFC 2616 - * HTTP/1.1. * * @return true if within range of codes that belongs to * Client Error messages. */ public boolean isClientError() { return HttpStatus.isClientError(this._code); } /** * Simple test against an code to determine if it falls into the * Server Error message category as defined in the RFC 1945 - HTTP/1.0, * and RFC 2616 - * HTTP/1.1. * * @return true if within range of codes that belongs to * Server Error messages. */ public boolean isServerError() { return HttpStatus.isServerError(this._code); } } /** * Get the HttpStatusCode for a specific code * * @param code * the code to lookup. * @return the {@link HttpStatus} if found, or null if not found. */ public static Code getCode(int code) { if (code <= MAX_CODE) { return codeMap[code]; } return null; } /** * Get the status message for a specific code. * * @param code * the code to look up * @return the specific message, or the code number itself if code * does not match known list. */ public static String getMessage(int code) { Code codeEnum = getCode(code); if (codeEnum != null) { return codeEnum.getMessage(); } else { return Integer.toString(code); } } /** * Simple test against an code to determine if it falls into the * Informational message category as defined in the RFC 1945 - HTTP/1.0, and RFC 2616 - HTTP/1.1. * * @param code * the code to test. * @return true if within range of codes that belongs to * Informational messages. */ public static boolean isInformational(int code) { return ((100 <= code) && (code <= 199)); } /** * Simple test against an code to determine if it falls into the * Success message category as defined in the RFC 1945 - HTTP/1.0, and RFC 2616 - HTTP/1.1. * * @param code * the code to test. * @return true if within range of codes that belongs to * Success messages. */ public static boolean isSuccess(int code) { return ((200 <= code) && (code <= 299)); } /** * Simple test against an code to determine if it falls into the * Redirection message category as defined in the RFC 1945 - HTTP/1.0, and RFC 2616 - HTTP/1.1. * * @param code * the code to test. * @return true if within range of codes that belongs to * Redirection messages. */ public static boolean isRedirection(int code) { return ((300 <= code) && (code <= 399)); } /** * Simple test against an code to determine if it falls into the * Client Error message category as defined in the RFC 1945 - HTTP/1.0, and RFC 2616 - HTTP/1.1. * * @param code * the code to test. * @return true if within range of codes that belongs to * Client Error messages. */ public static boolean isClientError(int code) { return ((400 <= code) && (code <= 499)); } /** * Simple test against an code to determine if it falls into the * Server Error message category as defined in the RFC 1945 - HTTP/1.0, and RFC 2616 - HTTP/1.1. * * @param code * the code to test. * @return true if within range of codes that belongs to * Server Error messages. */ public static boolean isServerError(int code) { return ((500 <= code) && (code <= 599)); } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpTokens.java000066400000000000000000000026071174773561500270460ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; /** * HTTP constants */ public interface HttpTokens { // Terminal symbols. static final byte COLON= (byte)':'; static final byte SPACE= 0x20; static final byte CARRIAGE_RETURN= 0x0D; static final byte LINE_FEED= 0x0A; static final byte[] CRLF = {CARRIAGE_RETURN,LINE_FEED}; static final byte SEMI_COLON= (byte)';'; static final byte TAB= 0x09; public static final int SELF_DEFINING_CONTENT= -4; public static final int UNKNOWN_CONTENT= -3; public static final int CHUNKED_CONTENT= -2; public static final int EOF_CONTENT= -1; public static final int NO_CONTENT= 0; } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java000066400000000000000000000436711174773561500262500ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.io.UnsupportedEncodingException; import java.net.URI; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.UrlEncoded; import org.eclipse.jetty.util.Utf8StringBuilder; /* ------------------------------------------------------------ */ /** Http URI. * Parse a HTTP URI from a string or byte array. Given a URI * http://user@host:port/path/info;param?query#fragment * this class will split it into the following undecoded optional elements:
    *
  • {@link #getScheme()} - http:
  • *
  • {@link #getAuthority()} - //name@host:port
  • *
  • {@link #getHost()} - host
  • *
  • {@link #getPort()} - port
  • *
  • {@link #getPath()} - /path/info
  • *
  • {@link #getParam()} - param
  • *
  • {@link #getQuery()} - query
  • *
  • {@link #getFragment()} - fragment
  • *
* */ public class HttpURI { private static final byte[] __empty={}; private final static int START=0, AUTH_OR_PATH=1, SCHEME_OR_PATH=2, AUTH=4, IPV6=5, PORT=6, PATH=7, PARAM=8, QUERY=9, ASTERISK=10; boolean _partial=false; byte[] _raw=__empty; String _rawString; int _scheme; int _authority; int _host; int _port; int _portValue; int _path; int _param; int _query; int _fragment; int _end; boolean _encoded=false; final Utf8StringBuilder _utf8b = new Utf8StringBuilder(64); public HttpURI() { } /* ------------------------------------------------------------ */ /** * @param parsePartialAuth If True, parse auth without prior scheme, else treat all URIs starting with / as paths */ public HttpURI(boolean parsePartialAuth) { _partial=parsePartialAuth; } public HttpURI(String raw) { _rawString=raw; byte[] b = raw.getBytes(); parse(b,0,b.length); } public HttpURI(byte[] raw,int offset, int length) { parse2(raw,offset,length); } public HttpURI(URI uri) { parse(uri.toASCIIString()); } public void parse(String raw) { byte[] b = raw.getBytes(); parse2(b,0,b.length); _rawString=raw; } public void parse(byte[] raw,int offset, int length) { _rawString=null; parse2(raw,offset,length); } public void parseConnect(byte[] raw,int offset, int length) { _rawString=null; _encoded=false; _raw=raw; int i=offset; int e=offset+length; int state=AUTH; int m=offset; _end=offset+length; _scheme=offset; _authority=offset; _host=offset; _port=_end; _portValue=-1; _path=_end; _param=_end; _query=_end; _fragment=_end; loop: while (i6 && c=='t') { if (_raw[offset+3]==':') { s=offset+3; i=offset+4; c=':'; } else if (_raw[offset+4]==':') { s=offset+4; i=offset+5; c=':'; } else if (_raw[offset+5]==':') { s=offset+5; i=offset+6; c=':'; } } switch (c) { case ':': { m = i++; _authority = m; _path = m; c = (char)(0xff & _raw[i]); if (c == '/') state = AUTH_OR_PATH; else { _host = m; _port = m; state = PATH; } break; } case '/': { state = PATH; break; } case ';': { _param = s; state = PARAM; break; } case '?': { _param = s; _query = s; state = QUERY; break; } case '#': { _param = s; _query = s; _fragment = s; break; } } continue; } case AUTH: { switch (c) { case '/': { m = s; _path = m; _port = _path; state = PATH; break; } case '@': { _host = i; break; } case ':': { _port = s; state = PORT; break; } case '[': { state = IPV6; break; } } continue; } case IPV6: { switch (c) { case '/': { throw new IllegalArgumentException("No closing ']' for " + StringUtil.toString(_raw,offset,length,URIUtil.__CHARSET)); } case ']': { state = AUTH; break; } } continue; } case PORT: { if (c=='/') { m=s; _path=m; if (_port<=_authority) _port=_path; state=PATH; } continue; } case PATH: { switch (c) { case ';': { _param = s; state = PARAM; break; } case '?': { _param = s; _query = s; state = QUERY; break; } case '#': { _param = s; _query = s; _fragment = s; break state; } case '%': { _encoded=true; } } continue; } case PARAM: { switch (c) { case '?': { _query = s; state = QUERY; break; } case '#': { _query = s; _fragment = s; break state; } } continue; } case QUERY: { if (c=='#') { _fragment=s; break state; } continue; } case ASTERISK: { throw new IllegalArgumentException("only '*'"); } } } if (_port<_path) _portValue=TypeUtil.parseInt(_raw, _port+1, _path-_port-1,10); } private String toUtf8String(int offset,int length) { _utf8b.reset(); _utf8b.append(_raw,offset,length); return _utf8b.toString(); } public String getScheme() { if (_scheme==_authority) return null; int l=_authority-_scheme; if (l==5 && _raw[_scheme]=='h' && _raw[_scheme+1]=='t' && _raw[_scheme+2]=='t' && _raw[_scheme+3]=='p' ) return HttpSchemes.HTTP; if (l==6 && _raw[_scheme]=='h' && _raw[_scheme+1]=='t' && _raw[_scheme+2]=='t' && _raw[_scheme+3]=='p' && _raw[_scheme+4]=='s' ) return HttpSchemes.HTTPS; return toUtf8String(_scheme,_authority-_scheme-1); } public String getAuthority() { if (_authority==_path) return null; return toUtf8String(_authority,_path-_authority); } public String getHost() { if (_host==_port) return null; return toUtf8String(_host,_port-_host); } public int getPort() { return _portValue; } public String getPath() { if (_path==_param) return null; return toUtf8String(_path,_param-_path); } public String getDecodedPath() { if (_path==_param) return null; int length = _param-_path; byte[] bytes=null; int n=0; for (int i=_path;i<_param;i++) { byte b = _raw[i]; if (b=='%') { if ((i+2)>=_param) throw new IllegalArgumentException("Bad % encoding: "+this); b=(byte)(0xff&TypeUtil.parseInt(_raw,i+1,2,16)); i+=2; } else if (bytes==null) { n++; continue; } if (bytes==null) { bytes=new byte[length]; System.arraycopy(_raw,_path,bytes,0,n); } bytes[n++]=b; } if (bytes==null) return toUtf8String(_path,length); _utf8b.reset(); _utf8b.append(bytes,0,n); return _utf8b.toString(); } public String getPathAndParam() { if (_path==_query) return null; return toUtf8String(_path,_query-_path); } public String getCompletePath() { if (_path==_end) return null; return toUtf8String(_path,_end-_path); } public String getParam() { if (_param==_query) return null; return toUtf8String(_param+1,_query-_param-1); } public String getQuery() { if (_query==_fragment) return null; return toUtf8String(_query+1,_fragment-_query-1); } public String getQuery(String encoding) { if (_query==_fragment) return null; return StringUtil.toString(_raw,_query+1,_fragment-_query-1,encoding); } public boolean hasQuery() { return (_fragment>_query); } public String getFragment() { if (_fragment==_end) return null; return toUtf8String(_fragment+1,_end-_fragment-1); } public void decodeQueryTo(MultiMap parameters) { if (_query==_fragment) return; _utf8b.reset(); UrlEncoded.decodeUtf8To(_raw,_query+1,_fragment-_query-1,parameters,_utf8b); } public void decodeQueryTo(MultiMap parameters, String encoding) throws UnsupportedEncodingException { if (_query==_fragment) return; if (encoding==null || StringUtil.isUTF8(encoding)) UrlEncoded.decodeUtf8To(_raw,_query+1,_fragment-_query-1,parameters); else UrlEncoded.decodeTo(toUtf8String(_query+1,_fragment-_query-1),parameters,encoding); } public void clear() { _scheme=_authority=_host=_port=_path=_param=_query=_fragment=_end=0; _raw=__empty; _rawString=""; _encoded=false; } @Override public String toString() { if (_rawString==null) _rawString=toUtf8String(_scheme,_end-_scheme); return _rawString; } public void writeTo(Utf8StringBuilder buf) { buf.append(_raw,_scheme,_end-_scheme); } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/HttpVersions.java000066400000000000000000000026771174773561500274220ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache; /* ------------------------------------------------------------------------------- */ /** * * */ public class HttpVersions { public final static String HTTP_0_9 = "", HTTP_1_0 = "HTTP/1.0", HTTP_1_1 = "HTTP/1.1"; public final static int HTTP_0_9_ORDINAL=9, HTTP_1_0_ORDINAL=10, HTTP_1_1_ORDINAL=11; public final static BufferCache CACHE = new BufferCache(); public final static Buffer HTTP_0_9_BUFFER=CACHE.add(HTTP_0_9,HTTP_0_9_ORDINAL), HTTP_1_0_BUFFER=CACHE.add(HTTP_1_0,HTTP_1_0_ORDINAL), HTTP_1_1_BUFFER=CACHE.add(HTTP_1_1,HTTP_1_1_ORDINAL); } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java000066400000000000000000000323161174773561500266570ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2000-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.BufferCache; import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ /** * */ public class MimeTypes { private static final Logger LOG = Log.getLogger(MimeTypes.class); public final static String FORM_ENCODED="application/x-www-form-urlencoded", MESSAGE_HTTP="message/http", MULTIPART_BYTERANGES="multipart/byteranges", TEXT_HTML="text/html", TEXT_PLAIN="text/plain", TEXT_XML="text/xml", TEXT_JSON="text/json", TEXT_HTML_8859_1="text/html;charset=ISO-8859-1", TEXT_PLAIN_8859_1="text/plain;charset=ISO-8859-1", TEXT_XML_8859_1="text/xml;charset=ISO-8859-1", TEXT_HTML_UTF_8="text/html;charset=UTF-8", TEXT_PLAIN_UTF_8="text/plain;charset=UTF-8", TEXT_XML_UTF_8="text/xml;charset=UTF-8", TEXT_JSON_UTF_8="text/json;charset=UTF-8"; private final static String TEXT_HTML__8859_1="text/html; charset=ISO-8859-1", TEXT_PLAIN__8859_1="text/plain; charset=ISO-8859-1", TEXT_XML__8859_1="text/xml; charset=ISO-8859-1", TEXT_HTML__UTF_8="text/html; charset=UTF-8", TEXT_PLAIN__UTF_8="text/plain; charset=UTF-8", TEXT_XML__UTF_8="text/xml; charset=UTF-8", TEXT_JSON__UTF_8="text/json; charset=UTF-8"; private final static int FORM_ENCODED_ORDINAL=1, MESSAGE_HTTP_ORDINAL=2, MULTIPART_BYTERANGES_ORDINAL=3, TEXT_HTML_ORDINAL=4, TEXT_PLAIN_ORDINAL=5, TEXT_XML_ORDINAL=6, TEXT_JSON_ORDINAL=7, TEXT_HTML_8859_1_ORDINAL=8, TEXT_PLAIN_8859_1_ORDINAL=9, TEXT_XML_8859_1_ORDINAL=10, TEXT_HTML_UTF_8_ORDINAL=11, TEXT_PLAIN_UTF_8_ORDINAL=12, TEXT_XML_UTF_8_ORDINAL=13, TEXT_JSON_UTF_8_ORDINAL=14; private static int __index=15; public final static BufferCache CACHE = new BufferCache(); public final static CachedBuffer FORM_ENCODED_BUFFER=CACHE.add(FORM_ENCODED,FORM_ENCODED_ORDINAL), MESSAGE_HTTP_BUFFER=CACHE.add(MESSAGE_HTTP, MESSAGE_HTTP_ORDINAL), MULTIPART_BYTERANGES_BUFFER=CACHE.add(MULTIPART_BYTERANGES,MULTIPART_BYTERANGES_ORDINAL), TEXT_HTML_BUFFER=CACHE.add(TEXT_HTML,TEXT_HTML_ORDINAL), TEXT_PLAIN_BUFFER=CACHE.add(TEXT_PLAIN,TEXT_PLAIN_ORDINAL), TEXT_XML_BUFFER=CACHE.add(TEXT_XML,TEXT_XML_ORDINAL), TEXT_JSON_BUFFER=CACHE.add(TEXT_JSON,TEXT_JSON_ORDINAL), TEXT_HTML_8859_1_BUFFER=CACHE.add(TEXT_HTML_8859_1,TEXT_HTML_8859_1_ORDINAL), TEXT_PLAIN_8859_1_BUFFER=CACHE.add(TEXT_PLAIN_8859_1,TEXT_PLAIN_8859_1_ORDINAL), TEXT_XML_8859_1_BUFFER=CACHE.add(TEXT_XML_8859_1,TEXT_XML_8859_1_ORDINAL), TEXT_HTML_UTF_8_BUFFER=CACHE.add(TEXT_HTML_UTF_8,TEXT_HTML_UTF_8_ORDINAL), TEXT_PLAIN_UTF_8_BUFFER=CACHE.add(TEXT_PLAIN_UTF_8,TEXT_PLAIN_UTF_8_ORDINAL), TEXT_XML_UTF_8_BUFFER=CACHE.add(TEXT_XML_UTF_8,TEXT_XML_UTF_8_ORDINAL), TEXT_JSON_UTF_8_BUFFER=CACHE.add(TEXT_JSON_UTF_8,TEXT_JSON_UTF_8_ORDINAL), TEXT_HTML__8859_1_BUFFER=CACHE.add(TEXT_HTML__8859_1,TEXT_HTML_8859_1_ORDINAL), TEXT_PLAIN__8859_1_BUFFER=CACHE.add(TEXT_PLAIN__8859_1,TEXT_PLAIN_8859_1_ORDINAL), TEXT_XML__8859_1_BUFFER=CACHE.add(TEXT_XML__8859_1,TEXT_XML_8859_1_ORDINAL), TEXT_HTML__UTF_8_BUFFER=CACHE.add(TEXT_HTML__UTF_8,TEXT_HTML_UTF_8_ORDINAL), TEXT_PLAIN__UTF_8_BUFFER=CACHE.add(TEXT_PLAIN__UTF_8,TEXT_PLAIN_UTF_8_ORDINAL), TEXT_XML__UTF_8_BUFFER=CACHE.add(TEXT_XML__UTF_8,TEXT_XML_UTF_8_ORDINAL), TEXT_JSON__UTF_8_BUFFER=CACHE.add(TEXT_JSON__UTF_8,TEXT_JSON_UTF_8_ORDINAL); /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ private final static Map __dftMimeMap = new HashMap(); private final static Map __encodings = new HashMap(); static { try { ResourceBundle mime = ResourceBundle.getBundle("org/eclipse/jetty/http/mime"); Enumeration i = mime.getKeys(); while(i.hasMoreElements()) { String ext = (String)i.nextElement(); String m = mime.getString(ext); __dftMimeMap.put(StringUtil.asciiToLowerCase(ext),normalizeMimeType(m)); } } catch(MissingResourceException e) { LOG.warn(e.toString()); LOG.debug(e); } try { ResourceBundle encoding = ResourceBundle.getBundle("org/eclipse/jetty/http/encoding"); Enumeration i = encoding.getKeys(); while(i.hasMoreElements()) { Buffer type = normalizeMimeType((String)i.nextElement()); __encodings.put(type,encoding.getString(type.toString())); } } catch(MissingResourceException e) { LOG.warn(e.toString()); LOG.debug(e); } TEXT_HTML_BUFFER.setAssociate("ISO-8859-1",TEXT_HTML_8859_1_BUFFER); TEXT_HTML_BUFFER.setAssociate("ISO_8859_1",TEXT_HTML_8859_1_BUFFER); TEXT_HTML_BUFFER.setAssociate("iso-8859-1",TEXT_HTML_8859_1_BUFFER); TEXT_PLAIN_BUFFER.setAssociate("ISO-8859-1",TEXT_PLAIN_8859_1_BUFFER); TEXT_PLAIN_BUFFER.setAssociate("ISO_8859_1",TEXT_PLAIN_8859_1_BUFFER); TEXT_PLAIN_BUFFER.setAssociate("iso-8859-1",TEXT_PLAIN_8859_1_BUFFER); TEXT_XML_BUFFER.setAssociate("ISO-8859-1",TEXT_XML_8859_1_BUFFER); TEXT_XML_BUFFER.setAssociate("ISO_8859_1",TEXT_XML_8859_1_BUFFER); TEXT_XML_BUFFER.setAssociate("iso-8859-1",TEXT_XML_8859_1_BUFFER); TEXT_HTML_BUFFER.setAssociate("UTF-8",TEXT_HTML_UTF_8_BUFFER); TEXT_HTML_BUFFER.setAssociate("UTF8",TEXT_HTML_UTF_8_BUFFER); TEXT_HTML_BUFFER.setAssociate("utf8",TEXT_HTML_UTF_8_BUFFER); TEXT_HTML_BUFFER.setAssociate("utf-8",TEXT_HTML_UTF_8_BUFFER); TEXT_PLAIN_BUFFER.setAssociate("UTF-8",TEXT_PLAIN_UTF_8_BUFFER); TEXT_PLAIN_BUFFER.setAssociate("UTF8",TEXT_PLAIN_UTF_8_BUFFER); TEXT_PLAIN_BUFFER.setAssociate("utf8",TEXT_PLAIN_UTF_8_BUFFER); TEXT_PLAIN_BUFFER.setAssociate("utf-8",TEXT_PLAIN_UTF_8_BUFFER); TEXT_XML_BUFFER.setAssociate("UTF-8",TEXT_XML_UTF_8_BUFFER); TEXT_XML_BUFFER.setAssociate("UTF8",TEXT_XML_UTF_8_BUFFER); TEXT_XML_BUFFER.setAssociate("utf8",TEXT_XML_UTF_8_BUFFER); TEXT_XML_BUFFER.setAssociate("utf-8",TEXT_XML_UTF_8_BUFFER); TEXT_JSON_BUFFER.setAssociate("UTF-8",TEXT_JSON_UTF_8_BUFFER); TEXT_JSON_BUFFER.setAssociate("UTF8",TEXT_JSON_UTF_8_BUFFER); TEXT_JSON_BUFFER.setAssociate("utf8",TEXT_JSON_UTF_8_BUFFER); TEXT_JSON_BUFFER.setAssociate("utf-8",TEXT_JSON_UTF_8_BUFFER); } /* ------------------------------------------------------------ */ private Map _mimeMap; /* ------------------------------------------------------------ */ /** Constructor. */ public MimeTypes() { } /* ------------------------------------------------------------ */ public synchronized Map getMimeMap() { return _mimeMap; } /* ------------------------------------------------------------ */ /** * @param mimeMap A Map of file extension to mime-type. */ public void setMimeMap(Map mimeMap) { if (mimeMap==null) { _mimeMap=null; return; } Map m=new HashMap(); Iterator i=mimeMap.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry)i.next(); m.put(entry.getKey(),normalizeMimeType(entry.getValue().toString())); } _mimeMap=m; } /* ------------------------------------------------------------ */ /** Get the MIME type by filename extension. * @param filename A file name * @return MIME type matching the longest dot extension of the * file name. */ public Buffer getMimeByExtension(String filename) { Buffer type=null; if (filename!=null) { int i=-1; while(type==null) { i=filename.indexOf(".",i+1); if (i<0 || i>=filename.length()) break; String ext=StringUtil.asciiToLowerCase(filename.substring(i+1)); if (_mimeMap!=null) type = (Buffer)_mimeMap.get(ext); if (type==null) type=(Buffer)__dftMimeMap.get(ext); } } if (type==null) { if (_mimeMap!=null) type=(Buffer)_mimeMap.get("*"); if (type==null) type=(Buffer)__dftMimeMap.get("*"); } return type; } /* ------------------------------------------------------------ */ /** Set a mime mapping * @param extension * @param type */ public void addMimeMapping(String extension,String type) { if (_mimeMap==null) _mimeMap=new HashMap(); _mimeMap.put(StringUtil.asciiToLowerCase(extension),normalizeMimeType(type)); } /* ------------------------------------------------------------ */ private static synchronized Buffer normalizeMimeType(String type) { Buffer b =CACHE.get(type); if (b==null) b=CACHE.add(type,__index++); return b; } /* ------------------------------------------------------------ */ public static String getCharsetFromContentType(Buffer value) { if (value instanceof CachedBuffer) { switch(((CachedBuffer)value).getOrdinal()) { case TEXT_HTML_8859_1_ORDINAL: case TEXT_PLAIN_8859_1_ORDINAL: case TEXT_XML_8859_1_ORDINAL: return StringUtil.__ISO_8859_1; case TEXT_HTML_UTF_8_ORDINAL: case TEXT_PLAIN_UTF_8_ORDINAL: case TEXT_XML_UTF_8_ORDINAL: case TEXT_JSON_UTF_8_ORDINAL: return StringUtil.__UTF8; } } int i=value.getIndex(); int end=value.putIndex(); int state=0; int start=0; boolean quote=false; for (;i * /foo/bar - an exact path specification. * /foo/* - a prefix path specification (must end '/*'). * *.ext - a suffix path specification. * / - the default path specification. * * Matching is performed in the following order *
  • Exact match. *
  • Longest prefix match. *
  • Longest suffix match. *
  • default. * * Multiple path specifications can be mapped by providing a list of * specifications. By default this class uses characters ":," as path * separators, unless configured differently by calling the static * method @see PathMap#setPathSpecSeparators(String) *

    * Special characters within paths such as '?� and ';' are not treated specially * as it is assumed they would have been either encoded in the original URL or * stripped from the path. *

    * This class is not synchronized. If concurrent modifications are * possible then it should be synchronized at a higher level. * * */ public class PathMap extends HashMap implements Externalizable { /* ------------------------------------------------------------ */ private static String __pathSpecSeparators = ":,"; /* ------------------------------------------------------------ */ /** Set the path spec separator. * Multiple path specification may be included in a single string * if they are separated by the characters set in this string. * By default this class uses ":," characters as path separators. * @param s separators */ public static void setPathSpecSeparators(String s) { __pathSpecSeparators=s; } /* --------------------------------------------------------------- */ final StringMap _prefixMap=new StringMap(); final StringMap _suffixMap=new StringMap(); final StringMap _exactMap=new StringMap(); List _defaultSingletonList=null; Entry _prefixDefault=null; Entry _default=null; final Set _entrySet; boolean _nodefault=false; /* --------------------------------------------------------------- */ /** Construct empty PathMap. */ public PathMap() { super(11); _entrySet=entrySet(); } /* --------------------------------------------------------------- */ /** Construct empty PathMap. */ public PathMap(boolean nodefault) { super(11); _entrySet=entrySet(); _nodefault=nodefault; } /* --------------------------------------------------------------- */ /** Construct empty PathMap. */ public PathMap(int capacity) { super (capacity); _entrySet=entrySet(); } /* --------------------------------------------------------------- */ /** Construct from dictionary PathMap. */ public PathMap(Map m) { putAll(m); _entrySet=entrySet(); } /* ------------------------------------------------------------ */ public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException { HashMap map = new HashMap(this); out.writeObject(map); } /* ------------------------------------------------------------ */ public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException { HashMap map = (HashMap)in.readObject(); this.putAll(map); } /* --------------------------------------------------------------- */ /** Add a single path match to the PathMap. * @param pathSpec The path specification, or comma separated list of * path specifications. * @param object The object the path maps to */ @Override public Object put(Object pathSpec, Object object) { String str = pathSpec.toString(); if ("".equals(str.trim())) { Entry entry = new Entry("",object); entry.setMapped(""); _exactMap.put("", entry); return super.put("", object); } StringTokenizer tok = new StringTokenizer(str,__pathSpecSeparators); Object old =null; while (tok.hasMoreTokens()) { String spec=tok.nextToken(); if (!spec.startsWith("/") && !spec.startsWith("*.")) throw new IllegalArgumentException("PathSpec "+spec+". must start with '/' or '*.'"); old = super.put(spec,object); // Make entry that was just created. Entry entry = new Entry(spec,object); if (entry.getKey().equals(spec)) { if (spec.equals("/*")) _prefixDefault=entry; else if (spec.endsWith("/*")) { String mapped=spec.substring(0,spec.length()-2); entry.setMapped(mapped); _prefixMap.put(mapped,entry); _exactMap.put(mapped,entry); _exactMap.put(spec.substring(0,spec.length()-1),entry); } else if (spec.startsWith("*.")) _suffixMap.put(spec.substring(2),entry); else if (spec.equals(URIUtil.SLASH)) { if (_nodefault) _exactMap.put(spec,entry); else { _default=entry; _defaultSingletonList= Collections.singletonList(_default); } } else { entry.setMapped(spec); _exactMap.put(spec,entry); } } } return old; } /* ------------------------------------------------------------ */ /** Get object matched by the path. * @param path the path. * @return Best matched object or null. */ public Object match(String path) { Map.Entry entry = getMatch(path); if (entry!=null) return entry.getValue(); return null; } /* --------------------------------------------------------------- */ /** Get the entry mapped by the best specification. * @param path the path. * @return Map.Entry of the best matched or null. */ public Entry getMatch(String path) { Map.Entry entry=null; if (path==null) return null; int l=path.length(); //special case if (l == 1 && path.charAt(0)=='/') { entry = (Map.Entry)_exactMap.get(""); if (entry != null) return (Entry)entry; } // try exact match entry=_exactMap.getEntry(path,0,l); if (entry!=null) return (Entry) entry.getValue(); // prefix search int i=l; while((i=path.lastIndexOf('/',i-1))>=0) { entry=_prefixMap.getEntry(path,0,i); if (entry!=null) return (Entry) entry.getValue(); } // Prefix Default if (_prefixDefault!=null) return _prefixDefault; // Extension search i=0; while ((i=path.indexOf('.',i+1))>0) { entry=_suffixMap.getEntry(path,i+1,l-i-1); if (entry!=null) return (Entry) entry.getValue(); } // Default return _default; } /* --------------------------------------------------------------- */ /** Get all entries matched by the path. * Best match first. * @param path Path to match * @return LazyList of Map.Entry instances key=pathSpec */ public Object getLazyMatches(String path) { Map.Entry entry; Object entries=null; if (path==null) return LazyList.getList(entries); int l=path.length(); // try exact match entry=_exactMap.getEntry(path,0,l); if (entry!=null) entries=LazyList.add(entries,entry.getValue()); // prefix search int i=l-1; while((i=path.lastIndexOf('/',i-1))>=0) { entry=_prefixMap.getEntry(path,0,i); if (entry!=null) entries=LazyList.add(entries,entry.getValue()); } // Prefix Default if (_prefixDefault!=null) entries=LazyList.add(entries,_prefixDefault); // Extension search i=0; while ((i=path.indexOf('.',i+1))>0) { entry=_suffixMap.getEntry(path,i+1,l-i-1); if (entry!=null) entries=LazyList.add(entries,entry.getValue()); } // Default if (_default!=null) { // Optimization for just the default if (entries==null) return _defaultSingletonList; entries=LazyList.add(entries,_default); } return entries; } /* --------------------------------------------------------------- */ /** Get all entries matched by the path. * Best match first. * @param path Path to match * @return List of Map.Entry instances key=pathSpec */ public List getMatches(String path) { return LazyList.getList(getLazyMatches(path)); } /* --------------------------------------------------------------- */ /** Return whether the path matches any entries in the PathMap, * excluding the default entry * @param path Path to match * @return Whether the PathMap contains any entries that match this */ public boolean containsMatch(String path) { Entry match = getMatch(path); return match!=null && !match.equals(_default); } /* --------------------------------------------------------------- */ @Override public Object remove(Object pathSpec) { if (pathSpec!=null) { String spec=(String) pathSpec; if (spec.equals("/*")) _prefixDefault=null; else if (spec.endsWith("/*")) { _prefixMap.remove(spec.substring(0,spec.length()-2)); _exactMap.remove(spec.substring(0,spec.length()-1)); _exactMap.remove(spec.substring(0,spec.length()-2)); } else if (spec.startsWith("*.")) _suffixMap.remove(spec.substring(2)); else if (spec.equals(URIUtil.SLASH)) { _default=null; _defaultSingletonList=null; } else _exactMap.remove(spec); } return super.remove(pathSpec); } /* --------------------------------------------------------------- */ @Override public void clear() { _exactMap.clear(); _prefixMap.clear(); _suffixMap.clear(); _default=null; _defaultSingletonList=null; super.clear(); } /* --------------------------------------------------------------- */ /** * @return true if match. */ public static boolean match(String pathSpec, String path) throws IllegalArgumentException { return match(pathSpec, path, false); } /* --------------------------------------------------------------- */ /** * @return true if match. */ public static boolean match(String pathSpec, String path, boolean noDefault) throws IllegalArgumentException { char c = pathSpec.charAt(0); if (c=='/') { if (!noDefault && pathSpec.length()==1 || pathSpec.equals(path)) return true; if(isPathWildcardMatch(pathSpec, path)) return true; } else if (c=='*') return path.regionMatches(path.length()-pathSpec.length()+1, pathSpec,1,pathSpec.length()-1); return false; } /* --------------------------------------------------------------- */ private static boolean isPathWildcardMatch(String pathSpec, String path) { // For a spec of "/foo/*" match "/foo" , "/foo/..." but not "/foobar" int cpl=pathSpec.length()-2; if (pathSpec.endsWith("/*") && path.regionMatches(0,pathSpec,0,cpl)) { if (path.length()==cpl || '/'==path.charAt(cpl)) return true; } return false; } /* --------------------------------------------------------------- */ /** Return the portion of a path that matches a path spec. * @return null if no match at all. */ public static String pathMatch(String pathSpec, String path) { char c = pathSpec.charAt(0); if (c=='/') { if (pathSpec.length()==1) return path; if (pathSpec.equals(path)) return path; if (isPathWildcardMatch(pathSpec, path)) return path.substring(0,pathSpec.length()-2); } else if (c=='*') { if (path.regionMatches(path.length()-(pathSpec.length()-1), pathSpec,1,pathSpec.length()-1)) return path; } return null; } /* --------------------------------------------------------------- */ /** Return the portion of a path that is after a path spec. * @return The path info string */ public static String pathInfo(String pathSpec, String path) { if ("".equals(pathSpec)) return path; //servlet 3 spec sec 12.2 will be '/' char c = pathSpec.charAt(0); if (c=='/') { if (pathSpec.length()==1) return null; boolean wildcard = isPathWildcardMatch(pathSpec, path); // handle the case where pathSpec uses a wildcard and path info is "/*" if (pathSpec.equals(path) && !wildcard) return null; if (wildcard) { if (path.length()==pathSpec.length()-2) return null; return path.substring(pathSpec.length()-2); } } return null; } /* ------------------------------------------------------------ */ /** Relative path. * @param base The base the path is relative to. * @param pathSpec The spec of the path segment to ignore. * @param path the additional path * @return base plus path with pathspec removed */ public static String relativePath(String base, String pathSpec, String path ) { String info=pathInfo(pathSpec,path); if (info==null) info=path; if( info.startsWith( "./")) info = info.substring( 2); if( base.endsWith( URIUtil.SLASH)) if( info.startsWith( URIUtil.SLASH)) path = base + info.substring(1); else path = base + info; else if( info.startsWith( URIUtil.SLASH)) path = base + info; else path = base + URIUtil.SLASH + info; return path; } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ public static class Entry implements Map.Entry { private final Object key; private final Object value; private String mapped; private transient String string; Entry(Object key, Object value) { this.key=key; this.value=value; } public Object getKey() { return key; } public Object getValue() { return value; } public Object setValue(Object o) { throw new UnsupportedOperationException(); } @Override public String toString() { if (string==null) string=key+"="+value; return string; } public String getMapped() { return mapped; } void setMapped(String mapped) { this.mapped = mapped; } } } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/000077500000000000000000000000001174773561500250445ustar00rootroot00000000000000jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java000066400000000000000000000240251174773561500326560ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http.gzip; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.zip.DeflaterOutputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.util.ByteArrayOutputStream2; /* ------------------------------------------------------------ */ /** * Skeletal implementation of a CompressedStream. This class adds compression features to a ServletOutputStream and takes care of setting response headers, etc. * Major work and configuration is done here. Subclasses using different kinds of compression only have to implement the abstract methods doCompress() and * setContentEncoding() using the desired compression and setting the appropriate Content-Encoding header string. */ public abstract class AbstractCompressedStream extends ServletOutputStream { private final String _encoding; protected HttpServletRequest _request; protected HttpServletResponse _response; protected OutputStream _out; protected ByteArrayOutputStream2 _bOut; protected DeflaterOutputStream _compressedOutputStream; protected boolean _closed; protected int _bufferSize; protected int _minCompressSize; protected long _contentLength; protected boolean _doNotCompress; /** * Instantiates a new compressed stream. * * @param request * the request * @param response * the response * @param contentLength * the content length * @param bufferSize * the buffer size * @param minCompressSize * the min compress size * @throws IOException * Signals that an I/O exception has occurred. */ public AbstractCompressedStream(String encoding,HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minCompressSize) throws IOException { _encoding=encoding; _request = request; _response = response; _contentLength = contentLength; _bufferSize = bufferSize; _minCompressSize = minCompressSize; if (minCompressSize == 0) doCompress(); } /** * Reset buffer. */ public void resetBuffer() { if (_response.isCommitted()) throw new IllegalStateException("Committed"); _closed = false; _out = null; _bOut = null; if (_compressedOutputStream != null) _response.setHeader("Content-Encoding",null); _compressedOutputStream = null; _doNotCompress = false; } /** * Sets the content length. * * @param length * the new content length */ public void setContentLength(long length) { _contentLength = length; if (_doNotCompress && length >= 0) { if (_contentLength < Integer.MAX_VALUE) _response.setContentLength((int)_contentLength); else _response.setHeader("Content-Length",Long.toString(_contentLength)); } } /* ------------------------------------------------------------ */ /** * @see java.io.OutputStream#flush() */ @Override public void flush() throws IOException { if (_out == null || _bOut != null) { if (_contentLength > 0 && _contentLength < _minCompressSize) doNotCompress(); else doCompress(); } _out.flush(); } /* ------------------------------------------------------------ */ /** * @see java.io.OutputStream#close() */ @Override public void close() throws IOException { if (_closed) return; if (_request.getAttribute("javax.servlet.include.request_uri") != null) flush(); else { if (_bOut != null) { if (_contentLength < 0) _contentLength = _bOut.getCount(); if (_contentLength < _minCompressSize) doNotCompress(); else doCompress(); } else if (_out == null) { doNotCompress(); } if (_compressedOutputStream != null) _compressedOutputStream.close(); else _out.close(); _closed = true; } } /** * Finish. * * @throws IOException * Signals that an I/O exception has occurred. */ public void finish() throws IOException { if (!_closed) { if (_out == null || _bOut != null) { if (_contentLength > 0 && _contentLength < _minCompressSize) doNotCompress(); else doCompress(); } if (_compressedOutputStream != null && !_closed) { _closed = true; _compressedOutputStream.close(); } } } /* ------------------------------------------------------------ */ /** * @see java.io.OutputStream#write(int) */ @Override public void write(int b) throws IOException { checkOut(1); _out.write(b); } /* ------------------------------------------------------------ */ /** * @see java.io.OutputStream#write(byte[]) */ @Override public void write(byte b[]) throws IOException { checkOut(b.length); _out.write(b); } /* ------------------------------------------------------------ */ /** * @see java.io.OutputStream#write(byte[], int, int) */ @Override public void write(byte b[], int off, int len) throws IOException { checkOut(len); _out.write(b,off,len); } /** * Do compress. * * @throws IOException Signals that an I/O exception has occurred. */ public void doCompress() throws IOException { if (_compressedOutputStream==null) { if (_response.isCommitted()) throw new IllegalStateException(); setHeader("Content-Encoding", _encoding); if (_response.containsHeader("Content-Encoding")) { _out=_compressedOutputStream=createStream(); if (_bOut!=null) { _out.write(_bOut.getBuf(),0,_bOut.getCount()); _bOut=null; } } else doNotCompress(); } } /** * Do not compress. * * @throws IOException * Signals that an I/O exception has occurred. */ public void doNotCompress() throws IOException { if (_compressedOutputStream != null) throw new IllegalStateException(); if (_out == null || _bOut != null) { _doNotCompress = true; _out = _response.getOutputStream(); setContentLength(_contentLength); if (_bOut != null) _out.write(_bOut.getBuf(),0,_bOut.getCount()); _bOut = null; } } /** * Check out. * * @param length * the length * @throws IOException * Signals that an I/O exception has occurred. */ private void checkOut(int length) throws IOException { if (_closed) throw new IOException("CLOSED"); if (_out == null) { if (_response.isCommitted() || (_contentLength >= 0 && _contentLength < _minCompressSize)) doNotCompress(); else if (length > _minCompressSize) doCompress(); else _out = _bOut = new ByteArrayOutputStream2(_bufferSize); } else if (_bOut != null) { if (_response.isCommitted() || (_contentLength >= 0 && _contentLength < _minCompressSize)) doNotCompress(); else if (length >= (_bOut.getBuf().length - _bOut.getCount())) doCompress(); } } /** * @see org.eclipse.jetty.http.gzip.CompressedStream#getOutputStream() */ public OutputStream getOutputStream() { return _out; } /** * @see org.eclipse.jetty.http.gzip.CompressedStream#isClosed() */ public boolean isClosed() { return _closed; } /** * Allows derived implementations to replace PrintWriter implementation. */ protected PrintWriter newWriter(OutputStream out, String encoding) throws UnsupportedEncodingException { return encoding == null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding)); } protected void setHeader(String name,String value) { _response.setHeader(name, value); } /** * Create the stream fitting to the underlying compression type. * * @throws IOException * Signals that an I/O exception has occurred. */ protected abstract DeflaterOutputStream createStream() throws IOException; } jetty8-8.1.3/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/CompressedResponseWrapper.java000066400000000000000000000320101174773561500330670ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http.gzip; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.Set; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import org.eclipse.jetty.util.StringUtil; /*------------------------------------------------------------ */ /** */ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapper { public static final int DEFAULT_BUFFER_SIZE = 8192; public static final int DEFAULT_MIN_COMPRESS_SIZE = 256; private Set _mimeTypes; private int _bufferSize=DEFAULT_BUFFER_SIZE; private int _minCompressSize=DEFAULT_MIN_COMPRESS_SIZE; protected HttpServletRequest _request; private PrintWriter _writer; private AbstractCompressedStream _compressedStream; private long _contentLength=-1; private boolean _noCompression; public CompressedResponseWrapper(HttpServletRequest request, HttpServletResponse response) { super(response); _request = request; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMimeTypes(java.util.Set) */ public void setMimeTypes(Set mimeTypes) { _mimeTypes = mimeTypes; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setBufferSize(int) */ @Override public void setBufferSize(int bufferSize) { _bufferSize = bufferSize; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMinCompressSize(int) */ public void setMinCompressSize(int minCompressSize) { _minCompressSize = minCompressSize; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentType(java.lang.String) */ @Override public void setContentType(String ct) { super.setContentType(ct); if (ct!=null) { int colon=ct.indexOf(";"); if (colon>0) ct=ct.substring(0,colon); } if ((_compressedStream==null || _compressedStream.getOutputStream()==null) && (_mimeTypes==null && ct!=null && ct.contains("gzip") || _mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct))))) { noCompression(); } } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int, java.lang.String) */ @Override public void setStatus(int sc, String sm) { super.setStatus(sc,sm); if (sc<200 || sc==204 || sc==205 || sc>=300) noCompression(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int) */ @Override public void setStatus(int sc) { super.setStatus(sc); if (sc<200 || sc==204 || sc==205 ||sc>=300) noCompression(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentLength(int) */ @Override public void setContentLength(int length) { setContentLength((long)length); } /* ------------------------------------------------------------ */ protected void setContentLength(long length) { _contentLength=length; if (_compressedStream!=null) _compressedStream.setContentLength(length); else if (_noCompression && _contentLength>=0) { HttpServletResponse response = (HttpServletResponse)getResponse(); if(_contentLength e = header.getFieldNames(); while (e.hasMoreElements()) { String o=e.nextElement(); if ("name0".equals(o)) matches++; if ("name1".equals(o)) matches++; if ("name2".equals(o)) matches++; } assertEquals(3, matches); e = header.getValues("name1"); assertEquals(true, e.hasMoreElements()); assertEquals(e.nextElement(), "value1"); assertEquals(false, e.hasMoreElements()); } @Test public void testRemovePut() throws Exception { HttpFields header = new HttpFields(); header.put("name0", "value0"); header.put("name1", "value1"); header.put("name2", "value2"); assertEquals("value0",header.getStringField("name0")); assertEquals("value1",header.getStringField("name1")); assertEquals("value2",header.getStringField("name2")); header.remove("name1"); assertEquals("value0",header.getStringField("name0")); assertNull(header.getStringField("name1")); assertEquals("value2",header.getStringField("name2")); assertNull(header.getStringField("name3")); int matches=0; Enumeration e = header.getFieldNames(); while (e.hasMoreElements()) { Object o=e.nextElement(); if ("name0".equals(o)) matches++; if ("name1".equals(o)) matches++; if ("name2".equals(o)) matches++; } assertEquals(2, matches); e = header.getValues("name1"); assertEquals(false, e.hasMoreElements()); } @Test public void testAdd() throws Exception { HttpFields fields = new HttpFields(); fields.add("name0", "value0"); fields.add("name1", "valueA"); fields.add("name2", "value2"); assertEquals("value0",fields.getStringField("name0")); assertEquals("valueA",fields.getStringField("name1")); assertEquals("value2",fields.getStringField("name2")); fields.add("name1", "valueB"); assertEquals("value0",fields.getStringField("name0")); assertEquals("valueA",fields.getStringField("name1")); assertEquals("value2",fields.getStringField("name2")); assertNull(fields.getStringField("name3")); int matches=0; Enumeration e = fields.getFieldNames(); while (e.hasMoreElements()) { Object o=e.nextElement(); if ("name0".equals(o)) matches++; if ("name1".equals(o)) matches++; if ("name2".equals(o)) matches++; } assertEquals(3, matches); e = fields.getValues("name1"); assertEquals(true, e.hasMoreElements()); assertEquals(e.nextElement(), "valueA"); assertEquals(true, e.hasMoreElements()); assertEquals(e.nextElement(), "valueB"); assertEquals(false, e.hasMoreElements()); } @Test public void testReuse() throws Exception { HttpFields header = new HttpFields(); Buffer n1=new ByteArrayBuffer("name1"); Buffer va=new ByteArrayBuffer("value1"); Buffer vb=new ByteArrayBuffer(10); vb.put((byte)'v'); vb.put((byte)'a'); vb.put((byte)'l'); vb.put((byte)'u'); vb.put((byte)'e'); vb.put((byte)'1'); header.put("name0", "value0"); header.put(n1,va); header.put("name2", "value2"); assertEquals("value0",header.getStringField("name0")); assertEquals("value1",header.getStringField("name1")); assertEquals("value2",header.getStringField("name2")); assertNull(header.getStringField("name3")); header.remove(n1); assertNull(header.getStringField("name1")); header.put(n1,vb); assertEquals("value1",header.getStringField("name1")); int matches=0; Enumeration e = header.getFieldNames(); while (e.hasMoreElements()) { Object o=e.nextElement(); if ("name0".equals(o)) matches++; if ("name1".equals(o)) matches++; if ("name2".equals(o)) matches++; } assertEquals(3, matches); e = header.getValues("name1"); assertEquals(true, e.hasMoreElements()); assertEquals(e.nextElement(), "value1"); assertEquals(false, e.hasMoreElements()); } @Test public void testCase() throws Exception { HttpFields fields= new HttpFields(); Set s; // 0123456789012345678901234567890 byte[] b ="Message-IDmessage-idvalueVALUE".getBytes(); ByteArrayBuffer buf= new ByteArrayBuffer(512); buf.put(b); View headUC= new View.CaseInsensitive(buf); View headLC= new View.CaseInsensitive(buf); View valUC = new View(buf); View valLC = new View(buf); headUC.update(0,10); headLC.update(10,20); valUC.update(20,25); valLC.update(25,30); fields.add("header","value"); fields.add(headUC,valLC); fields.add("other","data"); s=enum2set(fields.getFieldNames()); assertEquals(3,s.size()); assertTrue(s.contains("message-id")); assertEquals("value",fields.getStringField("message-id").toLowerCase()); assertEquals("value",fields.getStringField("Message-ID").toLowerCase()); fields.clear(); fields.add("header","value"); fields.add(headLC,valLC); fields.add("other","data"); s=enum2set(fields.getFieldNames()); assertEquals(3,s.size()); assertTrue(s.contains("message-id")); assertEquals("value",fields.getStringField("Message-ID").toLowerCase()); assertEquals("value",fields.getStringField("message-id").toLowerCase()); fields.clear(); fields.add("header","value"); fields.add(headUC,valUC); fields.add("other","data"); s=enum2set(fields.getFieldNames()); assertEquals(3,s.size()); assertTrue(s.contains("message-id")); assertEquals("value",fields.getStringField("message-id").toLowerCase()); assertEquals("value",fields.getStringField("Message-ID").toLowerCase()); fields.clear(); fields.add("header","value"); fields.add(headLC,valUC); fields.add("other","data"); s=enum2set(fields.getFieldNames()); assertEquals(3,s.size()); assertTrue(s.contains("message-id")); assertEquals("value",fields.getStringField("Message-ID").toLowerCase()); assertEquals("value",fields.getStringField("message-id").toLowerCase()); } @Test public void testHttpHeaderValues() throws Exception { assertTrue(((CachedBuffer)HttpHeaderValues.CACHE.lookup("unknown value")).getOrdinal()<0); assertTrue(((CachedBuffer)HttpHeaderValues.CACHE.lookup("close")).getOrdinal()>=0); } @Test public void testSetCookie() throws Exception { HttpFields fields = new HttpFields(); fields.addSetCookie("minimal","value",null,null,-1,null,false,false,-1); assertEquals("minimal=value",fields.getStringField("Set-Cookie")); fields.clear(); fields.addSetCookie("everything","wrong","wrong","wrong",0,"to be replaced",true,true,0); fields.addSetCookie("everything","value","domain","path",0,"comment",true,true,0); assertEquals("everything=value;Comment=comment;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",fields.getStringField("Set-Cookie")); Enumeration e =fields.getValues("Set-Cookie"); assertTrue(e.hasMoreElements()); assertEquals("everything=value;Comment=comment;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement()); assertFalse(e.hasMoreElements()); assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Expires")); fields.clear(); fields.addSetCookie("ev erything","va lue","do main","pa th",1,"co mment",true,true,2); String setCookie=fields.getStringField("Set-Cookie"); assertTrue(setCookie.startsWith("\"ev erything\"=\"va lue\";Comment=\"co mment\";Path=\"pa th\";Domain=\"do main\";Expires=")); assertTrue(setCookie.endsWith("GMT;Max-Age=1;Secure;HttpOnly")); fields.clear(); fields.addSetCookie("json","{\"services\":[\"cwa\", \"aa\"]}",null,null,-1,null,false,false,-1); assertEquals("json=\"{\\\"services\\\":[\\\"cwa\\\", \\\"aa\\\"]}\"",fields.getStringField("Set-Cookie")); fields.clear(); fields.addSetCookie("name","value","domain",null,-1,null,false,false,-1); fields.addSetCookie("name","other","domain",null,-1,null,false,false,-1); assertEquals("name=other;Domain=domain",fields.getStringField("Set-Cookie")); fields.addSetCookie("name","more","domain",null,-1,null,false,false,-1); assertEquals("name=more;Domain=domain",fields.getStringField("Set-Cookie")); fields.addSetCookie("foo","bar","domain",null,-1,null,false,false,-1); fields.addSetCookie("foo","bob","domain",null,-1,null,false,false,-1); assertEquals("name=more;Domain=domain",fields.getStringField("Set-Cookie")); e=fields.getValues("Set-Cookie"); assertEquals("name=more;Domain=domain",e.nextElement()); assertEquals("foo=bob;Domain=domain",e.nextElement()); } private Set enum2set(Enumeration e) { Set s=new HashSet(); while(e.hasMoreElements()) s.add(e.nextElement().toLowerCase()); return s; } @Test public void testDateFields() throws Exception { HttpFields fields = new HttpFields(); fields.put("D0", "Wed, 31 Dec 1969 23:59:59 GMT"); fields.put("D1", "Fri, 31 Dec 1999 23:59:59 GMT"); fields.put("D2", "Friday, 31-Dec-99 23:59:59 GMT"); fields.put("D3", "Fri Dec 31 23:59:59 1999"); fields.put("D4", "Mon Jan 1 2000 00:00:01"); fields.put("D5", "Tue Feb 29 2000 12:00:00"); long d1 = fields.getDateField("D1"); long d0 = fields.getDateField("D0"); long d2 = fields.getDateField("D2"); long d3 = fields.getDateField("D3"); long d4 = fields.getDateField("D4"); long d5 = fields.getDateField("D5"); assertTrue(d0!=-1); assertTrue(d1>0); assertTrue(d2>0); assertEquals(d1,d2); assertEquals(d2,d3); assertEquals(d3+2000,d4); assertEquals(951825600000L,d5); d1 = fields.getDateField("D1"); d2 = fields.getDateField("D2"); d3 = fields.getDateField("D3"); d4 = fields.getDateField("D4"); d5 = fields.getDateField("D5"); assertTrue(d1>0); assertTrue(d2>0); assertEquals(d1,d2); assertEquals(d2,d3); assertEquals(d3+2000,d4); assertEquals(951825600000L,d5); fields.putDateField("D2",d1); assertEquals("Fri, 31 Dec 1999 23:59:59 GMT",fields.getStringField("D2")); } @Test public void testNegDateFields() throws Exception { HttpFields fields = new HttpFields(); fields.putDateField("Dzero",0); assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Dzero")); fields.putDateField("Dminus",-1); assertEquals("Wed, 31 Dec 1969 23:59:59 GMT",fields.getStringField("Dminus")); fields.putDateField("Dminus",-1000); assertEquals("Wed, 31 Dec 1969 23:59:59 GMT",fields.getStringField("Dminus")); fields.putDateField("Dancient",Long.MIN_VALUE); assertEquals("Sun, 02 Dec 55 16:47:04 GMT",fields.getStringField("Dancient")); } @Test public void testLongFields() throws Exception { HttpFields header = new HttpFields(); header.put("I1", "42"); header.put("I2", " 43 99"); header.put("I3", "-44;"); header.put("I4", " - 45abc"); header.put("N1", " - "); header.put("N2", "xx"); long i1=header.getLongField("I1"); long i2=header.getLongField("I2"); long i3=header.getLongField("I3"); long i4=header.getLongField("I4"); try{ header.getLongField("N1"); assertTrue(false); } catch(NumberFormatException e) { assertTrue(true); } try{ header.getLongField("N2"); assertTrue(false); } catch(NumberFormatException e) { assertTrue(true); } assertEquals(42,i1); assertEquals(43,i2); assertEquals(-44,i3); assertEquals(-45,i4); header.putLongField("I5", 46); header.putLongField("I6",-47); assertEquals("46",header.getStringField("I5")); assertEquals("-47",header.getStringField("I6")); } @Test public void testToString() throws Exception { HttpFields header = new HttpFields(); header.put(new ByteArrayBuffer("name0"), new View(new ByteArrayBuffer("value0"))); header.put(new ByteArrayBuffer("name1"), new View(new ByteArrayBuffer("value1".getBytes()))); String s1=header.toString(); String s2=header.toString(); //System.err.println(s1); //System.err.println(s2); assertEquals(s1,s2); } } jetty8-8.1.3/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java000066400000000000000000000352551174773561500315700ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers.Type; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.io.PooledBuffers; import org.eclipse.jetty.io.SimpleBuffers; import org.eclipse.jetty.io.View; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class HttpGeneratorClientTest { public final static String CONTENT="The quick brown fox jumped over the lazy dog.\nNow is the time for all good men to come to the aid of the party\nThe moon is blue to a fish in love.\n"; public final static String[] connect={null,"keep-alive","close"}; @Test public void testContentLength() throws Exception { Buffer bb=new ByteArrayBuffer(8096); Buffer sb=new ByteArrayBuffer(1500); ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096); HttpGenerator generator = new HttpGenerator(new SimpleBuffers(sb,bb),endp); generator.setRequest("GET","/usr"); HttpFields fields = new HttpFields(); fields.add("Header","Value"); fields.add("Content-Type","text/plain"); String content = "The quick brown fox jumped over the lazy dog"; fields.addLongField("Content-Length",content.length()); generator.completeHeader(fields,false); generator.addContent(new ByteArrayBuffer(content).asMutableBuffer(),true); generator.flushBuffer(); generator.complete(); generator.flushBuffer(); String result=endp.getOut().toString().replace("\r\n","|").replace('\r','|').replace('\n','|'); assertEquals("GET /usr HTTP/1.1|Header: Value|Content-Type: text/plain|Content-Length: 44||"+content,result); } @Test public void testAutoContentLength() throws Exception { Buffer bb=new ByteArrayBuffer(8096); Buffer sb=new ByteArrayBuffer(1500); ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096); HttpGenerator generator = new HttpGenerator(new SimpleBuffers(sb,bb),endp); generator.setRequest("GET","/usr"); HttpFields fields = new HttpFields(); fields.add("Header","Value"); fields.add("Content-Type","text/plain"); String content = "The quick brown fox jumped over the lazy dog"; generator.addContent(new ByteArrayBuffer(content).asMutableBuffer(),true); generator.completeHeader(fields,true); generator.flushBuffer(); generator.complete(); generator.flushBuffer(); String result=endp.getOut().toString().replace("\r\n","|").replace('\r','|').replace('\n','|'); assertEquals("GET /usr HTTP/1.1|Header: Value|Content-Type: text/plain|Content-Length: 44||"+content,result); } @Test public void testChunked() throws Exception { Buffer bb=new ByteArrayBuffer(8096); Buffer sb=new ByteArrayBuffer(1500); ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096); HttpGenerator generator = new HttpGenerator(new SimpleBuffers(sb,bb),endp); generator.setRequest("GET","/usr"); HttpFields fields = new HttpFields(); fields.add("Header","Value"); fields.add("Content-Type","text/plain"); String content = "The quick brown fox jumped over the lazy dog"; generator.completeHeader(fields,false); generator.addContent(new ByteArrayBuffer(content).asMutableBuffer(),false); generator.flushBuffer(); generator.complete(); generator.flushBuffer(); String result=endp.getOut().toString().replace("\r\n","|").replace('\r','|').replace('\n','|'); assertEquals("GET /usr HTTP/1.1|Header: Value|Content-Type: text/plain|Transfer-Encoding: chunked||2C|"+content+"|0||",result); } /** * When the endpoint experiences back pressure, check that chunked transfer does not * screw up the chunking by leaving out the second chunk header. */ @Test public void testChunkedWithBackPressure() throws Exception { final AtomicInteger availableChannelBytes = new AtomicInteger(500); ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096) { @Override public int flush(Buffer buffer) throws IOException { // Simulate a socket that can only take 500 bytes at a time View view = new View(buffer, buffer.markIndex(), buffer.getIndex(), Math.min(buffer.putIndex(), buffer.getIndex()+availableChannelBytes.get()), buffer.isReadOnly()?Buffer.READONLY:Buffer.READWRITE); int read = super.flush(view); buffer.skip(read); availableChannelBytes.getAndAdd(-1*read); return read; } }; PooledBuffers pool = new PooledBuffers(Type.BYTE_ARRAY,1416,Type.BYTE_ARRAY,8096,Type.BYTE_ARRAY,10240); HttpGenerator generator = new HttpGenerator(pool,endp); generator.setRequest("GET","/usr"); HttpFields fields = new HttpFields(); fields.add("Header","Value"); fields.add("Content-Type","text/plain"); String content = "The quick brown fox jumped, "; // addContent only goes into "bypass" mode if the content is longer than 1024 characters. while (content.length() < 1024) { content = content + content; } String content2 = "over the lazy dog"; generator.completeHeader(fields,false); generator.addContent(new ByteArrayBuffer(content).asMutableBuffer(),false); generator.addContent(new ByteArrayBuffer(content2).asMutableBuffer(),false); // Now we'll allow more bytes to flow availableChannelBytes.set(5000); generator.flushBuffer(); generator.complete(); generator.flushBuffer(); String result=endp.getOut().toString(); System.err.println("result:"+result); result=result.replace("\r\n","|").replace('\r','|').replace('\n','|'); assertEquals("GET /usr HTTP/1.1|Header: Value|Content-Type: text/plain|Transfer-Encoding: chunked||700|"+content+"|11|"+content2+"|0||",result); } @Test public void testHTTP() throws Exception { Buffer bb=new ByteArrayBuffer(8096); Buffer sb=new ByteArrayBuffer(1500); HttpFields fields = new HttpFields(); ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096); HttpGenerator hb = new HttpGenerator(new SimpleBuffers(sb,bb),endp); Handler handler = new Handler(); HttpParser parser=null; // For HTTP version for (int v=9;v<=11;v++) { // For each test result for (int r=0;r2) continue; System.err.println(t); throw e; } String request=endp.getOut().toString(); // System.out.println(request+(hb.isPersistent()?"...\n":"---\n")); assertTrue(t,hb.isPersistent()); if (v==9) { assertEquals(t,"GET /context/path/info\r\n", request); continue; } parser=new HttpParser(new ByteArrayBuffer(request.getBytes()), handler); try { parser.parse(); } catch(IOException e) { if (tr[r].body!=null) throw e; continue; } if (tr[r].body!=null) assertEquals(t,tr[r].body, this.content); if (v==10) assertTrue(t,hb.isPersistent() || tr[r].values[1]==null || c==2 || c==0); else assertTrue(t,hb.isPersistent() || c==2); assertTrue(t,tr[r].values[1]==null || content.length()==Integer.parseInt(tr[r].values[1])); } } } } } private static final String[] headers= { "Content-Type","Content-Length","Connection","Transfer-Encoding","Other"}; private static class TR { private String[] values=new String[headers.length]; private String body; private TR(String ct, String cl ,String content) { values[0]=ct; values[1]=cl; values[4]="value"; this.body=content; } private void build(int version,HttpGenerator hb, String connection, String te, int chunks, HttpFields fields) throws Exception { values[2]=connection; values[3]=te; hb.setRequest(HttpMethods.GET,"/context/path/info"); hb.setVersion(version); for (int i=0;i9) assertEquals("OK Test",f2); if (content==null) assertTrue(t,tr[r]._body==null); else assertTrue(t,tr[r]._contentLength==null || content.length()==Integer.parseInt(tr[r]._contentLength)); } } } } } private static final String[] headers= { "Content-Type","Content-Length","Connection","Transfer-Encoding","Other"}; private static class TR { private int _code; private String _body; private boolean _head; String _contentType; String _contentLength; String _connection; String _te; String _other; private TR(int code,String contentType, String contentLength ,String content,boolean head) { _code=code; _contentType=contentType; _contentLength=contentLength; _other="value"; _body=content; _head=head; } private void build(int version,HttpGenerator hb,String reason, String connection, String te, int chunks, HttpFields fields) throws Exception { _connection=connection; _te=te; hb.setVersion(version); hb.setResponse(_code,reason); hb.setHead(_head); if (_contentType!=null) fields.put(new ByteArrayBuffer("Content-Type"),new ByteArrayBuffer(_contentType)); if (_contentLength!=null) fields.put(new ByteArrayBuffer("Content-Length"),new ByteArrayBuffer(_contentLength)); if (_connection!=null) fields.put(new ByteArrayBuffer("Connection"),new ByteArrayBuffer(_connection)); if (_te!=null) fields.put(new ByteArrayBuffer("Transfer-Encoding"),new ByteArrayBuffer(_te)); if (_other!=null) fields.put(new ByteArrayBuffer("Other"),new ByteArrayBuffer(_other)); if (_body!=null) { int inc=1+_body.length()/chunks; Buffer buf=new ByteArrayBuffer(_body); View view = new View(buf); for (int i=1;i=0); } } } @Test public void testResponseParse0() throws Exception { StringEndPoint io=new StringEndPoint(); io.setInput( "HTTP/1.1 200 Correct\015\012" + "Content-Length: 10\015\012" + "Content-Type: text/plain\015\012" + "\015\012" + "0123456789\015\012"); ByteArrayBuffer buffer= new ByteArrayBuffer(4096); SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); HttpParser parser= new HttpParser(buffers,io, handler); parser.parse(); assertEquals("HTTP/1.1", f0); assertEquals("200", f1); assertEquals("Correct", f2); assertEquals(_content.length(), 10); assertTrue(headerCompleted); assertTrue(messageCompleted); } @Test public void testResponseParse1() throws Exception { StringEndPoint io=new StringEndPoint(); io.setInput( "HTTP/1.1 304 Not-Modified\015\012" + "Connection: close\015\012" + "\015\012"); ByteArrayBuffer buffer= new ByteArrayBuffer(4096); SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); HttpParser parser= new HttpParser(buffers,io, handler); parser.parse(); assertEquals("HTTP/1.1", f0); assertEquals("304", f1); assertEquals("Not-Modified", f2); assertTrue(headerCompleted); assertTrue(messageCompleted); } @Test public void testResponseParse2() throws Exception { StringEndPoint io=new StringEndPoint(); io.setInput( "HTTP/1.1 204 No-Content\015\012" + "Header: value\015\012" + "\015\012" + "HTTP/1.1 200 Correct\015\012" + "Content-Length: 10\015\012" + "Content-Type: text/plain\015\012" + "\015\012" + "0123456789\015\012"); ByteArrayBuffer buffer= new ByteArrayBuffer(4096); SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); HttpParser parser= new HttpParser(buffers,io, handler); parser.parse(); assertEquals("HTTP/1.1", f0); assertEquals("204", f1); assertEquals("No-Content", f2); assertTrue(headerCompleted); assertTrue(messageCompleted); parser.parse(); assertEquals("HTTP/1.1", f0); assertEquals("200", f1); assertEquals("Correct", f2); assertEquals(_content.length(), 10); assertTrue(headerCompleted); assertTrue(messageCompleted); } @Test public void testResponseParse3() throws Exception { StringEndPoint io=new StringEndPoint(); io.setInput( "HTTP/1.1 200\015\012" + "Content-Length: 10\015\012" + "Content-Type: text/plain\015\012" + "\015\012" + "0123456789\015\012"); ByteArrayBuffer buffer= new ByteArrayBuffer(4096); SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); HttpParser parser= new HttpParser(buffers,io, handler); parser.parse(); assertEquals("HTTP/1.1", f0); assertEquals("200", f1); assertEquals(null, f2); assertEquals(_content.length(), 10); assertTrue(headerCompleted); assertTrue(messageCompleted); } @Test public void testResponseParse4() throws Exception { StringEndPoint io=new StringEndPoint(); io.setInput( "HTTP/1.1 200 \015\012" + "Content-Length: 10\015\012" + "Content-Type: text/plain\015\012" + "\015\012" + "0123456789\015\012"); ByteArrayBuffer buffer= new ByteArrayBuffer(4096); SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); HttpParser parser= new HttpParser(buffers,io, handler); parser.parse(); assertEquals("HTTP/1.1", f0); assertEquals("200", f1); assertEquals(null, f2); assertEquals(_content.length(), 10); assertTrue(headerCompleted); assertTrue(messageCompleted); } @Test public void testResponse304WithContentLength() throws Exception { StringEndPoint io=new StringEndPoint(); io.setInput( "HTTP/1.1 304 found\015\012" + "Content-Length: 10\015\012" + "\015\012"); ByteArrayBuffer buffer= new ByteArrayBuffer(4096); SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); HttpParser parser= new HttpParser(buffers,io, handler); parser.parse(); assertEquals("HTTP/1.1", f0); assertEquals("304", f1); assertEquals("found", f2); assertEquals(null,_content); assertTrue(headerCompleted); assertTrue(messageCompleted); } @Test public void testSeekEOF() throws Exception { StringEndPoint io=new StringEndPoint(); io.setInput( "HTTP/1.1 200 OK\015\012" + "Content-Length: 0\015\012" + "Connection: close\015\012" + "\015\012" + "\015\012" // extra CRLF ignored + "HTTP/1.1 400 OK\015\012"); // extra data causes close ByteArrayBuffer buffer= new ByteArrayBuffer(4096); SimpleBuffers buffers=new SimpleBuffers(buffer,null); Handler handler = new Handler(); HttpParser parser= new HttpParser(buffers,io, handler); parser.parse(); assertEquals("HTTP/1.1", f0); assertEquals("200", f1); assertEquals("OK", f2); assertEquals(null,_content); assertTrue(headerCompleted); assertTrue(messageCompleted); } private String _content; private String f0; private String f1; private String f2; private String[] hdr; private String[] val; private int h; private boolean headerCompleted; private boolean messageCompleted; private class Handler extends HttpParser.EventHandler { private HttpFields fields; private boolean request; public void content(Buffer ref) { if (_content==null) _content=""; _content= _content + ref; } public void startRequest(Buffer tok0, Buffer tok1, Buffer tok2) { try { request=true; h= -1; hdr= new String[9]; val= new String[9]; f0= tok0.toString(); f1=new String(tok1.array(),tok1.getIndex(),tok1.length(),StringUtil.__UTF8); if (tok2!=null) f2= tok2.toString(); else f2=null; fields=new HttpFields(); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } messageCompleted = false; headerCompleted = false; } public void parsedHeader(Buffer name, Buffer value) { hdr[++h]= name.toString(StringUtil.__ISO_8859_1); val[h]= value.toString(StringUtil.__ISO_8859_1); } public void headerComplete() { _content= null; String s0=fields.toString(); String s1=fields.toString(); if (!s0.equals(s1)) { //System.err.println(s0); //System.err.println(s1); throw new IllegalStateException(); } headerCompleted = true; } public void messageComplete(long contentLength) { messageCompleted = true; } public void startResponse(Buffer version, int status, Buffer reason) { request=false; f0 = version.toString(); f1 = Integer.toString(status); f2 = reason==null?null:reason.toString(); fields=new HttpFields(); hdr= new String[9]; val= new String[9]; messageCompleted = false; headerCompleted = false; } } } jetty8-8.1.3/jetty-http/src/test/java/org/eclipse/jetty/http/HttpStatusCodeTest.java000066400000000000000000000023211174773561500305450ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import org.junit.Test; public class HttpStatusCodeTest { @Test public void testInvalidGetCode() { assertNull("Invalid code: 800", HttpStatus.getCode(800)); assertNull("Invalid code: 190", HttpStatus.getCode(190)); } public void testHttpMethod() { assertEquals("GET",HttpMethods.GET_BUFFER.toString()); } } jetty8-8.1.3/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java000066400000000000000000000044741174773561500271410ustar00rootroot00000000000000// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import static org.junit.Assert.assertEquals; import java.net.URI; import org.junit.Test; /* ------------------------------------------------------------ */ public class HttpURITest { public static final String __input = "http://example.com:8080/path/to/context?parameter=%22value%22#fragment"; public static final String __scheme = "http"; public static final String __host = "example.com"; public static final int __port = 8080; public static final String __path = "/path/to/context"; public static final String __query = "parameter=%22value%22"; public static final String __fragment = "fragment"; /* ------------------------------------------------------------ */ @Test public void testFromString() throws Exception { HttpURI uri = new HttpURI(__input); assertEquals(__scheme, uri.getScheme()); assertEquals(__host,uri.getHost()); assertEquals(__port,uri.getPort()); assertEquals(__path,uri.getPath()); assertEquals(__query,uri.getQuery()); assertEquals(__fragment,uri.getFragment()); } /* ------------------------------------------------------------ */ @Test public void testFromURI() throws Exception { HttpURI uri = new HttpURI(new URI(__input)); assertEquals(__scheme, uri.getScheme()); assertEquals(__host,uri.getHost()); assertEquals(__port,uri.getPort()); assertEquals(__path,uri.getPath()); assertEquals(__query,uri.getQuery()); assertEquals(__fragment,uri.getFragment()); } } jetty8-8.1.3/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java000066400000000000000000000026401174773561500275470ustar00rootroot00000000000000package org.eclipse.jetty.http; import org.eclipse.jetty.io.Buffer; import org.junit.Assert; import org.junit.Test; public class MimeTypesTest { @Test public void testGetMimeByExtension_Gzip() { assertMimeTypeByExtension("application/gzip","test.gz"); } @Test public void testGetMimeByExtension_Png() { assertMimeTypeByExtension("image/png","test.png"); assertMimeTypeByExtension("image/png","TEST.PNG"); assertMimeTypeByExtension("image/png","Test.Png"); } @Test public void testGetMimeByExtension_Png_MultiDot() { assertMimeTypeByExtension("image/png","org.eclipse.jetty.Logo.png"); } @Test public void testGetMimeByExtension_Png_DeepPath() { assertMimeTypeByExtension("image/png","/org/eclipse/jetty/Logo.png"); } @Test public void testGetMimeByExtension_Text() { assertMimeTypeByExtension("text/plain","test.txt"); assertMimeTypeByExtension("text/plain","TEST.TXT"); } private void assertMimeTypeByExtension(String expectedMimeType, String filename) { MimeTypes mimetypes = new MimeTypes(); Buffer contentType = mimetypes.getMimeByExtension(filename); String prefix = "MimeTypes.getMimeByExtension(" + filename + ")"; Assert.assertNotNull(prefix,contentType); Assert.assertEquals(prefix,expectedMimeType,contentType.toString()); } } jetty8-8.1.3/jetty-http/src/test/java/org/eclipse/jetty/http/PathMapTest.java000066400000000000000000000201101174773561500271550ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.http; import junit.framework.TestCase; import org.junit.Test; /** * */ public class PathMapTest extends TestCase { @Test public void testPathMap() throws Exception { PathMap p = new PathMap(); p.put("/abs/path", "1"); p.put("/abs/path/longer", "2"); p.put("/animal/bird/*", "3"); p.put("/animal/fish/*", "4"); p.put("/animal/*", "5"); p.put("*.tar.gz", "6"); p.put("*.gz", "7"); p.put("/", "8"); p.put("/XXX:/YYY", "9"); p.put("", "10"); String[][] tests = { { "/abs/path", "1"}, { "/abs/path/xxx", "8"}, { "/abs/pith", "8"}, { "/abs/path/longer", "2"}, { "/abs/path/", "8"}, { "/abs/path/xxx", "8"}, { "/animal/bird/eagle/bald", "3"}, { "/animal/fish/shark/grey", "4"}, { "/animal/insect/bug", "5"}, { "/animal", "5"}, { "/animal/", "5"}, { "/animal/x", "5"}, { "/animal/*", "5"}, { "/suffix/path.tar.gz", "6"}, { "/suffix/path.gz", "7"}, { "/animal/path.gz", "5"}, { "/Other/path", "8"},}; for (String[] test : tests) { assertEquals(test[0], test[1], p.getMatch(test[0]).getValue()); } assertEquals("Get absolute path", "1", p.get("/abs/path")); assertEquals("Match absolute path", "/abs/path", p.getMatch("/abs/path").getKey()); assertEquals("all matches", "[/animal/bird/*=3, /animal/*=5, *.tar.gz=6, *.gz=7, /=8]", p.getMatches("/animal/bird/path.tar.gz").toString()); assertEquals("Dir matches", "[/animal/fish/*=4, /animal/*=5, /=8]", p.getMatches("/animal/fish/").toString()); assertEquals("Dir matches", "[/animal/fish/*=4, /animal/*=5, /=8]", p.getMatches("/animal/fish").toString()); assertEquals("Dir matches", "[/=8]", p.getMatches("/").toString()); assertEquals("Dir matches", "[=10, /=8]", p.getMatches("").toString()); assertEquals("pathMatch exact", "/Foo/bar", PathMap.pathMatch("/Foo/bar", "/Foo/bar")); assertEquals("pathMatch prefix", "/Foo", PathMap.pathMatch("/Foo/*", "/Foo/bar")); assertEquals("pathMatch prefix", "/Foo", PathMap.pathMatch("/Foo/*", "/Foo/")); assertEquals("pathMatch prefix", "/Foo", PathMap.pathMatch("/Foo/*", "/Foo")); assertEquals("pathMatch suffix", "/Foo/bar.ext", PathMap.pathMatch("*.ext", "/Foo/bar.ext")); assertEquals("pathMatch default", "/Foo/bar.ext", PathMap.pathMatch("/", "/Foo/bar.ext")); assertEquals("pathInfo exact", null, PathMap.pathInfo("/Foo/bar", "/Foo/bar")); assertEquals("pathInfo prefix", "/bar", PathMap.pathInfo("/Foo/*", "/Foo/bar")); assertEquals("pathInfo prefix", "/*", PathMap.pathInfo("/Foo/*", "/Foo/*")); assertEquals("pathInfo prefix", "/", PathMap.pathInfo("/Foo/*", "/Foo/")); assertEquals("pathInfo prefix", null, PathMap.pathInfo("/Foo/*", "/Foo")); assertEquals("pathInfo suffix", null, PathMap.pathInfo("*.ext", "/Foo/bar.ext")); assertEquals("pathInfo default", null, PathMap.pathInfo("/", "/Foo/bar.ext")); assertEquals("multi paths", "9", p.getMatch("/XXX").getValue()); assertEquals("multi paths", "9", p.getMatch("/YYY").getValue()); p.put("/*", "0"); assertEquals("Get absolute path", "1", p.get("/abs/path")); assertEquals("Match absolute path", "/abs/path", p.getMatch("/abs/path").getKey()); assertEquals("Match absolute path", "1", p.getMatch("/abs/path").getValue()); assertEquals("Mismatch absolute path", "0", p.getMatch("/abs/path/xxx").getValue()); assertEquals("Mismatch absolute path", "0", p.getMatch("/abs/pith").getValue()); assertEquals("Match longer absolute path", "2", p.getMatch("/abs/path/longer").getValue()); assertEquals("Not exact absolute path", "0", p.getMatch("/abs/path/").getValue()); assertEquals("Not exact absolute path", "0", p.getMatch("/abs/path/xxx").getValue()); assertEquals("Match longest prefix", "3", p.getMatch("/animal/bird/eagle/bald").getValue()); assertEquals("Match longest prefix", "4", p.getMatch("/animal/fish/shark/grey").getValue()); assertEquals("Match longest prefix", "5", p.getMatch("/animal/insect/bug").getValue()); assertEquals("mismatch exact prefix", "5", p.getMatch("/animal").getValue()); assertEquals("mismatch exact prefix", "5", p.getMatch("/animal/").getValue()); assertEquals("Match longest suffix", "0", p.getMatch("/suffix/path.tar.gz").getValue()); assertEquals("Match longest suffix", "0", p.getMatch("/suffix/path.gz").getValue()); assertEquals("prefix rather than suffix", "5", p.getMatch("/animal/path.gz").getValue()); assertEquals("default", "0", p.getMatch("/Other/path").getValue()); assertEquals("pathMatch /*", "", PathMap.pathMatch("/*", "/xxx/zzz")); assertEquals("pathInfo /*", "/xxx/zzz", PathMap.pathInfo("/*", "/xxx/zzz")); assertTrue("match /", PathMap.match("/", "/anything")); assertTrue("match /*", PathMap.match("/*", "/anything")); assertTrue("match /foo", PathMap.match("/foo", "/foo")); assertTrue("!match /foo", !PathMap.match("/foo", "/bar")); assertTrue("match /foo/*", PathMap.match("/foo/*", "/foo")); assertTrue("match /foo/*", PathMap.match("/foo/*", "/foo/")); assertTrue("match /foo/*", PathMap.match("/foo/*", "/foo/anything")); assertTrue("!match /foo/*", !PathMap.match("/foo/*", "/bar")); assertTrue("!match /foo/*", !PathMap.match("/foo/*", "/bar/")); assertTrue("!match /foo/*", !PathMap.match("/foo/*", "/bar/anything")); assertTrue("match *.foo", PathMap.match("*.foo", "anything.foo")); assertTrue("!match *.foo", !PathMap.match("*.foo", "anything.bar")); assertEquals("match / with ''", "10", p.getMatch("/").getValue()); } /** * See JIRA issue: JETTY-88. */ @Test public void testPathMappingsOnlyMatchOnDirectoryNames() throws Exception { String spec = "/xyz/*"; assertMatch(spec, "/xyz"); assertMatch(spec, "/xyz/"); assertMatch(spec, "/xyz/123"); assertMatch(spec, "/xyz/123/"); assertMatch(spec, "/xyz/123.txt"); assertNotMatch(spec, "/xyz123"); assertNotMatch(spec, "/xyz123;jessionid=99"); assertNotMatch(spec, "/xyz123/"); assertNotMatch(spec, "/xyz123/456"); assertNotMatch(spec, "/xyz.123"); assertNotMatch(spec, "/xyz;123"); // as if the ; was encoded and part of the path assertNotMatch(spec, "/xyz?123"); // as if the ? was encoded and part of the path } private void assertMatch(String spec, String path) { boolean match = PathMap.match(spec, path); assertTrue("PathSpec '" + spec + "' should match path '" + path + "'", match); } private void assertNotMatch(String spec, String path) { boolean match = PathMap.match(spec, path); assertFalse("PathSpec '" + spec + "' should not match path '" + path + "'", match); } } jetty8-8.1.3/jetty-http/src/test/resources/000077500000000000000000000000001174773561500206665ustar00rootroot00000000000000jetty8-8.1.3/jetty-http/src/test/resources/keystore000066400000000000000000000026221174773561500224600ustar00rootroot00000000000000mykey]A00 +*+!אu䛪7lMꔄ\%p.G#ݥzgZ-mv[¸73i:2$

    C $,ʉ@g Alx q* Iq"?1~jܩOl"[z{5anb],*Lu||<6=a$c+9ܢwmŝ`X.5090090  *H 010UUnknown10UUnknown10UUnknown10U Mort Bay Consulting1 0U Open Source Development10U Jetty Server0 001022135544Z 010120135544Z010UUnknown10UUnknown10UUnknown10U Mort Bay Consulting1 0U Open Source Development10U Jetty Server00  *H 04銴*?TVhUzi-. H?Ӡq9>?*]R@NbaI\@`Ŏ L~o==uzջI l E;rNT+4JPd`0  *H =6Bkј@Ъ>hT8V$Gwc\2Hz%eNs"øֶh.[7C|x5mp7=Ogi?QCDOALrPp>羴V[׼q"x?js>!sIAмx8*l:jetty8-8.1.3/jetty-io/000077500000000000000000000000001174773561500145365ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/pom.xml000066400000000000000000000040671174773561500160620ustar00rootroot00000000000000 jetty-project org.eclipse.jetty 8.1.3.v20120416 4.0.0 jetty-io Jetty :: IO Utility ${project.groupId}.io org.eclipse.jetty jetty-util ${project.version} org.eclipse.jetty.toolchain jetty-test-helper test org.apache.felix maven-bundle-plugin true manifest org.apache.maven.plugins maven-jar-plugin artifact-jar jar ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.io.* jetty8-8.1.3/jetty-io/src/000077500000000000000000000000001174773561500153255ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/main/000077500000000000000000000000001174773561500162515ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/main/java/000077500000000000000000000000001174773561500171725ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/main/java/org/000077500000000000000000000000001174773561500177615ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/000077500000000000000000000000001174773561500214055ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500225445ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/000077500000000000000000000000001174773561500231535ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffer.java000066400000000000000000000436641174773561500267300ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * * */ public abstract class AbstractBuffer implements Buffer { private static final Logger LOG = Log.getLogger(AbstractBuffer.class); private final static boolean __boundsChecking = Boolean.getBoolean("org.eclipse.jetty.io.AbstractBuffer.boundsChecking"); protected final static String __IMMUTABLE = "IMMUTABLE", __READONLY = "READONLY", __READWRITE = "READWRITE", __VOLATILE = "VOLATILE"; protected int _access; protected boolean _volatile; protected int _get; protected int _put; protected int _hash; protected int _hashGet; protected int _hashPut; protected int _mark; protected String _string; protected View _view; /** * Constructor for BufferView * * @param access 0==IMMUTABLE, 1==READONLY, 2==READWRITE */ public AbstractBuffer(int access, boolean isVolatile) { if (access == IMMUTABLE && isVolatile) throw new IllegalArgumentException("IMMUTABLE && VOLATILE"); setMarkIndex(-1); _access = access; _volatile = isVolatile; } /* * @see org.eclipse.io.Buffer#toArray() */ public byte[] asArray() { byte[] bytes = new byte[length()]; byte[] array = array(); if (array != null) System.arraycopy(array, getIndex(), bytes, 0, bytes.length); else peek(getIndex(), bytes, 0, length()); return bytes; } public ByteArrayBuffer duplicate(int access) { Buffer b=this.buffer(); if (this instanceof Buffer.CaseInsensitve || b instanceof Buffer.CaseInsensitve) return new ByteArrayBuffer.CaseInsensitive(asArray(), 0, length(),access); else return new ByteArrayBuffer(asArray(), 0, length(), access); } /* * @see org.eclipse.io.Buffer#asNonVolatile() */ public Buffer asNonVolatileBuffer() { if (!isVolatile()) return this; return duplicate(_access); } public Buffer asImmutableBuffer() { if (isImmutable()) return this; return duplicate(IMMUTABLE); } /* * @see org.eclipse.util.Buffer#asReadOnlyBuffer() */ public Buffer asReadOnlyBuffer() { if (isReadOnly()) return this; return new View(this, markIndex(), getIndex(), putIndex(), READONLY); } public Buffer asMutableBuffer() { if (!isImmutable()) return this; Buffer b=this.buffer(); if (b.isReadOnly()) { return duplicate(READWRITE); } return new View(b, markIndex(), getIndex(), putIndex(), _access); } public Buffer buffer() { return this; } public void clear() { setMarkIndex(-1); setGetIndex(0); setPutIndex(0); } public void compact() { if (isReadOnly()) throw new IllegalStateException(__READONLY); int s = markIndex() >= 0 ? markIndex() : getIndex(); if (s > 0) { byte array[] = array(); int length = putIndex() - s; if (length > 0) { if (array != null) System.arraycopy(array(), s, array(), 0, length); else poke(0, peek(s, length)); } if (markIndex() > 0) setMarkIndex(markIndex() - s); setGetIndex(getIndex() - s); setPutIndex(putIndex() - s); } } @Override public boolean equals(Object obj) { if (obj==this) return true; // reject non buffers; if (obj == null || !(obj instanceof Buffer)) return false; Buffer b = (Buffer) obj; if (this instanceof Buffer.CaseInsensitve || b instanceof Buffer.CaseInsensitve) return equalsIgnoreCase(b); // reject different lengths if (b.length() != length()) return false; // reject AbstractBuffer with different hash value if (_hash != 0 && obj instanceof AbstractBuffer) { AbstractBuffer ab = (AbstractBuffer) obj; if (ab._hash != 0 && _hash != ab._hash) return false; } // Nothing for it but to do the hard grind. int get=getIndex(); int bi=b.putIndex(); for (int i = putIndex(); i-->get;) { byte b1 = peek(i); byte b2 = b.peek(--bi); if (b1 != b2) return false; } return true; } public boolean equalsIgnoreCase(Buffer b) { if (b==this) return true; // reject different lengths if (b.length() != length()) return false; // reject AbstractBuffer with different hash value if (_hash != 0 && b instanceof AbstractBuffer) { AbstractBuffer ab = (AbstractBuffer) b; if (ab._hash != 0 && _hash != ab._hash) return false; } // Nothing for it but to do the hard grind. int get=getIndex(); int bi=b.putIndex(); byte[] array = array(); byte[] barray= b.array(); if (array!=null && barray!=null) { for (int i = putIndex(); i-->get;) { byte b1 = array[i]; byte b2 = barray[--bi]; if (b1 != b2) { if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A'); if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A'); if (b1 != b2) return false; } } } else { for (int i = putIndex(); i-->get;) { byte b1 = peek(i); byte b2 = b.peek(--bi); if (b1 != b2) { if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A'); if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A'); if (b1 != b2) return false; } } } return true; } public byte get() { return peek(_get++); } public int get(byte[] b, int offset, int length) { int gi = getIndex(); int l=length(); if (l==0) return -1; if (length>l) length=l; length = peek(gi, b, offset, length); if (length>0) setGetIndex(gi + length); return length; } public Buffer get(int length) { int gi = getIndex(); Buffer view = peek(gi, length); setGetIndex(gi + length); return view; } public final int getIndex() { return _get; } public boolean hasContent() { return _put > _get; } @Override public int hashCode() { if (_hash == 0 || _hashGet!=_get || _hashPut!=_put) { int get=getIndex(); byte[] array = array(); if (array==null) { for (int i = putIndex(); i-- >get;) { byte b = peek(i); if ('a' <= b && b <= 'z') b = (byte) (b - 'a' + 'A'); _hash = 31 * _hash + b; } } else { for (int i = putIndex(); i-- >get;) { byte b = array[i]; if ('a' <= b && b <= 'z') b = (byte) (b - 'a' + 'A'); _hash = 31 * _hash + b; } } if (_hash == 0) _hash = -1; _hashGet=_get; _hashPut=_put; } return _hash; } public boolean isImmutable() { return _access <= IMMUTABLE; } public boolean isReadOnly() { return _access <= READONLY; } public boolean isVolatile() { return _volatile; } public int length() { return _put - _get; } public void mark() { setMarkIndex(_get - 1); } public void mark(int offset) { setMarkIndex(_get + offset); } public int markIndex() { return _mark; } public byte peek() { return peek(_get); } public Buffer peek(int index, int length) { if (_view == null) { _view = new View(this, -1, index, index + length, isReadOnly() ? READONLY : READWRITE); } else { _view.update(this.buffer()); _view.setMarkIndex(-1); _view.setGetIndex(0); _view.setPutIndex(index + length); _view.setGetIndex(index); } return _view; } public int poke(int index, Buffer src) { _hash=0; /* if (isReadOnly()) throw new IllegalStateException(__READONLY); if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0"); */ int length=src.length(); if (index + length > capacity()) { length=capacity()-index; /* if (length<0) throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity()); */ } byte[] src_array = src.array(); byte[] dst_array = array(); if (src_array != null && dst_array != null) System.arraycopy(src_array, src.getIndex(), dst_array, index, length); else if (src_array != null) { int s=src.getIndex(); for (int i=0;i capacity()) { length=capacity()-index; /* if (length<0) throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity()); */ } byte[] dst_array = array(); if (dst_array != null) System.arraycopy(b, offset, dst_array, index, length); else { int s=offset; for (int i=0;i= 0) setGetIndex(markIndex()); } public void rewind() { setGetIndex(0); setMarkIndex(-1); } public void setGetIndex(int getIndex) { /* bounds checking if (isImmutable()) throw new IllegalStateException(__IMMUTABLE); if (getIndex < 0) throw new IllegalArgumentException("getIndex<0: " + getIndex + "<0"); if (getIndex > putIndex()) throw new IllegalArgumentException("getIndex>putIndex: " + getIndex + ">" + putIndex()); */ _get = getIndex; _hash=0; } public void setMarkIndex(int index) { /* if (index>=0 && isImmutable()) throw new IllegalStateException(__IMMUTABLE); */ _mark = index; } public void setPutIndex(int putIndex) { /* bounds checking if (isImmutable()) throw new IllegalStateException(__IMMUTABLE); if (putIndex > capacity()) throw new IllegalArgumentException("putIndex>capacity: " + putIndex + ">" + capacity()); if (getIndex() > putIndex) throw new IllegalArgumentException("getIndex>putIndex: " + getIndex() + ">" + putIndex); */ _put = putIndex; _hash=0; } public int skip(int n) { if (length() < n) n = length(); setGetIndex(getIndex() + n); return n; } public Buffer slice() { return peek(getIndex(), length()); } public Buffer sliceFromMark() { return sliceFromMark(getIndex() - markIndex() - 1); } public Buffer sliceFromMark(int length) { if (markIndex() < 0) return null; Buffer view = peek(markIndex(), length); setMarkIndex(-1); return view; } public int space() { return capacity() - _put; } public String toDetailString() { StringBuilder buf = new StringBuilder(); buf.append("["); buf.append(super.hashCode()); buf.append(","); buf.append(this.buffer().hashCode()); buf.append(",m="); buf.append(markIndex()); buf.append(",g="); buf.append(getIndex()); buf.append(",p="); buf.append(putIndex()); buf.append(",c="); buf.append(capacity()); buf.append("]={"); if (markIndex() >= 0) { for (int i = markIndex(); i < getIndex(); i++) { byte b = peek(i); TypeUtil.toHex(b,buf); } buf.append("}{"); } int count = 0; for (int i = getIndex(); i < putIndex(); i++) { byte b = peek(i); TypeUtil.toHex(b,buf); if (count++ == 50) { if (putIndex() - i > 20) { buf.append(" ... "); i = putIndex() - 20; } } } buf.append('}'); return buf.toString(); } /* ------------------------------------------------------------ */ @Override public String toString() { if (isImmutable()) { if (_string == null) _string = new String(asArray(), 0, length()); return _string; } return new String(asArray(), 0, length()); } /* ------------------------------------------------------------ */ public String toString(String charset) { try { byte[] bytes=array(); if (bytes!=null) return new String(bytes,getIndex(),length(),charset); return new String(asArray(), 0, length(),charset); } catch(Exception e) { LOG.warn(e); return new String(asArray(), 0, length()); } } /* ------------------------------------------------------------ */ public String toDebugString() { return getClass()+"@"+super.hashCode(); } /* ------------------------------------------------------------ */ public void writeTo(OutputStream out) throws IOException { byte[] array = array(); if (array!=null) { out.write(array,getIndex(),length()); } else { int len = this.length(); byte[] buf=new byte[len>1024?1024:len]; int offset=_get; while (len>0) { int l=peek(offset,buf,0,len>buf.length?buf.length:len); out.write(buf,0,l); offset+=l; len-=l; } } clear(); } /* ------------------------------------------------------------ */ public int readFrom(InputStream in,int max) throws IOException { byte[] array = array(); int s=space(); if (s>max) s=max; if (array!=null) { int l=in.read(array,_put,s); if (l>0) _put+=l; return l; } else { byte[] buf=new byte[s>1024?1024:s]; int total=0; while (s>0) { int l=in.read(buf,0,buf.length); if (l<0) return total>0?total:-1; int p=put(buf,0,l); assert l==p; s-=l; } return total; } } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffers.java000066400000000000000000000105561174773561500271050ustar00rootroot00000000000000package org.eclipse.jetty.io; import org.eclipse.jetty.io.nio.DirectNIOBuffer; import org.eclipse.jetty.io.nio.IndirectNIOBuffer; public abstract class AbstractBuffers implements Buffers { protected final Buffers.Type _headerType; protected final int _headerSize; protected final Buffers.Type _bufferType; protected final int _bufferSize; protected final Buffers.Type _otherType; /* ------------------------------------------------------------ */ public AbstractBuffers(Buffers.Type headerType, int headerSize, Buffers.Type bufferType, int bufferSize, Buffers.Type otherType) { _headerType=headerType; _headerSize=headerSize; _bufferType=bufferType; _bufferSize=bufferSize; _otherType=otherType; } /* ------------------------------------------------------------ */ /** * @return Returns the buffer size in bytes. */ public int getBufferSize() { return _bufferSize; } /* ------------------------------------------------------------ */ /** * @return Returns the header size in bytes. */ public int getHeaderSize() { return _headerSize; } /* ------------------------------------------------------------ */ /** * Create a new header Buffer * @return new Buffer */ final protected Buffer newHeader() { switch(_headerType) { case BYTE_ARRAY: return new ByteArrayBuffer(_headerSize); case DIRECT: return new DirectNIOBuffer(_headerSize); case INDIRECT: return new IndirectNIOBuffer(_headerSize); } throw new IllegalStateException(); } /* ------------------------------------------------------------ */ /** * Create a new content Buffer * @return new Buffer */ final protected Buffer newBuffer() { switch(_bufferType) { case BYTE_ARRAY: return new ByteArrayBuffer(_bufferSize); case DIRECT: return new DirectNIOBuffer(_bufferSize); case INDIRECT: return new IndirectNIOBuffer(_bufferSize); } throw new IllegalStateException(); } /* ------------------------------------------------------------ */ /** * Create a new content Buffer * @param size * @return new Buffer */ final protected Buffer newBuffer(int size) { switch(_otherType) { case BYTE_ARRAY: return new ByteArrayBuffer(size); case DIRECT: return new DirectNIOBuffer(size); case INDIRECT: return new IndirectNIOBuffer(size); } throw new IllegalStateException(); } /* ------------------------------------------------------------ */ /** * @param buffer * @return True if the buffer is the correct type to be a Header buffer */ public final boolean isHeader(Buffer buffer) { if (buffer.capacity()==_headerSize) { switch(_headerType) { case BYTE_ARRAY: return buffer instanceof ByteArrayBuffer && !(buffer instanceof IndirectNIOBuffer); case DIRECT: return buffer instanceof DirectNIOBuffer; case INDIRECT: return buffer instanceof IndirectNIOBuffer; } } return false; } /* ------------------------------------------------------------ */ /** * @param buffer * @return True if the buffer is the correct type to be a Header buffer */ public final boolean isBuffer(Buffer buffer) { if (buffer.capacity()==_bufferSize) { switch(_bufferType) { case BYTE_ARRAY: return buffer instanceof ByteArrayBuffer && !(buffer instanceof IndirectNIOBuffer); case DIRECT: return buffer instanceof DirectNIOBuffer; case INDIRECT: return buffer instanceof IndirectNIOBuffer; } } return false; } /* ------------------------------------------------------------ */ public String toString() { return String.format("%s [%d,%d]", getClass().getSimpleName(), _headerSize, _bufferSize); } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java000066400000000000000000000026641174773561500276110ustar00rootroot00000000000000package org.eclipse.jetty.io; import java.io.IOException; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public abstract class AbstractConnection implements Connection { private static final Logger LOG = Log.getLogger(AbstractConnection.class); private final long _timeStamp; protected final EndPoint _endp; public AbstractConnection(EndPoint endp) { _endp=(EndPoint)endp; _timeStamp = System.currentTimeMillis(); } public AbstractConnection(EndPoint endp,long timestamp) { _endp=(EndPoint)endp; _timeStamp = timestamp; } public long getTimeStamp() { return _timeStamp; } public EndPoint getEndPoint() { return _endp; } public void onIdleExpired(long idleForMs) { try { LOG.debug("onIdleExpired {}ms {} {}",idleForMs,this,_endp); if (_endp.isInputShutdown() || _endp.isOutputShutdown()) _endp.close(); else _endp.shutdownOutput(); } catch(IOException e) { LOG.ignore(e); try { _endp.close(); } catch(IOException e2) { LOG.ignore(e2); } } } public String toString() { return String.format("%s@%x", getClass().getSimpleName(), hashCode()); } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/AsyncEndPoint.java000066400000000000000000000054661174773561500265470ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import org.eclipse.jetty.util.thread.Timeout; public interface AsyncEndPoint extends ConnectedEndPoint { /* ------------------------------------------------------------ */ /** * Dispatch the endpoint if it is not already dispatched * */ public void dispatch(); /* ------------------------------------------------------------ */ /** * Dispatch the endpoint. If it is already dispatched, schedule a redispatch * */ public void asyncDispatch(); /* ------------------------------------------------------------ */ /** Schedule a write dispatch. * Set the endpoint to not be writable and schedule a dispatch when * it becomes writable. */ public void scheduleWrite(); /* ------------------------------------------------------------ */ /** Callback when idle. *

    An endpoint is idle if there has been no IO activity for * {@link #getMaxIdleTime()} and {@link #isCheckForIdle()} is true. * @param idleForMs TODO */ public void onIdleExpired(long idleForMs); /* ------------------------------------------------------------ */ /** Set if the endpoint should be checked for idleness */ public void setCheckForIdle(boolean check); /* ------------------------------------------------------------ */ /** Get if the endpoint should be checked for idleness */ public boolean isCheckForIdle(); /* ------------------------------------------------------------ */ public boolean isWritable(); /* ------------------------------------------------------------ */ /** * @return True if IO has been successfully performed since the last call to {@link #hasProgressed()} */ public boolean hasProgressed(); /* ------------------------------------------------------------ */ /** */ public void scheduleTimeout(Timeout.Task task, long timeoutMs); /* ------------------------------------------------------------ */ /** */ public void cancelTimeout(Timeout.Task task); } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/Buffer.java000066400000000000000000000253161174773561500252360ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Byte Buffer interface. * * This is a byte buffer that is designed to work like a FIFO for bytes. Puts and Gets operate on different * pointers into the buffer and the valid _content of the buffer is always between the getIndex and the putIndex. * * This buffer interface is designed to be similar, but not dependant on the java.nio buffers, which may * be used to back an implementation of this Buffer. The main difference is that NIO buffer after a put have * their valid _content before the position and a flip is required to access that data. * * For this buffer it is always true that: * markValue <= getIndex <= putIndex <= capacity * * * @version 1.0 */ public interface Buffer extends Cloneable { public final static int IMMUTABLE=0, // neither indexes or contexts can be changed READONLY=1, // indexes may be changed, but not content READWRITE=2; // anything can be changed public final boolean VOLATILE=true; // The buffer may change outside of current scope. public final boolean NON_VOLATILE=false; /** * Get the underlying array, if one exists. * @return a byte[] backing this buffer or null if none exists. */ byte[] array(); /** * * @return a byte[] value of the bytes from the getIndex to the putIndex. */ byte[] asArray(); /** * Get the unerlying buffer. If this buffer wraps a backing buffer. * @return The root backing buffer or this if there is no backing buffer; */ Buffer buffer(); /** * * @return a non volitile version of this Buffer value */ Buffer asNonVolatileBuffer(); /** * * @return a readonly version of this Buffer. */ Buffer asReadOnlyBuffer(); /** * * @return an immutable version of this Buffer. */ Buffer asImmutableBuffer(); /** * * @return an immutable version of this Buffer. */ Buffer asMutableBuffer(); /** * * The capacity of the buffer. This is the maximum putIndex that may be set. * @return an int value */ int capacity(); /** * the space remaining in the buffer. * @return capacity - putIndex */ int space(); /** * Clear the buffer. getIndex=0, putIndex=0. */ void clear(); /** * Compact the buffer by discarding bytes before the postion (or mark if set). * Bytes from the getIndex (or mark) to the putIndex are moved to the beginning of * the buffer and the values adjusted accordingly. */ void compact(); /** * Get the byte at the current getIndex and increment it. * @return The byte value from the current getIndex. */ byte get(); /** * Get bytes from the current postion and put them into the passed byte array. * The getIndex is incremented by the number of bytes copied into the array. * @param b The byte array to fill. * @param offset Offset in the array. * @param length The max number of bytes to read. * @return The number of bytes actually read. */ int get(byte[] b, int offset, int length); /** * * @param length an int value * @return a Buffer value */ Buffer get(int length); /** * The index within the buffer that will next be read or written. * @return an int value >=0 <= putIndex() */ int getIndex(); /** * @return true of putIndex > getIndex */ boolean hasContent(); /** * * @return a boolean value true if case sensitive comparison on this buffer */ boolean equalsIgnoreCase(Buffer buffer); /** * * @return a boolean value true if the buffer is immutable and that neither * the buffer contents nor the indexes may be changed. */ boolean isImmutable(); /** * * @return a boolean value true if the buffer is readonly. The buffer indexes may * be modified, but the buffer contents may not. For example a View onto an immutable Buffer will be * read only. */ boolean isReadOnly(); /** * * @return a boolean value true if the buffer contents may change * via alternate paths than this buffer. If the contents of this buffer are to be used outside of the * current context, then a copy must be made. */ boolean isVolatile(); /** * The number of bytes from the getIndex to the putIndex * @return an int == putIndex()-getIndex() */ int length(); /** * Set the mark to the current getIndex. */ void mark(); /** * Set the mark relative to the current getIndex * @param offset an int value to add to the current getIndex to obtain the mark value. */ void mark(int offset); /** * The current index of the mark. * @return an int index in the buffer or -1 if the mark is not set. */ int markIndex(); /** * Get the byte at the current getIndex without incrementing the getIndex. * @return The byte value from the current getIndex. */ byte peek(); /** * Get the byte at a specific index in the buffer. * @param index an int value * @return a byte value */ byte peek(int index); /** * * @param index an int value * @param length an int value * @return The Buffer value from the requested getIndex. */ Buffer peek(int index, int length); /** * * @param index an int value * @param b The byte array to peek into * @param offset The offset into the array to start peeking * @param length an int value * @return The number of bytes actually peeked */ int peek(int index, byte[] b, int offset, int length); /** * Put the contents of the buffer at the specific index. * @param index an int value * @param src a Buffer. If the source buffer is not modified * @return The number of bytes actually poked */ int poke(int index, Buffer src); /** * Put a specific byte to a specific getIndex. * @param index an int value * @param b a byte value */ void poke(int index, byte b); /** * Put a specific byte to a specific getIndex. * @param index an int value * @param b a byte array value * @return The number of bytes actually poked */ int poke(int index, byte b[], int offset, int length); /** * Write the bytes from the source buffer to the current getIndex. * @param src The source Buffer it is not modified. * @return The number of bytes actually poked */ int put(Buffer src); /** * Put a byte to the current getIndex and increment the getIndex. * @param b a byte value */ void put(byte b); /** * Put a byte to the current getIndex and increment the getIndex. * @param b a byte value * @return The number of bytes actually poked */ int put(byte[] b,int offset, int length); /** * Put a byte to the current getIndex and increment the getIndex. * @param b a byte value * @return The number of bytes actually poked */ int put(byte[] b); /** * The index of the first element that should not be read. * @return an int value >= getIndex() */ int putIndex(); /** * Reset the current getIndex to the mark */ void reset(); /** * Set the buffers start getIndex. * @param newStart an int value */ void setGetIndex(int newStart); /** * Set a specific value for the mark. * @param newMark an int value */ void setMarkIndex(int newMark); /** * * @param newLimit an int value */ void setPutIndex(int newLimit); /** * Skip _content. The getIndex is updated by min(remaining(), n) * @param n The number of bytes to skip * @return the number of bytes skipped. */ int skip(int n); /** * * @return a volitile Buffer from the postion to the putIndex. */ Buffer slice(); /** * * * @return a volitile Buffer value from the mark to the putIndex */ Buffer sliceFromMark(); /** * * * @param length an int value * @return a valitile Buffer value from the mark of the length requested. */ Buffer sliceFromMark(int length); /** * * @return a String value describing the state and contents of the buffer. */ String toDetailString(); /* ------------------------------------------------------------ */ /** Write the buffer's contents to the output stream * @param out */ void writeTo(OutputStream out) throws IOException; /* ------------------------------------------------------------ */ /** Read the buffer's contents from the input stream * @param in input stream * @param max maximum number of bytes that may be read * @return actual number of bytes read or -1 for EOF */ int readFrom(InputStream in, int max) throws IOException; /* ------------------------------------------------------------ */ String toString(String charset); /* * Buffers implementing this interface should be compared with case insensitive equals * */ public interface CaseInsensitve {} } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/BufferCache.java000066400000000000000000000114431174773561500261560ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.util.ArrayList; import java.util.HashMap; import java.util.Map.Entry; import org.eclipse.jetty.util.StringMap; /* ------------------------------------------------------------------------------- */ /** * Stores a collection of {@link Buffer} objects. * Buffers are stored in an ordered collection and can retreived by index or value * */ public class BufferCache { private final HashMap _bufferMap=new HashMap(); private final StringMap _stringMap=new StringMap(StringMap.CASE_INSENSTIVE); private final ArrayList _index= new ArrayList(); /* ------------------------------------------------------------------------------- */ /** Add a buffer to the cache at the specified index. * @param value The content of the buffer. */ public CachedBuffer add(String value, int ordinal) { CachedBuffer buffer= new CachedBuffer(value, ordinal); _bufferMap.put(buffer, buffer); _stringMap.put(value, buffer); while ((ordinal - _index.size()) >= 0) _index.add(null); if (_index.get(ordinal)==null) _index.add(ordinal, buffer); return buffer; } public CachedBuffer get(int ordinal) { if (ordinal < 0 || ordinal >= _index.size()) return null; return (CachedBuffer)_index.get(ordinal); } public CachedBuffer get(Buffer buffer) { return (CachedBuffer)_bufferMap.get(buffer); } public CachedBuffer get(String value) { return (CachedBuffer)_stringMap.get(value); } public Buffer lookup(Buffer buffer) { if (buffer instanceof CachedBuffer) return buffer; Buffer b= get(buffer); if (b == null) { if (buffer instanceof Buffer.CaseInsensitve) return buffer; return new ByteArrayBuffer.CaseInsensitive(buffer.asArray(),0,buffer.length(),Buffer.IMMUTABLE); } return b; } public CachedBuffer getBest(byte[] value, int offset, int maxLength) { Entry entry = _stringMap.getBestEntry(value, offset, maxLength); if (entry!=null) return (CachedBuffer)entry.getValue(); return null; } public Buffer lookup(String value) { Buffer b= get(value); if (b == null) { return new CachedBuffer(value,-1); } return b; } public String toString(Buffer buffer) { return lookup(buffer).toString(); } public int getOrdinal(String value) { CachedBuffer buffer = (CachedBuffer)_stringMap.get(value); return buffer==null?-1:buffer.getOrdinal(); } public int getOrdinal(Buffer buffer) { if (buffer instanceof CachedBuffer) return ((CachedBuffer)buffer).getOrdinal(); buffer=lookup(buffer); if (buffer!=null && buffer instanceof CachedBuffer) return ((CachedBuffer)buffer).getOrdinal(); return -1; } public static class CachedBuffer extends ByteArrayBuffer.CaseInsensitive { private final int _ordinal; private HashMap _associateMap=null; public CachedBuffer(String value, int ordinal) { super(value); _ordinal= ordinal; } public int getOrdinal() { return _ordinal; } public CachedBuffer getAssociate(Object key) { if (_associateMap==null) return null; return (CachedBuffer)_associateMap.get(key); } // TODO Replace Associate with a mime encoding specific solution public void setAssociate(Object key, CachedBuffer associate) { if (_associateMap==null) _associateMap=new HashMap(); _associateMap.put(key,associate); } } @Override public String toString() { return "CACHE["+ "bufferMap="+_bufferMap+ ",stringMap="+_stringMap+ ",index="+_index+ "]"; } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/BufferDateCache.java000066400000000000000000000030251174773561500267510ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.text.DateFormatSymbols; import java.util.Locale; import org.eclipse.jetty.util.DateCache; public class BufferDateCache extends DateCache { Buffer _buffer; String _last; public BufferDateCache() { super(); } public BufferDateCache(String format, DateFormatSymbols s) { super(format,s); } public BufferDateCache(String format, Locale l) { super(format,l); } public BufferDateCache(String format) { super(format); } public synchronized Buffer formatBuffer(long date) { String d = super.format(date); if (d==_last) return _buffer; _last=d; _buffer=new ByteArrayBuffer(d); return _buffer; } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/BufferUtil.java000066400000000000000000000221021174773561500260620ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.util.StringUtil; /* ------------------------------------------------------------------------------- */ /** Buffer utility methods. * * */ public class BufferUtil { static final byte SPACE= 0x20; static final byte MINUS= '-'; static final byte[] DIGIT= {(byte)'0',(byte)'1',(byte)'2',(byte)'3',(byte)'4',(byte)'5',(byte)'6',(byte)'7',(byte)'8',(byte)'9',(byte)'A',(byte)'B',(byte)'C',(byte)'D',(byte)'E',(byte)'F'}; /** * Convert buffer to an integer. * Parses up to the first non-numeric character. If no number is found an * IllegalArgumentException is thrown * @param buffer A buffer containing an integer. The position is not changed. * @return an int */ public static int toInt(Buffer buffer) { int val= 0; boolean started= false; boolean minus= false; for (int i= buffer.getIndex(); i < buffer.putIndex(); i++) { byte b= buffer.peek(i); if (b <= SPACE) { if (started) break; } else if (b >= '0' && b <= '9') { val= val * 10 + (b - '0'); started= true; } else if (b == MINUS && !started) { minus= true; } else break; } if (started) return minus ? (-val) : val; throw new NumberFormatException(buffer.toString()); } /** * Convert buffer to an long. * Parses up to the first non-numeric character. If no number is found an * IllegalArgumentException is thrown * @param buffer A buffer containing an integer. The position is not changed. * @return an int */ public static long toLong(Buffer buffer) { long val= 0; boolean started= false; boolean minus= false; for (int i= buffer.getIndex(); i < buffer.putIndex(); i++) { byte b= buffer.peek(i); if (b <= SPACE) { if (started) break; } else if (b >= '0' && b <= '9') { val= val * 10L + (b - '0'); started= true; } else if (b == MINUS && !started) { minus= true; } else break; } if (started) return minus ? (-val) : val; throw new NumberFormatException(buffer.toString()); } public static void putHexInt(Buffer buffer, int n) { if (n < 0) { buffer.put((byte)'-'); if (n == Integer.MIN_VALUE) { buffer.put((byte)(0x7f&'8')); buffer.put((byte)(0x7f&'0')); buffer.put((byte)(0x7f&'0')); buffer.put((byte)(0x7f&'0')); buffer.put((byte)(0x7f&'0')); buffer.put((byte)(0x7f&'0')); buffer.put((byte)(0x7f&'0')); buffer.put((byte)(0x7f&'0')); return; } n= -n; } if (n < 0x10) { buffer.put(DIGIT[n]); } else { boolean started= false; // This assumes constant time int arithmatic for (int i= 0; i < hexDivisors.length; i++) { if (n < hexDivisors[i]) { if (started) buffer.put((byte)'0'); continue; } started= true; int d= n / hexDivisors[i]; buffer.put(DIGIT[d]); n= n - d * hexDivisors[i]; } } } /* ------------------------------------------------------------ */ /** * Add hex integer BEFORE current getIndex. * @param buffer * @param n */ public static void prependHexInt(Buffer buffer, int n) { if (n==0) { int gi=buffer.getIndex(); buffer.poke(--gi,(byte)'0'); buffer.setGetIndex(gi); } else { boolean minus=false; if (n<0) { minus=true; n=-n; } int gi=buffer.getIndex(); while(n>0) { int d = 0xf&n; n=n>>4; buffer.poke(--gi,DIGIT[d]); } if (minus) buffer.poke(--gi,(byte)'-'); buffer.setGetIndex(gi); } } /* ------------------------------------------------------------ */ public static void putDecInt(Buffer buffer, int n) { if (n < 0) { buffer.put((byte)'-'); if (n == Integer.MIN_VALUE) { buffer.put((byte)'2'); n= 147483648; } else n= -n; } if (n < 10) { buffer.put(DIGIT[n]); } else { boolean started= false; // This assumes constant time int arithmatic for (int i= 0; i < decDivisors.length; i++) { if (n < decDivisors[i]) { if (started) buffer.put((byte)'0'); continue; } started= true; int d= n / decDivisors[i]; buffer.put(DIGIT[d]); n= n - d * decDivisors[i]; } } } public static void putDecLong(Buffer buffer, long n) { if (n < 0) { buffer.put((byte)'-'); if (n == Long.MIN_VALUE) { buffer.put((byte)'9'); n= 223372036854775808L; } else n= -n; } if (n < 10) { buffer.put(DIGIT[(int)n]); } else { boolean started= false; // This assumes constant time int arithmatic for (int i= 0; i < decDivisorsL.length; i++) { if (n < decDivisorsL[i]) { if (started) buffer.put((byte)'0'); continue; } started= true; long d= n / decDivisorsL[i]; buffer.put(DIGIT[(int)d]); n= n - d * decDivisorsL[i]; } } } public static Buffer toBuffer(long value) { ByteArrayBuffer buf=new ByteArrayBuffer(32); putDecLong(buf, value); return buf; } private final static int[] decDivisors= { 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 }; private final static int[] hexDivisors= { 0x10000000, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x1 }; private final static long[] decDivisorsL= { 1000000000000000000L, 100000000000000000L, 10000000000000000L, 1000000000000000L, 100000000000000L, 10000000000000L, 1000000000000L, 100000000000L, 10000000000L, 1000000000L, 100000000L, 10000000L, 1000000L, 100000L, 10000L, 1000L, 100L, 10L, 1L }; public static void putCRLF(Buffer buffer) { buffer.put((byte)13); buffer.put((byte)10); } public static boolean isPrefix(Buffer prefix,Buffer buffer) { if (prefix.length()>buffer.length()) return false; int bi=buffer.getIndex(); for (int i=prefix.getIndex(); i=0) return new PooledBuffers(headerType,headerSize,bufferType,bufferSize,otherType,maxSize); return new ThreadLocalBuffers(headerType,headerSize,bufferType,bufferSize,otherType); } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/ByteArrayBuffer.java000066400000000000000000000260731174773561500270620ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import org.eclipse.jetty.util.StringUtil; /* ------------------------------------------------------------------------------- */ /** * */ public class ByteArrayBuffer extends AbstractBuffer { final protected byte[] _bytes; protected ByteArrayBuffer(int size, int access, boolean isVolatile) { this(new byte[size],0,0,access, isVolatile); } public ByteArrayBuffer(byte[] bytes) { this(bytes, 0, bytes.length, READWRITE); } public ByteArrayBuffer(byte[] bytes, int index, int length) { this(bytes, index, length, READWRITE); } public ByteArrayBuffer(byte[] bytes, int index, int length, int access) { super(READWRITE, NON_VOLATILE); _bytes = bytes; setPutIndex(index + length); setGetIndex(index); _access = access; } public ByteArrayBuffer(byte[] bytes, int index, int length, int access, boolean isVolatile) { super(READWRITE, isVolatile); _bytes = bytes; setPutIndex(index + length); setGetIndex(index); _access = access; } public ByteArrayBuffer(int size) { this(new byte[size], 0, 0, READWRITE); setPutIndex(0); } public ByteArrayBuffer(String value) { super(READWRITE,NON_VOLATILE); _bytes = StringUtil.getBytes(value); setGetIndex(0); setPutIndex(_bytes.length); _access=IMMUTABLE; _string = value; } public ByteArrayBuffer(String value,boolean immutable) { super(READWRITE,NON_VOLATILE); _bytes = StringUtil.getBytes(value); setGetIndex(0); setPutIndex(_bytes.length); if (immutable) { _access=IMMUTABLE; _string = value; } } public ByteArrayBuffer(String value,String encoding) throws UnsupportedEncodingException { super(READWRITE,NON_VOLATILE); _bytes = value.getBytes(encoding); setGetIndex(0); setPutIndex(_bytes.length); _access=IMMUTABLE; _string = value; } public byte[] array() { return _bytes; } public int capacity() { return _bytes.length; } @Override public void compact() { if (isReadOnly()) throw new IllegalStateException(__READONLY); int s = markIndex() >= 0 ? markIndex() : getIndex(); if (s > 0) { int length = putIndex() - s; if (length > 0) { System.arraycopy(_bytes, s,_bytes, 0, length); } if (markIndex() > 0) setMarkIndex(markIndex() - s); setGetIndex(getIndex() - s); setPutIndex(putIndex() - s); } } @Override public boolean equals(Object obj) { if (obj==this) return true; if (obj == null || !(obj instanceof Buffer)) return false; if (obj instanceof Buffer.CaseInsensitve) return equalsIgnoreCase((Buffer)obj); Buffer b = (Buffer) obj; // reject different lengths if (b.length() != length()) return false; // reject AbstractBuffer with different hash value if (_hash != 0 && obj instanceof AbstractBuffer) { AbstractBuffer ab = (AbstractBuffer) obj; if (ab._hash != 0 && _hash != ab._hash) return false; } // Nothing for it but to do the hard grind. int get=getIndex(); int bi=b.putIndex(); for (int i = putIndex(); i-->get;) { byte b1 = _bytes[i]; byte b2 = b.peek(--bi); if (b1 != b2) return false; } return true; } @Override public boolean equalsIgnoreCase(Buffer b) { if (b==this) return true; // reject different lengths if (b==null || b.length() != length()) return false; // reject AbstractBuffer with different hash value if (_hash != 0 && b instanceof AbstractBuffer) { AbstractBuffer ab = (AbstractBuffer) b; if (ab._hash != 0 && _hash != ab._hash) return false; } // Nothing for it but to do the hard grind. int get=getIndex(); int bi=b.putIndex(); byte[] barray=b.array(); if (barray==null) { for (int i = putIndex(); i-->get;) { byte b1 = _bytes[i]; byte b2 = b.peek(--bi); if (b1 != b2) { if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A'); if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A'); if (b1 != b2) return false; } } } else { for (int i = putIndex(); i-->get;) { byte b1 = _bytes[i]; byte b2 = barray[--bi]; if (b1 != b2) { if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A'); if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A'); if (b1 != b2) return false; } } } return true; } @Override public byte get() { return _bytes[_get++]; } @Override public int hashCode() { if (_hash == 0 || _hashGet!=_get || _hashPut!=_put) { int get=getIndex(); for (int i = putIndex(); i-- >get;) { byte b = _bytes[i]; if ('a' <= b && b <= 'z') b = (byte) (b - 'a' + 'A'); _hash = 31 * _hash + b; } if (_hash == 0) _hash = -1; _hashGet=_get; _hashPut=_put; } return _hash; } public byte peek(int index) { return _bytes[index]; } public int peek(int index, byte[] b, int offset, int length) { int l = length; if (index + l > capacity()) { l = capacity() - index; if (l==0) return -1; } if (l < 0) return -1; System.arraycopy(_bytes, index, b, offset, l); return l; } public void poke(int index, byte b) { /* if (isReadOnly()) throw new IllegalStateException(__READONLY); if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0"); if (index > capacity()) throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity()); */ _bytes[index] = b; } @Override public int poke(int index, Buffer src) { _hash=0; /* if (isReadOnly()) throw new IllegalStateException(__READONLY); if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0"); */ int length=src.length(); if (index + length > capacity()) { length=capacity()-index; /* if (length<0) throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity()); */ } byte[] src_array = src.array(); if (src_array != null) System.arraycopy(src_array, src.getIndex(), _bytes, index, length); else { int s=src.getIndex(); for (int i=0;i capacity()) { length=capacity()-index; /* if (length<0) throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity()); */ } System.arraycopy(b, offset, _bytes, index, length); return length; } /* ------------------------------------------------------------ */ @Override public void writeTo(OutputStream out) throws IOException { out.write(_bytes,getIndex(),length()); if (!isImmutable()) clear(); } /* ------------------------------------------------------------ */ @Override public int readFrom(InputStream in,int max) throws IOException { if (max<0||max>space()) max=space(); int p = putIndex(); int len=0, total=0, available=max; while (total0) { p += len; total += len; available -= len; setPutIndex(p); } if (in.available()<=0) break; } if (len<0 && total==0) return -1; return total; } /* ------------------------------------------------------------ */ @Override public int space() { return _bytes.length - _put; } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ public static class CaseInsensitive extends ByteArrayBuffer implements Buffer.CaseInsensitve { public CaseInsensitive(String s) { super(s); } public CaseInsensitive(byte[] b, int o, int l, int rw) { super(b,o,l,rw); } @Override public boolean equals(Object obj) { return obj instanceof Buffer && equalsIgnoreCase((Buffer)obj); } } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/ByteArrayEndPoint.java000066400000000000000000000240041174773561500273610ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.io.IOException; /* ------------------------------------------------------------ */ /** ByteArrayEndPoint. * * */ public class ByteArrayEndPoint implements ConnectedEndPoint { protected byte[] _inBytes; protected ByteArrayBuffer _in; protected ByteArrayBuffer _out; protected boolean _closed; protected boolean _nonBlocking; protected boolean _growOutput; protected Connection _connection; protected int _maxIdleTime; /* ------------------------------------------------------------ */ /** * */ public ByteArrayEndPoint() { } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.io.ConnectedEndPoint#getConnection() */ public Connection getConnection() { return _connection; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.io.ConnectedEndPoint#setConnection(org.eclipse.jetty.io.Connection) */ public void setConnection(Connection connection) { _connection=connection; } /* ------------------------------------------------------------ */ /** * @return the nonBlocking */ public boolean isNonBlocking() { return _nonBlocking; } /* ------------------------------------------------------------ */ /** * @param nonBlocking the nonBlocking to set */ public void setNonBlocking(boolean nonBlocking) { _nonBlocking=nonBlocking; } /* ------------------------------------------------------------ */ /** * */ public ByteArrayEndPoint(byte[] input, int outputSize) { _inBytes=input; _in=new ByteArrayBuffer(input); _out=new ByteArrayBuffer(outputSize); } /* ------------------------------------------------------------ */ /** * @return Returns the in. */ public ByteArrayBuffer getIn() { return _in; } /* ------------------------------------------------------------ */ /** * @param in The in to set. */ public void setIn(ByteArrayBuffer in) { _in = in; } /* ------------------------------------------------------------ */ /** * @return Returns the out. */ public ByteArrayBuffer getOut() { return _out; } /* ------------------------------------------------------------ */ /** * @param out The out to set. */ public void setOut(ByteArrayBuffer out) { _out = out; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#isOpen() */ public boolean isOpen() { return !_closed; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.jetty.io.EndPoint#isInputShutdown() */ public boolean isInputShutdown() { return _closed; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.jetty.io.EndPoint#isOutputShutdown() */ public boolean isOutputShutdown() { return _closed; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#isBlocking() */ public boolean isBlocking() { return !_nonBlocking; } /* ------------------------------------------------------------ */ public boolean blockReadable(long millisecs) { return true; } /* ------------------------------------------------------------ */ public boolean blockWritable(long millisecs) { return true; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#shutdownOutput() */ public void shutdownOutput() throws IOException { close(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#shutdownInput() */ public void shutdownInput() throws IOException { close(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#close() */ public void close() throws IOException { _closed=true; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#fill(org.eclipse.io.Buffer) */ public int fill(Buffer buffer) throws IOException { if (_closed) throw new IOException("CLOSED"); if (_in!=null && _in.length()>0) { int len = buffer.put(_in); _in.skip(len); return len; } if (_in!=null && _in.length()==0 && _nonBlocking) return 0; close(); return -1; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#flush(org.eclipse.io.Buffer) */ public int flush(Buffer buffer) throws IOException { if (_closed) throw new IOException("CLOSED"); if (_growOutput && buffer.length()>_out.space()) { _out.compact(); if (buffer.length()>_out.space()) { ByteArrayBuffer n = new ByteArrayBuffer(_out.putIndex()+buffer.length()); n.put(_out.peek(0,_out.putIndex())); if (_out.getIndex()>0) { n.mark(); n.setGetIndex(_out.getIndex()); } _out=n; } } int len = _out.put(buffer); if (!buffer.isImmutable()) buffer.skip(len); return len; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#flush(org.eclipse.io.Buffer, org.eclipse.io.Buffer, org.eclipse.io.Buffer) */ public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException { if (_closed) throw new IOException("CLOSED"); int flushed=0; if (header!=null && header.length()>0) flushed=flush(header); if (header==null || header.length()==0) { if (buffer!=null && buffer.length()>0) flushed+=flush(buffer); if (buffer==null || buffer.length()==0) { if (trailer!=null && trailer.length()>0) { flushed+=flush(trailer); } } } return flushed; } /* ------------------------------------------------------------ */ /** * */ public void reset() { _closed=false; _in.clear(); _out.clear(); if (_inBytes!=null) _in.setPutIndex(_inBytes.length); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalAddr() */ public String getLocalAddr() { return null; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalHost() */ public String getLocalHost() { return null; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalPort() */ public int getLocalPort() { return 0; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemoteAddr() */ public String getRemoteAddr() { return null; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemoteHost() */ public String getRemoteHost() { return null; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemotePort() */ public int getRemotePort() { return 0; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getConnection() */ public Object getTransport() { return _inBytes; } /* ------------------------------------------------------------ */ public void flush() throws IOException { } /* ------------------------------------------------------------ */ /** * @return the growOutput */ public boolean isGrowOutput() { return _growOutput; } /* ------------------------------------------------------------ */ /** * @param growOutput the growOutput to set */ public void setGrowOutput(boolean growOutput) { _growOutput=growOutput; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.io.EndPoint#getMaxIdleTime() */ public int getMaxIdleTime() { return _maxIdleTime; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.io.EndPoint#setMaxIdleTime(int) */ public void setMaxIdleTime(int timeMs) throws IOException { _maxIdleTime=timeMs; } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectedEndPoint.java000066400000000000000000000002461174773561500273630ustar00rootroot00000000000000package org.eclipse.jetty.io; public interface ConnectedEndPoint extends EndPoint { Connection getConnection(); void setConnection(Connection connection); } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java000066400000000000000000000052511174773561500261200ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.io.IOException; /* ------------------------------------------------------------ */ /** Abstract Connection used by Jetty Connectors. *

    * Jetty will call the handle method of a connection when there is work * to be done on the connection. For blocking connections, this is soon * as the connection is open and handle will keep being called until the * connection is closed. For non-blocking connections, handle will only * be called if there are bytes to be read or the connection becomes writable * after being write blocked. * * @see org.eclipse.jetty.io.nio.SelectorManager */ public interface Connection { /* ------------------------------------------------------------ */ /** * Handle the connection. * @return The Connection to use for the next handling of the connection. * This allows protocol upgrades and support for CONNECT. * @throws IOException if the handling of I/O operations fail */ Connection handle() throws IOException; /** * @return the timestamp at which the connection was created */ long getTimeStamp(); /** * @return whether this connection is idle, that is not parsing and not generating * @see #onIdleExpired(long) */ boolean isIdle(); /** *

    The semantic of this method is to return true to indicate interest in further reads, * or false otherwise, but it is misnamed and should be really called isReadInterested().

    * * @return true to indicate interest in further reads, false otherwise */ // TODO: rename to isReadInterested() in the next release boolean isSuspended(); /** * Called after the connection is closed */ void onClose(); /** * Called when the connection idle timeout expires * @param idleForMs how long the connection has been idle * @see #isIdle() */ void onIdleExpired(long idleForMs); } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/EndPoint.java000066400000000000000000000156411174773561500255450ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.io.IOException; /** * * A transport EndPoint */ public interface EndPoint { /** * Shutdown any backing output stream associated with the endpoint */ void shutdownOutput() throws IOException; boolean isOutputShutdown(); /** * Shutdown any backing input stream associated with the endpoint */ void shutdownInput() throws IOException; boolean isInputShutdown(); /** * Close any backing stream associated with the endpoint */ void close() throws IOException; /** * Fill the buffer from the current putIndex to it's capacity from whatever * byte source is backing the buffer. The putIndex is increased if bytes filled. * The buffer may chose to do a compact before filling. * @return an int value indicating the number of bytes * filled or -1 if EOF is reached. * @throws EofException If input is shutdown or the endpoint is closed. */ int fill(Buffer buffer) throws IOException; /** * Flush the buffer from the current getIndex to it's putIndex using whatever byte * sink is backing the buffer. The getIndex is updated with the number of bytes flushed. * Any mark set is cleared. * If the entire contents of the buffer are flushed, then an implicit empty() is done. * * @param buffer The buffer to flush. This buffers getIndex is updated. * @return the number of bytes written * @throws EofException If the endpoint is closed or output is shutdown. */ int flush(Buffer buffer) throws IOException; /** * Flush the buffer from the current getIndex to it's putIndex using whatever byte * sink is backing the buffer. The getIndex is updated with the number of bytes flushed. * Any mark set is cleared. * If the entire contents of the buffer are flushed, then an implicit empty() is done. * The passed header/trailer buffers are written before/after the contents of this buffer. This may be done * either as gather writes, as a poke into this buffer or as several writes. The implementation is free to * select the optimal mechanism. * @param header A buffer to write before flushing this buffer. This buffers getIndex is updated. * @param buffer The buffer to flush. This buffers getIndex is updated. * @param trailer A buffer to write after flushing this buffer. This buffers getIndex is updated. * @return the total number of bytes written. */ int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException; /* ------------------------------------------------------------ */ /** * @return The local IP address to which this EndPoint is bound, or null * if this EndPoint does not represent a network connection. */ public String getLocalAddr(); /* ------------------------------------------------------------ */ /** * @return The local host name to which this EndPoint is bound, or null * if this EndPoint does not represent a network connection. */ public String getLocalHost(); /* ------------------------------------------------------------ */ /** * @return The local port number on which this EndPoint is listening, or 0 * if this EndPoint does not represent a network connection. */ public int getLocalPort(); /* ------------------------------------------------------------ */ /** * @return The remote IP address to which this EndPoint is connected, or null * if this EndPoint does not represent a network connection. */ public String getRemoteAddr(); /* ------------------------------------------------------------ */ /** * @return The host name of the remote machine to which this EndPoint is connected, or null * if this EndPoint does not represent a network connection. */ public String getRemoteHost(); /* ------------------------------------------------------------ */ /** * @return The remote port number to which this EndPoint is connected, or 0 * if this EndPoint does not represent a network connection. */ public int getRemotePort(); /* ------------------------------------------------------------ */ public boolean isBlocking(); /* ------------------------------------------------------------ */ public boolean blockReadable(long millisecs) throws IOException; /* ------------------------------------------------------------ */ public boolean blockWritable(long millisecs) throws IOException; /* ------------------------------------------------------------ */ public boolean isOpen(); /* ------------------------------------------------------------ */ /** * @return The underlying transport object (socket, channel, etc.) */ public Object getTransport(); /* ------------------------------------------------------------ */ /** Flush any buffered output. * May fail to write all data if endpoint is non-blocking * @throws EofException If the endpoint is closed or output is shutdown. */ public void flush() throws IOException; /* ------------------------------------------------------------ */ /** Get the max idle time in ms. *

    The max idle time is the time the endpoint can be idle before * extraordinary handling takes place. This loosely corresponds to * the {@link java.net.Socket#getSoTimeout()} for blocking connections, * but {@link AsyncEndPoint} implementations must use other mechanisms * to implement the max idle time. * @return the max idle time in ms or if ms <= 0 implies an infinite timeout */ public int getMaxIdleTime(); /* ------------------------------------------------------------ */ /** Set the max idle time. * @param timeMs the max idle time in MS. Timeout <= 0 implies an infinite timeout * @throws IOException if the timeout cannot be set. */ public void setMaxIdleTime(int timeMs) throws IOException; } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/EofException.java000066400000000000000000000026551174773561500264160ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.io.EOFException; /* ------------------------------------------------------------ */ /** A Jetty specialization of EOFException. *

    This is thrown by Jetty to distinguish between EOF received from * the connection, vs and EOF thrown by some application talking to some other file/socket etc. * The only difference in handling is that Jetty EOFs are logged less verbosely. */ public class EofException extends EOFException { public EofException() { } public EofException(String reason) { super(reason); } public EofException(Throwable th) { if (th!=null) initCause(th); } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/NetworkTrafficListener.java000066400000000000000000000075021174773561500304600ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2011 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.net.Socket; /** *

    A listener for raw network traffic within Jetty.

    *

    {@link NetworkTrafficListener}s can be installed in a * org.eclipse.jetty.server.nio.NetworkTrafficSelectChannelConnector, * and are notified of the following network traffic events:

    *
      *
    • Connection opened, when the server has accepted the connection from a remote client
    • *
    • Incoming bytes, when the server receives bytes sent from a remote client
    • *
    • Outgoing bytes, when the server sends bytes to a remote client
    • *
    • Connection closed, when the server has closed the connection to a remote client
    • *
    *

    {@link NetworkTrafficListener}s can be used to log the network traffic viewed by * a Jetty server (for example logging to filesystem) for activities such as debugging * or request/response cycles or for replaying request/response cycles to other servers.

    */ public interface NetworkTrafficListener { /** *

    Callback method invoked when a connection from a remote client has been accepted.

    *

    The {@code socket} parameter can be used to extract socket address information of * the remote client.

    * * @param socket the socket associated with the remote client */ public void opened(Socket socket); /** *

    Callback method invoked when bytes sent by a remote client arrived on the server.

    * * @param socket the socket associated with the remote client * @param bytes the read-only buffer containing the incoming bytes */ public void incoming(Socket socket, Buffer bytes); /** *

    Callback method invoked when bytes are sent to a remote client from the server.

    *

    This method is invoked after the bytes have been actually written to the remote client.

    * * @param socket the socket associated with the remote client * @param bytes the read-only buffer containing the outgoing bytes */ public void outgoing(Socket socket, Buffer bytes); /** *

    Callback method invoked when a connection to a remote client has been closed.

    *

    The {@code socket} parameter is already closed when this method is called, so it * cannot be queried for socket address information of the remote client.
    * However, the {@code socket} parameter is the same object passed to {@link #opened(Socket)}, * so it is possible to map socket information in {@link #opened(Socket)} and retrieve it * in this method. * * @param socket the (closed) socket associated with the remote client */ public void closed(Socket socket); /** *

    A commodity class that implements {@link NetworkTrafficListener} with empty methods.

    */ public static class Empty implements NetworkTrafficListener { public void opened(Socket socket) { } public void incoming(Socket socket, Buffer bytes) { } public void outgoing(Socket socket, Buffer bytes) { } public void closed(Socket socket) { } } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/PooledBuffers.java000066400000000000000000000062441174773561500265630ustar00rootroot00000000000000package org.eclipse.jetty.io; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; public class PooledBuffers extends AbstractBuffers { private final Queue _headers; private final Queue _buffers; private final Queue _others; private final AtomicInteger _size = new AtomicInteger(); private final int _maxSize; private final boolean _otherHeaders; private final boolean _otherBuffers; /* ------------------------------------------------------------ */ public PooledBuffers(Buffers.Type headerType, int headerSize, Buffers.Type bufferType, int bufferSize, Buffers.Type otherType,int maxSize) { super(headerType,headerSize,bufferType,bufferSize,otherType); _headers=new ConcurrentLinkedQueue(); _buffers=new ConcurrentLinkedQueue(); _others=new ConcurrentLinkedQueue(); _otherHeaders=headerType==otherType; _otherBuffers=bufferType==otherType; _maxSize=maxSize; } /* ------------------------------------------------------------ */ public Buffer getHeader() { Buffer buffer = _headers.poll(); if (buffer==null) buffer=newHeader(); else _size.decrementAndGet(); return buffer; } /* ------------------------------------------------------------ */ public Buffer getBuffer() { Buffer buffer = _buffers.poll(); if (buffer==null) buffer=newBuffer(); else _size.decrementAndGet(); return buffer; } /* ------------------------------------------------------------ */ public Buffer getBuffer(int size) { if (_otherHeaders && size==getHeaderSize()) return getHeader(); if (_otherBuffers && size==getBufferSize()) return getBuffer(); // Look for an other buffer Buffer buffer = _others.poll(); // consume all other buffers until one of the right size is found while (buffer!=null && buffer.capacity()!=size) { _size.decrementAndGet(); buffer = _others.poll(); } if (buffer==null) buffer=newBuffer(size); else _size.decrementAndGet(); return buffer; } /* ------------------------------------------------------------ */ public void returnBuffer(Buffer buffer) { buffer.clear(); if (buffer.isVolatile() || buffer.isImmutable()) return; if (_size.incrementAndGet() > _maxSize) _size.decrementAndGet(); else { if (isHeader(buffer)) _headers.add(buffer); else if (isBuffer(buffer)) _buffers.add(buffer); else _others.add(buffer); } } public String toString() { return String.format("%s [%d/%d@%d,%d/%d@%d,%d/%d@-]", getClass().getSimpleName(), _headers.size(),_maxSize,_headerSize, _buffers.size(),_maxSize,_bufferSize, _others.size(),_maxSize); } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/RuntimeIOException.java000066400000000000000000000026041174773561500275520ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; /* ------------------------------------------------------------ */ /** * Subclass of {@link java.lang.RuntimeException} used to signal that there * was an {@link java.io.IOException} thrown by underlying {@link java.io.Writer} */ public class RuntimeIOException extends RuntimeException { public RuntimeIOException() { super(); } public RuntimeIOException(String message) { super(message); } public RuntimeIOException(Throwable cause) { super(cause); } public RuntimeIOException(String message, Throwable cause) { super(message,cause); } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/SimpleBuffers.java000066400000000000000000000064371174773561500265760ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; /* ------------------------------------------------------------ */ /** SimpleBuffers. * Simple implementation of Buffers holder. * * */ public class SimpleBuffers implements Buffers { final Buffer _header; final Buffer _buffer; boolean _headerOut; boolean _bufferOut; /* ------------------------------------------------------------ */ /** * */ public SimpleBuffers(Buffer header, Buffer buffer) { _header=header; _buffer=buffer; } /* ------------------------------------------------------------ */ public Buffer getBuffer() { synchronized(this) { if (_buffer!=null && !_bufferOut) { _bufferOut=true; return _buffer; } if (_buffer!=null && _header!=null && _header.capacity()==_buffer.capacity() && !_headerOut) { _headerOut=true; return _header; } if (_buffer!=null) return new ByteArrayBuffer(_buffer.capacity()); return new ByteArrayBuffer(4096); } } /* ------------------------------------------------------------ */ public Buffer getHeader() { synchronized(this) { if (_header!=null && !_headerOut) { _headerOut=true; return _header; } if (_buffer!=null && _header!=null && _header.capacity()==_buffer.capacity() && !_bufferOut) { _bufferOut=true; return _buffer; } if (_header!=null) return new ByteArrayBuffer(_header.capacity()); return new ByteArrayBuffer(4096); } } /* ------------------------------------------------------------ */ public Buffer getBuffer(int size) { synchronized(this) { if (_header!=null && _header.capacity()==size) return getHeader(); if (_buffer!=null && _buffer.capacity()==size) return getBuffer(); return null; } } /* ------------------------------------------------------------ */ public void returnBuffer(Buffer buffer) { synchronized(this) { buffer.clear(); if (buffer==_header) _headerOut=false; if (buffer==_buffer) _bufferOut=false; } } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/ThreadLocalBuffers.java000066400000000000000000000076571174773561500275340ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; /* ------------------------------------------------------------ */ /** Abstract Buffer pool. * simple unbounded pool of buffers for header, request and response sizes. * */ public class ThreadLocalBuffers extends AbstractBuffers { /* ------------------------------------------------------------ */ private final ThreadLocal _buffers=new ThreadLocal() { @Override protected ThreadBuffers initialValue() { return new ThreadBuffers(); } }; /* ------------------------------------------------------------ */ public ThreadLocalBuffers(Buffers.Type headerType, int headerSize, Buffers.Type bufferType, int bufferSize, Buffers.Type otherType) { super(headerType,headerSize,bufferType,bufferSize,otherType); } /* ------------------------------------------------------------ */ public Buffer getBuffer() { ThreadBuffers buffers = _buffers.get(); if (buffers._buffer!=null) { Buffer b=buffers._buffer; buffers._buffer=null; return b; } if (buffers._other!=null && isBuffer(buffers._other)) { Buffer b=buffers._other; buffers._other=null; return b; } return newBuffer(); } /* ------------------------------------------------------------ */ public Buffer getHeader() { ThreadBuffers buffers = _buffers.get(); if (buffers._header!=null) { Buffer b=buffers._header; buffers._header=null; return b; } if (buffers._other!=null && isHeader(buffers._other)) { Buffer b=buffers._other; buffers._other=null; return b; } return newHeader(); } /* ------------------------------------------------------------ */ public Buffer getBuffer(int size) { ThreadBuffers buffers = _buffers.get(); if (buffers._other!=null && buffers._other.capacity()==size) { Buffer b=buffers._other; buffers._other=null; return b; } return newBuffer(size); } /* ------------------------------------------------------------ */ public void returnBuffer(Buffer buffer) { buffer.clear(); if (buffer.isVolatile() || buffer.isImmutable()) return; ThreadBuffers buffers = _buffers.get(); if (buffers._header==null && isHeader(buffer)) buffers._header=buffer; else if (buffers._buffer==null && isBuffer(buffer)) buffers._buffer=buffer; else buffers._other=buffer; } /* ------------------------------------------------------------ */ @Override public String toString() { return "{{"+getHeaderSize()+","+getBufferSize()+"}}"; } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ protected static class ThreadBuffers { Buffer _buffer; Buffer _header; Buffer _other; } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/UncheckedIOException.java000066400000000000000000000026241174773561500300220ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; /* ------------------------------------------------------------ */ /** * Subclass of {@link java.lang.RuntimeException} used to signal that there * was an {@link java.io.IOException} thrown by underlying {@link UncheckedPrintWriter} */ public class UncheckedIOException extends RuntimeException { public UncheckedIOException() { super(); } public UncheckedIOException(String message) { super(message); } public UncheckedIOException(Throwable cause) { super(cause); } public UncheckedIOException(String message, Throwable cause) { super(message,cause); } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/UncheckedPrintWriter.java000066400000000000000000000464341174773561500301340ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.io.BufferedWriter; import java.io.IOException; import java.io.InterruptedIOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Writer; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ /** * A wrapper for the {@link java.io.PrintWriter} that re-throws the instances of * {@link java.io.IOException} thrown by the underlying implementation of * {@link java.io.Writer} as {@link RuntimeIOException} instances. */ public class UncheckedPrintWriter extends PrintWriter { private static final Logger LOG = Log.getLogger(UncheckedPrintWriter.class); private boolean _autoFlush = false; private IOException _ioException; private boolean _isClosed = false; /* ------------------------------------------------------------ */ /** * Line separator string. This is the value of the line.separator property * at the moment that the stream was created. */ private String _lineSeparator; public UncheckedPrintWriter(Writer out) { this(out,false); } /* ------------------------------------------------------------ */ /** * Create a new PrintWriter. * * @param out * A character-output stream * @param autoFlush * A boolean; if true, the println() methods will flush the * output buffer */ public UncheckedPrintWriter(Writer out, boolean autoFlush) { super(out,autoFlush); this._autoFlush = autoFlush; this._lineSeparator = System.getProperty("line.separator"); } /* ------------------------------------------------------------ */ /** * Create a new PrintWriter, without automatic line flushing, from an * existing OutputStream. This convenience constructor creates the necessary * intermediate OutputStreamWriter, which will convert characters into bytes * using the default character encoding. * * @param out * An output stream * * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) */ public UncheckedPrintWriter(OutputStream out) { this(out,false); } /* ------------------------------------------------------------ */ /** * Create a new PrintWriter from an existing OutputStream. This convenience * constructor creates the necessary intermediate OutputStreamWriter, which * will convert characters into bytes using the default character encoding. * * @param out * An output stream * @param autoFlush * A boolean; if true, the println() methods will flush the * output buffer * * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) */ public UncheckedPrintWriter(OutputStream out, boolean autoFlush) { this(new BufferedWriter(new OutputStreamWriter(out)),autoFlush); } /* ------------------------------------------------------------ */ public boolean checkError() { return _ioException!=null || super.checkError(); } /* ------------------------------------------------------------ */ private void setError(Throwable th) { super.setError(); if (th instanceof IOException) _ioException=(IOException)th; else { _ioException=new IOException(String.valueOf(th)); _ioException.initCause(th); } LOG.debug(th); } @Override protected void setError() { setError(new IOException()); } /* ------------------------------------------------------------ */ /** Check to make sure that the stream has not been closed */ private void isOpen() throws IOException { if (_ioException!=null) throw new RuntimeIOException(_ioException); if (_isClosed) throw new IOException("Stream closed"); } /* ------------------------------------------------------------ */ /** * Flush the stream. */ @Override public void flush() { try { synchronized (lock) { isOpen(); out.flush(); } } catch (IOException ex) { setError(ex); } } /* ------------------------------------------------------------ */ /** * Close the stream. */ @Override public void close() { try { synchronized (lock) { out.close(); _isClosed = true; } } catch (IOException ex) { setError(ex); } } /* ------------------------------------------------------------ */ /** * Write a single character. * * @param c * int specifying a character to be written. */ @Override public void write(int c) { try { synchronized (lock) { isOpen(); out.write(c); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); } catch (IOException ex) { setError(ex); } } /* ------------------------------------------------------------ */ /** * Write a portion of an array of characters. * * @param buf * Array of characters * @param off * Offset from which to start writing characters * @param len * Number of characters to write */ @Override public void write(char buf[], int off, int len) { try { synchronized (lock) { isOpen(); out.write(buf,off,len); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); } catch (IOException ex) { setError(ex); } } /* ------------------------------------------------------------ */ /** * Write an array of characters. This method cannot be inherited from the * Writer class because it must suppress I/O exceptions. * * @param buf * Array of characters to be written */ @Override public void write(char buf[]) { this.write(buf,0,buf.length); } /* ------------------------------------------------------------ */ /** * Write a portion of a string. * * @param s * A String * @param off * Offset from which to start writing characters * @param len * Number of characters to write */ @Override public void write(String s, int off, int len) { try { synchronized (lock) { isOpen(); out.write(s,off,len); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); } catch (IOException ex) { setError(ex); } } /* ------------------------------------------------------------ */ /** * Write a string. This method cannot be inherited from the Writer class * because it must suppress I/O exceptions. * * @param s * String to be written */ @Override public void write(String s) { this.write(s,0,s.length()); } private void newLine() { try { synchronized (lock) { isOpen(); out.write(_lineSeparator); if (_autoFlush) out.flush(); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); } catch (IOException ex) { setError(ex); } } /* ------------------------------------------------------------ */ /** * Print a boolean value. The string produced by {@link * java.lang.String#valueOf(boolean)} is translated into bytes * according to the platform's default character encoding, and these bytes * are written in exactly the manner of the {@link * #write(int)} method. * * @param b * The boolean to be printed */ @Override public void print(boolean b) { this.write(b?"true":"false"); } /* ------------------------------------------------------------ */ /** * Print a character. The character is translated into one or more bytes * according to the platform's default character encoding, and these bytes * are written in exactly the manner of the {@link * #write(int)} method. * * @param c * The char to be printed */ @Override public void print(char c) { this.write(c); } /* ------------------------------------------------------------ */ /** * Print an integer. The string produced by {@link * java.lang.String#valueOf(int)} is translated into bytes according * to the platform's default character encoding, and these bytes are written * in exactly the manner of the {@link #write(int)} method. * * @param i * The int to be printed * @see java.lang.Integer#toString(int) */ @Override public void print(int i) { this.write(String.valueOf(i)); } /* ------------------------------------------------------------ */ /** * Print a long integer. The string produced by {@link * java.lang.String#valueOf(long)} is translated into bytes according * to the platform's default character encoding, and these bytes are written * in exactly the manner of the {@link #write(int)} method. * * @param l * The long to be printed * @see java.lang.Long#toString(long) */ @Override public void print(long l) { this.write(String.valueOf(l)); } /* ------------------------------------------------------------ */ /** * Print a floating-point number. The string produced by {@link * java.lang.String#valueOf(float)} is translated into bytes * according to the platform's default character encoding, and these bytes * are written in exactly the manner of the {@link #write(int)} * method. * * @param f * The float to be printed * @see java.lang.Float#toString(float) */ @Override public void print(float f) { this.write(String.valueOf(f)); } /* ------------------------------------------------------------ */ /** * Print a double-precision floating-point number. The string produced by * {@link java.lang.String#valueOf(double)} is translated into * bytes according to the platform's default character encoding, and these * bytes are written in exactly the manner of the {@link * #write(int)} method. * * @param d * The double to be printed * @see java.lang.Double#toString(double) */ @Override public void print(double d) { this.write(String.valueOf(d)); } /* ------------------------------------------------------------ */ /** * Print an array of characters. The characters are converted into bytes * according to the platform's default character encoding, and these bytes * are written in exactly the manner of the {@link #write(int)} * method. * * @param s * The array of chars to be printed * * @throws NullPointerException * If s is null */ @Override public void print(char s[]) { this.write(s); } /* ------------------------------------------------------------ */ /** * Print a string. If the argument is null then the string * "null" is printed. Otherwise, the string's characters are * converted into bytes according to the platform's default character * encoding, and these bytes are written in exactly the manner of the * {@link #write(int)} method. * * @param s * The String to be printed */ @Override public void print(String s) { if (s == null) { s = "null"; } this.write(s); } /* ------------------------------------------------------------ */ /** * Print an object. The string produced by the {@link * java.lang.String#valueOf(Object)} method is translated into bytes * according to the platform's default character encoding, and these bytes * are written in exactly the manner of the {@link #write(int)} * method. * * @param obj * The Object to be printed * @see java.lang.Object#toString() */ @Override public void print(Object obj) { this.write(String.valueOf(obj)); } /* ------------------------------------------------------------ */ /** * Terminate the current line by writing the line separator string. The line * separator string is defined by the system property * line.separator, and is not necessarily a single newline * character ('\n'). */ @Override public void println() { this.newLine(); } /* ------------------------------------------------------------ */ /** * Print a boolean value and then terminate the line. This method behaves as * though it invokes {@link #print(boolean)} and then * {@link #println()}. * * @param x * the boolean value to be printed */ @Override public void println(boolean x) { synchronized (lock) { this.print(x); this.println(); } } /* ------------------------------------------------------------ */ /** * Print a character and then terminate the line. This method behaves as * though it invokes {@link #print(char)} and then {@link * #println()}. * * @param x * the char value to be printed */ @Override public void println(char x) { synchronized (lock) { this.print(x); this.println(); } } /* ------------------------------------------------------------ */ /** * Print an integer and then terminate the line. This method behaves as * though it invokes {@link #print(int)} and then {@link * #println()}. * * @param x * the int value to be printed */ @Override public void println(int x) { synchronized (lock) { this.print(x); this.println(); } } /* ------------------------------------------------------------ */ /** * Print a long integer and then terminate the line. This method behaves as * though it invokes {@link #print(long)} and then * {@link #println()}. * * @param x * the long value to be printed */ @Override public void println(long x) { synchronized (lock) { this.print(x); this.println(); } } /* ------------------------------------------------------------ */ /** * Print a floating-point number and then terminate the line. This method * behaves as though it invokes {@link #print(float)} and then * {@link #println()}. * * @param x * the float value to be printed */ @Override public void println(float x) { synchronized (lock) { this.print(x); this.println(); } } /* ------------------------------------------------------------ */ /** * Print a double-precision floating-point number and then terminate the * line. This method behaves as though it invokes {@link * #print(double)} and then {@link #println()}. * * @param x * the double value to be printed */ /* ------------------------------------------------------------ */ @Override public void println(double x) { synchronized (lock) { this.print(x); this.println(); } } /* ------------------------------------------------------------ */ /** * Print an array of characters and then terminate the line. This method * behaves as though it invokes {@link #print(char[])} and then * {@link #println()}. * * @param x * the array of char values to be printed */ @Override public void println(char x[]) { synchronized (lock) { this.print(x); this.println(); } } /* ------------------------------------------------------------ */ /** * Print a String and then terminate the line. This method behaves as though * it invokes {@link #print(String)} and then * {@link #println()}. * * @param x * the String value to be printed */ @Override public void println(String x) { synchronized (lock) { this.print(x); this.println(); } } /* ------------------------------------------------------------ */ /** * Print an Object and then terminate the line. This method behaves as * though it invokes {@link #print(Object)} and then * {@link #println()}. * * @param x * the Object value to be printed */ @Override public void println(Object x) { synchronized (lock) { this.print(x); this.println(); } } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/View.java000066400000000000000000000136361174773561500247410ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; /** * A View on another buffer. Allows operations that do not change the _content or * indexes of the backing buffer. * * * */ public class View extends AbstractBuffer { Buffer _buffer; /** * @param buffer The Buffer on which we are presenting a View. * @param mark The initial value of the {@link Buffer#markIndex mark index} * @param get The initial value of the {@link Buffer#getIndex get index} * @param put The initial value of the {@link Buffer#putIndex put index} * @param access The access level - one of the constants from {@link Buffer}. */ public View(Buffer buffer, int mark, int get, int put,int access) { super(READWRITE,!buffer.isImmutable()); _buffer=buffer.buffer(); setPutIndex(put); setGetIndex(get); setMarkIndex(mark); _access=access; } public View(Buffer buffer) { super(READWRITE,!buffer.isImmutable()); _buffer=buffer.buffer(); setPutIndex(buffer.putIndex()); setGetIndex(buffer.getIndex()); setMarkIndex(buffer.markIndex()); _access=buffer.isReadOnly()?READONLY:READWRITE; } public View() { super(READWRITE,true); } /** * Update view to buffer */ public void update(Buffer buffer) { _access=READWRITE; _buffer=buffer.buffer(); setGetIndex(0); setPutIndex(buffer.putIndex()); setGetIndex(buffer.getIndex()); setMarkIndex(buffer.markIndex()); _access=buffer.isReadOnly()?READONLY:READWRITE; } public void update(int get, int put) { int a=_access; _access=READWRITE; setGetIndex(0); setPutIndex(put); setGetIndex(get); setMarkIndex(-1); _access=a; } /** * @return The {@link Buffer#array()} from the underlying buffer. */ public byte[] array() { return _buffer.array(); } /** * @return The {@link Buffer#buffer()} from the underlying buffer. */ @Override public Buffer buffer() { return _buffer.buffer(); } /** * @return The {@link Buffer#capacity} of the underlying buffer. */ public int capacity() { return _buffer.capacity(); } /** * */ @Override public void clear() { setMarkIndex(-1); setGetIndex(0); setPutIndex(_buffer.getIndex()); setGetIndex(_buffer.getIndex()); } /** * */ @Override public void compact() { // TODO } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { return this==obj ||((obj instanceof Buffer)&& obj.equals(this)) || super.equals(obj); } /** * @return Whether the underlying buffer is {@link Buffer#isReadOnly read only} */ @Override public boolean isReadOnly() { return _buffer.isReadOnly(); } /** * @return Whether the underlying buffer is {@link Buffer#isVolatile volatile} */ @Override public boolean isVolatile() { return true; } /** * @return The result of calling {@link Buffer#peek(int)} on the underlying buffer */ public byte peek(int index) { return _buffer.peek(index); } /** * @return The result of calling {@link Buffer#peek(int, byte[], int, int)} on the underlying buffer */ public int peek(int index, byte[] b, int offset, int length) { return _buffer.peek(index,b,offset,length); } /** * @return The result of calling {@link Buffer#peek(int, int)} on the underlying buffer */ @Override public Buffer peek(int index, int length) { return _buffer.peek(index, length); } /** * @param index * @param src */ @Override public int poke(int index, Buffer src) { return _buffer.poke(index,src); } /** * @param index * @param b */ public void poke(int index, byte b) { _buffer.poke(index,b); } /** * @param index * @param b * @param offset * @param length */ @Override public int poke(int index, byte[] b, int offset, int length) { return _buffer.poke(index,b,offset,length); } @Override public String toString() { if (_buffer==null) return "INVALID"; return super.toString(); } public static class CaseInsensitive extends View implements Buffer.CaseInsensitve { public CaseInsensitive() { super(); } public CaseInsensitive(Buffer buffer, int mark, int get, int put, int access) { super(buffer,mark,get,put,access); } public CaseInsensitive(Buffer buffer) { super(buffer); } @Override public boolean equals(Object obj) { return this==obj ||((obj instanceof Buffer)&&((Buffer)obj).equalsIgnoreCase(this)) || super.equals(obj); } } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/WriterOutputStream.java000066400000000000000000000055321174773561500276740ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; /* ------------------------------------------------------------ */ /** Wrap a Writer as an OutputStream. * When all you have is a Writer and only an OutputStream will do. * Try not to use this as it indicates that your design is a dogs * breakfast (JSP made me write it). * */ public class WriterOutputStream extends OutputStream { protected final Writer _writer; protected final String _encoding; private final byte[] _buf=new byte[1]; /* ------------------------------------------------------------ */ public WriterOutputStream(Writer writer, String encoding) { _writer=writer; _encoding=encoding; } /* ------------------------------------------------------------ */ public WriterOutputStream(Writer writer) { _writer=writer; _encoding=null; } /* ------------------------------------------------------------ */ @Override public void close() throws IOException { _writer.close(); } /* ------------------------------------------------------------ */ @Override public void flush() throws IOException { _writer.flush(); } /* ------------------------------------------------------------ */ @Override public void write(byte[] b) throws IOException { if (_encoding==null) _writer.write(new String(b)); else _writer.write(new String(b,_encoding)); } /* ------------------------------------------------------------ */ @Override public void write(byte[] b, int off, int len) throws IOException { if (_encoding==null) _writer.write(new String(b,off,len)); else _writer.write(new String(b,off,len,_encoding)); } /* ------------------------------------------------------------ */ @Override public synchronized void write(int b) throws IOException { _buf[0]=(byte)b; write(_buf); } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/bio/000077500000000000000000000000001174773561500237245ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/bio/SocketEndPoint.java000066400000000000000000000174051174773561500274670ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2010 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.bio; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import javax.net.ssl.SSLSocket; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public class SocketEndPoint extends StreamEndPoint { private static final Logger LOG = Log.getLogger(SocketEndPoint.class); final Socket _socket; final InetSocketAddress _local; final InetSocketAddress _remote; /* ------------------------------------------------------------ */ /** * */ public SocketEndPoint(Socket socket) throws IOException { super(socket.getInputStream(),socket.getOutputStream()); _socket=socket; _local=(InetSocketAddress)_socket.getLocalSocketAddress(); _remote=(InetSocketAddress)_socket.getRemoteSocketAddress(); super.setMaxIdleTime(_socket.getSoTimeout()); } /* ------------------------------------------------------------ */ /** * */ protected SocketEndPoint(Socket socket, int maxIdleTime) throws IOException { super(socket.getInputStream(),socket.getOutputStream()); _socket=socket; _local=(InetSocketAddress)_socket.getLocalSocketAddress(); _remote=(InetSocketAddress)_socket.getRemoteSocketAddress(); _socket.setSoTimeout(maxIdleTime>0?maxIdleTime:0); super.setMaxIdleTime(maxIdleTime); } /* ------------------------------------------------------------ */ /* (non-Javadoc) * @see org.eclipse.io.BufferIO#isClosed() */ @Override public boolean isOpen() { return super.isOpen() && _socket!=null && !_socket.isClosed(); } /* ------------------------------------------------------------ */ @Override public boolean isInputShutdown() { if (_socket instanceof SSLSocket) return super.isInputShutdown(); return _socket.isClosed() || _socket.isInputShutdown(); } /* ------------------------------------------------------------ */ @Override public boolean isOutputShutdown() { if (_socket instanceof SSLSocket) return super.isOutputShutdown(); return _socket.isClosed() || _socket.isOutputShutdown(); } /* ------------------------------------------------------------ */ /* */ protected final void shutdownSocketOutput() throws IOException { if (!_socket.isClosed()) { if (!_socket.isOutputShutdown()) _socket.shutdownOutput(); if (_socket.isInputShutdown()) _socket.close(); } } /* ------------------------------------------------------------ */ /* * @see org.eclipse.jetty.io.bio.StreamEndPoint#shutdownOutput() */ @Override public void shutdownOutput() throws IOException { if (_socket instanceof SSLSocket) super.shutdownOutput(); else shutdownSocketOutput(); } /* ------------------------------------------------------------ */ /* */ public void shutdownSocketInput() throws IOException { if (!_socket.isClosed()) { if (!_socket.isInputShutdown()) _socket.shutdownInput(); if (_socket.isOutputShutdown()) _socket.close(); } } /* ------------------------------------------------------------ */ /* * @see org.eclipse.jetty.io.bio.StreamEndPoint#shutdownOutput() */ @Override public void shutdownInput() throws IOException { if (_socket instanceof SSLSocket) super.shutdownInput(); else shutdownSocketInput(); } /* ------------------------------------------------------------ */ /* (non-Javadoc) * @see org.eclipse.io.BufferIO#close() */ @Override public void close() throws IOException { _socket.close(); _in=null; _out=null; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalAddr() */ @Override public String getLocalAddr() { if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress()) return StringUtil.ALL_INTERFACES; return _local.getAddress().getHostAddress(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalHost() */ @Override public String getLocalHost() { if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress()) return StringUtil.ALL_INTERFACES; return _local.getAddress().getCanonicalHostName(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalPort() */ @Override public int getLocalPort() { if (_local==null) return -1; return _local.getPort(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemoteAddr() */ @Override public String getRemoteAddr() { if (_remote==null) return null; InetAddress addr = _remote.getAddress(); return ( addr == null ? null : addr.getHostAddress() ); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemoteHost() */ @Override public String getRemoteHost() { if (_remote==null) return null; return _remote.getAddress().getCanonicalHostName(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemotePort() */ @Override public int getRemotePort() { if (_remote==null) return -1; return _remote.getPort(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getConnection() */ @Override public Object getTransport() { return _socket; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.io.bio.StreamEndPoint#setMaxIdleTime(int) */ @Override public void setMaxIdleTime(int timeMs) throws IOException { if (timeMs!=getMaxIdleTime()) _socket.setSoTimeout(timeMs>0?timeMs:0); super.setMaxIdleTime(timeMs); } /* ------------------------------------------------------------ */ @Override protected void idleExpired() throws IOException { try { if (!isInputShutdown()) shutdownInput(); } catch(IOException e) { LOG.ignore(e); _socket.close(); } } @Override public String toString() { return _local + " <--> " + _remote; } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/bio/StreamEndPoint.java000066400000000000000000000163251174773561500274720ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.bio; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.SocketTimeoutException; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.EndPoint; public class StreamEndPoint implements EndPoint { InputStream _in; OutputStream _out; int _maxIdleTime; boolean _ishut; boolean _oshut; /** * */ public StreamEndPoint(InputStream in, OutputStream out) { _in=in; _out=out; } public boolean isBlocking() { return true; } public boolean blockReadable(long millisecs) throws IOException { return true; } public boolean blockWritable(long millisecs) throws IOException { return true; } /* * @see org.eclipse.io.BufferIO#isOpen() */ public boolean isOpen() { return _in!=null; } /* * @see org.eclipse.io.BufferIO#isOpen() */ public final boolean isClosed() { return !isOpen(); } public void shutdownOutput() throws IOException { _oshut = true; if (_ishut && _out!=null) _out.close(); } public boolean isInputShutdown() { return _ishut; } public void shutdownInput() throws IOException { _ishut = true; if (_oshut&&_in!=null) _in.close(); } public boolean isOutputShutdown() { return _oshut; } /* * @see org.eclipse.io.BufferIO#close() */ public void close() throws IOException { if (_in!=null) _in.close(); _in=null; if (_out!=null) _out.close(); _out=null; } protected void idleExpired() throws IOException { if (_in!=null) _in.close(); } /* (non-Javadoc) * @see org.eclipse.io.BufferIO#fill(org.eclipse.io.Buffer) */ public int fill(Buffer buffer) throws IOException { if (_ishut) return -1; if (_in==null) return 0; int space=buffer.space(); if (space<=0) { if (buffer.hasContent()) return 0; throw new IOException("FULL"); } try { int filled=buffer.readFrom(_in, space); if (filled<0) shutdownInput(); return filled; } catch(SocketTimeoutException e) { idleExpired(); return -1; } } /* (non-Javadoc) * @see org.eclipse.io.BufferIO#flush(org.eclipse.io.Buffer) */ public int flush(Buffer buffer) throws IOException { if (_oshut) return -1; if (_out==null) return 0; int length=buffer.length(); if (length>0) buffer.writeTo(_out); if (!buffer.isImmutable()) buffer.clear(); return length; } /* (non-Javadoc) * @see org.eclipse.io.BufferIO#flush(org.eclipse.io.Buffer, org.eclipse.io.Buffer, org.eclipse.io.Buffer) */ public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException { int len=0; if (header!=null) { int tw=header.length(); if (tw>0) { int f=flush(header); len=f; if (f0) { int f=flush(buffer); if (f<0) return len>0?len:f; len+=f; if (f0) { int f=flush(trailer); if (f<0) return len>0?len:f; len+=f; } } return len; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalAddr() */ public String getLocalAddr() { return null; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalHost() */ public String getLocalHost() { return null; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalPort() */ public int getLocalPort() { return 0; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemoteAddr() */ public String getRemoteAddr() { return null; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemoteHost() */ public String getRemoteHost() { return null; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemotePort() */ public int getRemotePort() { return 0; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getConnection() */ public Object getTransport() { return null; } /* ------------------------------------------------------------ */ public InputStream getInputStream() { return _in; } /* ------------------------------------------------------------ */ public void setInputStream(InputStream in) { _in=in; } /* ------------------------------------------------------------ */ public OutputStream getOutputStream() { return _out; } /* ------------------------------------------------------------ */ public void setOutputStream(OutputStream out) { _out=out; } /* ------------------------------------------------------------ */ public void flush() throws IOException { if (_out != null) _out.flush(); } /* ------------------------------------------------------------ */ public int getMaxIdleTime() { return _maxIdleTime; } /* ------------------------------------------------------------ */ public void setMaxIdleTime(int timeMs) throws IOException { _maxIdleTime=timeMs; } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/bio/StringEndPoint.java000066400000000000000000000047311174773561500275030ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.bio; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import org.eclipse.jetty.util.StringUtil; /** * * * To change the template for this generated type comment go to * Window - Preferences - Java - Code Generation - Code and Comments */ public class StringEndPoint extends StreamEndPoint { String _encoding=StringUtil.__UTF8; ByteArrayInputStream _bin = new ByteArrayInputStream(new byte[0]); ByteArrayOutputStream _bout = new ByteArrayOutputStream(); public StringEndPoint() { super(null,null); _in=_bin; _out=_bout; } public StringEndPoint(String encoding) { this(); if (encoding!=null) _encoding=encoding; } public void setInput(String s) { try { byte[] bytes = s.getBytes(_encoding); _bin=new ByteArrayInputStream(bytes); _in=_bin; _bout = new ByteArrayOutputStream(); _out=_bout; _ishut=false; _oshut=false; } catch(Exception e) { throw new IllegalStateException(e.toString()); } } public String getOutput() { try { String s = new String(_bout.toByteArray(),_encoding); _bout.reset(); return s; } catch(final Exception e) { throw new IllegalStateException(_encoding) { {initCause(e);} }; } } /** * @return true if there are bytes remaining to be read from the encoded input */ public boolean hasMore() { return _bin.available()>0; } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio/000077500000000000000000000000001174773561500237405ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio/AsyncConnection.java000066400000000000000000000016731174773561500277070ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2010 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import java.io.IOException; import org.eclipse.jetty.io.Connection; public interface AsyncConnection extends Connection { void onInputShutdown() throws IOException; } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio/ChannelEndPoint.java000066400000000000000000000343041174773561500276200ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; import java.nio.ByteBuffer; import java.nio.channels.ByteChannel; import java.nio.channels.GatheringByteChannel; import java.nio.channels.SelectableChannel; import java.nio.channels.SocketChannel; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * Channel End Point. *

    Holds the channel and socket for an NIO endpoint. * */ public class ChannelEndPoint implements EndPoint { private static final Logger LOG = Log.getLogger(ChannelEndPoint.class); protected final ByteChannel _channel; protected final ByteBuffer[] _gather2=new ByteBuffer[2]; protected final Socket _socket; protected final InetSocketAddress _local; protected final InetSocketAddress _remote; protected volatile int _maxIdleTime; private volatile boolean _ishut; private volatile boolean _oshut; public ChannelEndPoint(ByteChannel channel) throws IOException { super(); this._channel = channel; _socket=(channel instanceof SocketChannel)?((SocketChannel)channel).socket():null; if (_socket!=null) { _local=(InetSocketAddress)_socket.getLocalSocketAddress(); _remote=(InetSocketAddress)_socket.getRemoteSocketAddress(); _maxIdleTime=_socket.getSoTimeout(); } else { _local=_remote=null; } } protected ChannelEndPoint(ByteChannel channel, int maxIdleTime) throws IOException { this._channel = channel; _maxIdleTime=maxIdleTime; _socket=(channel instanceof SocketChannel)?((SocketChannel)channel).socket():null; if (_socket!=null) { _local=(InetSocketAddress)_socket.getLocalSocketAddress(); _remote=(InetSocketAddress)_socket.getRemoteSocketAddress(); _socket.setSoTimeout(_maxIdleTime); } else { _local=_remote=null; } } public boolean isBlocking() { return !(_channel instanceof SelectableChannel) || ((SelectableChannel)_channel).isBlocking(); } public boolean blockReadable(long millisecs) throws IOException { return true; } public boolean blockWritable(long millisecs) throws IOException { return true; } /* * @see org.eclipse.io.EndPoint#isOpen() */ public boolean isOpen() { return _channel.isOpen(); } /** Shutdown the channel Input. * Cannot be overridden. To override, see {@link #shutdownInput()} * @throws IOException */ protected final void shutdownChannelInput() throws IOException { LOG.debug("ishut {}", this); _ishut = true; if (_channel.isOpen()) { if (_socket != null) { try { if (!_socket.isInputShutdown()) { _socket.shutdownInput(); } } catch (SocketException e) { LOG.debug(e.toString()); LOG.ignore(e); } finally { if (_oshut) { close(); } } } } } /* (non-Javadoc) * @see org.eclipse.io.EndPoint#close() */ public void shutdownInput() throws IOException { shutdownChannelInput(); } protected final void shutdownChannelOutput() throws IOException { LOG.debug("oshut {}",this); _oshut = true; if (_channel.isOpen()) { if (_socket != null) { try { if (!_socket.isOutputShutdown()) { _socket.shutdownOutput(); } } catch (SocketException e) { LOG.debug(e.toString()); LOG.ignore(e); } finally { if (_ishut) { close(); } } } } } /* (non-Javadoc) * @see org.eclipse.io.EndPoint#close() */ public void shutdownOutput() throws IOException { shutdownChannelOutput(); } public boolean isOutputShutdown() { return _oshut || !_channel.isOpen() || _socket != null && _socket.isOutputShutdown(); } public boolean isInputShutdown() { return _ishut || !_channel.isOpen() || _socket != null && _socket.isInputShutdown(); } /* (non-Javadoc) * @see org.eclipse.io.EndPoint#close() */ public void close() throws IOException { LOG.debug("close {}",this); _channel.close(); } /* (non-Javadoc) * @see org.eclipse.io.EndPoint#fill(org.eclipse.io.Buffer) */ public int fill(Buffer buffer) throws IOException { if (_ishut) return -1; Buffer buf = buffer.buffer(); int len=0; if (buf instanceof NIOBuffer) { final NIOBuffer nbuf = (NIOBuffer)buf; final ByteBuffer bbuf=nbuf.getByteBuffer(); //noinspection SynchronizationOnLocalVariableOrMethodParameter try { synchronized(bbuf) { try { bbuf.position(buffer.putIndex()); len=_channel.read(bbuf); } finally { buffer.setPutIndex(bbuf.position()); bbuf.position(0); } } if (len<0 && isOpen()) { if (!isInputShutdown()) shutdownInput(); if (isOutputShutdown()) _channel.close(); } } catch (IOException x) { LOG.debug("Exception while filling", x); try { if (_channel.isOpen()) _channel.close(); } catch (Exception xx) { LOG.ignore(xx); } if (len>0) throw x; len=-1; } } else { throw new IOException("Not Implemented"); } return len; } /* (non-Javadoc) * @see org.eclipse.io.EndPoint#flush(org.eclipse.io.Buffer) */ public int flush(Buffer buffer) throws IOException { Buffer buf = buffer.buffer(); int len=0; if (buf instanceof NIOBuffer) { final NIOBuffer nbuf = (NIOBuffer)buf; final ByteBuffer bbuf=nbuf.getByteBuffer().asReadOnlyBuffer(); try { bbuf.position(buffer.getIndex()); bbuf.limit(buffer.putIndex()); len=_channel.write(bbuf); } finally { if (len>0) buffer.skip(len); } } else if (buf instanceof RandomAccessFileBuffer) { len = ((RandomAccessFileBuffer)buf).writeTo(_channel,buffer.getIndex(),buffer.length()); if (len>0) buffer.skip(len); } else if (buffer.array()!=null) { ByteBuffer b = ByteBuffer.wrap(buffer.array(), buffer.getIndex(), buffer.length()); len=_channel.write(b); if (len>0) buffer.skip(len); } else { throw new IOException("Not Implemented"); } return len; } /* (non-Javadoc) * @see org.eclipse.io.EndPoint#flush(org.eclipse.io.Buffer, org.eclipse.io.Buffer, org.eclipse.io.Buffer) */ public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException { int length=0; Buffer buf0 = header==null?null:header.buffer(); Buffer buf1 = buffer==null?null:buffer.buffer(); if (_channel instanceof GatheringByteChannel && header!=null && header.length()!=0 && buf0 instanceof NIOBuffer && buffer!=null && buffer.length()!=0 && buf1 instanceof NIOBuffer) { length = gatheringFlush(header,((NIOBuffer)buf0).getByteBuffer(),buffer,((NIOBuffer)buf1).getByteBuffer()); } else { // flush header if (header!=null && header.length()>0) length=flush(header); // flush buffer if ((header==null || header.length()==0) && buffer!=null && buffer.length()>0) length+=flush(buffer); // flush trailer if ((header==null || header.length()==0) && (buffer==null || buffer.length()==0) && trailer!=null && trailer.length()>0) length+=flush(trailer); } return length; } protected int gatheringFlush(Buffer header, ByteBuffer bbuf0, Buffer buffer, ByteBuffer bbuf1) throws IOException { int length; synchronized(this) { // Adjust position indexs of buf0 and buf1 bbuf0=bbuf0.asReadOnlyBuffer(); bbuf0.position(header.getIndex()); bbuf0.limit(header.putIndex()); bbuf1=bbuf1.asReadOnlyBuffer(); bbuf1.position(buffer.getIndex()); bbuf1.limit(buffer.putIndex()); _gather2[0]=bbuf0; _gather2[1]=bbuf1; // do the gathering write. length=(int)((GatheringByteChannel)_channel).write(_gather2); int hl=header.length(); if (length>hl) { header.clear(); buffer.skip(length-hl); } else if (length>0) { header.skip(length); } } return length; } /* ------------------------------------------------------------ */ /** * @return Returns the channel. */ public ByteChannel getChannel() { return _channel; } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalAddr() */ public String getLocalAddr() { if (_socket==null) return null; if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress()) return StringUtil.ALL_INTERFACES; return _local.getAddress().getHostAddress(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalHost() */ public String getLocalHost() { if (_socket==null) return null; if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress()) return StringUtil.ALL_INTERFACES; return _local.getAddress().getCanonicalHostName(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getLocalPort() */ public int getLocalPort() { if (_socket==null) return 0; if (_local==null) return -1; return _local.getPort(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemoteAddr() */ public String getRemoteAddr() { if (_socket==null) return null; if (_remote==null) return null; return _remote.getAddress().getHostAddress(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemoteHost() */ public String getRemoteHost() { if (_socket==null) return null; if (_remote==null) return null; return _remote.getAddress().getCanonicalHostName(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getRemotePort() */ public int getRemotePort() { if (_socket==null) return 0; return _remote==null?-1:_remote.getPort(); } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.EndPoint#getConnection() */ public Object getTransport() { return _channel; } /* ------------------------------------------------------------ */ public void flush() throws IOException { } /* ------------------------------------------------------------ */ public int getMaxIdleTime() { return _maxIdleTime; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.io.bio.StreamEndPoint#setMaxIdleTime(int) */ public void setMaxIdleTime(int timeMs) throws IOException { if (_socket!=null && timeMs!=_maxIdleTime) _socket.setSoTimeout(timeMs>0?timeMs:0); _maxIdleTime=timeMs; } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio/DirectNIOBuffer.java000066400000000000000000000221631174773561500275210ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import org.eclipse.jetty.io.AbstractBuffer; import org.eclipse.jetty.io.Buffer; /* ------------------------------------------------------------------------------- */ /** * * */ public class DirectNIOBuffer extends AbstractBuffer implements NIOBuffer { protected final ByteBuffer _buf; private ReadableByteChannel _in; private InputStream _inStream; private WritableByteChannel _out; private OutputStream _outStream; public DirectNIOBuffer(int size) { super(READWRITE,NON_VOLATILE); _buf = ByteBuffer.allocateDirect(size); _buf.position(0); _buf.limit(_buf.capacity()); } public DirectNIOBuffer(ByteBuffer buffer,boolean immutable) { super(immutable?IMMUTABLE:READWRITE,NON_VOLATILE); if (!buffer.isDirect()) throw new IllegalArgumentException(); _buf = buffer; setGetIndex(buffer.position()); setPutIndex(buffer.limit()); } /** * @param file */ public DirectNIOBuffer(File file) throws IOException { super(READONLY,NON_VOLATILE); FileInputStream fis = new FileInputStream(file); FileChannel fc = fis.getChannel(); _buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); setGetIndex(0); setPutIndex((int)file.length()); _access=IMMUTABLE; } /* ------------------------------------------------------------ */ public boolean isDirect() { return true; } /* ------------------------------------------------------------ */ public byte[] array() { return null; } /* ------------------------------------------------------------ */ public int capacity() { return _buf.capacity(); } /* ------------------------------------------------------------ */ public byte peek(int position) { return _buf.get(position); } public int peek(int index, byte[] b, int offset, int length) { int l = length; if (index+l > capacity()) { l=capacity()-index; if (l==0) return -1; } if (l < 0) return -1; try { _buf.position(index); _buf.get(b,offset,l); } finally { _buf.position(0); } return l; } public void poke(int index, byte b) { if (isReadOnly()) throw new IllegalStateException(__READONLY); if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0"); if (index > capacity()) throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity()); _buf.put(index,b); } @Override public int poke(int index, Buffer src) { if (isReadOnly()) throw new IllegalStateException(__READONLY); byte[] array=src.array(); if (array!=null) { return poke(index,array,src.getIndex(),src.length()); } else { Buffer src_buf=src.buffer(); if (src_buf instanceof DirectNIOBuffer) { ByteBuffer src_bytebuf = ((DirectNIOBuffer)src_buf)._buf; if (src_bytebuf==_buf) src_bytebuf=_buf.duplicate(); try { _buf.position(index); int space = _buf.remaining(); int length=src.length(); if (length>space) length=space; src_bytebuf.position(src.getIndex()); src_bytebuf.limit(src.getIndex()+length); _buf.put(src_bytebuf); return length; } finally { _buf.position(0); src_bytebuf.limit(src_bytebuf.capacity()); src_bytebuf.position(0); } } else return super.poke(index,src); } } @Override public int poke(int index, byte[] b, int offset, int length) { if (isReadOnly()) throw new IllegalStateException(__READONLY); if (index < 0) throw new IllegalArgumentException("index<0: " + index + "<0"); if (index + length > capacity()) { length=capacity()-index; if (length<0) throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity()); } try { _buf.position(index); int space=_buf.remaining(); if (length>space) length=space; if (length>0) _buf.put(b,offset,length); return length; } finally { _buf.position(0); } } /* ------------------------------------------------------------ */ public ByteBuffer getByteBuffer() { return _buf; } /* ------------------------------------------------------------ */ @Override public int readFrom(InputStream in, int max) throws IOException { if (_in==null || !_in.isOpen() || in!=_inStream) { _in=Channels.newChannel(in); _inStream=in; } if (max<0 || max>space()) max=space(); int p = putIndex(); try { int len=0, total=0, available=max; int loop=0; while (total0) { p += len; total += len; available -= len; setPutIndex(p); loop=0; } else if (loop++>1) break; if (in.available()<=0) break; } if (len<0 && total==0) return -1; return total; } catch(IOException e) { _in=null; _inStream=in; throw e; } finally { if (_in!=null && !_in.isOpen()) { _in=null; _inStream=in; } _buf.position(0); _buf.limit(_buf.capacity()); } } /* ------------------------------------------------------------ */ @Override public void writeTo(OutputStream out) throws IOException { if (_out==null || !_out.isOpen() || out!=_outStream) { _out=Channels.newChannel(out); _outStream=out; } synchronized (_buf) { try { int loop=0; while(hasContent() && _out.isOpen()) { _buf.position(getIndex()); _buf.limit(putIndex()); int len=_out.write(_buf); if (len<0) break; else if (len>0) { skip(len); loop=0; } else if (loop++>1) break; } } catch(IOException e) { _out=null; _outStream=null; throw e; } finally { if (_out!=null && !_out.isOpen()) { _out=null; _outStream=null; } _buf.position(0); _buf.limit(_buf.capacity()); } } } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio/IndirectNIOBuffer.java000066400000000000000000000037141174773561500300510ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import java.nio.ByteBuffer; import org.eclipse.jetty.io.ByteArrayBuffer; public class IndirectNIOBuffer extends ByteArrayBuffer implements NIOBuffer { protected final ByteBuffer _buf; /* ------------------------------------------------------------ */ public IndirectNIOBuffer(int size) { super(size,READWRITE,NON_VOLATILE); _buf = ByteBuffer.wrap(_bytes); _buf.position(0); _buf.limit(_buf.capacity()); } /* ------------------------------------------------------------ */ public IndirectNIOBuffer(ByteBuffer buffer,boolean immutable) { super(buffer.array(),0,0, immutable?IMMUTABLE:READWRITE,NON_VOLATILE); if (buffer.isDirect()) throw new IllegalArgumentException(); _buf = buffer; _get=buffer.position(); _put=buffer.limit(); buffer.position(0); buffer.limit(buffer.capacity()); } /* ------------------------------------------------------------ */ public ByteBuffer getByteBuffer() { return _buf; } /* ------------------------------------------------------------ */ public boolean isDirect() { return false; } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio/NIOBuffer.java000066400000000000000000000023011174773561500263560ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import java.nio.ByteBuffer; import org.eclipse.jetty.io.Buffer; /* ------------------------------------------------------------------------------- */ /** * * */ public interface NIOBuffer extends Buffer { /* ------------------------------------------------------------ */ public ByteBuffer getByteBuffer(); /* ------------------------------------------------------------ */ public boolean isDirect(); } NetworkTrafficSelectChannelEndPoint.java000066400000000000000000000110371174773561500335500ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio// ======================================================================== // Copyright (c) 2011 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; import java.util.List; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.NetworkTrafficListener; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public class NetworkTrafficSelectChannelEndPoint extends SelectChannelEndPoint { private static final Logger LOG = Log.getLogger(NetworkTrafficSelectChannelEndPoint.class); private final List listeners; public NetworkTrafficSelectChannelEndPoint(SocketChannel channel, SelectorManager.SelectSet selectSet, SelectionKey key, int maxIdleTime, List listeners) throws IOException { super(channel, selectSet, key, maxIdleTime); this.listeners = listeners; } @Override public int fill(Buffer buffer) throws IOException { int read = super.fill(buffer); notifyIncoming(buffer, read); return read; } @Override public int flush(Buffer buffer) throws IOException { int position = buffer.getIndex(); int written = super.flush(buffer); notifyOutgoing(buffer, position, written); return written; } @Override protected int gatheringFlush(Buffer header, ByteBuffer bbuf0, Buffer buffer, ByteBuffer bbuf1) throws IOException { int headerPosition = header.getIndex(); int headerLength = header.length(); int bufferPosition = buffer.getIndex(); int written = super.gatheringFlush(header, bbuf0, buffer,bbuf1); notifyOutgoing(header, headerPosition, written > headerLength ? headerLength : written); notifyOutgoing(buffer, bufferPosition, written > headerLength ? written - headerLength : 0); return written; } public void notifyOpened() { if (listeners != null && !listeners.isEmpty()) { for (NetworkTrafficListener listener : listeners) { try { listener.opened(_socket); } catch (Exception x) { LOG.warn(x); } } } } public void notifyIncoming(Buffer buffer, int read) { if (listeners != null && !listeners.isEmpty() && read > 0) { for (NetworkTrafficListener listener : listeners) { try { Buffer view = buffer.asReadOnlyBuffer(); listener.incoming(_socket, view); } catch (Exception x) { LOG.warn(x); } } } } public void notifyOutgoing(Buffer buffer, int position, int written) { if (listeners != null && !listeners.isEmpty() && written > 0) { for (NetworkTrafficListener listener : listeners) { try { Buffer view = buffer.asReadOnlyBuffer(); view.setGetIndex(position); view.setPutIndex(position + written); listener.outgoing(_socket, view); } catch (Exception x) { LOG.warn(x); } } } } public void notifyClosed() { if (listeners != null && !listeners.isEmpty()) { for (NetworkTrafficListener listener : listeners) { try { listener.closed(_socket); } catch (Exception x) { LOG.warn(x); } } } } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio/RandomAccessFileBuffer.java000066400000000000000000000114661174773561500311070ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; import org.eclipse.jetty.io.AbstractBuffer; import org.eclipse.jetty.io.Buffer; public class RandomAccessFileBuffer extends AbstractBuffer implements Buffer { final RandomAccessFile _file; final FileChannel _channel; final int _capacity; public RandomAccessFileBuffer(File file) throws FileNotFoundException { super(READWRITE,true); assert file.length()<=Integer.MAX_VALUE; _file = new RandomAccessFile(file,"rw"); _channel=_file.getChannel(); _capacity=Integer.MAX_VALUE; setGetIndex(0); setPutIndex((int)file.length()); } public RandomAccessFileBuffer(File file,int capacity) throws FileNotFoundException { super(READWRITE,true); assert capacity>=file.length(); assert file.length()<=Integer.MAX_VALUE; _capacity=capacity; _file = new RandomAccessFile(file,"rw"); _channel=_file.getChannel(); setGetIndex(0); setPutIndex((int)file.length()); } public RandomAccessFileBuffer(File file,int capacity,int access) throws FileNotFoundException { super(access,true); assert capacity>=file.length(); assert file.length()<=Integer.MAX_VALUE; _capacity=capacity; _file = new RandomAccessFile(file,access==READWRITE?"rw":"r"); _channel=_file.getChannel(); setGetIndex(0); setPutIndex((int)file.length()); } public byte[] array() { return null; } public int capacity() { return _capacity; } @Override public void clear() { try { synchronized (_file) { super.clear(); _file.setLength(0); } } catch(Exception e) { throw new RuntimeException(e); } } @Override public byte peek() { synchronized (_file) { try { if (_get!=_file.getFilePointer()) _file.seek(_get); return _file.readByte(); } catch(Exception e) { throw new RuntimeException(e); } } } public byte peek(int index) { synchronized (_file) { try { _file.seek(index); return _file.readByte(); } catch(Exception e) { throw new RuntimeException(e); } } } public int peek(int index, byte[] b, int offset, int length) { synchronized (_file) { try { _file.seek(index); return _file.read(b,offset,length); } catch(Exception e) { throw new RuntimeException(e); } } } public void poke(int index, byte b) { synchronized (_file) { try { _file.seek(index); _file.writeByte(b); } catch(Exception e) { throw new RuntimeException(e); } } } @Override public int poke(int index, byte[] b, int offset, int length) { synchronized (_file) { try { _file.seek(index); _file.write(b,offset,length); return length; } catch(Exception e) { throw new RuntimeException(e); } } } public int writeTo(WritableByteChannel channel,int index, int length) throws IOException { synchronized (_file) { return (int)_channel.transferTo(index,length,channel); } } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java000066400000000000000000000567111174773561500307660ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import java.io.IOException; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.nio.SelectorManager.SelectSet; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.Timeout.Task; /* ------------------------------------------------------------ */ /** * An Endpoint that can be scheduled by {@link SelectorManager}. */ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPoint, ConnectedEndPoint { public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio"); private final boolean WORK_AROUND_JVM_BUG_6346658 = System.getProperty("os.name").toLowerCase().contains("win"); private final SelectorManager.SelectSet _selectSet; private final SelectorManager _manager; private SelectionKey _key; private final Runnable _handler = new Runnable() { public void run() { handle(); } }; /** The desired value for {@link SelectionKey#interestOps()} */ private int _interestOps; /** * The connection instance is the handler for any IO activity on the endpoint. * There is a different type of connection for HTTP, AJP, WebSocket and * ProxyConnect. The connection may change for an SCEP as it is upgraded * from HTTP to proxy connect or websocket. */ private volatile AsyncConnection _connection; /** true if a thread has been dispatched to handle this endpoint */ private boolean _dispatched = false; /** true if a non IO dispatch (eg async resume) is outstanding */ private boolean _asyncDispatch = false; /** true if the last write operation succeed and wrote all offered bytes */ private volatile boolean _writable = true; /** True if a thread has is blocked in {@link #blockReadable(long)} */ private boolean _readBlocked; /** True if a thread has is blocked in {@link #blockWritable(long)} */ private boolean _writeBlocked; /** true if {@link SelectSet#destroyEndPoint(SelectChannelEndPoint)} has not been called */ private boolean _open; private volatile long _idleTimestamp; private boolean _ishut; /* ------------------------------------------------------------ */ public SelectChannelEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key, int maxIdleTime) throws IOException { super(channel, maxIdleTime); _manager = selectSet.getManager(); _selectSet = selectSet; _dispatched = false; _asyncDispatch = false; _open=true; _key = key; setCheckForIdle(true); } /* ------------------------------------------------------------ */ public SelectionKey getSelectionKey() { synchronized (this) { return _key; } } /* ------------------------------------------------------------ */ public SelectorManager getSelectManager() { return _manager; } /* ------------------------------------------------------------ */ public Connection getConnection() { return _connection; } /* ------------------------------------------------------------ */ public void setConnection(Connection connection) { Connection old=_connection; _connection=(AsyncConnection)connection; if (old!=null && old!=_connection) _manager.endPointUpgraded(this,old); } /* ------------------------------------------------------------ */ public long getIdleTimestamp() { return _idleTimestamp; } /* ------------------------------------------------------------ */ /** Called by selectSet to schedule handling * */ public void schedule() { synchronized (this) { // If there is no key, then do nothing if (_key == null || !_key.isValid()) { _readBlocked=false; _writeBlocked=false; this.notifyAll(); return; } // If there are threads dispatched reading and writing if (_readBlocked || _writeBlocked) { // assert _dispatched; if (_readBlocked && _key.isReadable()) _readBlocked=false; if (_writeBlocked && _key.isWritable()) _writeBlocked=false; // wake them up is as good as a dispatched. this.notifyAll(); // we are not interested in further selecting _key.interestOps(0); if (!_dispatched) updateKey(); return; } // Remove writeable op if ((_key.readyOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE && (_key.interestOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE) { // Remove writeable op _interestOps = _key.interestOps() & ~SelectionKey.OP_WRITE; _key.interestOps(_interestOps); _writable = true; // Once writable is in ops, only removed with dispatch. } // If dispatched, then deregister interest if (_dispatched) _key.interestOps(0); else { // other wise do the dispatch dispatch(); if (_dispatched && !_selectSet.getManager().isDeferringInterestedOps0()) { _key.interestOps(0); } } } } /* ------------------------------------------------------------ */ public void asyncDispatch() { synchronized(this) { if (_dispatched) _asyncDispatch=true; else dispatch(); } } /* ------------------------------------------------------------ */ public void dispatch() { synchronized(this) { if (!_dispatched) { _dispatched = true; boolean dispatched = _manager.dispatch(_handler); if(!dispatched) { _dispatched = false; LOG.warn("Dispatched Failed! "+this+" to "+_manager); updateKey(); } } } } /* ------------------------------------------------------------ */ /** * Called when a dispatched thread is no longer handling the endpoint. * The selection key operations are updated. * @return If false is returned, the endpoint has been redispatched and * thread must keep handling the endpoint. */ protected boolean undispatch() { synchronized (this) { if (_asyncDispatch) { _asyncDispatch=false; return false; } _dispatched = false; updateKey(); } return true; } /* ------------------------------------------------------------ */ public void cancelTimeout(Task task) { getSelectSet().cancelTimeout(task); } /* ------------------------------------------------------------ */ public void scheduleTimeout(Task task, long timeoutMs) { getSelectSet().scheduleTimeout(task,timeoutMs); } /* ------------------------------------------------------------ */ public void setCheckForIdle(boolean check) { _idleTimestamp=check?System.currentTimeMillis():0; } /* ------------------------------------------------------------ */ public boolean isCheckForIdle() { return _idleTimestamp!=0; } /* ------------------------------------------------------------ */ protected void notIdle() { if (_idleTimestamp!=0) _idleTimestamp=System.currentTimeMillis(); } /* ------------------------------------------------------------ */ public void checkIdleTimestamp(long now) { long idleTimestamp=_idleTimestamp; if (idleTimestamp!=0 && _maxIdleTime>0) { long idleForMs=now-idleTimestamp; if (idleForMs>_maxIdleTime) { onIdleExpired(idleForMs); _idleTimestamp=now; } } } /* ------------------------------------------------------------ */ public void onIdleExpired(long idleForMs) { _connection.onIdleExpired(idleForMs); } /* ------------------------------------------------------------ */ @Override public int fill(Buffer buffer) throws IOException { int fill=super.fill(buffer); if (fill>0) notIdle(); return fill; } /* ------------------------------------------------------------ */ @Override public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException { int l = super.flush(header, buffer, trailer); // If there was something to write and it wasn't written, then we are not writable. if (l==0 && ( header!=null && header.hasContent() || buffer!=null && buffer.hasContent() || trailer!=null && trailer.hasContent())) { synchronized (this) { if (_dispatched) _writable=false; } } else if (l>0) { _writable=true; notIdle(); } return l; } /* ------------------------------------------------------------ */ /* */ @Override public int flush(Buffer buffer) throws IOException { int l = super.flush(buffer); // If there was something to write and it wasn't written, then we are not writable. if (l==0 && buffer!=null && buffer.hasContent()) { synchronized (this) { if (_dispatched) _writable=false; } } else if (l>0) { _writable=true; notIdle(); } return l; } /* ------------------------------------------------------------ */ /* * Allows thread to block waiting for further events. */ @Override public boolean blockReadable(long timeoutMs) throws IOException { synchronized (this) { if (isInputShutdown()) throw new EofException(); long now=_selectSet.getNow(); long end=now+timeoutMs; boolean check=isCheckForIdle(); setCheckForIdle(true); try { _readBlocked=true; while (!isInputShutdown() && _readBlocked) { try { updateKey(); this.wait(timeoutMs>0?(end-now):10000); } catch (InterruptedException e) { LOG.warn(e); } finally { now=_selectSet.getNow(); } if (_readBlocked && timeoutMs>0 && now>=end) return false; } } finally { _readBlocked=false; setCheckForIdle(check); } } return true; } /* ------------------------------------------------------------ */ /* * Allows thread to block waiting for further events. */ @Override public boolean blockWritable(long timeoutMs) throws IOException { synchronized (this) { if (isOutputShutdown()) throw new EofException(); long now=_selectSet.getNow(); long end=now+timeoutMs; boolean check=isCheckForIdle(); setCheckForIdle(true); try { _writeBlocked=true; while (_writeBlocked && !isOutputShutdown()) { try { updateKey(); this.wait(timeoutMs>0?(end-now):10000); } catch (InterruptedException e) { LOG.warn(e); } finally { now=_selectSet.getNow(); } if (_writeBlocked && timeoutMs>0 && now>=end) return false; } } finally { _writeBlocked=false; setCheckForIdle(check); } } return true; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.io.AsyncEndPoint#scheduleWrite() */ public void scheduleWrite() { if (_writable) LOG.debug("Required scheduleWrite {}",this); _writable=false; updateKey(); } /* ------------------------------------------------------------ */ public boolean isWritable() { return _writable; } /* ------------------------------------------------------------ */ public boolean hasProgressed() { return false; } /* ------------------------------------------------------------ */ /** * Updates selection key. Adds operations types to the selection key as needed. No operations * are removed as this is only done during dispatch. This method records the new key and * schedules a call to doUpdateKey to do the keyChange */ private void updateKey() { final boolean changed; synchronized (this) { int current_ops=-1; if (getChannel().isOpen()) { boolean read_interest = _readBlocked || (!_dispatched && !_connection.isSuspended()); boolean write_interest= _writeBlocked || (!_dispatched && !_writable); _interestOps = ((!_socket.isInputShutdown() && read_interest ) ? SelectionKey.OP_READ : 0) | ((!_socket.isOutputShutdown()&& write_interest) ? SelectionKey.OP_WRITE : 0); try { current_ops = ((_key!=null && _key.isValid())?_key.interestOps():-1); } catch(Exception e) { _key=null; LOG.ignore(e); } } changed=_interestOps!=current_ops; } if(changed) { _selectSet.addChange(this); _selectSet.wakeup(); } } /* ------------------------------------------------------------ */ /** * Synchronize the interestOps with the actual key. Call is scheduled by a call to updateKey */ void doUpdateKey() { synchronized (this) { if (getChannel().isOpen()) { if (_interestOps>0) { if (_key==null || !_key.isValid()) { SelectableChannel sc = (SelectableChannel)getChannel(); if (sc.isRegistered()) { updateKey(); } else { try { _key=((SelectableChannel)getChannel()).register(_selectSet.getSelector(),_interestOps,this); } catch (Exception e) { LOG.ignore(e); if (_key!=null && _key.isValid()) { _key.cancel(); } if (_open) { _selectSet.destroyEndPoint(this); } _open=false; _key = null; } } } else { _key.interestOps(_interestOps); } } else { if (_key!=null && _key.isValid()) _key.interestOps(0); else _key=null; } } else { if (_key!=null && _key.isValid()) _key.cancel(); if (_open) { _open=false; _selectSet.destroyEndPoint(this); } _key = null; } } } /* ------------------------------------------------------------ */ /* */ protected void handle() { boolean dispatched=true; try { while(dispatched) { try { while(true) { final AsyncConnection next = (AsyncConnection)_connection.handle(); if (next!=_connection) { LOG.debug("{} replaced {}",next,_connection); Connection old=_connection; _connection=next; _manager.endPointUpgraded(this,old); continue; } break; } } catch (ClosedChannelException e) { LOG.ignore(e); } catch (EofException e) { LOG.debug("EOF", e); try{close();} catch(IOException e2){LOG.ignore(e2);} } catch (IOException e) { LOG.warn(e.toString()); try{close();} catch(IOException e2){LOG.ignore(e2);} } catch (Throwable e) { LOG.warn("handle failed", e); try{close();} catch(IOException e2){LOG.ignore(e2);} } finally { if (!_ishut && isInputShutdown() && isOpen()) { _ishut=true; try { _connection.onInputShutdown(); } catch(Throwable x) { LOG.warn("onInputShutdown failed", x); try{close();} catch(IOException e2){LOG.ignore(e2);} } finally { updateKey(); } } dispatched=!undispatch(); } } } finally { if (dispatched) { dispatched=!undispatch(); while (dispatched) { LOG.warn("SCEP.run() finally DISPATCHED"); dispatched=!undispatch(); } } } } /* ------------------------------------------------------------ */ /* * @see org.eclipse.io.nio.ChannelEndPoint#close() */ @Override public void close() throws IOException { // On unix systems there is a JVM issue that if you cancel before closing, it can // cause the selector to block waiting for a channel to close and that channel can // block waiting for the remote end. But on windows, if you don't cancel before a // close, then the selector can block anyway! // https://bugs.eclipse.org/bugs/show_bug.cgi?id=357318 if (WORK_AROUND_JVM_BUG_6346658) { try { SelectionKey key = _key; if (key!=null) key.cancel(); } catch (Throwable e) { LOG.ignore(e); } } try { super.close(); } catch (IOException e) { LOG.ignore(e); } finally { updateKey(); } } /* ------------------------------------------------------------ */ @Override public String toString() { // Do NOT use synchronized (this) // because it's very easy to deadlock when debugging is enabled. // We do a best effort to print the right toString() and that's it. SelectionKey key = _key; String keyString = ""; if (key != null) { if (key.isValid()) { if (key.isReadable()) keyString += "r"; if (key.isWritable()) keyString += "w"; } else { keyString += "!"; } } else { keyString += "-"; } return String.format("SCEP@%x{l(%s)<->r(%s),d=%b,open=%b,ishut=%b,oshut=%b,rb=%b,wb=%b,w=%b,i=%d%s}-{%s}", hashCode(), _socket.getRemoteSocketAddress(), _socket.getLocalSocketAddress(), _dispatched, isOpen(), isInputShutdown(), isOutputShutdown(), _readBlocked, _writeBlocked, _writable, _interestOps, keyString, _connection); } /* ------------------------------------------------------------ */ public SelectSet getSelectSet() { return _selectSet; } /* ------------------------------------------------------------ */ /** * Don't set the SoTimeout * @see org.eclipse.jetty.io.nio.ChannelEndPoint#setMaxIdleTime(int) */ @Override public void setMaxIdleTime(int timeMs) throws IOException { _maxIdleTime=timeMs; } } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectorManager.java000066400000000000000000001074541174773561500276710ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import java.io.IOException; import java.nio.channels.CancelledKeyException; import java.nio.channels.Channel; import java.nio.channels.ClosedSelectorException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.Timeout; import org.eclipse.jetty.util.thread.Timeout.Task; /* ------------------------------------------------------------ */ /** * The Selector Manager manages and number of SelectSets to allow * NIO scheduling to scale to large numbers of connections. *

    */ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpable { public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio"); private static final int __MONITOR_PERIOD=Integer.getInteger("org.eclipse.jetty.io.nio.MONITOR_PERIOD",1000).intValue(); private static final int __MAX_SELECTS=Integer.getInteger("org.eclipse.jetty.io.nio.MAX_SELECTS",100000).intValue(); private static final int __BUSY_PAUSE=Integer.getInteger("org.eclipse.jetty.io.nio.BUSY_PAUSE",50).intValue(); private static final int __IDLE_TICK=Integer.getInteger("org.eclipse.jetty.io.nio.IDLE_TICK",400).intValue(); private int _maxIdleTime; private int _lowResourcesMaxIdleTime; private long _lowResourcesConnections; private SelectSet[] _selectSet; private int _selectSets=1; private volatile int _set=0; private boolean _deferringInterestedOps0=true; private int _selectorPriorityDelta=0; /* ------------------------------------------------------------ */ /** * @param maxIdleTime The maximum period in milli seconds that a connection may be idle before it is closed. * @see #setLowResourcesMaxIdleTime(long) */ public void setMaxIdleTime(long maxIdleTime) { _maxIdleTime=(int)maxIdleTime; } /* ------------------------------------------------------------ */ /** * @param selectSets number of select sets to create */ public void setSelectSets(int selectSets) { long lrc = _lowResourcesConnections * _selectSets; _selectSets=selectSets; _lowResourcesConnections=lrc/_selectSets; } /* ------------------------------------------------------------ */ /** * @return the max idle time */ public long getMaxIdleTime() { return _maxIdleTime; } /* ------------------------------------------------------------ */ /** * @return the number of select sets in use */ public int getSelectSets() { return _selectSets; } /* ------------------------------------------------------------ */ /** * @param i * @return The select set */ public SelectSet getSelectSet(int i) { return _selectSet[i]; } /* ------------------------------------------------------------ */ /** Register a channel * @param channel * @param att Attached Object */ public void register(SocketChannel channel, Object att) { // The ++ increment here is not atomic, but it does not matter. // so long as the value changes sometimes, then connections will // be distributed over the available sets. int s=_set++; if (s<0) s=-s; s=s%_selectSets; SelectSet[] sets=_selectSet; if (sets!=null) { SelectSet set=sets[s]; set.addChange(channel,att); set.wakeup(); } } /* ------------------------------------------------------------ */ /** Register a channel * @param channel */ public void register(SocketChannel channel) { // The ++ increment here is not atomic, but it does not matter. // so long as the value changes sometimes, then connections will // be distributed over the available sets. int s=_set++; if (s<0) s=-s; s=s%_selectSets; SelectSet[] sets=_selectSet; if (sets!=null) { SelectSet set=sets[s]; set.addChange(channel); set.wakeup(); } } /* ------------------------------------------------------------ */ /** Register a {@link ServerSocketChannel} * @param acceptChannel */ public void register(ServerSocketChannel acceptChannel) { int s=_set++; if (s<0) s=-s; s=s%_selectSets; SelectSet set=_selectSet[s]; set.addChange(acceptChannel); set.wakeup(); } /* ------------------------------------------------------------ */ /** * @return delta The value to add to the selector thread priority. */ public int getSelectorPriorityDelta() { return _selectorPriorityDelta; } /* ------------------------------------------------------------ */ /** Set the selector thread priorty delta. * @param delta The value to add to the selector thread priority. */ public void setSelectorPriorityDelta(int delta) { _selectorPriorityDelta=delta; } /* ------------------------------------------------------------ */ /** * @return the lowResourcesConnections */ public long getLowResourcesConnections() { return _lowResourcesConnections*_selectSets; } /* ------------------------------------------------------------ */ /** * Set the number of connections, which if exceeded places this manager in low resources state. * This is not an exact measure as the connection count is averaged over the select sets. * @param lowResourcesConnections the number of connections * @see #setLowResourcesMaxIdleTime(long) */ public void setLowResourcesConnections(long lowResourcesConnections) { _lowResourcesConnections=(lowResourcesConnections+_selectSets-1)/_selectSets; } /* ------------------------------------------------------------ */ /** * @return the lowResourcesMaxIdleTime */ public long getLowResourcesMaxIdleTime() { return _lowResourcesMaxIdleTime; } /* ------------------------------------------------------------ */ /** * @param lowResourcesMaxIdleTime the period in ms that a connection is allowed to be idle when this SelectSet has more connections than {@link #getLowResourcesConnections()} * @see #setMaxIdleTime(long) */ public void setLowResourcesMaxIdleTime(long lowResourcesMaxIdleTime) { _lowResourcesMaxIdleTime=(int)lowResourcesMaxIdleTime; } /* ------------------------------------------------------------------------------- */ public abstract boolean dispatch(Runnable task); /* ------------------------------------------------------------ */ /* (non-Javadoc) * @see org.eclipse.component.AbstractLifeCycle#doStart() */ @Override protected void doStart() throws Exception { _selectSet = new SelectSet[_selectSets]; for (int i=0;i<_selectSet.length;i++) _selectSet[i]= new SelectSet(i); super.doStart(); // start a thread to Select for (int i=0;i _changes = new ConcurrentLinkedQueue(); private volatile Selector _selector; private volatile Thread _selecting; private int _busySelects; private long _monitorNext; private boolean _pausing; private boolean _paused; private volatile long _idleTick; private ConcurrentMap _endPoints = new ConcurrentHashMap(); /* ------------------------------------------------------------ */ SelectSet(int acceptorID) throws Exception { _setID=acceptorID; _idleTick = System.currentTimeMillis(); _timeout = new Timeout(this); _timeout.setDuration(0L); // create a selector; _selector = Selector.open(); _monitorNext=System.currentTimeMillis()+__MONITOR_PERIOD; } /* ------------------------------------------------------------ */ public void addChange(Object change) { _changes.add(change); } /* ------------------------------------------------------------ */ public void addChange(SelectableChannel channel, Object att) { if (att==null) addChange(channel); else if (att instanceof EndPoint) addChange(att); else addChange(new ChannelAndAttachment(channel,att)); } /* ------------------------------------------------------------ */ /** * Select and dispatch tasks found from changes and the selector. * * @throws IOException */ public void doSelect() throws IOException { try { _selecting=Thread.currentThread(); final Selector selector=_selector; // Stopped concurrently ? if (selector == null) return; // Make any key changes required Object change; int changes=_changes.size(); while (changes-->0 && (change=_changes.poll())!=null) { Channel ch=null; SelectionKey key=null; try { if (change instanceof EndPoint) { // Update the operations for a key. SelectChannelEndPoint endpoint = (SelectChannelEndPoint)change; ch=endpoint.getChannel(); endpoint.doUpdateKey(); } else if (change instanceof ChannelAndAttachment) { // finish accepting/connecting this connection final ChannelAndAttachment asc = (ChannelAndAttachment)change; final SelectableChannel channel=asc._channel; ch=channel; final Object att = asc._attachment; if ((channel instanceof SocketChannel) && ((SocketChannel)channel).isConnected()) { key = channel.register(selector,SelectionKey.OP_READ,att); SelectChannelEndPoint endpoint = createEndPoint((SocketChannel)channel,key); key.attach(endpoint); endpoint.schedule(); } else if (channel.isOpen()) { key = channel.register(selector,SelectionKey.OP_CONNECT,att); } } else if (change instanceof SocketChannel) { // Newly registered channel final SocketChannel channel=(SocketChannel)change; ch=channel; key = channel.register(selector,SelectionKey.OP_READ,null); SelectChannelEndPoint endpoint = createEndPoint(channel,key); key.attach(endpoint); endpoint.schedule(); } else if (change instanceof ChangeTask) { ((Runnable)change).run(); } else if (change instanceof Runnable) { dispatch((Runnable)change); } else throw new IllegalArgumentException(change.toString()); } catch (CancelledKeyException e) { LOG.ignore(e); } catch (Throwable e) { if (isRunning()) LOG.warn(e); else LOG.debug(e); try { if (ch!=null) ch.close(); } catch(IOException e2) { LOG.debug(e2); } } } // Do and instant select to see if any connections can be handled. int selected=selector.selectNow(); long now=System.currentTimeMillis(); // if no immediate things to do if (selected==0 && selector.selectedKeys().isEmpty()) { // If we are in pausing mode if (_pausing) { try { Thread.sleep(__BUSY_PAUSE); // pause to reduce impact of busy loop } catch(InterruptedException e) { LOG.ignore(e); } now=System.currentTimeMillis(); } // workout how long to wait in select _timeout.setNow(now); long to_next_timeout=_timeout.getTimeToNext(); long wait = _changes.size()==0?__IDLE_TICK:0L; if (wait > 0 && to_next_timeout >= 0 && wait > to_next_timeout) wait = to_next_timeout; // If we should wait with a select if (wait>0) { long before=now; selected=selector.select(wait); now = System.currentTimeMillis(); _timeout.setNow(now); // If we are monitoring for busy selector // and this select did not wait more than 1ms if (__MONITOR_PERIOD>0 && now-before <=1) { // count this as a busy select and if there have been too many this monitor cycle if (++_busySelects>__MAX_SELECTS) { // Start injecting pauses _pausing=true; // if this is the first pause if (!_paused) { // Log and dump some status _paused=true; LOG.warn("Selector {} is too busy, pausing!",this); } } } } } // have we been destroyed while sleeping if (_selector==null || !selector.isOpen()) return; // Look for things to do for (SelectionKey key: selector.selectedKeys()) { SocketChannel channel=null; try { if (!key.isValid()) { key.cancel(); SelectChannelEndPoint endpoint = (SelectChannelEndPoint)key.attachment(); if (endpoint != null) endpoint.doUpdateKey(); continue; } Object att = key.attachment(); if (att instanceof SelectChannelEndPoint) { if (key.isReadable()||key.isWritable()) ((SelectChannelEndPoint)att).schedule(); } else if (key.isConnectable()) { // Complete a connection of a registered channel channel = (SocketChannel)key.channel(); boolean connected=false; try { connected=channel.finishConnect(); } catch(Exception e) { connectionFailed(channel,e,att); } finally { if (connected) { key.interestOps(SelectionKey.OP_READ); SelectChannelEndPoint endpoint = createEndPoint(channel,key); key.attach(endpoint); endpoint.schedule(); } else { key.cancel(); } } } else { // Wrap readable registered channel in an endpoint channel = (SocketChannel)key.channel(); SelectChannelEndPoint endpoint = createEndPoint(channel,key); key.attach(endpoint); if (key.isReadable()) endpoint.schedule(); } key = null; } catch (CancelledKeyException e) { LOG.ignore(e); } catch (Exception e) { if (isRunning()) LOG.warn(e); else LOG.ignore(e); try { if (channel!=null) channel.close(); } catch(IOException e2) { LOG.debug(e2); } if (key != null && !(key.channel() instanceof ServerSocketChannel) && key.isValid()) key.cancel(); } } // Everything always handled selector.selectedKeys().clear(); now=System.currentTimeMillis(); _timeout.setNow(now); Task task = _timeout.expired(); while (task!=null) { if (task instanceof Runnable) dispatch((Runnable)task); task = _timeout.expired(); } // Idle tick if (now-_idleTick>__IDLE_TICK) { _idleTick=now; final long idle_now=((_lowResourcesConnections>0 && selector.keys().size()>_lowResourcesConnections)) ?(now+_maxIdleTime-_lowResourcesMaxIdleTime) :now; dispatch(new Runnable() { public void run() { for (SelectChannelEndPoint endp:_endPoints.keySet()) { endp.checkIdleTimestamp(idle_now); } } public String toString() {return "Idle-"+super.toString();} }); } // Reset busy select monitor counts if (__MONITOR_PERIOD>0 && now>_monitorNext) { _busySelects=0; _pausing=false; _monitorNext=now+__MONITOR_PERIOD; } } catch (ClosedSelectorException e) { if (isRunning()) LOG.warn(e); else LOG.ignore(e); } catch (CancelledKeyException e) { LOG.ignore(e); } finally { _selecting=null; } } /* ------------------------------------------------------------ */ private void renewSelector() { try { synchronized (this) { Selector selector=_selector; if (selector==null) return; final Selector new_selector = Selector.open(); for (SelectionKey k: selector.keys()) { if (!k.isValid() || k.interestOps()==0) continue; final SelectableChannel channel = k.channel(); final Object attachment = k.attachment(); if (attachment==null) addChange(channel); else addChange(channel,attachment); } _selector.close(); _selector=new_selector; } } catch(IOException e) { throw new RuntimeException("recreating selector",e); } } /* ------------------------------------------------------------ */ public SelectorManager getManager() { return SelectorManager.this; } /* ------------------------------------------------------------ */ public long getNow() { return _timeout.getNow(); } /* ------------------------------------------------------------ */ /** * @param task The task to timeout. If it implements Runnable, then * expired will be called from a dispatched thread. * * @param timeoutMs */ public void scheduleTimeout(Timeout.Task task, long timeoutMs) { if (!(task instanceof Runnable)) throw new IllegalArgumentException("!Runnable"); _timeout.schedule(task, timeoutMs); } /* ------------------------------------------------------------ */ public void cancelTimeout(Timeout.Task task) { task.cancel(); } /* ------------------------------------------------------------ */ public void wakeup() { try { Selector selector = _selector; if (selector!=null) selector.wakeup(); } catch(Exception e) { addChange(new ChangeTask() { public void run() { renewSelector(); } }); renewSelector(); } } /* ------------------------------------------------------------ */ private SelectChannelEndPoint createEndPoint(SocketChannel channel, SelectionKey sKey) throws IOException { SelectChannelEndPoint endp = newEndPoint(channel,this,sKey); LOG.debug("created {}",endp); endPointOpened(endp); _endPoints.put(endp,this); return endp; } /* ------------------------------------------------------------ */ public void destroyEndPoint(SelectChannelEndPoint endp) { LOG.debug("destroyEndPoint {}",endp); _endPoints.remove(endp); endPointClosed(endp); } /* ------------------------------------------------------------ */ Selector getSelector() { return _selector; } /* ------------------------------------------------------------ */ void stop() throws Exception { // Spin for a while waiting for selector to complete // to avoid unneccessary closed channel exceptions try { for (int i=0;i<100 && _selecting!=null;i++) { wakeup(); Thread.sleep(10); } } catch(Exception e) { LOG.ignore(e); } // close endpoints and selector synchronized (this) { Selector selector=_selector; for (SelectionKey key:selector.keys()) { if (key==null) continue; Object att=key.attachment(); if (att instanceof EndPoint) { EndPoint endpoint = (EndPoint)att; try { endpoint.close(); } catch(IOException e) { LOG.ignore(e); } } } _timeout.cancelAll(); try { selector=_selector; if (selector != null) selector.close(); } catch (IOException e) { LOG.ignore(e); } _selector=null; } } /* ------------------------------------------------------------ */ public String dump() { return AggregateLifeCycle.dump(this); } /* ------------------------------------------------------------ */ public void dump(Appendable out, String indent) throws IOException { out.append(String.valueOf(this)).append(" id=").append(String.valueOf(_setID)).append("\n"); Thread selecting = _selecting; Object where = "not selecting"; StackTraceElement[] trace =selecting==null?null:selecting.getStackTrace(); if (trace!=null) { for (StackTraceElement t:trace) if (t.getClassName().startsWith("org.eclipse.jetty.")) { where=t; break; } } Selector selector=_selector; if (selector!=null) { final ArrayList dump = new ArrayList(selector.keys().size()*2); dump.add(where); final CountDownLatch latch = new CountDownLatch(1); addChange(new ChangeTask() { public void run() { dumpKeyState(dump); latch.countDown(); } }); try { latch.await(5,TimeUnit.SECONDS); } catch(InterruptedException e) { LOG.ignore(e); } AggregateLifeCycle.dump(out,indent,dump); } } /* ------------------------------------------------------------ */ public void dumpKeyState(List dumpto) { Selector selector=_selector; Set keys = selector.keys(); dumpto.add(selector + " keys=" + keys.size()); for (SelectionKey key: keys) { if (key.isValid()) dumpto.add(key.attachment()+" iOps="+key.interestOps()+" rOps="+key.readyOps()); else dumpto.add(key.attachment()+" iOps=-1 rOps=-1"); } } /* ------------------------------------------------------------ */ public String toString() { Selector selector=_selector; return String.format("%s keys=%d selected=%d", super.toString(), selector != null && selector.isOpen() ? selector.keys().size() : -1, selector != null && selector.isOpen() ? selector.selectedKeys().size() : -1); } } /* ------------------------------------------------------------ */ private static class ChannelAndAttachment { final SelectableChannel _channel; final Object _attachment; public ChannelAndAttachment(SelectableChannel channel, Object attachment) { super(); _channel = channel; _attachment = attachment; } } /* ------------------------------------------------------------ */ public boolean isDeferringInterestedOps0() { return _deferringInterestedOps0; } /* ------------------------------------------------------------ */ public void setDeferringInterestedOps0(boolean deferringInterestedOps0) { _deferringInterestedOps0 = deferringInterestedOps0; } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ private interface ChangeTask extends Runnable {} } jetty8-8.1.3/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java000066400000000000000000000651451174773561500273770ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicBoolean; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.Timeout.Task; /* ------------------------------------------------------------ */ /** SSL Connection. * An AysyncConnection that acts as an interceptor between and EndPoint and another * Connection, that implements TLS encryption using an {@link SSLEngine}. *

    * The connector uses an {@link AsyncEndPoint} (like {@link SelectChannelEndPoint}) as * it's source/sink of encrypted data. It then provides {@link #getSslEndPoint()} to * expose a source/sink of unencrypted data to another connection (eg HttpConnection). */ public class SslConnection extends AbstractConnection implements AsyncConnection { private final Logger _logger = Log.getLogger("org.eclipse.jetty.io.nio.ssl"); private static final NIOBuffer __ZERO_BUFFER=new IndirectNIOBuffer(0); private static final ThreadLocal __buffers = new ThreadLocal(); private final SSLEngine _engine; private final SSLSession _session; private AsyncConnection _connection; private final SslEndPoint _sslEndPoint; private int _allocations; private SslBuffers _buffers; private NIOBuffer _inbound; private NIOBuffer _unwrapBuf; private NIOBuffer _outbound; private AsyncEndPoint _aEndp; private boolean _allowRenegotiate=true; private boolean _handshook; private boolean _ishut; private boolean _oshut; private final AtomicBoolean _progressed = new AtomicBoolean(); /* ------------------------------------------------------------ */ /* this is a half baked buffer pool */ private static class SslBuffers { final NIOBuffer _in; final NIOBuffer _out; final NIOBuffer _unwrap; SslBuffers(int packetSize, int appSize) { _in=new IndirectNIOBuffer(packetSize); _out=new IndirectNIOBuffer(packetSize); _unwrap=new IndirectNIOBuffer(appSize); } } /* ------------------------------------------------------------ */ public SslConnection(SSLEngine engine,EndPoint endp) { this(engine,endp,System.currentTimeMillis()); } /* ------------------------------------------------------------ */ public SslConnection(SSLEngine engine,EndPoint endp, long timeStamp) { super(endp,timeStamp); _engine=engine; _session=_engine.getSession(); _aEndp=(AsyncEndPoint)endp; _sslEndPoint = newSslEndPoint(); } /* ------------------------------------------------------------ */ protected SslEndPoint newSslEndPoint() { return new SslEndPoint(); } /* ------------------------------------------------------------ */ /** * @return True if SSL re-negotiation is allowed (default false) */ public boolean isAllowRenegotiate() { return _allowRenegotiate; } /* ------------------------------------------------------------ */ /** * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered * a vulnerability in SSL/TLS with re-negotiation. If your JVM * does not have CVE-2009-3555 fixed, then re-negotiation should * not be allowed. CVE-2009-3555 was fixed in Sun java 1.6 with a ban * of renegotiates in u19 and with RFC5746 in u22. * * @param allowRenegotiate * true if re-negotiation is allowed (default false) */ public void setAllowRenegotiate(boolean allowRenegotiate) { _allowRenegotiate = allowRenegotiate; } /* ------------------------------------------------------------ */ private void allocateBuffers() { synchronized (this) { if (_allocations++==0) { if (_buffers==null) { _buffers=__buffers.get(); if (_buffers==null) _buffers=new SslBuffers(_session.getPacketBufferSize()*2,_session.getApplicationBufferSize()*2); _inbound=_buffers._in; _outbound=_buffers._out; _unwrapBuf=_buffers._unwrap; __buffers.set(null); } } } } /* ------------------------------------------------------------ */ private void releaseBuffers() { synchronized (this) { if (--_allocations==0) { if (_buffers!=null && _inbound.length()==0 && _outbound.length()==0 && _unwrapBuf.length()==0) { _inbound=null; _outbound=null; _unwrapBuf=null; __buffers.set(_buffers); _buffers=null; } } } } /* ------------------------------------------------------------ */ public Connection handle() throws IOException { try { allocateBuffers(); boolean progress=true; while (progress) { progress=false; // If we are handshook let the delegate connection if (_engine.getHandshakeStatus()!=HandshakeStatus.NOT_HANDSHAKING) progress=process(null,null); // handle the delegate connection AsyncConnection next = (AsyncConnection)_connection.handle(); if (next!=_connection && next!=null) { _connection=next; progress=true; } _logger.debug("{} handle {} progress={}", _session, this, progress); } } finally { releaseBuffers(); if (!_ishut && _sslEndPoint.isInputShutdown() && _sslEndPoint.isOpen()) { _ishut=true; try { _connection.onInputShutdown(); } catch(Throwable x) { _logger.warn("onInputShutdown failed", x); try{_sslEndPoint.close();} catch(IOException e2){ _logger.ignore(e2);} } } } return this; } /* ------------------------------------------------------------ */ public boolean isIdle() { return false; } /* ------------------------------------------------------------ */ public boolean isSuspended() { return false; } /* ------------------------------------------------------------ */ public void onClose() { Connection connection = _sslEndPoint.getConnection(); if (connection != null && connection != this) connection.onClose(); } /* ------------------------------------------------------------ */ @Override public void onIdleExpired(long idleForMs) { try { _logger.debug("onIdleExpired {}ms on {}",idleForMs,this); if (_endp.isOutputShutdown()) _sslEndPoint.close(); else _sslEndPoint.shutdownOutput(); } catch (IOException e) { _logger.warn(e); super.onIdleExpired(idleForMs); } } /* ------------------------------------------------------------ */ public void onInputShutdown() throws IOException { } /* ------------------------------------------------------------ */ private synchronized boolean process(Buffer toFill, Buffer toFlush) throws IOException { boolean some_progress=false; try { // We need buffers to progress allocateBuffers(); // if we don't have a buffer to put received data into if (toFill==null) { // use the unwrapbuffer to hold received data. _unwrapBuf.compact(); toFill=_unwrapBuf; } // Else if the fill buffer is too small for the SSL session else if (toFill.capacity()<_session.getApplicationBufferSize()) { // fill to the temporary unwrapBuffer boolean progress=process(null,toFlush); // if we received any data, if (_unwrapBuf!=null && _unwrapBuf.hasContent()) { // transfer from temp buffer to fill buffer _unwrapBuf.skip(toFill.put(_unwrapBuf)); return true; } else // return progress from recursive call return progress; } // Else if there is some temporary data else if (_unwrapBuf!=null && _unwrapBuf.hasContent()) { // transfer from temp buffer to fill buffer _unwrapBuf.skip(toFill.put(_unwrapBuf)); return true; } // If we are here, we have a buffer ready into which we can put some read data. // If we have no data to flush, flush the empty buffer if (toFlush==null) toFlush=__ZERO_BUFFER; // While we are making progress processing SSL engine boolean progress=true; while (progress) { progress=false; // Do any real IO int filled=0,flushed=0; try { // Read any available data if (_inbound.space()>0 && (filled=_endp.fill(_inbound))>0) progress = true; // flush any output data if (_outbound.hasContent() && (flushed=_endp.flush(_outbound))>0) progress = true; } catch (IOException e) { _endp.close(); throw e; } finally { _logger.debug("{} {} {} filled={}/{} flushed={}/{}",_session,this,_engine.getHandshakeStatus(),filled,_inbound.length(),flushed,_outbound.length()); } // handle the current hand share status switch(_engine.getHandshakeStatus()) { case FINISHED: throw new IllegalStateException(); case NOT_HANDSHAKING: { // Try unwrapping some application data if (toFill.space()>0 && _inbound.hasContent() && unwrap(toFill)) progress=true; // Try wrapping some application data if (toFlush.hasContent() && _outbound.space()>0 && wrap(toFlush)) progress=true; } break; case NEED_TASK: { // A task needs to be run, so run it! Runnable task; while ((task=_engine.getDelegatedTask())!=null) { progress=true; task.run(); } } break; case NEED_WRAP: { // The SSL needs to send some handshake data to the other side if (_handshook && !_allowRenegotiate) _endp.close(); else if (wrap(toFlush)) progress=true; } break; case NEED_UNWRAP: { // The SSL needs to receive some handshake data from the other side if (_handshook && !_allowRenegotiate) _endp.close(); else if (!_inbound.hasContent()&&filled==-1) { // No more input coming _endp.shutdownInput(); } else if (unwrap(toFill)) progress=true; } break; } // pass on ishut/oshut state if (_endp.isOpen() && _endp.isInputShutdown() && !_inbound.hasContent()) _engine.closeInbound(); if (_endp.isOpen() && _engine.isOutboundDone() && !_outbound.hasContent()) _endp.shutdownOutput(); // remember if any progress has been made some_progress|=progress; } // If we are reading into the temp buffer and it has some content, then we should be dispatched. if (toFill==_unwrapBuf && _unwrapBuf.hasContent() && !_connection.isSuspended()) _aEndp.dispatch(); } finally { releaseBuffers(); if (some_progress) _progressed.set(true); } return some_progress; } private synchronized boolean wrap(final Buffer buffer) throws IOException { ByteBuffer bbuf=extractByteBuffer(buffer); final SSLEngineResult result; synchronized(bbuf) { _outbound.compact(); ByteBuffer out_buffer=_outbound.getByteBuffer(); synchronized(out_buffer) { try { bbuf.position(buffer.getIndex()); bbuf.limit(buffer.putIndex()); out_buffer.position(_outbound.putIndex()); out_buffer.limit(out_buffer.capacity()); result=_engine.wrap(bbuf,out_buffer); if (_logger.isDebugEnabled()) _logger.debug("{} wrap {} {} consumed={} produced={}", _session, result.getStatus(), result.getHandshakeStatus(), result.bytesConsumed(), result.bytesProduced()); buffer.skip(result.bytesConsumed()); _outbound.setPutIndex(_outbound.putIndex()+result.bytesProduced()); } catch(SSLException e) { _logger.debug(String.valueOf(_endp), e); _endp.close(); throw e; } finally { out_buffer.position(0); out_buffer.limit(out_buffer.capacity()); bbuf.position(0); bbuf.limit(bbuf.capacity()); } } } switch(result.getStatus()) { case BUFFER_UNDERFLOW: throw new IllegalStateException(); case BUFFER_OVERFLOW: break; case OK: if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) _handshook=true; break; case CLOSED: _logger.debug("wrap CLOSE {} {}",this,result); if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) _endp.close(); break; default: _logger.debug("{} wrap default {}",_session,result); throw new IOException(result.toString()); } return result.bytesConsumed()>0 || result.bytesProduced()>0; } private synchronized boolean unwrap(final Buffer buffer) throws IOException { if (!_inbound.hasContent()) return false; ByteBuffer bbuf=extractByteBuffer(buffer); final SSLEngineResult result; synchronized(bbuf) { ByteBuffer in_buffer=_inbound.getByteBuffer(); synchronized(in_buffer) { try { bbuf.position(buffer.putIndex()); bbuf.limit(buffer.capacity()); in_buffer.position(_inbound.getIndex()); in_buffer.limit(_inbound.putIndex()); result=_engine.unwrap(in_buffer,bbuf); if (_logger.isDebugEnabled()) _logger.debug("{} unwrap {} {} consumed={} produced={}", _session, result.getStatus(), result.getHandshakeStatus(), result.bytesConsumed(), result.bytesProduced()); _inbound.skip(result.bytesConsumed()); _inbound.compact(); buffer.setPutIndex(buffer.putIndex()+result.bytesProduced()); } catch(SSLException e) { _logger.debug(String.valueOf(_endp), e); _endp.close(); throw e; } finally { in_buffer.position(0); in_buffer.limit(in_buffer.capacity()); bbuf.position(0); bbuf.limit(bbuf.capacity()); } } } switch(result.getStatus()) { case BUFFER_UNDERFLOW: if (_endp.isInputShutdown()) _inbound.clear(); break; case BUFFER_OVERFLOW: if (_logger.isDebugEnabled()) _logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString()); break; case OK: if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) _handshook=true; break; case CLOSED: _logger.debug("unwrap CLOSE {} {}",this,result); if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) _endp.close(); break; default: _logger.debug("{} wrap default {}",_session,result); throw new IOException(result.toString()); } //if (LOG.isDebugEnabled() && result.bytesProduced()>0) // LOG.debug("{} unwrapped '{}'",_session,buffer); return result.bytesConsumed()>0 || result.bytesProduced()>0; } /* ------------------------------------------------------------ */ private ByteBuffer extractByteBuffer(Buffer buffer) { if (buffer.buffer() instanceof NIOBuffer) return ((NIOBuffer)buffer.buffer()).getByteBuffer(); return ByteBuffer.wrap(buffer.array()); } /* ------------------------------------------------------------ */ public AsyncEndPoint getSslEndPoint() { return _sslEndPoint; } /* ------------------------------------------------------------ */ public String toString() { return String.format("%s %s", super.toString(), _sslEndPoint); } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ public class SslEndPoint implements AsyncEndPoint { public SSLEngine getSslEngine() { return _engine; } public AsyncEndPoint getEndpoint() { return _aEndp; } public void shutdownOutput() throws IOException { synchronized (SslConnection.this) { _logger.debug("{} ssl endp.oshut {}",_session,this); _engine.closeOutbound(); _oshut=true; } flush(); } public boolean isOutputShutdown() { synchronized (SslConnection.this) { return _oshut||!isOpen()||_engine.isOutboundDone(); } } public void shutdownInput() throws IOException { _logger.debug("{} ssl endp.ishut!",_session); // We do not do a closeInput here, as SSL does not support half close. // isInputShutdown works it out itself from buffer state and underlying endpoint state. } public boolean isInputShutdown() { synchronized (SslConnection.this) { return _endp.isInputShutdown() && !(_unwrapBuf!=null&&_unwrapBuf.hasContent()) && !(_inbound!=null&&_inbound.hasContent()); } } public void close() throws IOException { _logger.debug("{} ssl endp.close",_session); _endp.close(); } public int fill(Buffer buffer) throws IOException { int size=buffer.length(); process(buffer, null); int filled=buffer.length()-size; if (filled==0 && isInputShutdown()) return -1; return filled; } public int flush(Buffer buffer) throws IOException { int size = buffer.length(); process(null, buffer); return size-buffer.length(); } public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException { if (header!=null && header.hasContent()) return flush(header); if (buffer!=null && buffer.hasContent()) return flush(buffer); if (trailer!=null && trailer.hasContent()) return flush(trailer); return 0; } public boolean blockReadable(long millisecs) throws IOException { long now = System.currentTimeMillis(); long end=millisecs>0?(now+millisecs):Long.MAX_VALUE; while (now0) assertEquals(i,index); else assertEquals(-1,index); } } @Test public void testGetBuffer() { for (int i=0; i0) assertEquals(i,b.peek(1)-'0'); else assertEquals(null,b); } } @Test public void testLookupBuffer() { for (int i=0; i0) assertSame(""+i, S[i], b.toString()); else { assertNotSame(""+i, S[i], b.toString()); assertEquals(""+i, S[i], b.toString()); } } } @Test public void testLookupPartialBuffer() { cache.add("44444",4); ByteArrayBuffer buf=new ByteArrayBuffer("44444"); Buffer b=cache.lookup(buf); assertEquals("44444",b.toString()); assertEquals(4,cache.getOrdinal(b)); buf=new ByteArrayBuffer("4444"); b=cache.lookup(buf); assertEquals(-1,cache.getOrdinal(b)); buf=new ByteArrayBuffer("44444x"); b=cache.lookup(buf); assertEquals(-1,cache.getOrdinal(b)); } @Test public void testInsensitiveLookupBuffer() { for (int i=0; i0) assertSame("test"+i, S[i], b.toString()); else assertNotSame("test"+i, S[i], b.toString()); } } @Test public void testToString() { for (int i=0; i0) assertSame(S[i], b); else assertNotSame(S[i], b); } } } jetty8-8.1.3/jetty-io/src/test/java/org/eclipse/jetty/io/BufferTest.java000066400000000000000000000174501174773561500261310ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; import org.eclipse.jetty.io.nio.DirectNIOBuffer; import org.eclipse.jetty.io.nio.IndirectNIOBuffer; import org.eclipse.jetty.io.nio.RandomAccessFileBuffer; import org.eclipse.jetty.util.StringUtil; import org.junit.Before; import org.junit.Test; /** * */ public class BufferTest { private Buffer[] buffer; @Before public void init() throws Exception { File file = File.createTempFile("test",".buf"); file.deleteOnExit(); buffer=new Buffer[]{ new RandomAccessFileBuffer(file,10), new ByteArrayBuffer(10), new IndirectNIOBuffer(10), new DirectNIOBuffer(10) }; } @Test public void testBuffer() throws Exception { for (int i=0;i { public static class EndPointPair { public T client; public T server; } protected abstract EndPointPair newConnection() throws Exception; @Test public void testClientServerExchange() throws Exception { EndPointPair c = newConnection(); Buffer buffer = new IndirectNIOBuffer(4096); // Client sends a request c.client.flush(new ByteArrayBuffer("request")); // Server receives the request int len = c.server.fill(buffer); assertEquals(7,len); assertEquals("request",buffer.toString()); // Client and server are open assertTrue(c.client.isOpen()); assertFalse(c.client.isInputShutdown()); assertFalse(c.client.isOutputShutdown()); assertTrue(c.server.isOpen()); assertFalse(c.server.isInputShutdown()); assertFalse(c.server.isOutputShutdown()); // Server sends response and closes output c.server.flush(new ByteArrayBuffer("response")); c.server.shutdownOutput(); // client server are open, server is oshut assertTrue(c.client.isOpen()); assertFalse(c.client.isInputShutdown()); assertFalse(c.client.isOutputShutdown()); assertTrue(c.server.isOpen()); assertFalse(c.server.isInputShutdown()); assertTrue(c.server.isOutputShutdown()); // Client reads response buffer.clear(); len = c.client.fill(buffer); assertEquals(8,len); assertEquals("response",buffer.toString()); // Client and server are open, server is oshut assertTrue(c.client.isOpen()); assertFalse(c.client.isInputShutdown()); assertFalse(c.client.isOutputShutdown()); assertTrue(c.server.isOpen()); assertFalse(c.server.isInputShutdown()); assertTrue(c.server.isOutputShutdown()); // Client reads -1 buffer.clear(); len = c.client.fill(buffer); assertEquals(-1,len); // Client and server are open, server is oshut, client is ishut assertTrue(c.client.isOpen()); assertTrue(c.client.isInputShutdown()); assertFalse(c.client.isOutputShutdown()); assertTrue(c.server.isOpen()); assertFalse(c.server.isInputShutdown()); assertTrue(c.server.isOutputShutdown()); // Client shutsdown output, which is a close because already ishut c.client.shutdownOutput(); // Client is closed. Server is open and oshut assertFalse(c.client.isOpen()); assertTrue(c.client.isInputShutdown()); assertTrue(c.client.isOutputShutdown()); assertTrue(c.server.isOpen()); assertFalse(c.server.isInputShutdown()); assertTrue(c.server.isOutputShutdown()); // Server reads close buffer.clear(); len = c.server.fill(buffer); assertEquals(-1,len); // Client and Server are closed assertFalse(c.client.isOpen()); assertTrue(c.client.isInputShutdown()); assertTrue(c.client.isOutputShutdown()); assertFalse(c.server.isOpen()); assertTrue(c.server.isInputShutdown()); assertTrue(c.server.isOutputShutdown()); } @Test public void testClientClose() throws Exception { EndPointPair c = newConnection(); Buffer buffer = new IndirectNIOBuffer(4096); c.client.flush(new ByteArrayBuffer("request")); int len = c.server.fill(buffer); assertEquals(7,len); assertEquals("request",buffer.toString()); assertTrue(c.client.isOpen()); assertFalse(c.client.isInputShutdown()); assertFalse(c.client.isOutputShutdown()); assertTrue(c.server.isOpen()); assertFalse(c.server.isInputShutdown()); assertFalse(c.server.isOutputShutdown()); c.client.close(); assertFalse(c.client.isOpen()); assertTrue(c.client.isInputShutdown()); assertTrue(c.client.isOutputShutdown()); assertTrue(c.server.isOpen()); assertFalse(c.server.isInputShutdown()); assertFalse(c.server.isOutputShutdown()); len = c.server.fill(buffer); assertEquals(-1,len); assertFalse(c.client.isOpen()); assertTrue(c.client.isInputShutdown()); assertTrue(c.client.isOutputShutdown()); assertTrue(c.server.isOpen()); assertTrue(c.server.isInputShutdown()); assertFalse(c.server.isOutputShutdown()); c.server.shutdownOutput(); assertFalse(c.client.isOpen()); assertTrue(c.client.isInputShutdown()); assertTrue(c.client.isOutputShutdown()); assertFalse(c.server.isOpen()); assertTrue(c.server.isInputShutdown()); assertTrue(c.server.isOutputShutdown()); } } jetty8-8.1.3/jetty-io/src/test/java/org/eclipse/jetty/io/IOTest.java000066400000000000000000000245271174773561500252320ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import junit.framework.Assert; import org.eclipse.jetty.toolchain.test.OS; import org.eclipse.jetty.util.IO; import org.junit.Test; /** * */ public class IOTest { @Test public void testIO() throws InterruptedException { // Only a little test ByteArrayInputStream in = new ByteArrayInputStream ("The quick brown fox jumped over the lazy dog".getBytes()); ByteArrayOutputStream out = new ByteArrayOutputStream(); IO.copyThread(in,out); Thread.sleep(1500); // System.err.println(out); assertEquals( "copyThread", out.toString(), "The quick brown fox jumped over the lazy dog"); } @Test public void testHalfClose() throws Exception { ServerSocket connector = new ServerSocket(0); Socket client = new Socket("localhost",connector.getLocalPort()); Socket server = connector.accept(); // we can write both ways client.getOutputStream().write(1); assertEquals(1,server.getInputStream().read()); server.getOutputStream().write(1); assertEquals(1,client.getInputStream().read()); // shutdown output results in read -1 client.shutdownOutput(); assertEquals(-1,server.getInputStream().read()); // Even though EOF has been read, the server input is not seen as shutdown assertFalse(server.isInputShutdown()); // and we can read -1 again assertEquals(-1,server.getInputStream().read()); // but cannot write try { client.getOutputStream().write(1); fail("exception expected"); } catch (SocketException e) {} // but can still write in opposite direction. server.getOutputStream().write(1); assertEquals(1,client.getInputStream().read()); // server can shutdown input to match the shutdown out of client server.shutdownInput(); // now we EOF instead of reading -1 try { server.getInputStream().read(); fail("exception expected"); } catch (SocketException e) {} // but can still write in opposite direction. server.getOutputStream().write(1); assertEquals(1,client.getInputStream().read()); // client can shutdown input client.shutdownInput(); // now we EOF instead of reading -1 try { client.getInputStream().read(); fail("exception expected"); } catch (SocketException e) {} // But we can still write at the server (data which will never be read) server.getOutputStream().write(1); // and the server output is not shutdown assertFalse( server.isOutputShutdown() ); // until we explictly shut it down server.shutdownOutput(); // and now we can't write try { server.getOutputStream().write(1); fail("exception expected"); } catch (SocketException e) {} // but the sockets are still open assertFalse(client.isClosed()); assertFalse(server.isClosed()); // but if we close one end client.close(); // it is seen as closed. assertTrue(client.isClosed()); // but not the other end assertFalse(server.isClosed()); // which has to be closed explictly server.close(); assertTrue(server.isClosed()); } @Test public void testHalfCloseClientServer() throws Exception { ServerSocketChannel connector = ServerSocketChannel.open(); connector.socket().bind(null); Socket client = SocketChannel.open(connector.socket().getLocalSocketAddress()).socket(); client.setSoTimeout(1000); client.setSoLinger(false,-1); Socket server = connector.accept().socket(); server.setSoTimeout(1000); server.setSoLinger(false,-1); // Write from client to server client.getOutputStream().write(1); // Server reads assertEquals(1,server.getInputStream().read()); // Write from server to client with oshut server.getOutputStream().write(1); // System.err.println("OSHUT "+server); server.shutdownOutput(); // Client reads response assertEquals(1,client.getInputStream().read()); try { // Client reads -1 and does ishut assertEquals(-1,client.getInputStream().read()); assertFalse(client.isInputShutdown()); //System.err.println("ISHUT "+client); client.shutdownInput(); // Client ??? //System.err.println("OSHUT "+client); client.shutdownOutput(); //System.err.println("CLOSE "+client); client.close(); // Server reads -1, does ishut and then close assertEquals(-1,server.getInputStream().read()); assertFalse(server.isInputShutdown()); //System.err.println("ISHUT "+server); try { server.shutdownInput(); } catch(SocketException e) { // System.err.println(e); } //System.err.println("CLOSE "+server); server.close(); } catch(Exception e) { System.err.println(e); assertTrue(OS.IS_OSX); } } @Test public void testHalfCloseBadClient() throws Exception { ServerSocketChannel connector = ServerSocketChannel.open(); connector.socket().bind(null); Socket client = SocketChannel.open(connector.socket().getLocalSocketAddress()).socket(); client.setSoTimeout(1000); client.setSoLinger(false,-1); Socket server = connector.accept().socket(); server.setSoTimeout(1000); server.setSoLinger(false,-1); // Write from client to server client.getOutputStream().write(1); // Server reads assertEquals(1,server.getInputStream().read()); // Write from server to client with oshut server.getOutputStream().write(1); //System.err.println("OSHUT "+server); server.shutdownOutput(); try { // Client reads response assertEquals(1,client.getInputStream().read()); // Client reads -1 assertEquals(-1,client.getInputStream().read()); assertFalse(client.isInputShutdown()); // Client can still write as we are half closed client.getOutputStream().write(1); // Server can still read assertEquals(1,server.getInputStream().read()); // Server now closes server.close(); // Client still reads -1 (not broken pipe !!) assertEquals(-1,client.getInputStream().read()); assertFalse(client.isInputShutdown()); Thread.sleep(100); // Client still reads -1 (not broken pipe !!) assertEquals(-1,client.getInputStream().read()); assertFalse(client.isInputShutdown()); // Client can still write data even though server is closed??? client.getOutputStream().write(1); // Client eventually sees Broken Pipe int i=0; try { for (i=0;i<100000;i++) client.getOutputStream().write(1); Assert.fail(); } catch (IOException e) { } client.close(); } catch (Exception e) { System.err.println("PLEASE INVESTIGATE:"); e.printStackTrace(); } } @Test public void testReset() throws Exception { ServerSocket connector; Socket client; Socket server; connector = new ServerSocket(0); client = new Socket("127.0.0.1",connector.getLocalPort()); server = connector.accept(); client.setTcpNoDelay(true); client.setSoLinger(true,0); server.setTcpNoDelay(true); server.setSoLinger(true,0); client.getOutputStream().write(1); assertEquals(1,server.getInputStream().read()); server.getOutputStream().write(1); assertEquals(1,client.getInputStream().read()); // Server generator shutdowns output after non persistent sending response. server.shutdownOutput(); // client endpoint reads EOF and shutdown input as result assertEquals(-1,client.getInputStream().read()); client.shutdownInput(); // client connection see's EOF and shutsdown output as no more requests to be sent. client.shutdownOutput(); // Since input already shutdown, client also closes socket. client.close(); // Server reads the EOF from client oshut and shut's down it's input assertEquals(-1,server.getInputStream().read()); server.shutdownInput(); // Since output was already shutdown, server closes server.close(); } } jetty8-8.1.3/jetty-io/src/test/java/org/eclipse/jetty/io/ThreadLocalBuffersTest.java000066400000000000000000000156101174773561500304130ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicLong; import org.eclipse.jetty.toolchain.test.Stress; import org.junit.Test; public class ThreadLocalBuffersTest { private Buffers httpBuffers; private List threadList = new ArrayList(); private int numThreads = Stress.isEnabled()?100:10; private int runTestLength = Stress.isEnabled()?5000:1000; private boolean runTest = false; private AtomicLong buffersRetrieved; private void execAbstractBuffer() throws Exception { threadList.clear(); buffersRetrieved = new AtomicLong( 0 ); httpBuffers = new InnerBuffers(1024,4096); for ( int i = 0; i < numThreads; ++i ) { threadList.add( new BufferPeeper( "BufferPeeper: " + i ) ); } System.gc(); System.gc(); System.gc(); System.gc(); System.gc(); System.gc(); System.gc(); System.gc(); long mem0 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); runTest = true; Thread.sleep( runTestLength ); System.gc(); System.gc(); System.gc(); System.gc(); System.gc(); System.gc(); System.gc(); System.gc(); long mem1 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); runTest = false; long totalBuffersRetrieved = buffersRetrieved.get(); System.out.println( "Buffers Retrieved: " + totalBuffersRetrieved ); System.out.println( "Memory Used: " + ( mem1 - mem0 ) ); for (Thread t : threadList) t.stop(); } @Test public void testAbstractBuffers() throws Exception { execAbstractBuffer( ); } @Test public void testDifferentSizes() throws Exception { InnerBuffers buffers = new InnerBuffers(128,256); Buffer h1 = buffers.getHeader(); Buffer h2 = buffers.getHeader(); Buffer b1 = buffers.getBuffer(); Buffer b2 = buffers.getBuffer(); Buffer b3 = buffers.getBuffer(512); buffers.returnBuffer(h1); buffers.returnBuffer(h2); buffers.returnBuffer(b1); buffers.returnBuffer(b2); buffers.returnBuffer(b3); assertTrue(h1==buffers.getHeader()); // pooled header assertTrue(h2!=buffers.getHeader()); // b2 replaced h2 in other slot assertTrue(b1==buffers.getBuffer()); // pooled buffer assertTrue(b2!=buffers.getBuffer()); // b3 replaced b2 in other slot assertTrue(b3==buffers.getBuffer(512)); // b2 from other slot buffers.returnBuffer(h1); buffers.returnBuffer(h2); buffers.returnBuffer(b1); assertTrue(h1==buffers.getHeader()); // pooled header assertTrue(h2==buffers.getHeader()); // h2 in other slot assertTrue(b1==buffers.getBuffer()); // pooled buffer assertTrue(b2!=buffers.getBuffer()); // new buffer assertTrue(b3!=buffers.getBuffer(512)); // new buffer // check that sizes are respected buffers.returnBuffer(b3); buffers.returnBuffer(b1); buffers.returnBuffer(b2); buffers.returnBuffer(h1); buffers.returnBuffer(h2); assertTrue(h1==buffers.getHeader()); // pooled header assertTrue(h2==buffers.getHeader()); // h2 in other slot assertTrue(b1==buffers.getBuffer()); // pooled buffer assertTrue(b2!=buffers.getBuffer()); // new buffer assertTrue(b3!=buffers.getBuffer(512)); // new buffer } @Test public void testSameSizes() throws Exception { InnerBuffers buffers = new InnerBuffers(128,128); Buffer h1 = buffers.getHeader(); Buffer h2 = buffers.getHeader(); Buffer b1 = buffers.getBuffer(); Buffer b2 = buffers.getBuffer(); Buffer b3 = buffers.getBuffer(128); List known = new ArrayList(); known.add(h1); known.add(h2); known.add(b1); known.add(b2); known.add(b3); buffers.returnBuffer(h1); // header slot * buffers.returnBuffer(h2); // other slot buffers.returnBuffer(b1); // buffer slot * buffers.returnBuffer(b2); // other slot buffers.returnBuffer(b3); // other slot * assertTrue(h1==buffers.getHeader()); // pooled header Buffer buffer = buffers.getHeader(); for (Buffer b:known) assertTrue(b!=buffer); // new buffer assertTrue(b1==buffers.getBuffer()); // b1 used from buffer slot buffer = buffers.getBuffer(); for (Buffer b:known) assertTrue(b!=buffer); // new buffer assertTrue(b3==buffers.getBuffer(128)); // b3 from other slot } private static class HeaderBuffer extends ByteArrayBuffer { public HeaderBuffer(int size) { super(size); } } private static class InnerBuffers extends ThreadLocalBuffers { InnerBuffers(int headerSize,int bufferSize) { super(Type.DIRECT,headerSize,Type.BYTE_ARRAY,bufferSize,Type.INDIRECT); } } private class BufferPeeper extends Thread { private final String _bufferName; public BufferPeeper( String bufferName ) { _bufferName = bufferName; start(); } @Override public void run() { while ( true ) { try { if ( runTest ) { Buffer buf = httpBuffers.getHeader(); buffersRetrieved.getAndIncrement(); buf.put(new Byte("2")); // sleep( threadWaitTime ); httpBuffers.returnBuffer(buf); } else { sleep( 1 ); } } catch ( Exception e ) { e.printStackTrace(); break; } } } } } jetty8-8.1.3/jetty-io/src/test/java/org/eclipse/jetty/io/bio/000077500000000000000000000000001174773561500237575ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/test/java/org/eclipse/jetty/io/bio/SocketEndPointTest.java000066400000000000000000000016561174773561500303630ustar00rootroot00000000000000package org.eclipse.jetty.io.bio; import java.net.ServerSocket; import java.net.Socket; import org.eclipse.jetty.io.EndPointTest; import org.junit.AfterClass; import org.junit.BeforeClass; public class SocketEndPointTest extends EndPointTest { static ServerSocket connector; @BeforeClass public static void open() throws Exception { connector = new ServerSocket(); connector.bind(null); } @AfterClass public static void close() throws Exception { connector.close(); connector=null; } @Override protected EndPointPair newConnection() throws Exception { EndPointPair c = new EndPointPair(); c.client=new SocketEndPoint(new Socket(connector.getInetAddress(),connector.getLocalPort())); c.server=new SocketEndPoint(connector.accept()); return c; } } jetty8-8.1.3/jetty-io/src/test/java/org/eclipse/jetty/io/nio/000077500000000000000000000000001174773561500237735ustar00rootroot00000000000000jetty8-8.1.3/jetty-io/src/test/java/org/eclipse/jetty/io/nio/ChannelEndPointTest.java000066400000000000000000000021601174773561500305060ustar00rootroot00000000000000package org.eclipse.jetty.io.nio; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import org.eclipse.jetty.io.EndPointTest; import org.junit.AfterClass; import org.junit.BeforeClass; public class ChannelEndPointTest extends EndPointTest { static ServerSocketChannel connector; @BeforeClass public static void open() throws Exception { connector = ServerSocketChannel.open(); connector.socket().bind(null); } @AfterClass public static void close() throws Exception { connector.close(); connector=null; } @Override protected EndPointPair newConnection() throws Exception { EndPointPair c = new EndPointPair(); c.client=new ChannelEndPoint(SocketChannel.open(connector.socket().getLocalSocketAddress())); c.server=new ChannelEndPoint(connector.accept()); return c; } @Override public void testClientServerExchange() throws Exception { super.testClientServerExchange(); } } jetty8-8.1.3/jetty-io/src/test/java/org/eclipse/jetty/io/nio/NIOTest.java000066400000000000000000000113501174773561500261230ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.io.nio; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import java.net.ServerSocket; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import org.junit.Test; /** * */ public class NIOTest { @Test public void testSelector() throws Exception { ServerSocket acceptor = new ServerSocket(0); Selector selector = Selector.open(); // Create client server socket pair SocketChannel client = SocketChannel.open(acceptor.getLocalSocketAddress()); Socket server = acceptor.accept(); server.setTcpNoDelay(true); // Make the client non blocking and register it with selector for reads client.configureBlocking(false); SelectionKey key = client.register(selector,SelectionKey.OP_READ); // assert it is not selected assertTrue(key.isValid()); assertFalse(key.isReadable()); assertEquals(0,key.readyOps()); // try selecting and assert nothing selected int selected = selector.selectNow(); assertEquals(0,selected); assertEquals(0,selector.selectedKeys().size()); assertTrue(key.isValid()); assertFalse(key.isReadable()); assertEquals(0,key.readyOps()); // Write a byte from server to client server.getOutputStream().write(42); server.getOutputStream().flush(); // select again and assert selection found for read selected = selector.select(1000); assertEquals(1,selected); assertEquals(1,selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1,key.readyOps()); // select again and see that it is not reselect, but stays selected selected = selector.select(100); assertEquals(0,selected); assertEquals(1,selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1,key.readyOps()); // read the byte ByteBuffer buf = ByteBuffer.allocate(1024); int len=client.read(buf); assertEquals(1,len); buf.flip(); assertEquals(42,buf.get()); buf.clear(); // But this does not change the key assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1,key.readyOps()); // Even if we select again ? selected = selector.select(100); assertEquals(0,selected); assertEquals(1,selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1,key.readyOps()); // Unless we remove the key from the select set // and then it is still flagged as isReadable() selector.selectedKeys().clear(); assertEquals(0,selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1,key.readyOps()); // Now if we select again - it is still flagged as readable!!! selected = selector.select(100); assertEquals(0,selected); assertEquals(0,selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isReadable()); assertEquals(1,key.readyOps()); // Only when it is selected for something else does that state change. key.interestOps(SelectionKey.OP_READ|SelectionKey.OP_WRITE); selected = selector.select(1000); assertEquals(1,selected); assertEquals(1,selector.selectedKeys().size()); assertTrue(key.isValid()); assertTrue(key.isWritable()); assertFalse(key.isReadable()); assertEquals(SelectionKey.OP_WRITE,key.readyOps()); } } jetty8-8.1.3/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java000066400000000000000000000146771174773561500323500ustar00rootroot00000000000000package org.eclipse.jetty.io.nio; import java.io.File; import java.io.IOException; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLSocket; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest { static SslContextFactory __sslCtxFactory=new SslContextFactory(); @BeforeClass public static void initSslEngine() throws Exception { File keystore = MavenTestingUtils.getTestResourceFile("keystore"); __sslCtxFactory.setKeyStorePath(keystore.getAbsolutePath()); __sslCtxFactory.setKeyStorePassword("storepwd"); __sslCtxFactory.setKeyManagerPassword("keypwd"); __sslCtxFactory.start(); } @Override protected Socket newClient() throws IOException { SSLSocket socket = __sslCtxFactory.newSslSocket(); socket.connect(_connector.socket().getLocalSocketAddress()); return socket; } @Override protected AsyncConnection newConnection(SocketChannel channel, EndPoint endpoint) { SSLEngine engine = __sslCtxFactory.newSslEngine(); engine.setUseClientMode(false); SslConnection connection = new SslConnection(engine,endpoint); AsyncConnection delegate = super.newConnection(channel,connection.getSslEndPoint()); connection.getSslEndPoint().setConnection(delegate); return connection; } @Test @Override public void testEcho() throws Exception { super.testEcho(); } @Test @Override public void testShutdown() throws Exception { // SSL does not do half closes } @Test public void testTcpClose() throws Exception { // This test replaces SSLSocket() with a very manual SSL client // so we can close TCP underneath SSL. SocketChannel client = SocketChannel.open(_connector.socket().getLocalSocketAddress()); client.socket().setSoTimeout(500); SocketChannel server = _connector.accept(); server.configureBlocking(false); _manager.register(server); SSLEngine engine = __sslCtxFactory.newSslEngine(); engine.setUseClientMode(true); engine.beginHandshake(); ByteBuffer appOut = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer sslOut = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()*2); ByteBuffer appIn = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer sslIn = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()*2); boolean debug=false; if (debug) System.err.println(engine.getHandshakeStatus()); int loop=20; while (engine.getHandshakeStatus()!=HandshakeStatus.NOT_HANDSHAKING) { if (--loop==0) throw new IllegalStateException(); if (engine.getHandshakeStatus()==HandshakeStatus.NEED_WRAP) { if (debug) System.err.printf("sslOut %d-%d-%d%n",sslOut.position(),sslOut.limit(),sslOut.capacity()); if (debug) System.err.printf("appOut %d-%d-%d%n",appOut.position(),appOut.limit(),appOut.capacity()); SSLEngineResult result =engine.wrap(appOut,sslOut); if (debug) System.err.println(result); sslOut.flip(); int flushed=client.write(sslOut); if (debug) System.err.println("out="+flushed); sslOut.clear(); } if (engine.getHandshakeStatus()==HandshakeStatus.NEED_UNWRAP) { if (debug) System.err.printf("sslIn %d-%d-%d%n",sslIn.position(),sslIn.limit(),sslIn.capacity()); if (sslIn.position()==0) { int filled=client.read(sslIn); if (debug) System.err.println("in="+filled); } sslIn.flip(); if (debug) System.err.printf("sslIn %d-%d-%d%n",sslIn.position(),sslIn.limit(),sslIn.capacity()); SSLEngineResult result =engine.unwrap(sslIn,appIn); if (debug) System.err.println(result); if (debug) System.err.printf("sslIn %d-%d-%d%n",sslIn.position(),sslIn.limit(),sslIn.capacity()); if (sslIn.hasRemaining()) sslIn.compact(); else sslIn.clear(); if (debug) System.err.printf("sslIn %d-%d-%d%n",sslIn.position(),sslIn.limit(),sslIn.capacity()); } if (engine.getHandshakeStatus()==HandshakeStatus.NEED_TASK) { Runnable task; while ((task=engine.getDelegatedTask())!=null) task.run(); if (debug) System.err.println(engine.getHandshakeStatus()); } } if (debug) System.err.println("\nSay Hello"); // write a message appOut.put("HelloWorld".getBytes("UTF-8")); appOut.flip(); SSLEngineResult result =engine.wrap(appOut,sslOut); if (debug) System.err.println(result); sslOut.flip(); int flushed=client.write(sslOut); if (debug) System.err.println("out="+flushed); sslOut.clear(); appOut.clear(); // read the response int filled=client.read(sslIn); if (debug) System.err.println("in="+filled); sslIn.flip(); result =engine.unwrap(sslIn,appIn); if (debug) System.err.println(result); if (sslIn.hasRemaining()) sslIn.compact(); else sslIn.clear(); appIn.flip(); String reply= new String(appIn.array(),appIn.arrayOffset(),appIn.remaining()); appIn.clear(); Assert.assertEquals("HelloWorld",reply); SelectorManager.LOG.info("javax.net.ssl.SSLException: Inbound closed... is expected soon"); if (debug) System.err.println("\nSudden Death"); client.socket().shutdownOutput(); filled=client.read(sslIn); Assert.assertEquals(-1,filled); } @Test public void testStress() throws Exception { super.testStress(); } } jetty8-8.1.3/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java000066400000000000000000000302331174773561500316500ustar00rootroot00000000000000package org.eclipse.jetty.io.nio; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.greaterThan; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.SocketTimeoutException; import java.nio.channels.SelectionKey; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class SelectChannelEndPointTest { protected SelectChannelEndPoint _lastEndp; protected ServerSocketChannel _connector; protected QueuedThreadPool _threadPool = new QueuedThreadPool(); protected SelectorManager _manager = new SelectorManager() { @Override public boolean dispatch(Runnable task) { return _threadPool.dispatch(task); } @Override protected void endPointClosed(SelectChannelEndPoint endpoint) { } @Override protected void endPointOpened(SelectChannelEndPoint endpoint) { } @Override protected void endPointUpgraded(ConnectedEndPoint endpoint, org.eclipse.jetty.io.Connection oldConnection) { } @Override public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment) { return SelectChannelEndPointTest.this.newConnection(channel,endpoint); } @Override protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException { SelectChannelEndPoint endp = new SelectChannelEndPoint(channel,selectSet,key,2000); endp.setConnection(selectSet.getManager().newConnection(channel,endp, key.attachment())); _lastEndp=endp; return endp; } }; // Must be volatile or the test may fail spuriously private volatile int _blockAt=0; @Before public void startManager() throws Exception { _connector = ServerSocketChannel.open(); _connector.socket().bind(null); _threadPool.start(); _manager.start(); } @After public void stopManager() throws Exception { _manager.stop(); _threadPool.stop(); _connector.close(); } protected Socket newClient() throws IOException { return new Socket(_connector.socket().getInetAddress(),_connector.socket().getLocalPort()); } protected AsyncConnection newConnection(SocketChannel channel, EndPoint endpoint) { return new TestConnection(endpoint); } public class TestConnection extends AbstractConnection implements AsyncConnection { NIOBuffer _in = new IndirectNIOBuffer(32*1024); NIOBuffer _out = new IndirectNIOBuffer(32*1024); public TestConnection(EndPoint endp) { super(endp); } public org.eclipse.jetty.io.Connection handle() throws IOException { boolean progress=true; while(progress) { progress=false; _in.compact(); if (_in.space()>0 && _endp.fill(_in)>0) progress=true; while (_blockAt>0 && _in.length()>0 && _in.length()<_blockAt) { _endp.blockReadable(10000); if (_in.space()>0 && _endp.fill(_in)>0) progress=true; } if (_in.hasContent() && _in.skip(_out.put(_in))>0) progress=true; if (_out.hasContent() && _endp.flush(_out)>0) progress=true; _out.compact(); if (!_out.hasContent() && _endp.isInputShutdown()) _endp.shutdownOutput(); } return this; } public boolean isIdle() { return false; } public boolean isSuspended() { return false; } public void onClose() { // System.err.println("onClose"); } public void onInputShutdown() throws IOException { // System.err.println("onInputShutdown"); } } @Test public void testEcho() throws Exception { Socket client = newClient(); client.setSoTimeout(500); SocketChannel server = _connector.accept(); server.configureBlocking(false); _manager.register(server); // Write client to server client.getOutputStream().write("HelloWorld".getBytes("UTF-8")); // Verify echo server to client for (char c : "HelloWorld".toCharArray()) { int b = client.getInputStream().read(); assertTrue(b>0); assertEquals(c,(char)b); } // wait for read timeout long start=System.currentTimeMillis(); try { client.getInputStream().read(); Assert.fail(); } catch(SocketTimeoutException e) { long duration = System.currentTimeMillis()-start; Assert.assertThat("timeout duration", duration, greaterThanOrEqualTo(400L)); } // write then shutdown client.getOutputStream().write("Goodbye Cruel TLS".getBytes("UTF-8")); // Verify echo server to client for (char c : "Goodbye Cruel TLS".toCharArray()) { int b = client.getInputStream().read(); Assert.assertThat("expect valid char integer", b, greaterThan(0)); assertEquals("expect characters to be same", c,(char)b); } client.close(); int i=0; while (server.isOpen()) { assert(i++<10); Thread.sleep(10); } } @Test public void testShutdown() throws Exception { Socket client = newClient(); client.setSoTimeout(500); SocketChannel server = _connector.accept(); server.configureBlocking(false); _manager.register(server); // Write client to server client.getOutputStream().write("HelloWorld".getBytes("UTF-8")); // Verify echo server to client for (char c : "HelloWorld".toCharArray()) { int b = client.getInputStream().read(); assertTrue(b>0); assertEquals(c,(char)b); } // wait for read timeout long start=System.currentTimeMillis(); try { client.getInputStream().read(); Assert.fail(); } catch(SocketTimeoutException e) { assertTrue(System.currentTimeMillis()-start>=400); } // write then shutdown client.getOutputStream().write("Goodbye Cruel TLS".getBytes("UTF-8")); client.shutdownOutput(); // Verify echo server to client for (char c : "Goodbye Cruel TLS".toCharArray()) { int b = client.getInputStream().read(); assertTrue(b>0); assertEquals(c,(char)b); } // Read close assertEquals(-1,client.getInputStream().read()); } @Test public void testBlockIn() throws Exception { Socket client = newClient(); SocketChannel server = _connector.accept(); server.configureBlocking(false); _manager.register(server); OutputStream clientOutputStream = client.getOutputStream(); InputStream clientInputStream = client.getInputStream(); int specifiedTimeout = 400; client.setSoTimeout(specifiedTimeout); // Write 8 and cause block for 10 _blockAt=10; clientOutputStream.write("12345678".getBytes("UTF-8")); clientOutputStream.flush(); Thread.sleep(2 * specifiedTimeout); // No echo as blocking for 10 long start=System.currentTimeMillis(); try { int b = clientInputStream.read(); Assert.fail("Should have timed out waiting for a response, but read "+b); } catch(SocketTimeoutException e) { int elapsed = Long.valueOf(System.currentTimeMillis() - start).intValue(); System.err.println("blocked for " + elapsed+ "ms"); Assert.assertThat("Expected timeout", elapsed, greaterThanOrEqualTo(3*specifiedTimeout/4)); } // write remaining characters clientOutputStream.write("90ABCDEF".getBytes("UTF-8")); clientOutputStream.flush(); // Verify echo server to client for (char c : "1234567890ABCDEF".toCharArray()) { int b = clientInputStream.read(); assertTrue(b>0); assertEquals(c,(char)b); } } @Test public void testIdle() throws Exception { Socket client = newClient(); client.setSoTimeout(3000); SocketChannel server = _connector.accept(); server.configureBlocking(false); _manager.register(server); // Write client to server client.getOutputStream().write("HelloWorld".getBytes("UTF-8")); // Verify echo server to client for (char c : "HelloWorld".toCharArray()) { int b = client.getInputStream().read(); assertTrue(b>0); assertEquals(c,(char)b); } // Set Max idle _lastEndp.setMaxIdleTime(500); // read until idle shutdown received long start=System.currentTimeMillis(); int b=client.getInputStream().read(); assertEquals(-1,b); long idle=System.currentTimeMillis()-start; assertTrue(idle>400); assertTrue(idle<2000); // But endpoint is still open. assertTrue(_lastEndp.isOpen()); // Wait for another idle callback Thread.sleep(2000); // endpoint is closed. assertFalse(_lastEndp.isOpen()); } @Test public void testStress() throws Exception { Socket client = newClient(); client.setSoTimeout(30000); SocketChannel server = _connector.accept(); server.configureBlocking(false); _manager.register(server); int writes = 100000; final byte[] bytes="HelloWorld".getBytes("UTF-8"); final CountDownLatch latch = new CountDownLatch(writes); final InputStream in = new BufferedInputStream(client.getInputStream()); final long start = System.currentTimeMillis(); client.getOutputStream().write(bytes); client.getOutputStream().flush(); new Thread() { public void run() { try { while (latch.getCount()>0) { // Verify echo server to client for (byte b0 : bytes) { int b = in.read(); assertTrue(b>0); assertEquals(0xff&b0,b); } latch.countDown(); } } catch(Throwable e) { System.err.println("latch="+latch.getCount()); System.err.println("time="+(System.currentTimeMillis()-start)); e.printStackTrace(); } } }.start(); // Write client to server for (int i=1;iC $,ʉ@g Alx q* Iq"?1~jܩOl"[z{5anb],*Lu||<6=a$c+9ܢwmŝ`X.5090090  *H 010UUnknown10UUnknown10UUnknown10U Mort Bay Consulting1 0U Open Source Development10U Jetty Server0 001022135544Z 010120135544Z010UUnknown10UUnknown10UUnknown10U Mort Bay Consulting1 0U Open Source Development10U Jetty Server00  *H 04銴*?TVhUzi-. H?Ӡq9>?*]R@NbaI\@`Ŏ L~o==uzջI l E;rNT+4JPd`0  *H =6Bkј@Ъ>hT8V$Gwc\2Hz%eNs"øֶh.[7C|x5mp7=Ogi?QCDOALrPp>羴V[׼q"x?js>!sIAмx8*l:jetty8-8.1.3/jetty-jaspi/000077500000000000000000000000001174773561500152355ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/pom.xml000066400000000000000000000046131174773561500165560ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 jetty-jaspi Jetty :: JASPI Security Jetty security infrastructure ${project.groupId}.jaspi org.apache.felix maven-bundle-plugin true manifest javax.servlet.*;version="2.6.0",* org.eclipse.jetty.security.jaspi.*;version="${parsedVersion.osgiVersion}" org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.jaspi.* org.eclipse.jetty jetty-security ${project.version} junit junit test org.eclipse.jetty.orbit javax.security.auth.message jetty8-8.1.3/jetty-jaspi/src/000077500000000000000000000000001174773561500160245ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/000077500000000000000000000000001174773561500167505ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/000077500000000000000000000000001174773561500176715ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/000077500000000000000000000000001174773561500204605ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/000077500000000000000000000000001174773561500221045ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500232435ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/000077500000000000000000000000001174773561500251125ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/000077500000000000000000000000001174773561500262205ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java000066400000000000000000000175001174773561500326670ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi; import java.security.Principal; import java.util.Map; import java.util.Set; import javax.security.auth.Subject; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.callback.CallerPrincipalCallback; import javax.security.auth.message.callback.GroupPrincipalCallback; import javax.security.auth.message.config.ServerAuthConfig; import javax.security.auth.message.config.ServerAuthContext; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.eclipse.jetty.security.Authenticator; import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.security.ServerAuthException; import org.eclipse.jetty.security.UserAuthentication; import org.eclipse.jetty.security.authentication.DeferredAuthentication; import org.eclipse.jetty.server.Authentication; import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.server.Authentication.User; /** * @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $ */ public class JaspiAuthenticator implements Authenticator { private final ServerAuthConfig _authConfig; private final Map _authProperties; private final ServletCallbackHandler _callbackHandler; private final Subject _serviceSubject; private final boolean _allowLazyAuthentication; private final IdentityService _identityService; private final DeferredAuthentication _deferred; public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler, Subject serviceSubject, boolean allowLazyAuthentication, IdentityService identityService) { // TODO maybe pass this in via setConfiguration ? if (callbackHandler == null) throw new NullPointerException("No CallbackHandler"); if (authConfig == null) throw new NullPointerException("No AuthConfig"); this._authConfig = authConfig; this._authProperties = authProperties; this._callbackHandler = callbackHandler; this._serviceSubject = serviceSubject; this._allowLazyAuthentication = allowLazyAuthentication; this._identityService = identityService; this._deferred = new DeferredAuthentication(this); } public void setConfiguration(AuthConfiguration configuration) { } public String getAuthMethod() { return "JASPI"; } public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException { JaspiMessageInfo info = new JaspiMessageInfo(request, response, mandatory); request.setAttribute("org.eclipse.jetty.security.jaspi.info", info); Authentication a = validateRequest(info); //if its not mandatory to authenticate, and the authenticator returned UNAUTHENTICATED, we treat it as authentication deferred if (_allowLazyAuthentication && !info.isAuthMandatory() && a == Authentication.UNAUTHENTICATED) a =_deferred; return a; } // most likely validatedUser is not needed here. public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException { JaspiMessageInfo info = (JaspiMessageInfo) req.getAttribute("org.eclipse.jetty.security.jaspi.info"); if (info == null) throw new NullPointerException("MessageInfo from request missing: " + req); return secureResponse(info, validatedUser); } public Authentication validateRequest(JaspiMessageInfo messageInfo) throws ServerAuthException { try { String authContextId = _authConfig.getAuthContextID(messageInfo); ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties); Subject clientSubject = new Subject(); AuthStatus authStatus = authContext.validateRequest(messageInfo, clientSubject, _serviceSubject); if (authStatus == AuthStatus.SEND_CONTINUE) return Authentication.SEND_CONTINUE; if (authStatus == AuthStatus.SEND_FAILURE) return Authentication.SEND_FAILURE; if (authStatus == AuthStatus.SUCCESS) { Set ids = clientSubject.getPrivateCredentials(UserIdentity.class); UserIdentity userIdentity; if (ids.size() > 0) { userIdentity = ids.iterator().next(); } else { CallerPrincipalCallback principalCallback = _callbackHandler.getThreadCallerPrincipalCallback(); if (principalCallback == null) { return Authentication.UNAUTHENTICATED; } Principal principal = principalCallback.getPrincipal(); if (principal == null) { String principalName = principalCallback.getName(); Set principals = principalCallback.getSubject().getPrincipals(); for (Principal p : principals) { if (p.getName().equals(principalName)) { principal = p; break; } } if (principal == null) { return Authentication.UNAUTHENTICATED; } } GroupPrincipalCallback groupPrincipalCallback = _callbackHandler.getThreadGroupPrincipalCallback(); String[] groups = groupPrincipalCallback == null ? null : groupPrincipalCallback.getGroups(); userIdentity = _identityService.newUserIdentity(clientSubject, principal, groups); } return new UserAuthentication(getAuthMethod(), userIdentity); } if (authStatus == AuthStatus.SEND_SUCCESS) { // we are processing a message in a secureResponse dialog. return Authentication.SEND_SUCCESS; } // should not happen throw new NullPointerException("No AuthStatus returned"); } catch (AuthException e) { throw new ServerAuthException(e); } } public boolean secureResponse(JaspiMessageInfo messageInfo, Authentication validatedUser) throws ServerAuthException { try { String authContextId = _authConfig.getAuthContextID(messageInfo); ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties); // TODO // authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject()); AuthStatus status = authContext.secureResponse(messageInfo, _serviceSubject); return (AuthStatus.SEND_SUCCESS.equals(status)); } catch (AuthException e) { throw new ServerAuthException(e); } } } JaspiAuthenticatorFactory.java000066400000000000000000000135201174773561500341360ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi; import java.security.Principal; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.security.auth.Subject; import javax.security.auth.message.AuthException; import javax.security.auth.message.config.AuthConfigFactory; import javax.security.auth.message.config.AuthConfigProvider; import javax.security.auth.message.config.RegistrationListener; import javax.security.auth.message.config.ServerAuthConfig; import javax.servlet.ServletContext; import org.eclipse.jetty.security.Authenticator; import org.eclipse.jetty.security.DefaultAuthenticatorFactory; import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.Authenticator.AuthConfiguration; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public class JaspiAuthenticatorFactory extends DefaultAuthenticatorFactory { private static final Logger LOG = Log.getLogger(JaspiAuthenticatorFactory.class); private static String MESSAGE_LAYER = "HTTP"; private Subject _serviceSubject; private String _serverName; /* ------------------------------------------------------------ */ /** * @return the serviceSubject */ public Subject getServiceSubject() { return _serviceSubject; } /* ------------------------------------------------------------ */ /** * @param serviceSubject the serviceSubject to set */ public void setServiceSubject(Subject serviceSubject) { _serviceSubject = serviceSubject; } /* ------------------------------------------------------------ */ /** * @return the serverName */ public String getServerName() { return _serverName; } /* ------------------------------------------------------------ */ /** * @param serverName the serverName to set */ public void setServerName(String serverName) { _serverName = serverName; } /* ------------------------------------------------------------ */ public Authenticator getAuthenticator(Server server, ServletContext context, AuthConfiguration configuration, IdentityService identityService, LoginService loginService) { Authenticator authenticator=null; try { AuthConfigFactory authConfigFactory = AuthConfigFactory.getFactory(); RegistrationListener listener = new RegistrationListener() { public void notify(String layer, String appContext) {} }; Subject serviceSubject=findServiceSubject(server); String serverName=findServerName(server,serviceSubject); String appContext = serverName + " " + context.getContextPath(); AuthConfigProvider authConfigProvider = authConfigFactory.getConfigProvider(MESSAGE_LAYER,appContext,listener); if (authConfigProvider != null) { ServletCallbackHandler servletCallbackHandler = new ServletCallbackHandler(loginService); ServerAuthConfig serverAuthConfig = authConfigProvider.getServerAuthConfig(MESSAGE_LAYER,appContext,servletCallbackHandler); if (serverAuthConfig != null) { Map map = new HashMap(); for (String key : configuration.getInitParameterNames()) map.put(key,configuration.getInitParameter(key)); authenticator= new JaspiAuthenticator(serverAuthConfig,map,servletCallbackHandler, serviceSubject,true, identityService); } } } catch (AuthException e) { LOG.warn(e); } return authenticator; } /* ------------------------------------------------------------ */ /** Find a service Subject. * If {@link #setServiceSubject(Subject)} has not been used to * set a subject, then the {@link Server#getBeans(Class)} method is * used to look for a Subject. */ protected Subject findServiceSubject(Server server) { if (_serviceSubject!=null) return _serviceSubject; List subjects = server.getBeans(Subject.class); if (subjects.size()>0) return (Subject)subjects.get(0); return null; } /* ------------------------------------------------------------ */ /** Find a servername. * If {@link #setServerName(String)} has not been called, then * use the name of the a principal in the service subject. * If not found, return "server". */ protected String findServerName(Server server, Subject subject) { if (_serverName!=null) return _serverName; if (subject!=null) { Set principals = subject.getPrincipals(); if (principals!=null && !principals.isEmpty()) return principals.iterator().next().getName(); } return "server"; } } jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiMessageInfo.java000066400000000000000000000143361174773561500322610ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.security.auth.message.MessageInfo; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Almost an implementation of jaspi MessageInfo. * * @version $Rev: 4660 $ $Date: 2009-02-25 17:29:53 +0100 (Wed, 25 Feb 2009) $ */ public class JaspiMessageInfo implements MessageInfo { public static final String MANDATORY_KEY = "javax.security.auth.message.MessagePolicy.isMandatory"; public static final String AUTH_METHOD_KEY = "javax.servlet.http.authType"; private ServletRequest request; private ServletResponse response; private final MIMap map; public JaspiMessageInfo(ServletRequest request, ServletResponse response, boolean isAuthMandatory) { this.request = request; this.response = response; //JASPI 3.8.1 map = new MIMap(isAuthMandatory); } public Map getMap() { return map; } public Object getRequestMessage() { return request; } public Object getResponseMessage() { return response; } public void setRequestMessage(Object request) { this.request = (ServletRequest)request; } public void setResponseMessage(Object response) { this.response = (ServletResponse)response; } public String getAuthMethod() { return map.getAuthMethod(); } public boolean isAuthMandatory() { return map.isAuthMandatory(); } //TODO this has bugs in the view implementations. Changing them will not affect the hardcoded values. private static class MIMap implements Map { private final boolean isMandatory; private String authMethod; private Map delegate; private MIMap(boolean mandatory) { isMandatory = mandatory; } public int size() { return (isMandatory? 1:0) + (authMethod == null? 0: 1) + (delegate == null? 0: delegate.size()); } public boolean isEmpty() { return !isMandatory && authMethod == null && (delegate == null || delegate.isEmpty()); } public boolean containsKey(Object key) { if (MANDATORY_KEY.equals(key)) return isMandatory; if (AUTH_METHOD_KEY.equals(key)) return authMethod != null; return delegate != null && delegate.containsKey(key); } public boolean containsValue(Object value) { if (isMandatory && "true".equals(value)) return true; if (authMethod == value || (authMethod != null && authMethod.equals(value))) return true; return delegate != null && delegate.containsValue(value); } public Object get(Object key) { if (MANDATORY_KEY.equals(key)) return isMandatory? "true": null; if (AUTH_METHOD_KEY.equals(key)) return authMethod; if (delegate == null) return null; return delegate.get(key); } public Object put(Object key, Object value) { if (MANDATORY_KEY.equals(key)) { throw new IllegalArgumentException("Mandatory not mutable"); } if (AUTH_METHOD_KEY.equals(key)) { String authMethod = this.authMethod; this.authMethod = (String) value; if (delegate != null) delegate.put(AUTH_METHOD_KEY, value); return authMethod; } return getDelegate(true).put(key, value); } public Object remove(Object key) { if (MANDATORY_KEY.equals(key)) { throw new IllegalArgumentException("Mandatory not mutable"); } if (AUTH_METHOD_KEY.equals(key)) { String authMethod = this.authMethod; this.authMethod = null; if (delegate != null) delegate.remove(AUTH_METHOD_KEY); return authMethod; } if (delegate == null) return null; return delegate.remove(key); } public void putAll(Map map) { if (map != null) { for (Object o: map.entrySet()) { Map.Entry entry = (Entry) o; put(entry.getKey(), entry.getValue()); } } } public void clear() { authMethod = null; delegate = null; } public Set keySet() { return getDelegate(true).keySet(); } public Collection values() { return getDelegate(true).values(); } public Set entrySet() { return getDelegate(true).entrySet(); } private Map getDelegate(boolean create) { if (!create || delegate != null) return delegate; if (create) { delegate = new HashMap(); if (isMandatory) delegate.put(MANDATORY_KEY, "true"); if (authMethod != null) delegate.put(AUTH_METHOD_KEY, authMethod); } return delegate; } boolean isAuthMandatory() { return isMandatory; } String getAuthMethod() { return authMethod; } } } jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/ServletCallbackHandler.java000066400000000000000000000134701174773561500334270ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi; import java.io.IOException; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.message.callback.CallerPrincipalCallback; import javax.security.auth.message.callback.CertStoreCallback; import javax.security.auth.message.callback.GroupPrincipalCallback; import javax.security.auth.message.callback.PasswordValidationCallback; import javax.security.auth.message.callback.PrivateKeyCallback; import javax.security.auth.message.callback.SecretKeyCallback; import javax.security.auth.message.callback.TrustStoreCallback; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.LoginCallback; import org.eclipse.jetty.security.authentication.LoginCallbackImpl; import org.eclipse.jetty.security.jaspi.callback.CredentialValidationCallback; import org.eclipse.jetty.server.UserIdentity; /** * * Idiot class required by jaspi stupidity * * @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $ */ public class ServletCallbackHandler implements CallbackHandler { private final LoginService _loginService; private final ThreadLocal _callerPrincipals = new ThreadLocal(); private final ThreadLocal _groupPrincipals = new ThreadLocal(); public ServletCallbackHandler(LoginService loginService) { _loginService = loginService; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { // jaspi to server communication if (callback instanceof CallerPrincipalCallback) { _callerPrincipals.set((CallerPrincipalCallback) callback); } else if (callback instanceof GroupPrincipalCallback) { _groupPrincipals.set((GroupPrincipalCallback) callback); } else if (callback instanceof PasswordValidationCallback) { PasswordValidationCallback passwordValidationCallback = (PasswordValidationCallback) callback; Subject subject = passwordValidationCallback.getSubject(); UserIdentity user = _loginService.login(passwordValidationCallback.getUsername(),passwordValidationCallback.getPassword()); if (user!=null) { passwordValidationCallback.setResult(true); passwordValidationCallback.getSubject().getPrincipals().addAll(user.getSubject().getPrincipals()); passwordValidationCallback.getSubject().getPrivateCredentials().add(user); } } else if (callback instanceof CredentialValidationCallback) { CredentialValidationCallback credentialValidationCallback = (CredentialValidationCallback) callback; Subject subject = credentialValidationCallback.getSubject(); LoginCallback loginCallback = new LoginCallbackImpl(subject, credentialValidationCallback.getUsername(), credentialValidationCallback.getCredential()); UserIdentity user = _loginService.login(credentialValidationCallback.getUsername(),credentialValidationCallback.getCredential()); if (user!=null) { loginCallback.setUserPrincipal(user.getUserPrincipal()); credentialValidationCallback.getSubject().getPrivateCredentials().add(loginCallback); credentialValidationCallback.setResult(true); credentialValidationCallback.getSubject().getPrincipals().addAll(user.getSubject().getPrincipals()); credentialValidationCallback.getSubject().getPrivateCredentials().add(user); } } // server to jaspi communication // TODO implement these else if (callback instanceof CertStoreCallback) { } else if (callback instanceof PrivateKeyCallback) { } else if (callback instanceof SecretKeyCallback) { } else if (callback instanceof TrustStoreCallback) { } else { throw new UnsupportedCallbackException(callback); } } } public CallerPrincipalCallback getThreadCallerPrincipalCallback() { CallerPrincipalCallback callerPrincipalCallback = _callerPrincipals.get(); _callerPrincipals.remove(); return callerPrincipalCallback; } public GroupPrincipalCallback getThreadGroupPrincipalCallback() { GroupPrincipalCallback groupPrincipalCallback = _groupPrincipals.get(); _groupPrincipals.remove(); return groupPrincipalCallback; } } jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/SimpleAuthConfig.java000066400000000000000000000042431174773561500322670ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.message.AuthException; import javax.security.auth.message.MessageInfo; import javax.security.auth.message.config.ServerAuthConfig; import javax.security.auth.message.config.ServerAuthContext; /** * @version $Rev: 4660 $ $Date: 2009-02-25 17:29:53 +0100 (Wed, 25 Feb 2009) $ */ public class SimpleAuthConfig implements ServerAuthConfig { public static final String HTTP_SERVLET = "HttpServlet"; private final String _appContext; private final ServerAuthContext _serverAuthContext; public SimpleAuthConfig(String appContext, ServerAuthContext serverAuthContext) { this._appContext = appContext; this._serverAuthContext = serverAuthContext; } public ServerAuthContext getAuthContext(String authContextID, Subject serviceSubject, Map properties) throws AuthException { return _serverAuthContext; } // supposed to be of form host-namecontext-path public String getAppContext() { return _appContext; } // not used yet public String getAuthContextID(MessageInfo messageInfo) throws IllegalArgumentException { return null; } public String getMessageLayer() { return HTTP_SERVLET; } public boolean isProtected() { return true; } public void refresh() { } } jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/callback/000077500000000000000000000000001174773561500277545ustar00rootroot00000000000000CredentialValidationCallback.java000066400000000000000000000036771174773561500362570ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/callback// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi.callback; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import org.eclipse.jetty.util.security.Credential; /** * CredentialValidationCallback * * Store a jetty Credential for a user so that it can be * validated by jaspi */ public class CredentialValidationCallback implements Callback { private Credential _credential; private boolean _result; private Subject _subject; private String _userName; public CredentialValidationCallback (Subject subject, String userName, Credential credential) { _subject = subject; _userName = userName; _credential = credential; } public Credential getCredential () { return _credential; } public void clearCredential () { _credential = null; } public boolean getResult() { return _result; } public javax.security.auth.Subject getSubject() { return _subject; } public java.lang.String getUsername() { return _userName; } public void setResult(boolean result) { _result = result; } } jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/000077500000000000000000000000001174773561500276705ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/BaseAuthModule.java000066400000000000000000000142531174773561500334020ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi.modules; import java.io.IOException; import java.util.Map; import java.util.Set; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.MessageInfo; import javax.security.auth.message.MessagePolicy; import javax.security.auth.message.callback.CallerPrincipalCallback; import javax.security.auth.message.callback.GroupPrincipalCallback; import javax.security.auth.message.config.ServerAuthContext; import javax.security.auth.message.module.ServerAuthModule; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.util.security.Credential; import org.eclipse.jetty.util.security.Password; import org.eclipse.jetty.security.authentication.LoginCallbackImpl; import org.eclipse.jetty.security.jaspi.JaspiMessageInfo; import org.eclipse.jetty.security.jaspi.callback.CredentialValidationCallback; import org.eclipse.jetty.util.B64Code; import org.eclipse.jetty.util.StringUtil; /** * @deprecated use *ServerAuthentication * @version $Rev: 4792 $ $Date: 2009-03-18 22:55:52 +0100 (Wed, 18 Mar 2009) $ */ public class BaseAuthModule implements ServerAuthModule, ServerAuthContext { private static final Class[] SUPPORTED_MESSAGE_TYPES = new Class[] { HttpServletRequest.class, HttpServletResponse.class }; protected static final String LOGIN_SERVICE_KEY = "org.eclipse.jetty.security.jaspi.modules.LoginService"; protected CallbackHandler callbackHandler; public Class[] getSupportedMessageTypes() { return SUPPORTED_MESSAGE_TYPES; } public BaseAuthModule() { } public BaseAuthModule(CallbackHandler callbackHandler) { this.callbackHandler = callbackHandler; } public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options) throws AuthException { this.callbackHandler = handler; } public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException { // TODO apparently we either get the LoginCallback or the LoginService // but not both :-( // Set loginCallbacks = // subject.getPrivateCredentials(LoginCallback.class); // if (!loginCallbacks.isEmpty()) { // LoginCallback loginCallback = loginCallbacks.iterator().next(); // } // try { // loginService.logout(subject); // } catch (ServerAuthException e) { // throw new AuthException(e.getMessage()); // } } public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException { // servlets do not need secured responses return AuthStatus.SEND_SUCCESS; } public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { return AuthStatus.SEND_FAILURE; } /** * @param messageInfo message info to examine for mandatory flag * @return whether authentication is mandatory or optional */ protected boolean isMandatory(MessageInfo messageInfo) { String mandatory = (String) messageInfo.getMap().get(JaspiMessageInfo.MANDATORY_KEY); if (mandatory == null) return false; return Boolean.valueOf(mandatory); } protected boolean login(Subject clientSubject, String credentials, String authMethod, MessageInfo messageInfo) throws IOException, UnsupportedCallbackException { credentials = credentials.substring(credentials.indexOf(' ')+1); credentials = B64Code.decode(credentials,StringUtil.__ISO_8859_1); int i = credentials.indexOf(':'); String userName = credentials.substring(0,i); String password = credentials.substring(i+1); return login(clientSubject, userName, new Password(password), authMethod, messageInfo); } protected boolean login(Subject clientSubject, String username, Credential credential, String authMethod, MessageInfo messageInfo) throws IOException, UnsupportedCallbackException { CredentialValidationCallback credValidationCallback = new CredentialValidationCallback(clientSubject, username, credential); callbackHandler.handle(new Callback[] { credValidationCallback }); if (credValidationCallback.getResult()) { Set loginCallbacks = clientSubject.getPrivateCredentials(LoginCallbackImpl.class); if (!loginCallbacks.isEmpty()) { LoginCallbackImpl loginCallback = loginCallbacks.iterator().next(); CallerPrincipalCallback callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, loginCallback.getUserPrincipal()); GroupPrincipalCallback groupPrincipalCallback = new GroupPrincipalCallback(clientSubject, loginCallback.getRoles()); callbackHandler.handle(new Callback[] { callerPrincipalCallback, groupPrincipalCallback }); } messageInfo.getMap().put(JaspiMessageInfo.AUTH_METHOD_KEY, authMethod); } return credValidationCallback.getResult(); } } jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/BasicAuthModule.java000066400000000000000000000071421174773561500335500ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi.modules; import java.io.IOException; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.MessageInfo; import javax.security.auth.message.MessagePolicy; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * @deprecated use *ServerAuthentication * @version $Rev: 4660 $ $Date: 2009-02-25 17:29:53 +0100 (Wed, 25 Feb 2009) $ */ public class BasicAuthModule extends BaseAuthModule { private static final Logger LOG = Log.getLogger(BasicAuthModule.class); private String realmName; private static final String REALM_KEY = "org.eclipse.jetty.security.jaspi.modules.RealmName"; public BasicAuthModule() { } public BasicAuthModule(CallbackHandler callbackHandler, String realmName) { super(callbackHandler); this.realmName = realmName; } @Override public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options) throws AuthException { super.initialize(requestPolicy, responsePolicy, handler, options); realmName = (String) options.get(REALM_KEY); } @Override public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage(); HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage(); String credentials = request.getHeader(HttpHeaders.AUTHORIZATION); try { if (credentials != null) { if (LOG.isDebugEnabled()) LOG.debug("Credentials: " + credentials); if (login(clientSubject, credentials, Constraint.__BASIC_AUTH, messageInfo)) { return AuthStatus.SUCCESS; } } if (!isMandatory(messageInfo)) { return AuthStatus.SUCCESS; } response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "basic realm=\"" + realmName + '"'); response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return AuthStatus.SEND_CONTINUE; } catch (IOException e) { throw new AuthException(e.getMessage()); } catch (UnsupportedCallbackException e) { throw new AuthException(e.getMessage()); } } } ClientCertAuthModule.java000066400000000000000000000073551174773561500345120ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi.modules; import java.io.IOException; import java.security.Principal; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.MessageInfo; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.util.security.Password; import org.eclipse.jetty.util.B64Code; /** * @deprecated use *ServerAuthentication * @version $Rev: 4530 $ $Date: 2009-02-13 00:47:44 +0100 (Fri, 13 Feb 2009) $ */ public class ClientCertAuthModule extends BaseAuthModule { public ClientCertAuthModule() { } public ClientCertAuthModule(CallbackHandler callbackHandler) { super(callbackHandler); } @Override public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage(); HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage(); java.security.cert.X509Certificate[] certs = (java.security.cert.X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); try { // Need certificates. if (certs == null || certs.length == 0 || certs[0] == null) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "A client certificate is required for accessing this web application but the server's listener is not configured for mutual authentication (or the client did not provide a certificate)."); return AuthStatus.SEND_FAILURE; } Principal principal = certs[0].getSubjectDN(); if (principal == null) principal = certs[0].getIssuerDN(); final String username = principal == null ? "clientcert" : principal.getName(); // TODO no idea if this is correct final String password = new String(B64Code.encode(certs[0].getSignature())); // TODO is cert_auth correct? if (login(clientSubject, username, new Password(password), Constraint.__CERT_AUTH, messageInfo)) { return AuthStatus.SUCCESS; } if (!isMandatory(messageInfo)) { return AuthStatus.SUCCESS; } response.sendError(HttpServletResponse.SC_FORBIDDEN, "The provided client certificate does not correspond to a trusted user."); return AuthStatus.SEND_FAILURE; } catch (IOException e) { throw new AuthException(e.getMessage()); } catch (UnsupportedCallbackException e) { throw new AuthException(e.getMessage()); } } } DigestAuthModule.java000066400000000000000000000310751174773561500336710ustar00rootroot00000000000000jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi.modules; import java.io.IOException; import java.security.MessageDigest; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.MessageInfo; import javax.security.auth.message.MessagePolicy; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.util.security.Credential; import org.eclipse.jetty.util.B64Code; import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * @deprecated use *ServerAuthentication * @version $Rev: 4627 $ $Date: 2009-02-20 00:07:19 +0100 (Fri, 20 Feb 2009) $ */ public class DigestAuthModule extends BaseAuthModule { private static final Logger LOG = Log.getLogger(DigestAuthModule.class); protected long maxNonceAge = 0; protected long nonceSecret = this.hashCode() ^ System.currentTimeMillis(); protected boolean useStale = false; private String realmName; private static final String REALM_KEY = "org.eclipse.jetty.security.jaspi.modules.RealmName"; public DigestAuthModule() { } public DigestAuthModule(CallbackHandler callbackHandler, String realmName) { super(callbackHandler); this.realmName = realmName; } @Override public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options) throws AuthException { super.initialize(requestPolicy, responsePolicy, handler, options); realmName = (String) options.get(REALM_KEY); } @Override public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage(); HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage(); String credentials = request.getHeader(HttpHeaders.AUTHORIZATION); try { boolean stale = false; // TODO extract from request long timestamp = System.currentTimeMillis(); if (credentials != null) { if (LOG.isDebugEnabled()) LOG.debug("Credentials: " + credentials); QuotedStringTokenizer tokenizer = new QuotedStringTokenizer(credentials, "=, ", true, false); final Digest digest = new Digest(request.getMethod()); String last = null; String name = null; while (tokenizer.hasMoreTokens()) { String tok = tokenizer.nextToken(); char c = (tok.length() == 1) ? tok.charAt(0) : '\0'; switch (c) { case '=': name = last; last = tok; break; case ',': name = null; case ' ': break; default: last = tok; if (name != null) { if ("username".equalsIgnoreCase(name)) digest.username = tok; else if ("realm".equalsIgnoreCase(name)) digest.realm = tok; else if ("nonce".equalsIgnoreCase(name)) digest.nonce = tok; else if ("nc".equalsIgnoreCase(name)) digest.nc = tok; else if ("cnonce".equalsIgnoreCase(name)) digest.cnonce = tok; else if ("qop".equalsIgnoreCase(name)) digest.qop = tok; else if ("uri".equalsIgnoreCase(name)) digest.uri = tok; else if ("response".equalsIgnoreCase(name)) digest.response = tok; break; } } } int n = checkNonce(digest.nonce, timestamp); if (n > 0) { if (login(clientSubject, digest.username, digest, Constraint.__DIGEST_AUTH, messageInfo)) { return AuthStatus.SUCCESS; } } else if (n == 0) stale = true; } if (!isMandatory(messageInfo)) { return AuthStatus.SUCCESS; } String domain = request.getContextPath(); if (domain == null) domain = "/"; response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"" + realmName + "\", domain=\"" + domain + "\", nonce=\"" + newNonce(timestamp) + "\", algorithm=MD5, qop=\"auth\"" + (useStale ? (" stale=" + stale) : "")); response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return AuthStatus.SEND_CONTINUE; } catch (IOException e) { throw new AuthException(e.getMessage()); } catch (UnsupportedCallbackException e) { throw new AuthException(e.getMessage()); } } public String newNonce(long ts) { // long ts=request.getTimeStamp(); long sk = nonceSecret; byte[] nounce = new byte[24]; for (int i = 0; i < 8; i++) { nounce[i] = (byte) (ts & 0xff); ts = ts >> 8; nounce[8 + i] = (byte) (sk & 0xff); sk = sk >> 8; } byte[] hash = null; try { MessageDigest md = MessageDigest.getInstance("MD5"); md.reset(); md.update(nounce, 0, 16); hash = md.digest(); } catch (Exception e) { LOG.warn(e); } for (int i = 0; i < hash.length; i++) { nounce[8 + i] = hash[i]; if (i == 23) break; } return new String(B64Code.encode(nounce)); } /** * @param nonce * @param timestamp should be timestamp of request. * @return -1 for a bad nonce, 0 for a stale none, 1 for a good nonce */ /* ------------------------------------------------------------ */ public int checkNonce(String nonce, long timestamp) { try { byte[] n = B64Code.decode(nonce.toCharArray()); if (n.length != 24) return -1; long ts = 0; long sk = nonceSecret; byte[] n2 = new byte[16]; System.arraycopy(n, 0, n2, 0, 8); for (int i = 0; i < 8; i++) { n2[8 + i] = (byte) (sk & 0xff); sk = sk >> 8; ts = (ts << 8) + (0xff & (long) n[7 - i]); } long age = timestamp - ts; if (LOG.isDebugEnabled()) LOG.debug("age=" + age); byte[] hash = null; try { MessageDigest md = MessageDigest.getInstance("MD5"); md.reset(); md.update(n2, 0, 16); hash = md.digest(); } catch (Exception e) { LOG.warn(e); } for (int i = 0; i < 16; i++) if (n[i + 8] != hash[i]) return -1; if (maxNonceAge > 0 && (age < 0 || age > maxNonceAge)) return 0; // stale return 1; } catch (Exception e) { LOG.ignore(e); } return -1; } private static class Digest extends Credential { private static final long serialVersionUID = -1866670896275159116L; String method = null; String username = null; String realm = null; String nonce = null; String nc = null; String cnonce = null; String qop = null; String uri = null; String response = null; /* ------------------------------------------------------------ */ Digest(String m) { method = m; } /* ------------------------------------------------------------ */ @Override public boolean check(Object credentials) { String password = (credentials instanceof String) ? (String) credentials : credentials.toString(); try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] ha1; if (credentials instanceof Credential.MD5) { // Credentials are already a MD5 digest - assume it's in // form user:realm:password (we have no way to know since // it's a digest, alright?) ha1 = ((Credential.MD5) credentials).getDigest(); } else { // calc A1 digest md.update(username.getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(realm.getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(password.getBytes(StringUtil.__ISO_8859_1)); ha1 = md.digest(); } // calc A2 digest md.reset(); md.update(method.getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(uri.getBytes(StringUtil.__ISO_8859_1)); byte[] ha2 = md.digest(); // calc digest // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" // nc-value ":" unq(cnonce-value) ":" unq(qop-value) ":" H(A2) ) // <"> // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) // ) > <"> md.update(TypeUtil.toString(ha1, 16).getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(nonce.getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(nc.getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(cnonce.getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(qop.getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(TypeUtil.toString(ha2, 16).getBytes(StringUtil.__ISO_8859_1)); byte[] digest = md.digest(); // check digest return (TypeUtil.toString(digest, 16).equalsIgnoreCase(response)); } catch (Exception e) { LOG.warn(e); } return false; } @Override public String toString() { return username + "," + response; } } } jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java000066400000000000000000000340251174773561500334320ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi.modules; import java.io.IOException; import java.io.Serializable; import java.security.Principal; import java.util.Arrays; import java.util.Map; import java.util.Set; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.MessageInfo; import javax.security.auth.message.MessagePolicy; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.util.security.Password; import org.eclipse.jetty.security.CrossContextPsuedoSession; import org.eclipse.jetty.security.authentication.DeferredAuthentication; import org.eclipse.jetty.security.authentication.LoginCallbackImpl; import org.eclipse.jetty.server.Authentication; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * @deprecated use *ServerAuthentication * @version $Rev: 4792 $ $Date: 2009-03-18 22:55:52 +0100 (Wed, 18 Mar 2009) $ */ public class FormAuthModule extends BaseAuthModule { private static final Logger LOG = Log.getLogger(FormAuthModule.class); /* ------------------------------------------------------------ */ public final static String __J_URI = "org.eclipse.jetty.util.URI"; public final static String __J_AUTHENTICATED = "org.eclipse.jetty.server.Auth"; public final static String __J_SECURITY_CHECK = "/j_security_check"; public final static String __J_USERNAME = "j_username"; public final static String __J_PASSWORD = "j_password"; // private String realmName; public static final String LOGIN_PAGE_KEY = "org.eclipse.jetty.security.jaspi.modules.LoginPage"; public static final String ERROR_PAGE_KEY = "org.eclipse.jetty.security.jaspi.modules.ErrorPage"; public static final String SSO_SOURCE_KEY = "org.eclipse.jetty.security.jaspi.modules.SsoSource"; private String _formErrorPage; private String _formErrorPath; private String _formLoginPage; private String _formLoginPath; private CrossContextPsuedoSession ssoSource; public FormAuthModule() { } public FormAuthModule(CallbackHandler callbackHandler, String loginPage, String errorPage) { super(callbackHandler); setLoginPage(loginPage); setErrorPage(errorPage); } public FormAuthModule(CallbackHandler callbackHandler, CrossContextPsuedoSession ssoSource, String loginPage, String errorPage) { super(callbackHandler); this.ssoSource = ssoSource; setLoginPage(loginPage); setErrorPage(errorPage); } @Override public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options) throws AuthException { super.initialize(requestPolicy, responsePolicy, handler, options); setLoginPage((String) options.get(LOGIN_PAGE_KEY)); setErrorPage((String) options.get(ERROR_PAGE_KEY)); ssoSource = (CrossContextPsuedoSession) options.get(SSO_SOURCE_KEY); } private void setLoginPage(String path) { if (!path.startsWith("/")) { LOG.warn("form-login-page must start with /"); path = "/" + path; } _formLoginPage = path; _formLoginPath = path; if (_formLoginPath.indexOf('?') > 0) _formLoginPath = _formLoginPath.substring(0, _formLoginPath.indexOf('?')); } /* ------------------------------------------------------------ */ private void setErrorPage(String path) { if (path == null || path.trim().length() == 0) { _formErrorPath = null; _formErrorPage = null; } else { if (!path.startsWith("/")) { LOG.warn("form-error-page must start with /"); path = "/" + path; } _formErrorPage = path; _formErrorPath = path; if (_formErrorPath.indexOf('?') > 0) _formErrorPath = _formErrorPath.substring(0, _formErrorPath.indexOf('?')); } } @Override public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage(); HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage(); String uri = request.getRequestURI(); if (uri==null) uri=URIUtil.SLASH; boolean mandatory = isMandatory(messageInfo); mandatory |= isJSecurityCheck(uri); HttpSession session = request.getSession(mandatory); // not mandatory or its the login or login error page don't authenticate if (!mandatory || isLoginOrErrorPage(URIUtil.addPaths(request.getServletPath(),request.getPathInfo()))) return AuthStatus.SUCCESS; try { // Handle a request for authentication. if (isJSecurityCheck(uri)) { final String username = request.getParameter(__J_USERNAME); final String password = request.getParameter(__J_PASSWORD); boolean success = tryLogin(messageInfo, clientSubject, response, session, username, new Password(password)); if (success) { // Redirect to original request String nuri=null; synchronized(session) { nuri = (String) session.getAttribute(__J_URI); } if (nuri == null || nuri.length() == 0) { nuri = request.getContextPath(); if (nuri.length() == 0) nuri = URIUtil.SLASH; } response.setContentLength(0); response.sendRedirect(response.encodeRedirectURL(nuri)); return AuthStatus.SEND_CONTINUE; } // not authenticated if (LOG.isDebugEnabled()) LOG.debug("Form authentication FAILED for " + StringUtil.printable(username)); if (_formErrorPage == null) { if (response != null) response.sendError(HttpServletResponse.SC_FORBIDDEN); } else { response.setContentLength(0); response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(), _formErrorPage))); } // TODO is this correct response if isMandatory false??? Can // that occur? return AuthStatus.SEND_FAILURE; } // Check if the session is already authenticated. FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED); if (form_cred != null) { //TODO: ideally we would like the form auth module to be able to invoke the //loginservice.validate() method to check the previously authed user, but it is not visible //to FormAuthModule if (form_cred._subject == null) return AuthStatus.SEND_FAILURE; Set credentials = form_cred._subject.getPrivateCredentials(); if (credentials == null || credentials.isEmpty()) return AuthStatus.SEND_FAILURE; //if no private credentials, assume it cannot be authenticated clientSubject.getPrivateCredentials().addAll(credentials); //boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword))); return AuthStatus.SUCCESS; } else if (ssoSource != null) { UserInfo userInfo = ssoSource.fetch(request); if (userInfo != null) { boolean success = tryLogin(messageInfo, clientSubject, response, session, userInfo.getUserName(), new Password(new String(userInfo.getPassword()))); if (success) { return AuthStatus.SUCCESS; } } } // if we can't send challenge if (DeferredAuthentication.isDeferred(response)) return AuthStatus.SUCCESS; // redirect to login page StringBuffer buf = request.getRequestURL(); if (request.getQueryString() != null) buf.append("?").append(request.getQueryString()); synchronized (session) { session.setAttribute(__J_URI, buf.toString()); } response.setContentLength(0); response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(), _formLoginPage))); return AuthStatus.SEND_CONTINUE; } catch (IOException e) { throw new AuthException(e.getMessage()); } catch (UnsupportedCallbackException e) { throw new AuthException(e.getMessage()); } } /* ------------------------------------------------------------ */ public boolean isJSecurityCheck(String uri) { int jsc = uri.indexOf(__J_SECURITY_CHECK); if (jsc<0) return false; int e=jsc+__J_SECURITY_CHECK.length(); if (e==uri.length()) return true; char c = uri.charAt(e); return c==';'||c=='#'||c=='/'||c=='?'; } private boolean tryLogin(MessageInfo messageInfo, Subject clientSubject, HttpServletResponse response, HttpSession session, String username, Password password) throws AuthException, IOException, UnsupportedCallbackException { if (login(clientSubject, username, password, Constraint.__FORM_AUTH, messageInfo)) { char[] pwdChars = password.toString().toCharArray(); Set loginCallbacks = clientSubject.getPrivateCredentials(LoginCallbackImpl.class); if (!loginCallbacks.isEmpty()) { LoginCallbackImpl loginCallback = loginCallbacks.iterator().next(); FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal(), loginCallback.getSubject()); session.setAttribute(__J_AUTHENTICATED, form_cred); } // Sign-on to SSO mechanism if (ssoSource != null) { UserInfo userInfo = new UserInfo(username, pwdChars); ssoSource.store(userInfo, response); } return true; } return false; } public boolean isLoginOrErrorPage(String pathInContext) { return pathInContext != null && (pathInContext.equals(_formErrorPath) || pathInContext.equals(_formLoginPath)); } /* ------------------------------------------------------------ */ /** * FORM Authentication credential holder. */ private static class FormCredential implements Serializable, HttpSessionBindingListener { String _jUserName; char[] _jPassword; transient Principal _userPrincipal; transient Subject _subject; private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal, Subject subject) { this._jUserName = _jUserName; this._jPassword = _jPassword; this._userPrincipal = _userPrincipal; this._subject = subject; } public void valueBound(HttpSessionBindingEvent event) { } public void valueUnbound(HttpSessionBindingEvent event) { if (LOG.isDebugEnabled()) LOG.debug("Logout " + _jUserName); // TODO jaspi call cleanSubject() // if (_realm instanceof SSORealm) // ((SSORealm) _realm).clearSingleSignOn(_jUserName); // // if (_realm != null && _userPrincipal != null) // _realm.logout(_userPrincipal); } public int hashCode() { return _jUserName.hashCode() + _jPassword.hashCode(); } public boolean equals(Object o) { if (!(o instanceof FormCredential)) return false; FormCredential fc = (FormCredential) o; return _jUserName.equals(fc._jUserName) && Arrays.equals(_jPassword, fc._jPassword); } public String toString() { return "Cred[" + _jUserName + "]"; } } } jetty8-8.1.3/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/UserInfo.java000066400000000000000000000025631174773561500322730ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.security.jaspi.modules; import java.util.Arrays; /** * @version $Rev: 4466 $ $Date: 2009-02-10 23:42:54 +0100 (Tue, 10 Feb 2009) $ */ public class UserInfo { private final String userName; private char[] password; public UserInfo(String userName, char[] password) { this.userName = userName; this.password = password; } public String getUserName() { return userName; } public char[] getPassword() { return password; } public void clearPassword() { Arrays.fill(password, (char) 0); password = null; } } jetty8-8.1.3/jetty-jmx/000077500000000000000000000000001174773561500147255ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/pom.xml000066400000000000000000000051371174773561500162500ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 jetty-jmx Jetty :: JMX Management JMX management artifact for jetty. ${project.groupId}.jmx org.apache.felix maven-bundle-plugin true manifest javax.management.*,* org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.apache.maven.plugins maven-assembly-plugin package single config org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.jmx.* junit junit test org.eclipse.jetty jetty-util ${project.version} jetty8-8.1.3/jetty-jmx/src/000077500000000000000000000000001174773561500155145ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/000077500000000000000000000000001174773561500164405ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/config/000077500000000000000000000000001174773561500177055ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/config/etc/000077500000000000000000000000001174773561500204605ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/config/etc/jetty-jmx.xml000066400000000000000000000106151174773561500231400ustar00rootroot00000000000000 true jetty8-8.1.3/jetty-jmx/src/main/java/000077500000000000000000000000001174773561500173615ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/java/org/000077500000000000000000000000001174773561500201505ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/java/org/eclipse/000077500000000000000000000000001174773561500215745ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500227335ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/000077500000000000000000000000001174773561500235315ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ConnectorServer.java000066400000000000000000000150601174773561500275170ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jmx; import java.lang.management.ManagementFactory; import java.net.InetAddress; import java.net.ServerSocket; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import java.util.Map; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.ShutdownThread; /* ------------------------------------------------------------ */ /** * AbstractLifeCycle wrapper for JMXConnector Server */ public class ConnectorServer extends AbstractLifeCycle { private static final Logger LOG = Log.getLogger(ConnectorServer.class); JMXConnectorServer _connectorServer; Registry _registry; /* ------------------------------------------------------------ */ /** * Constructs connector server * * @param serviceURL the address of the new connector server. * The actual address of the new connector server, as returned * by its getAddress method, will not necessarily be exactly the same. * @param name object name string to be assigned to connector server bean * @throws Exception */ public ConnectorServer(JMXServiceURL serviceURL, String name) throws Exception { this(serviceURL, null, name); } /* ------------------------------------------------------------ */ /** * Constructs connector server * * @param svcUrl the address of the new connector server. * The actual address of the new connector server, as returned * by its getAddress method, will not necessarily be exactly the same. * @param environment a set of attributes to control the new connector * server's behavior. This parameter can be null. Keys in this map must * be Strings. The appropriate type of each associated value depends on * the attribute. The contents of environment are not changed by this call. * @param name object name string to be assigned to connector server bean * @throws Exception */ public ConnectorServer(JMXServiceURL svcUrl, Map environment, String name) throws Exception { String urlPath = svcUrl.getURLPath(); int idx = urlPath.indexOf("rmi://"); if (idx > 0) { String hostPort = urlPath.substring(idx+6, urlPath.indexOf('/', idx+6)); String regHostPort = startRegistry(hostPort); if (regHostPort != null) { urlPath = urlPath.replace(hostPort,regHostPort); svcUrl = new JMXServiceURL(svcUrl.getProtocol(), svcUrl.getHost(), svcUrl.getPort(), urlPath); } } MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); _connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(svcUrl, environment, mbeanServer); mbeanServer.registerMBean(_connectorServer,new ObjectName(name)); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() */ @Override public void doStart() throws Exception { _connectorServer.start(); ShutdownThread.register(0, this); LOG.info("JMX Remote URL: {}", _connectorServer.getAddress().toString()); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop() */ @Override public void doStop() throws Exception { ShutdownThread.deregister(this); _connectorServer.stop(); stopRegistry(); } /** * Check that local RMI registry is used, and ensure it is started. If local RMI registry is being used and not started, start it. * * @param hostPath * hostname and port number of RMI registry * @throws Exception */ private String startRegistry(String hostPath) throws Exception { int rmiPort = 1099; // default RMI registry port String rmiHost = hostPath; int idx = hostPath.indexOf(':'); if (idx > 0) { rmiPort = Integer.parseInt(hostPath.substring(idx + 1)); rmiHost = hostPath.substring(0,idx); } // Verify that local registry is being used InetAddress hostAddress = InetAddress.getByName(rmiHost); if(hostAddress.isLoopbackAddress()) { if (rmiPort == 0) { ServerSocket socket = new ServerSocket(0); rmiPort = socket.getLocalPort(); socket.close(); } else { try { // Check if a local registry is already running LocateRegistry.getRegistry(rmiPort).list(); return null; } catch (Exception ex) { LOG.ignore(ex); } } _registry = LocateRegistry.createRegistry(rmiPort); Thread.sleep(1000); rmiHost = InetAddress.getLocalHost().getCanonicalHostName(); return rmiHost + ':' + Integer.toString(rmiPort); } return null; } private void stopRegistry() { if (_registry != null) { try { UnicastRemoteObject.unexportObject(_registry,true); } catch (Exception ex) { LOG.ignore(ex); } } } } jetty8-8.1.3/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java000066400000000000000000000256071174773561500272330ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2005-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jmx; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import javax.management.MBeanServer; import javax.management.ObjectInstance; import javax.management.ObjectName; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.Container; import org.eclipse.jetty.util.component.Container.Relationship; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.StdErrLog; import org.eclipse.jetty.util.thread.ShutdownThread; /** * Container class for the MBean instances */ public class MBeanContainer extends AbstractLifeCycle implements Container.Listener, Dumpable { private final static Logger LOG = Log.getLogger(MBeanContainer.class.getName()); private final MBeanServer _server; private final WeakHashMap _beans = new WeakHashMap(); private final HashMap _unique = new HashMap(); private final WeakHashMap> _relations = new WeakHashMap>(); private String _domain = null; /** * Lookup an object name by instance * * @param object instance for which object name is looked up * @return object name associated with specified instance, or null if not found */ public synchronized ObjectName findMBean(Object object) { ObjectName bean = _beans.get(object); return bean == null ? null : bean; } /** * Lookup an instance by object name * * @param oname object name of instance * @return instance associated with specified object name, or null if not found */ public synchronized Object findBean(ObjectName oname) { for (Map.Entry entry : _beans.entrySet()) { ObjectName bean = entry.getValue(); if (bean.equals(oname)) return entry.getKey(); } return null; } /** * Constructs MBeanContainer * * @param server instance of MBeanServer for use by container */ public MBeanContainer(MBeanServer server) { _server = server; } /** * Retrieve instance of MBeanServer used by container * * @return instance of MBeanServer */ public MBeanServer getMBeanServer() { return _server; } /** * Set domain to be used to add MBeans * * @param domain domain name */ public void setDomain(String domain) { _domain = domain; } /** * Retrieve domain name used to add MBeans * * @return domain name */ public String getDomain() { return _domain; } /** * Implementation of Container.Listener interface * * @see org.eclipse.jetty.util.component.Container.Listener#add(org.eclipse.jetty.util.component.Container.Relationship) */ public synchronized void add(Relationship relationship) { LOG.debug("add {}",relationship); ObjectName parent = _beans.get(relationship.getParent()); if (parent == null) { addBean(relationship.getParent()); parent = _beans.get(relationship.getParent()); } ObjectName child = _beans.get(relationship.getChild()); if (child == null) { addBean(relationship.getChild()); child = _beans.get(relationship.getChild()); } if (parent != null && child != null) { List rels = _relations.get(parent); if (rels==null) { rels=new ArrayList(); _relations.put(parent,rels); } rels.add(relationship); } } /** * Implementation of Container.Listener interface * * @see org.eclipse.jetty.util.component.Container.Listener#remove(org.eclipse.jetty.util.component.Container.Relationship) */ public synchronized void remove(Relationship relationship) { LOG.debug("remove {}",relationship); ObjectName parent = _beans.get(relationship.getParent()); ObjectName child = _beans.get(relationship.getChild()); if (parent != null && child != null) { List rels = _relations.get(parent); if (rels!=null) { for (Iterator i=rels.iterator();i.hasNext();) { Container.Relationship r = i.next(); if (relationship.equals(r) || r.getChild()==null) i.remove(); } } } } /** * Implementation of Container.Listener interface * * @see org.eclipse.jetty.util.component.Container.Listener#removeBean(java.lang.Object) */ public synchronized void removeBean(Object obj) { LOG.debug("removeBean {}",obj); ObjectName bean = _beans.remove(obj); if (bean != null) { List beanRelations= _relations.remove(bean); if (beanRelations != null) { LOG.debug("Unregister {}", beanRelations); List removeList = new ArrayList(beanRelations); for (Object r : removeList) { Container.Relationship relation = (Relationship)r; relation.getContainer().update(relation.getParent(), relation.getChild(), null, relation.getRelationship(), true); } } try { _server.unregisterMBean(bean); LOG.debug("Unregistered {}", bean); } catch (javax.management.InstanceNotFoundException e) { LOG.ignore(e); } catch (Exception e) { LOG.warn(e); } } } /** * Implementation of Container.Listener interface * * @see org.eclipse.jetty.util.component.Container.Listener#addBean(java.lang.Object) */ public synchronized void addBean(Object obj) { LOG.debug("addBean {}",obj); try { if (obj == null || _beans.containsKey(obj)) return; Object mbean = ObjectMBean.mbeanFor(obj); if (mbean == null) return; ObjectName oname = null; if (mbean instanceof ObjectMBean) { ((ObjectMBean)mbean).setMBeanContainer(this); oname = ((ObjectMBean)mbean).getObjectName(); } //no override mbean object name, so make a generic one if (oname == null) { String type = obj.getClass().getName().toLowerCase(); int dot = type.lastIndexOf('.'); if (dot >= 0) type = type.substring(dot + 1); String context = null; if (mbean instanceof ObjectMBean) { context = makeName(((ObjectMBean)mbean).getObjectContextBasis()); } String name = null; if (mbean instanceof ObjectMBean) { name = makeName(((ObjectMBean)mbean).getObjectNameBasis()); } StringBuffer buf = new StringBuffer(); buf.append("type=").append(type); if (context != null && context.length()>1) { buf.append(buf.length()>0 ? ",":""); buf.append("context=").append(context); } if (name != null && name.length()>1) { buf.append(buf.length()>0 ? ",":""); buf.append("name=").append(name); } String basis = buf.toString(); Integer count = _unique.get(basis); count = count == null ? 0 : 1 + count; _unique.put(basis, count); //if no explicit domain, create one String domain = _domain; if (domain == null) domain = obj.getClass().getPackage().getName(); oname = ObjectName.getInstance(domain + ":" + basis + ",id=" + count); } ObjectInstance oinstance = _server.registerMBean(mbean, oname); LOG.debug("Registered {}", oinstance.getObjectName()); _beans.put(obj, oinstance.getObjectName()); } catch (Exception e) { LOG.warn("bean: " + obj, e); } } /** * @param basis name to strip of special characters. * @return normalized name */ public String makeName(String basis) { if (basis==null) return basis; return basis.replace(':', '_').replace('*', '_').replace('?', '_').replace('=', '_').replace(',', '_').replace(' ', '_'); } /** * Perform actions needed to start lifecycle * * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() */ public void doStart() { ShutdownThread.register(this); } /** * Perform actions needed to stop lifecycle * * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop() */ public void doStop() { Set removeSet = new HashSet(_beans.keySet()); for (Object removeObj : removeSet) { removeBean(removeObj); } } public void dump(Appendable out, String indent) throws IOException { AggregateLifeCycle.dumpObject(out,this); AggregateLifeCycle.dump(out, indent, _beans.entrySet()); } public String dump() { return AggregateLifeCycle.dump(this); } } jetty8-8.1.3/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ObjectMBean.java000066400000000000000000000676321174773561500265230ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jmx; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.DynamicMBean; import javax.management.InvalidAttributeValueException; import javax.management.MBeanAttributeInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanNotificationInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.modelmbean.ModelMBean; import org.eclipse.jetty.util.LazyList; import org.eclipse.jetty.util.Loader; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ /** ObjectMBean. * A dynamic MBean that can wrap an arbitary Object instance. * the attributes and methods exposed by this bean are controlled by * the merge of property bundles discovered by names related to all * superclasses and all superinterfaces. * * Attributes and methods exported may be "Object" and must exist on the * wrapped object, or "MBean" and must exist on a subclass of OBjectMBean * or "MObject" which exists on the wrapped object, but whose values are * converted to MBean object names. * */ public class ObjectMBean implements DynamicMBean { private static final Logger LOG = Log.getLogger(ObjectMBean.class); private static Class[] OBJ_ARG = new Class[]{Object.class}; protected Object _managed; private MBeanInfo _info; private Map _getters=new HashMap(); private Map _setters=new HashMap(); private Map _methods=new HashMap(); private Set _convert=new HashSet(); private ClassLoader _loader; private MBeanContainer _mbeanContainer; private static String OBJECT_NAME_CLASS = ObjectName.class.getName(); private static String OBJECT_NAME_ARRAY_CLASS = ObjectName[].class.getName(); /* ------------------------------------------------------------ */ /** * Create MBean for Object. Attempts to create an MBean for the object by searching the package * and class name space. For example an object of the type * *
         * class com.acme.MyClass extends com.acme.util.BaseClass implements com.acme.Iface
         * 
    * * Then this method would look for the following classes: *
      *
    • com.acme.jmx.MyClassMBean *
    • com.acme.util.jmx.BaseClassMBean *
    • org.eclipse.jetty.jmx.ObjectMBean *
    * * @param o The object * @return A new instance of an MBean for the object or null. */ public static Object mbeanFor(Object o) { try { Class oClass = o.getClass(); Object mbean = null; while (mbean == null && oClass != null) { String pName = oClass.getPackage().getName(); String cName = oClass.getName().substring(pName.length() + 1); String mName = pName + ".jmx." + cName + "MBean"; try { Class mClass = (Object.class.equals(oClass))?oClass=ObjectMBean.class:Loader.loadClass(oClass,mName,true); if (LOG.isDebugEnabled()) LOG.debug("mbeanFor " + o + " mClass=" + mClass); try { Constructor constructor = mClass.getConstructor(OBJ_ARG); mbean=constructor.newInstance(new Object[]{o}); } catch(Exception e) { LOG.ignore(e); if (ModelMBean.class.isAssignableFrom(mClass)) { mbean=mClass.newInstance(); ((ModelMBean)mbean).setManagedResource(o, "objectReference"); } } if (LOG.isDebugEnabled()) LOG.debug("mbeanFor " + o + " is " + mbean); return mbean; } catch (ClassNotFoundException e) { // The code below was modified to fix bugs 332200 and JETTY-1416 // The issue was caused by additional information added to the // message after the class name when running in Apache Felix, // as well as before the class name when running in JBoss. if (e.getMessage().contains(mName)) LOG.ignore(e); else LOG.warn(e); } catch (Error e) { LOG.warn(e); mbean = null; } catch (Exception e) { LOG.warn(e); mbean = null; } oClass = oClass.getSuperclass(); } } catch (Exception e) { LOG.ignore(e); } return null; } public ObjectMBean(Object managedObject) { _managed = managedObject; _loader = Thread.currentThread().getContextClassLoader(); } public Object getManagedObject() { return _managed; } public ObjectName getObjectName() { return null; } public String getObjectContextBasis() { return null; } public String getObjectNameBasis() { return null; } protected void setMBeanContainer(MBeanContainer container) { this._mbeanContainer = container; } public MBeanContainer getMBeanContainer () { return this._mbeanContainer; } public MBeanInfo getMBeanInfo() { try { if (_info==null) { // Start with blank lazy lists attributes etc. String desc=null; Object attributes=null; Object constructors=null; Object operations=null; Object notifications=null; // Find list of classes that can influence the mbean Class o_class=_managed.getClass(); Object influences = findInfluences(null, _managed.getClass()); // Set to record defined items Set defined=new HashSet(); // For each influence for (int i=0;i0) { // define an operation if (!defined.contains(key) && key.indexOf('[')<0) { defined.add(key); operations=LazyList.add(operations,defineOperation(key, value, bundle)); } } else { // define an attribute if (!defined.contains(key)) { defined.add(key); MBeanAttributeInfo info=defineAttribute(key, value); if (info!=null) attributes=LazyList.add(attributes,info); } } } } catch(MissingResourceException e) { LOG.ignore(e); } } _info = new MBeanInfo(o_class.getName(), desc, (MBeanAttributeInfo[])LazyList.toArray(attributes, MBeanAttributeInfo.class), (MBeanConstructorInfo[])LazyList.toArray(constructors, MBeanConstructorInfo.class), (MBeanOperationInfo[])LazyList.toArray(operations, MBeanOperationInfo.class), (MBeanNotificationInfo[])LazyList.toArray(notifications, MBeanNotificationInfo.class)); } } catch(RuntimeException e) { LOG.warn(e); throw e; } return _info; } /* ------------------------------------------------------------ */ public Object getAttribute(String name) throws AttributeNotFoundException, MBeanException, ReflectionException { Method getter = (Method) _getters.get(name); if (getter == null) throw new AttributeNotFoundException(name); try { Object o = _managed; if (getter.getDeclaringClass().isInstance(this)) o = this; // mbean method // get the attribute Object r=getter.invoke(o, (java.lang.Object[]) null); // convert to ObjectName if need be. if (r!=null && _convert.contains(name)) { if (r.getClass().isArray()) { ObjectName[] on = new ObjectName[Array.getLength(r)]; for (int i=0;i) { Collection c = (Collection)r; ObjectName[] on = new ObjectName[c.size()]; int i=0; for (Object obj :c) on[i++]=_mbeanContainer.findMBean(obj); r=on; } else { ObjectName mbean = _mbeanContainer.findMBean(r); if (mbean==null) return null; r=mbean; } } return r; } catch (IllegalAccessException e) { LOG.warn(Log.EXCEPTION, e); throw new AttributeNotFoundException(e.toString()); } catch (InvocationTargetException e) { LOG.warn(Log.EXCEPTION, e); throw new ReflectionException(new Exception(e.getCause())); } } /* ------------------------------------------------------------ */ public AttributeList getAttributes(String[] names) { AttributeList results = new AttributeList(names.length); for (int i = 0; i < names.length; i++) { try { results.add(new Attribute(names[i], getAttribute(names[i]))); } catch (Exception e) { LOG.warn(Log.EXCEPTION, e); } } return results; } /* ------------------------------------------------------------ */ public void setAttribute(Attribute attr) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { if (attr == null) return; if (LOG.isDebugEnabled()) LOG.debug("setAttribute " + _managed + ":" +attr.getName() + "=" + attr.getValue()); Method setter = (Method) _setters.get(attr.getName()); if (setter == null) throw new AttributeNotFoundException(attr.getName()); try { Object o = _managed; if (setter.getDeclaringClass().isInstance(this)) o = this; // get the value Object value = attr.getValue(); // convert from ObjectName if need be if (value!=null && _convert.contains(attr.getName())) { if (value.getClass().isArray()) { Class t=setter.getParameterTypes()[0].getComponentType(); Object na = Array.newInstance(t,Array.getLength(value)); for (int i=Array.getLength(value);i-->0;) Array.set(na, i, _mbeanContainer.findBean((ObjectName)Array.get(value, i))); value=na; } else value=_mbeanContainer.findBean((ObjectName)value); } // do the setting setter.invoke(o, new Object[]{ value }); } catch (IllegalAccessException e) { LOG.warn(Log.EXCEPTION, e); throw new AttributeNotFoundException(e.toString()); } catch (InvocationTargetException e) { LOG.warn(Log.EXCEPTION, e); throw new ReflectionException(new Exception(e.getCause())); } } /* ------------------------------------------------------------ */ public AttributeList setAttributes(AttributeList attrs) { LOG.debug("setAttributes"); AttributeList results = new AttributeList(attrs.size()); Iterator iter = attrs.iterator(); while (iter.hasNext()) { try { Attribute attr = (Attribute) iter.next(); setAttribute(attr); results.add(new Attribute(attr.getName(), getAttribute(attr.getName()))); } catch (Exception e) { LOG.warn(Log.EXCEPTION, e); } } return results; } /* ------------------------------------------------------------ */ public Object invoke(String name, Object[] params, String[] signature) throws MBeanException, ReflectionException { if (LOG.isDebugEnabled()) LOG.debug("invoke " + name); String methodKey = name + "("; if (signature != null) for (int i = 0; i < signature.length; i++) methodKey += (i > 0 ? "," : "") + signature[i]; methodKey += ")"; ClassLoader old_loader=Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(_loader); Method method = (Method) _methods.get(methodKey); if (method == null) throw new NoSuchMethodException(methodKey); Object o = _managed; if (method.getDeclaringClass().isInstance(this)) o = this; return method.invoke(o, params); } catch (NoSuchMethodException e) { LOG.warn(Log.EXCEPTION, e); throw new ReflectionException(e); } catch (IllegalAccessException e) { LOG.warn(Log.EXCEPTION, e); throw new MBeanException(e); } catch (InvocationTargetException e) { LOG.warn(Log.EXCEPTION, e); throw new ReflectionException(new Exception(e.getCause())); } finally { Thread.currentThread().setContextClassLoader(old_loader); } } private static Object findInfluences(Object influences, Class aClass) { if (aClass!=null) { // This class is an influence influences=LazyList.add(influences,aClass); // So are the super classes influences=findInfluences(influences,aClass.getSuperclass()); // So are the interfaces Class[] ifs = aClass.getInterfaces(); for (int i=0;ifs!=null && i *
  • "Object" The field/method is on the managed object. *
  • "MBean" The field/method is on the mbean proxy object *
  • "MObject" The field/method is on the managed object and value should be converted to MBean reference *
  • "MMBean" The field/method is on the mbean proxy object and value should be converted to MBean reference * * the access is either "RW" or "RO". */ public MBeanAttributeInfo defineAttribute(String name, String metaData) { String description = ""; boolean writable = true; boolean onMBean = false; boolean convert = false; if (metaData!= null) { String[] tokens = metaData.split(":", 3); for (int t=0;t0?",":"(")+args[i]; } signature+=(i>0?")":"()"); // Build param infos for (i = 0; i < args.length; i++) { String param_desc = bundle.getString(signature + "[" + i + "]"); parts=param_desc.split(" *: *",2); if (LOG.isDebugEnabled()) LOG.debug(parts[0]+": "+parts[1]); pInfo[i] = new MBeanParameterInfo(parts[0].trim(), args[i], parts[1].trim()); } // build the operation info Method method = oClass.getMethod(method_name, types); Class returnClass = method.getReturnType(); _methods.put(signature, method); if (convert) _convert.add(signature); return new MBeanOperationInfo(method_name, description, pInfo, returnClass.isPrimitive() ? TypeUtil.toName(returnClass) : (returnClass.getName()), impact); } catch (Exception e) { LOG.warn("Operation '"+signature+"'", e); throw new IllegalArgumentException(e.toString()); } } } jetty8-8.1.3/jetty-jmx/src/main/java/org/eclipse/jetty/util/000077500000000000000000000000001174773561500237105ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/java/org/eclipse/jetty/util/log/000077500000000000000000000000001174773561500244715ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/java/org/eclipse/jetty/util/log/jmx/000077500000000000000000000000001174773561500252675ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/java/org/eclipse/jetty/util/log/jmx/LogMBean.java000066400000000000000000000030001174773561500275470ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.util.log.jmx; import java.util.ArrayList; import java.util.List; import org.eclipse.jetty.jmx.ObjectMBean; import org.eclipse.jetty.util.log.Log; /* ------------------------------------------------------------ */ /** */ public class LogMBean extends ObjectMBean { public LogMBean(Object managedObject) { super(managedObject); } public List getLoggers() { List keySet = new ArrayList(Log.getLoggers().keySet()); return keySet; } public boolean isDebugEnabled(String logger) { return Log.getLogger(logger).isDebugEnabled(); } public void setDebugEnabled(String logger, Boolean enabled) { Log.getLogger(logger).setDebugEnabled(enabled); } } jetty8-8.1.3/jetty-jmx/src/main/resources/000077500000000000000000000000001174773561500204525ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/000077500000000000000000000000001174773561500212415ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/000077500000000000000000000000001174773561500226655ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/000077500000000000000000000000001174773561500240245ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/000077500000000000000000000000001174773561500250015ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/component/000077500000000000000000000000001174773561500270035ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/component/jmx/000077500000000000000000000000001174773561500276015ustar00rootroot00000000000000AggregateLifeCycle-mbean.properties000066400000000000000000000001701174773561500363640ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/component/jmxAggregateLifeCycle: A LifeCycle holding other LifeCycles dumpStdErr():Object:INFO:Dump the nested Object state to StdErrDumpable-mbean.properties000066400000000000000000000001251174773561500344470ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/component/jmxDumpable: Dumpable Object dump():Object:INFO:Dump the nested Object state as a StringLifeCycle-mbean.properties000066400000000000000000000004171174773561500345610ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/component/jmxLifeCycle: Startable object start(): Starts the instance stop(): Stops the instance running: Instance is started or starting started: Instance is started starting: Instance is starting stopping: Instance is stopping stopped: Instance is stopped failed: Instance is failedjetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/log/000077500000000000000000000000001174773561500255625ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/log/jmx/000077500000000000000000000000001174773561500263605ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/log/jmx/Log-mbean.properties000066400000000000000000000012051174773561500322750ustar00rootroot00000000000000Log: Jetty Logging implementaton loggers:MBean: List of all instantiated loggers debugEnabled:RW: True if debug enabled for root logger Log.LOG isDebugEnabled(java.lang.String):MBean:INFO: True if debug is enabled for the given logger isDebugEnabled(java.lang.String)[0]:loggerName: Name of the logger to return isDebugEnabled for setDebugEnabled(java.lang.String,java.lang.Boolean):MBean:ACTION: Set debug enabled for the given logger setDebugEnabled(java.lang.String,java.lang.Boolean)[0]:loggerName: Name of the logger to set debug enabled setDebugEnabled(java.lang.String,java.lang.Boolean)[1]:enabled: true to enable debug, false otherwise jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/thread/000077500000000000000000000000001174773561500262505ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/thread/jmx/000077500000000000000000000000001174773561500270465ustar00rootroot00000000000000QueuedThreadPool-mbean.properties000066400000000000000000000012061174773561500353760ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/thread/jmxQueuedThreadPool: A thread pool with no max bound by default minThreads: Minimum number of threads in the pool maxThreads: Maximum number threads in the pool name: Name of the thread pool daemon: Is pool thread using daemon thread threadsPriority: The priority of threads in the pool maxIdleTimeMs: Maximum time a thread may be idle in ms detailedDump: Full stack detail in dump output dump(): Dump thread state stopThread(long): Stop a pool thread stopThread(long)[0]: id:Thread ID interruptThread(long): Interrupt a pool thread interruptThread(long)[0]: id:Thread ID dumpThread(long): Dump a pool thread stack dumpThread(long)[0]: id:Thread ID ThreadPool-mbean.properties000066400000000000000000000002621174773561500342260ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/main/resources/org/eclipse/jetty/util/thread/jmxThreadPool: Pool of threads threads: RO:Number of Threads in pool idleThreads: RO:Number of idle Threads in pool lowOnThreads: RO:Indicates the pool is low on available threads. jetty8-8.1.3/jetty-jmx/src/test/000077500000000000000000000000001174773561500164735ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/java/000077500000000000000000000000001174773561500174145ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/java/com/000077500000000000000000000000001174773561500201725ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/java/com/acme/000077500000000000000000000000001174773561500210775ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/java/com/acme/Base.java000066400000000000000000000046351174773561500226240ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package com.acme; import org.eclipse.jetty.util.component.AbstractLifeCycle; public class Base extends AbstractLifeCycle { String name; int value; String[] messages; /* ------------------------------------------------------------ */ /** * @return Returns the messages. */ public String[] getMessages() { return messages; } /* ------------------------------------------------------------ */ /** * @param messages The messages to set. */ public void setMessages(String[] messages) { this.messages = messages; } /* ------------------------------------------------------------ */ /** * @return Returns the name. */ public String getName() { return name; } /* ------------------------------------------------------------ */ /** * @param name The name to set. */ public void setName(String name) { this.name = name; } /* ------------------------------------------------------------ */ /** * @return Returns the value. */ public int getValue() { return value; } /* ------------------------------------------------------------ */ /** * @param value The value to set. */ public void setValue(int value) { this.value = value; } /* ------------------------------------------------------------ */ public void doSomething(int arg) { System.err.println("doSomething "+arg); } /* ------------------------------------------------------------ */ public String findSomething(int arg) { return ("found "+arg); } } jetty8-8.1.3/jetty-jmx/src/test/java/com/acme/Derived.java000066400000000000000000000023251174773561500233260ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package com.acme; public class Derived extends Base implements Signature { String fname="Full Name"; public String getFullName() { return fname; } public void setFullName(String name) { fname=name; } public void publish() { System.err.println("publish"); } public void doodle(String doodle) { System.err.println("doodle "+doodle); } public void somethingElse() { } } jetty8-8.1.3/jetty-jmx/src/test/java/com/acme/Signature.java000066400000000000000000000015271174773561500237100ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package com.acme; public interface Signature { String getFullName(); void publish(); } jetty8-8.1.3/jetty-jmx/src/test/java/org/000077500000000000000000000000001174773561500202035ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/java/org/eclipse/000077500000000000000000000000001174773561500216275ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500227665ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/000077500000000000000000000000001174773561500235645ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ConnectorServerTest.java000066400000000000000000000022401174773561500304060ustar00rootroot00000000000000//======================================================================== //Copyright (c) Webtide LLC //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. // //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html // //The Apache License v2.0 is available at //http://www.apache.org/licenses/LICENSE-2.0.txt // //You may elect to redistribute this code under either of these licenses. //======================================================================== package org.eclipse.jetty.jmx; import javax.management.remote.JMXServiceURL; import org.junit.Test; public class ConnectorServerTest { @Test public void randomPortTest() throws Exception { ConnectorServer srv = new ConnectorServer( new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:0/jettytest"), "org.eclipse.jetty:name=rmiconnectorserver"); srv.start(); Thread.sleep(5000); } } jetty8-8.1.3/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanTest.java000066400000000000000000000021651174773561500274040ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jmx; import static org.junit.Assert.assertTrue; import org.junit.Test; import com.acme.Derived; public class ObjectMBeanTest { @Test public void testMbeanInfo() { Derived derived = new Derived(); ObjectMBean mbean = new ObjectMBean(derived); assertTrue(mbean.getMBeanInfo()!=null); // TODO do more than just run it } } jetty8-8.1.3/jetty-jmx/src/test/resources/000077500000000000000000000000001174773561500205055ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/resources/org/000077500000000000000000000000001174773561500212745ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/resources/org/eclipse/000077500000000000000000000000001174773561500227205ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/resources/org/eclipse/jetty/000077500000000000000000000000001174773561500240575ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/resources/org/eclipse/jetty/com/000077500000000000000000000000001174773561500246355ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/resources/org/eclipse/jetty/com/acme/000077500000000000000000000000001174773561500255425ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/resources/org/eclipse/jetty/com/acme/jmx/000077500000000000000000000000001174773561500263405ustar00rootroot00000000000000jetty8-8.1.3/jetty-jmx/src/test/resources/org/eclipse/jetty/com/acme/jmx/Derived-mbean.properties000066400000000000000000000003321174773561500331160ustar00rootroot00000000000000Derived: Test the mbean stuff fullName : The full name of something publish() : publish something doodle(java.lang.String) : ACTION:Doodle something doodle(java.lang.String)[0] : argname: A description of the argument.jetty8-8.1.3/jetty-jndi/000077500000000000000000000000001174773561500150535ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/pom.xml000066400000000000000000000051271174773561500163750ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 jetty-jndi Jetty :: JNDI Naming JNDI spi impl for java namespace. ${project.groupId}.jndi org.apache.felix maven-bundle-plugin true manifest javax.naming.*,* org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.jndi.* junit junit test org.eclipse.jetty jetty-webapp ${project.version} provided org.eclipse.jetty.orbit javax.mail.glassfish below-jdk1.6 (,1.6) org.eclipse.jetty.orbit javax.activation jetty8-8.1.3/jetty-jndi/src/000077500000000000000000000000001174773561500156425ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/000077500000000000000000000000001174773561500165665ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/java/000077500000000000000000000000001174773561500175075ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/java/org/000077500000000000000000000000001174773561500202765ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/000077500000000000000000000000001174773561500217225ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500230615ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/000077500000000000000000000000001174773561500240055ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/BindingEnumeration.java000066400000000000000000000036121174773561500304330ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jndi; import java.util.Iterator; import javax.naming.Binding; import javax.naming.NamingEnumeration; import javax.naming.NamingException; /** BindingEnumeration *

    Implementation of NamingEnumeration * *

    Notes

    *

    Used to return results of Context.listBindings(); * *

    Usage

    * */ public class BindingEnumeration implements NamingEnumeration { Iterator _delegate; public BindingEnumeration (Iterator e) { _delegate = e; } public void close() throws NamingException { } public boolean hasMore () throws NamingException { return _delegate.hasNext(); } public Binding next() throws NamingException { Binding b = (Binding)_delegate.next(); return new Binding (b.getName(), b.getClassName(), b.getObject(), true); } public boolean hasMoreElements() { return _delegate.hasNext(); } public Binding nextElement() { Binding b = (Binding)_delegate.next(); return new Binding (b.getName(), b.getClassName(), b.getObject(),true); } }jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/ContextFactory.java000066400000000000000000000165521174773561500276350ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jndi; import java.io.IOException; import java.util.Hashtable; import java.util.Map; import java.util.WeakHashMap; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameParser; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.naming.spi.ObjectFactory; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.log.Logger; /** * ContextFactory.java * * This is an object factory that produces a jndi naming * context based on a classloader. * * It is used for the java:comp context. * * This object factory is bound at java:comp. When a * lookup arrives for java:comp, this object factory * is invoked and will return a context specific to * the caller's environment (so producing the java:comp/env * specific to a webapp). * * The context selected is based on classloaders. First * we try looking in at the classloader that is associated * with the current webapp context (if there is one). If * not, we use the thread context classloader. * * Created: Fri Jun 27 09:26:40 2003 * * * */ public class ContextFactory implements ObjectFactory { private static Logger __log = NamingUtil.__log; /** * Map of classloaders to contexts. */ private static final WeakHashMap __contextMap = new WeakHashMap(); /** * Threadlocal for injecting a context to use * instead of looking up the map. */ private static final ThreadLocal __threadContext = new ThreadLocal(); /** * Find or create a context which pertains to a classloader. * * We use either the classloader for the current ContextHandler if * we are handling a request, OR we use the thread context classloader * if we are not processing a request. * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable) */ public Object getObjectInstance (Object obj, Name name, Context nameCtx, Hashtable env) throws Exception { //First, see if we have had a context injected into us to use. Context ctx = (Context)__threadContext.get(); if (ctx != null) { if(__log.isDebugEnabled()) __log.debug("Using the Context that is bound on the thread"); return ctx; } // Next, see if we are in a webapp context, if we are, use // the classloader of the webapp to find the right jndi comp context ClassLoader loader = null; if (ContextHandler.getCurrentContext() != null) { loader = ContextHandler.getCurrentContext().getContextHandler().getClassLoader(); } if (loader != null) { if (__log.isDebugEnabled()) __log.debug("Using classloader of current org.eclipse.jetty.server.handler.ContextHandler"); } else { //Not already in a webapp context, in that case, we try the //curren't thread's classloader instead loader = Thread.currentThread().getContextClassLoader(); if (__log.isDebugEnabled()) __log.debug("Using thread context classloader"); } //Get the context matching the classloader ctx = (Context)__contextMap.get(loader); //The map does not contain an entry for this classloader if (ctx == null) { //Check if a parent classloader has created the context ctx = getParentClassLoaderContext(loader); //Didn't find a context to match any of the ancestors //of the classloader, so make a context if (ctx == null) { Reference ref = (Reference)obj; StringRefAddr parserAddr = (StringRefAddr)ref.get("parser"); String parserClassName = (parserAddr==null?null:(String)parserAddr.getContent()); NameParser parser = (NameParser)(parserClassName==null?null:loader.loadClass(parserClassName).newInstance()); ctx = new NamingContext (env, name.get(0), (NamingContext)nameCtx, parser); if(__log.isDebugEnabled())__log.debug("No entry for classloader: "+loader); __contextMap.put (loader, ctx); } } return ctx; } /** * Keep trying ancestors of the given classloader to find one to which * the context is bound. * @param loader * @return the context from the parent class loader */ public Context getParentClassLoaderContext (ClassLoader loader) { Context ctx = null; ClassLoader cl = loader; for (cl = cl.getParent(); (cl != null) && (ctx == null); cl = cl.getParent()) { ctx = (Context)__contextMap.get(cl); } return ctx; } /** * Associate the given Context with the current thread. * resetComponentContext method should be called to reset the context. * @param ctx the context to associate to the current thread. * @return the previous context associated on the thread (can be null) */ public static Context setComponentContext(final Context ctx) { Context previous = (Context)__threadContext.get(); __threadContext.set(ctx); return previous; } /** * Set back the context with the given value. * Don't return the previous context, use setComponentContext() method for this. * @param ctx the context to associate to the current thread. */ public static void resetComponentContext(final Context ctx) { __threadContext.set(ctx); } public static void dump(Appendable out, String indent) throws IOException { out.append("o.e.j.jndi.ContextFactory@").append(Long.toHexString(__contextMap.hashCode())).append("\n"); int size=__contextMap.size(); int i=0; for (Map.Entry entry : ((Map)__contextMap).entrySet()) { boolean last=++i==size; ClassLoader loader=entry.getKey(); out.append(indent).append(" +- ").append(loader.getClass().getSimpleName()).append("@").append(Long.toHexString(loader.hashCode())).append(": "); NamingContext context = entry.getValue(); context.dump(out,indent+(last?" ":" | ")); } } } jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java000066400000000000000000000037451174773561500300630ustar00rootroot00000000000000package org.eclipse.jetty.jndi; import java.lang.reflect.Method; import java.sql.Statement; import javax.sql.DataSource; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.Destroyable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** * Close a DataSource. * Some {@link DataSource}'s need to be close (eg. Atomikos). This bean is a {@link Destroyable} and * may be added to any {@link AggregateLifeCycle} so that {@link #destroy()} * will be called. The {@link #destroy()} method calls any no-arg method called "close" on the passed DataSource. * */ public class DataSourceCloser implements Destroyable { private static final Logger LOG = Log.getLogger(DataSourceCloser.class); final DataSource _datasource; final String _shutdown; public DataSourceCloser(DataSource datasource) { if (datasource==null) throw new IllegalArgumentException(); _datasource=datasource; _shutdown=null; } public DataSourceCloser(DataSource datasource,String shutdownSQL) { if (datasource==null) throw new IllegalArgumentException(); _datasource=datasource; _shutdown=shutdownSQL; } public void destroy() { try { if (_shutdown!=null) { LOG.info("Shutdown datasource {}",_datasource); Statement stmt = _datasource.getConnection().createStatement(); stmt.executeUpdate(_shutdown); stmt.close(); } } catch (Exception e) { LOG.warn(e); } try { Method close = _datasource.getClass().getMethod("close", new Class[]{}); LOG.info("Close datasource {}",_datasource); close.invoke(_datasource, new Object[]{}); } catch (Exception e) { LOG.warn(e); } } } jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/InitialContextFactory.java000066400000000000000000000051511174773561500311400ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jndi; import java.util.Hashtable; import java.util.Properties; import javax.naming.CompoundName; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameParser; import javax.naming.NamingException; import org.eclipse.jetty.jndi.local.localContextRoot; import org.eclipse.jetty.util.log.Logger; /*------------------------------------------------*/ /** * InitialContextFactory.java * * Factory for the default InitialContext. * Created: Tue Jul 1 19:08:08 2003 * * * @version 1.0 */ public class InitialContextFactory implements javax.naming.spi.InitialContextFactory { private static Logger __log = NamingUtil.__log; public static class DefaultParser implements NameParser { static Properties syntax = new Properties(); static { syntax.put("jndi.syntax.direction", "left_to_right"); syntax.put("jndi.syntax.separator", "/"); syntax.put("jndi.syntax.ignorecase", "false"); } public Name parse (String name) throws NamingException { return new CompoundName (name, syntax); } }; /*------------------------------------------------*/ /** * Get Context that has access to default Namespace. * This method won't be called if a name URL beginning * with java: is passed to an InitialContext. * * @see org.eclipse.jetty.jndi.java.javaURLContextFactory * @param env a Hashtable value * @return a Context value */ public Context getInitialContext(Hashtable env) { __log.debug("InitialContextFactory.getInitialContext()"); Context ctx = new localContextRoot(env); if(__log.isDebugEnabled())__log.debug("Created initial context delegate for local namespace:"+ctx); return ctx; } } jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/NameEnumeration.java000066400000000000000000000036131174773561500277420ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jndi; import java.util.Iterator; import javax.naming.Binding; import javax.naming.NameClassPair; import javax.naming.NamingEnumeration; import javax.naming.NamingException; /** NameEnumeration *

    Implementation of NamingEnumeration interface. * *

    Notes

    *

    Used for returning results of Context.list(); * *

    Usage

    * */ public class NameEnumeration implements NamingEnumeration { Iterator _delegate; public NameEnumeration (Iterator e) { _delegate = e; } public void close() throws NamingException { } public boolean hasMore () throws NamingException { return _delegate.hasNext(); } public NameClassPair next() throws NamingException { Binding b = _delegate.next(); return new NameClassPair(b.getName(),b.getClassName(),true); } public boolean hasMoreElements() { return _delegate.hasNext(); } public NameClassPair nextElement() { Binding b = _delegate.next(); return new NameClassPair(b.getName(),b.getClassName(),true); } }jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/NamingContext.java000066400000000000000000001213411174773561500274300ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jndi; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; import javax.naming.Binding; import javax.naming.CompoundName; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.LinkRef; import javax.naming.Name; import javax.naming.NameAlreadyBoundException; import javax.naming.NameNotFoundException; import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.NotContextException; import javax.naming.OperationNotSupportedException; import javax.naming.Reference; import javax.naming.Referenceable; import javax.naming.spi.NamingManager; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.log.Logger; /*------------------------------------------------*/ /** NamingContext *

    Implementation of Context interface. * *

    Notes

    *

    All Names are expected to be Compound, not Composite. * * */ public class NamingContext implements Context, Cloneable, Dumpable { private final static Logger __log=NamingUtil.__log; private final static List __empty = Collections.emptyList(); public static final String LOCK_PROPERTY = "org.eclipse.jndi.lock"; public static final String UNLOCK_PROPERTY = "org.eclipse.jndi.unlock"; protected final Hashtable _env = new Hashtable(); protected Map _bindings = new HashMap(); protected NamingContext _parent = null; protected String _name = null; protected NameParser _parser = null; private Collection _listeners; /*------------------------------------------------*/ /** * Naming Context Listener. */ public interface Listener { /** * Called by {@link NamingContext#addBinding(Name, Object)} when adding * a binding. * @param ctx The context to add to. * @param binding The binding to add. * @return The binding to bind, or null if the binding should be ignored. */ Binding bind(NamingContext ctx, Binding binding); /** * @param ctx The context to unbind from * @param binding The binding that was unbound. */ void unbind(NamingContext ctx, Binding binding); } /*------------------------------------------------*/ /** * Constructor * * @param env environment properties * @param name relative name of this context * @param parent immediate ancestor Context (can be null) * @param parser NameParser for this Context */ public NamingContext(Hashtable env, String name, NamingContext parent, NameParser parser) { if (env != null) _env.putAll(env); _name = name; _parent = parent; _parser = parser; } /*------------------------------------------------*/ /** * Clone this NamingContext * * @return copy of this NamingContext * @exception CloneNotSupportedException if an error occurs */ public Object clone () throws CloneNotSupportedException { NamingContext ctx = (NamingContext)super.clone(); ctx._env.putAll(_env); ctx._bindings.putAll(_bindings); return ctx; } /*------------------------------------------------*/ /** * Getter for _name * * @return name of this Context (relative, not absolute) */ public String getName () { return _name; } /*------------------------------------------------*/ /** * Getter for _parent * * @return parent Context */ public Context getParent() { return _parent; } /*------------------------------------------------*/ /** * Setter for _parser * * */ public void setNameParser (NameParser parser) { _parser = parser; } public void setEnv (Hashtable env) { _env.clear(); _env.putAll(env); } public Map getBindings () { return _bindings; } public void setBindings(Map bindings) { _bindings = bindings; } /*------------------------------------------------*/ /** * Bind a name to an object * * @param name Name of the object * @param obj object to bind * @exception NamingException if an error occurs */ public void bind(Name name, Object obj) throws NamingException { if (isLocked()) throw new NamingException ("This context is immutable"); Name cname = toCanonicalName(name); if (cname == null) throw new NamingException ("Name is null"); if (cname.size() == 0) throw new NamingException ("Name is empty"); //if no subcontexts, just bind it if (cname.size() == 1) { //get the object to be bound Object objToBind = NamingManager.getStateToBind(obj, name,this, _env); // Check for Referenceable if (objToBind instanceof Referenceable) { objToBind = ((Referenceable)objToBind).getReference(); } //anything else we should be able to bind directly addBinding (cname, objToBind); } else { if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0)); //walk down the subcontext hierarchy //need to ignore trailing empty "" name components String firstComponent = cname.get(0); Object ctx = null; if (firstComponent.equals("")) ctx = this; else { Binding binding = getBinding (firstComponent); if (binding == null) throw new NameNotFoundException (firstComponent+ " is not bound"); ctx = binding.getObject(); if (ctx instanceof Reference) { //deference the object try { ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env); } catch (NamingException e) { throw e; } catch (Exception e) { __log.warn("",e); throw new NamingException (e.getMessage()); } } } if (ctx instanceof Context) { ((Context)ctx).bind (cname.getSuffix(1), obj); } else throw new NotContextException ("Object bound at "+firstComponent +" is not a Context"); } } /*------------------------------------------------*/ /** * Bind a name (as a String) to an object * * @param name a String value * @param obj an Object value * @exception NamingException if an error occurs */ public void bind(String name, Object obj) throws NamingException { bind (_parser.parse(name), obj); } /*------------------------------------------------*/ /** * Create a context as a child of this one * * @param name a Name value * @return a Context value * @exception NamingException if an error occurs */ public Context createSubcontext (Name name) throws NamingException { if (isLocked()) { NamingException ne = new NamingException ("This context is immutable"); ne.setRemainingName(name); throw ne; } Name cname = toCanonicalName (name); if (cname == null) throw new NamingException ("Name is null"); if (cname.size() == 0) throw new NamingException ("Name is empty"); if (cname.size() == 1) { //not permitted to bind if something already bound at that name Binding binding = getBinding (cname); if (binding != null) throw new NameAlreadyBoundException (cname.toString()); Context ctx = new NamingContext ((Hashtable)_env.clone(), cname.get(0), this, _parser); addBinding (cname, ctx); return ctx; } //If the name has multiple subcontexts, walk the hierarchy by //fetching the first one. All intermediate subcontexts in the //name must already exist. String firstComponent = cname.get(0); Object ctx = null; if (firstComponent.equals("")) ctx = this; else { Binding binding = getBinding (firstComponent); if (binding == null) throw new NameNotFoundException (firstComponent + " is not bound"); ctx = binding.getObject(); if (ctx instanceof Reference) { //deference the object if(__log.isDebugEnabled())__log.debug("Object bound at "+firstComponent +" is a Reference"); try { ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env); } catch (NamingException e) { throw e; } catch (Exception e) { __log.warn("",e); throw new NamingException (e.getMessage()); } } } if (ctx instanceof Context) { return ((Context)ctx).createSubcontext (cname.getSuffix(1)); } else throw new NotContextException (firstComponent +" is not a Context"); } /*------------------------------------------------*/ /** * Create a Context as a child of this one * * @param name a String value * @return a Context value * @exception NamingException if an error occurs */ public Context createSubcontext (String name) throws NamingException { return createSubcontext(_parser.parse(name)); } /*------------------------------------------------*/ /** * * * @param name name of subcontext to remove * @exception NamingException if an error occurs */ public void destroySubcontext (String name) throws NamingException { removeBinding(_parser.parse(name)); } /*------------------------------------------------*/ /** * * * @param name name of subcontext to remove * @exception NamingException if an error occurs */ public void destroySubcontext (Name name) throws NamingException { removeBinding(name); } /*------------------------------------------------*/ /** * Lookup a binding by name * * @param name name of bound object * @exception NamingException if an error occurs */ public Object lookup(Name name) throws NamingException { if(__log.isDebugEnabled())__log.debug("Looking up name=\""+name+"\""); Name cname = toCanonicalName(name); if ((cname == null) || (cname.size() == 0)) { __log.debug("Null or empty name, returning copy of this context"); NamingContext ctx = new NamingContext (_env, _name, _parent, _parser); ctx._bindings=_bindings; return ctx; } if (cname.size() == 1) { Binding binding = getBinding (cname); if (binding == null) { NameNotFoundException nnfe = new NameNotFoundException(); nnfe.setRemainingName(cname); throw nnfe; } Object o = binding.getObject(); //handle links by looking up the link if (o instanceof LinkRef) { //if link name starts with ./ it is relative to current context String linkName = ((LinkRef)o).getLinkName(); if (linkName.startsWith("./")) return this.lookup (linkName.substring(2)); else { //link name is absolute InitialContext ictx = new InitialContext(); return ictx.lookup (linkName); } } else if (o instanceof Reference) { //deference the object try { return NamingManager.getObjectInstance(o, cname, this, _env); } catch (NamingException e) { throw e; } catch (Exception e) { __log.warn("",e); throw new NamingException (e.getMessage()); } } else return o; } //it is a multipart name, recurse to the first subcontext String firstComponent = cname.get(0); Object ctx = null; if (firstComponent.equals("")) ctx = this; else { Binding binding = getBinding (firstComponent); if (binding == null) { NameNotFoundException nnfe = new NameNotFoundException(); nnfe.setRemainingName(cname); throw nnfe; } //as we have bound a reference to an object factory //for the component specific contexts //at "comp" we need to resolve the reference ctx = binding.getObject(); if (ctx instanceof Reference) { //deference the object try { ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env); } catch (NamingException e) { throw e; } catch (Exception e) { __log.warn("",e); throw new NamingException (e.getMessage()); } } } if (!(ctx instanceof Context)) throw new NotContextException(); return ((Context)ctx).lookup (cname.getSuffix(1)); } /*------------------------------------------------*/ /** * Lookup binding of an object by name * * @param name name of bound object * @return object bound to name * @exception NamingException if an error occurs */ public Object lookup (String name) throws NamingException { return lookup (_parser.parse(name)); } /*------------------------------------------------*/ /** * Lookup link bound to name * * @param name name of link binding * @return LinkRef or plain object bound at name * @exception NamingException if an error occurs */ public Object lookupLink (Name name) throws NamingException { Name cname = toCanonicalName(name); if (cname == null) { NamingContext ctx = new NamingContext (_env, _name, _parent, _parser); ctx._bindings=_bindings; return ctx; } if (cname.size() == 0) throw new NamingException ("Name is empty"); if (cname.size() == 1) { Binding binding = getBinding (cname); if (binding == null) throw new NameNotFoundException(); Object o = binding.getObject(); //handle links by looking up the link if (o instanceof Reference) { //deference the object try { return NamingManager.getObjectInstance(o, cname.getPrefix(1), this, _env); } catch (NamingException e) { throw e; } catch (Exception e) { __log.warn("",e); throw new NamingException (e.getMessage()); } } else { //object is either a LinkRef which we don't dereference //or a plain object in which case spec says we return it return o; } } //it is a multipart name, recurse to the first subcontext String firstComponent = cname.get(0); Object ctx = null; if (firstComponent.equals("")) ctx = this; else { Binding binding = getBinding (firstComponent); if (binding == null) throw new NameNotFoundException (); ctx = binding.getObject(); if (ctx instanceof Reference) { //deference the object try { ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env); } catch (NamingException e) { throw e; } catch (Exception e) { __log.warn("",e); throw new NamingException (e.getMessage()); } } } if (!(ctx instanceof Context)) throw new NotContextException(); return ((Context)ctx).lookup (cname.getSuffix(1)); } /*------------------------------------------------*/ /** * Lookup link bound to name * * @param name name of link binding * @return LinkRef or plain object bound at name * @exception NamingException if an error occurs */ public Object lookupLink (String name) throws NamingException { return lookupLink (_parser.parse(name)); } /*------------------------------------------------*/ /** * List all names bound at Context named by Name * * @param name a Name value * @return a NamingEnumeration value * @exception NamingException if an error occurs */ public NamingEnumeration list(Name name) throws NamingException { if(__log.isDebugEnabled())__log.debug("list() on Context="+getName()+" for name="+name); Name cname = toCanonicalName(name); if (cname == null) { return new NameEnumeration(__empty.iterator()); } if (cname.size() == 0) { return new NameEnumeration (_bindings.values().iterator()); } //multipart name String firstComponent = cname.get(0); Object ctx = null; if (firstComponent.equals("")) ctx = this; else { Binding binding = getBinding (firstComponent); if (binding == null) throw new NameNotFoundException (); ctx = binding.getObject(); if (ctx instanceof Reference) { //deference the object if(__log.isDebugEnabled())__log.debug("Dereferencing Reference for "+name.get(0)); try { ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env); } catch (NamingException e) { throw e; } catch (Exception e) { __log.warn("",e); throw new NamingException (e.getMessage()); } } } if (!(ctx instanceof Context)) throw new NotContextException(); return ((Context)ctx).list (cname.getSuffix(1)); } /*------------------------------------------------*/ /** * List all names bound at Context named by Name * * @param name a Name value * @return a NamingEnumeration value * @exception NamingException if an error occurs */ public NamingEnumeration list(String name) throws NamingException { return list(_parser.parse(name)); } /*------------------------------------------------*/ /** * List all Bindings present at Context named by Name * * @param name a Name value * @return a NamingEnumeration value * @exception NamingException if an error occurs */ public NamingEnumeration listBindings(Name name) throws NamingException { Name cname = toCanonicalName (name); if (cname == null) { return new BindingEnumeration(__empty.iterator()); } if (cname.size() == 0) { return new BindingEnumeration (_bindings.values().iterator()); } //multipart name String firstComponent = cname.get(0); Object ctx = null; //if a name has a leading "/" it is parsed as "" so ignore it by staying //at this level in the tree if (firstComponent.equals("")) ctx = this; else { //it is a non-empty name component Binding binding = getBinding (firstComponent); if (binding == null) throw new NameNotFoundException (); ctx = binding.getObject(); if (ctx instanceof Reference) { //deference the object try { ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env); } catch (NamingException e) { throw e; } catch (Exception e) { __log.warn("",e); throw new NamingException (e.getMessage()); } } } if (!(ctx instanceof Context)) throw new NotContextException(); return ((Context)ctx).listBindings (cname.getSuffix(1)); } /*------------------------------------------------*/ /** * List all Bindings at Name * * @param name a String value * @return a NamingEnumeration value * @exception NamingException if an error occurs */ public NamingEnumeration listBindings(String name) throws NamingException { return listBindings (_parser.parse(name)); } /*------------------------------------------------*/ /** * Overwrite or create a binding * * @param name a Name value * @param obj an Object value * @exception NamingException if an error occurs */ public void rebind(Name name, Object obj) throws NamingException { if (isLocked()) throw new NamingException ("This context is immutable"); Name cname = toCanonicalName(name); if (cname == null) throw new NamingException ("Name is null"); if (cname.size() == 0) throw new NamingException ("Name is empty"); //if no subcontexts, just bind it if (cname.size() == 1) { //check if it is a Referenceable Object objToBind = NamingManager.getStateToBind(obj, name, this, _env); if (objToBind instanceof Referenceable) { objToBind = ((Referenceable)objToBind).getReference(); } removeBinding(cname); addBinding (cname, objToBind); } else { //walk down the subcontext hierarchy if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0)); String firstComponent = cname.get(0); Object ctx = null; if (firstComponent.equals("")) ctx = this; else { Binding binding = getBinding (name.get(0)); if (binding == null) throw new NameNotFoundException (name.get(0)+ " is not bound"); ctx = binding.getObject(); if (ctx instanceof Reference) { //deference the object try { ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env); } catch (NamingException e) { throw e; } catch (Exception e) { __log.warn("",e); throw new NamingException (e.getMessage()); } } } if (ctx instanceof Context) { ((Context)ctx).rebind (cname.getSuffix(1), obj); } else throw new NotContextException ("Object bound at "+firstComponent +" is not a Context"); } } /*------------------------------------------------*/ /** * Overwrite or create a binding from Name to Object * * @param name a String value * @param obj an Object value * @exception NamingException if an error occurs */ public void rebind (String name, Object obj) throws NamingException { rebind (_parser.parse(name), obj); } /*------------------------------------------------*/ /** * Not supported. * * @param name a String value * @exception NamingException if an error occurs */ public void unbind (String name) throws NamingException { unbind(_parser.parse(name)); } /*------------------------------------------------*/ /** * Not supported. * * @param name a String value * @exception NamingException if an error occurs */ public void unbind (Name name) throws NamingException { if (name.size() == 0) return; if (isLocked()) throw new NamingException ("This context is immutable"); Name cname = toCanonicalName(name); if (cname == null) throw new NamingException ("Name is null"); if (cname.size() == 0) throw new NamingException ("Name is empty"); //if no subcontexts, just unbind it if (cname.size() == 1) { removeBinding (cname); } else { //walk down the subcontext hierarchy if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0)); String firstComponent = cname.get(0); Object ctx = null; if (firstComponent.equals("")) ctx = this; else { Binding binding = getBinding (name.get(0)); if (binding == null) throw new NameNotFoundException (name.get(0)+ " is not bound"); ctx = binding.getObject(); if (ctx instanceof Reference) { //deference the object try { ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env); } catch (NamingException e) { throw e; } catch (Exception e) { __log.warn("",e); throw new NamingException (e.getMessage()); } } } if (ctx instanceof Context) { ((Context)ctx).unbind (cname.getSuffix(1)); } else throw new NotContextException ("Object bound at "+firstComponent +" is not a Context"); } } /*------------------------------------------------*/ /** * Not supported * * @param oldName a Name value * @param newName a Name value * @exception NamingException if an error occurs */ public void rename(Name oldName, Name newName) throws NamingException { throw new OperationNotSupportedException(); } /*------------------------------------------------*/ /** * Not supported * * @param oldName a Name value * @param newName a Name value * @exception NamingException if an error occurs */ public void rename(String oldName, String newName) throws NamingException { throw new OperationNotSupportedException(); } /*------------------------------------------------*/ /** Join two names together. These are treated as * CompoundNames. * * @param name a Name value * @param prefix a Name value * @return a Name value * @exception NamingException if an error occurs */ public Name composeName(Name name, Name prefix) throws NamingException { if (name == null) throw new NamingException ("Name cannot be null"); if (prefix == null) throw new NamingException ("Prefix cannot be null"); Name compoundName = (CompoundName)prefix.clone(); compoundName.addAll (name); return compoundName; } /*------------------------------------------------*/ /** Join two names together. These are treated as * CompoundNames. * * @param name a Name value * @param prefix a Name value * @return a Name value * @exception NamingException if an error occurs */ public String composeName (String name, String prefix) throws NamingException { if (name == null) throw new NamingException ("Name cannot be null"); if (prefix == null) throw new NamingException ("Prefix cannot be null"); Name compoundName = _parser.parse(prefix); compoundName.add (name); return compoundName.toString(); } /*------------------------------------------------*/ /** * Do nothing * * @exception NamingException if an error occurs */ public void close () throws NamingException { } /*------------------------------------------------*/ /** * Return a NameParser for this Context. * * @param name a Name value * @return a NameParser value */ public NameParser getNameParser (Name name) { return _parser; } /*------------------------------------------------*/ /** * Return a NameParser for this Context. * * @param name a Name value * @return a NameParser value */ public NameParser getNameParser (String name) { return _parser; } /*------------------------------------------------*/ /** * Get the full name of this Context node * by visiting it's ancestors back to root. * * NOTE: if this Context has a URL namespace then * the URL prefix will be missing * * @return the full name of this Context * @exception NamingException if an error occurs */ public String getNameInNamespace () throws NamingException { Name name = _parser.parse(""); NamingContext c = this; while (c != null) { String str = c.getName(); if (str != null) name.add(0, str); c = (NamingContext)c.getParent(); } return name.toString(); } /*------------------------------------------------*/ /** * Add an environment setting to this Context * * @param propName name of the property to add * @param propVal value of the property to add * @return propVal or previous value of the property * @exception NamingException if an error occurs */ public Object addToEnvironment(String propName, Object propVal) throws NamingException { if (isLocked() && !(propName.equals(UNLOCK_PROPERTY))) throw new NamingException ("This context is immutable"); return _env.put (propName, propVal); } /*------------------------------------------------*/ /** * Remove a property from this Context's environment. * * @param propName name of property to remove * @return value of property or null if it didn't exist * @exception NamingException if an error occurs */ public Object removeFromEnvironment(String propName) throws NamingException { if (isLocked()) throw new NamingException ("This context is immutable"); return _env.remove (propName); } /*------------------------------------------------*/ /** * Get the environment of this Context. * * @return a copy of the environment of this Context. */ public Hashtable getEnvironment () { return (Hashtable)_env.clone(); } /*------------------------------------------------*/ /** * Add a name to object binding to this Context. * * @param name a Name value * @param obj an Object value */ public void addBinding (Name name, Object obj) throws NameAlreadyBoundException { String key = name.toString(); Binding binding=new Binding (key, obj); Collection list = findListeners(); for (Listener listener : list) { binding=listener.bind(this,binding); if (binding==null) break; } if(__log.isDebugEnabled()) __log.debug("Adding binding with key="+key+" obj="+obj+" for context="+_name+" as "+binding); if (binding!=null) { if (_bindings.containsKey(key)) throw new NameAlreadyBoundException(name.toString()); _bindings.put(key,binding); } } /*------------------------------------------------*/ /** * Get a name to object binding from this Context * * @param name a Name value * @return a Binding value */ public Binding getBinding (Name name) { return (Binding) _bindings.get(name.toString()); } /*------------------------------------------------*/ /** * Get a name to object binding from this Context * * @param name as a String * @return null or the Binding */ public Binding getBinding (String name) { return (Binding) _bindings.get(name); } /*------------------------------------------------*/ public void removeBinding (Name name) { String key = name.toString(); if (__log.isDebugEnabled()) __log.debug("Removing binding with key="+key); Binding binding = _bindings.remove(key); if (binding!=null) { Collection list = findListeners(); for (Listener listener : list) listener.unbind(this,binding); } } /*------------------------------------------------*/ /** * Remove leading or trailing empty components from * name. Eg "/comp/env/" -> "comp/env" * * @param name the name to normalize * @return normalized name */ public Name toCanonicalName (Name name) { Name canonicalName = name; if (name != null) { if (canonicalName.size() > 1) { if (canonicalName.get(0).equals("")) canonicalName = canonicalName.getSuffix(1); if (canonicalName.get(canonicalName.size()-1).equals("")) canonicalName = canonicalName.getPrefix(canonicalName.size()-1); } } return canonicalName; } /* ------------------------------------------------------------ */ public boolean isLocked() { if ((_env.get(LOCK_PROPERTY) == null) && (_env.get(UNLOCK_PROPERTY) == null)) return false; Object lockKey = _env.get(LOCK_PROPERTY); Object unlockKey = _env.get(UNLOCK_PROPERTY); if ((lockKey != null) && (unlockKey != null) && (lockKey.equals(unlockKey))) return false; return true; } /* ------------------------------------------------------------ */ public String dump() { StringBuilder buf = new StringBuilder(); try { dump(buf,""); } catch(Exception e) { __log.warn(e); } return buf.toString(); } /* ------------------------------------------------------------ */ public void dump(Appendable out,String indent) throws IOException { out.append(this.getClass().getSimpleName()).append("@").append(Long.toHexString(this.hashCode())).append("\n"); int size=_bindings.size(); int i=0; for (Map.Entry entry : ((Map)_bindings).entrySet()) { boolean last=++i==size; out.append(indent).append(" +- ").append(entry.getKey()).append(": "); Binding binding = entry.getValue(); Object value = binding.getObject(); if ("comp".equals(entry.getKey()) && value instanceof Reference && "org.eclipse.jetty.jndi.ContextFactory".equals(((Reference)value).getFactoryClassName())) { ContextFactory.dump(out,indent+(last?" ":" | ")); } else if (value instanceof Dumpable) { ((Dumpable)value).dump(out,indent+(last?" ":" | ")); } else { out.append(value.getClass().getSimpleName()).append("="); out.append(String.valueOf(value).replace('\n','|').replace('\r','|')); out.append("\n"); } } } private Collection findListeners() { Collection list = new ArrayList(); NamingContext ctx=this; while (ctx!=null) { if (ctx._listeners!=null) list.addAll(ctx._listeners); ctx=(NamingContext)ctx.getParent(); } return list; } public void addListener(Listener listener) { if (_listeners==null) _listeners=new ArrayList(); _listeners.add(listener); } public boolean removeListener(Listener listener) { return _listeners.remove(listener); } } jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/NamingUtil.java000066400000000000000000000106551174773561500267260ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jndi; import java.util.HashMap; import java.util.Map; import javax.naming.Binding; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameNotFoundException; import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import org.eclipse.jetty.util.log.Logger; /** * Util.java * * * Created: Tue Jul 1 18:26:17 2003 * * * @version 1.0 */ public class NamingUtil { public final static Logger __log=org.eclipse.jetty.util.log.Log.getLogger("jndi"); /* ------------------------------------------------------------ */ /** * Bind an object to a context ensuring all sub-contexts * are created if necessary * * @param ctx the context into which to bind * @param nameStr the name relative to context to bind * @param obj the object to be bound * @exception NamingException if an error occurs */ public static Context bind (Context ctx, String nameStr, Object obj) throws NamingException { Name name = ctx.getNameParser("").parse(nameStr); //no name, nothing to do if (name.size() == 0) return null; Context subCtx = ctx; //last component of the name will be the name to bind for (int i=0; i < name.size() - 1; i++) { try { subCtx = (Context)subCtx.lookup (name.get(i)); if(__log.isDebugEnabled()) __log.debug("Subcontext "+name.get(i)+" already exists"); } catch (NameNotFoundException e) { subCtx = subCtx.createSubcontext(name.get(i)); if(__log.isDebugEnabled()) __log.debug("Subcontext "+name.get(i)+" created"); } } subCtx.rebind (name.get(name.size() - 1), obj); if(__log.isDebugEnabled()) __log.debug("Bound object to "+name.get(name.size() - 1)); return subCtx; } public static void unbind (Context ctx) throws NamingException { //unbind everything in the context and all of its subdirectories NamingEnumeration ne = ctx.listBindings(ctx.getNameInNamespace()); while (ne.hasMoreElements()) { Binding b = (Binding)ne.nextElement(); if (b.getObject() instanceof Context) { unbind((Context)b.getObject()); } else ctx.unbind(b.getName()); } } /** * Do a deep listing of the bindings for a context. * @param ctx the context containing the name for which to list the bindings * @param name the name in the context to list * @return map: key is fully qualified name, value is the bound object * @throws NamingException */ public static Map flattenBindings (Context ctx, String name) throws NamingException { HashMap map = new HashMap(); //the context representation of name arg Context c = (Context)ctx.lookup (name); NameParser parser = c.getNameParser(""); NamingEnumeration enm = ctx.listBindings(name); while (enm.hasMore()) { Binding b = (Binding)enm.next(); if (b.getObject() instanceof Context) { map.putAll(flattenBindings (c, b.getName())); } else { Name compoundName = parser.parse (c.getNameInNamespace()); compoundName.add(b.getName()); map.put (compoundName.toString(), b.getObject()); } } return map; } } jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/factories/000077500000000000000000000000001174773561500257645ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/factories/MailSessionReference.java000066400000000000000000000131041174773561500326730ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jndi.factories; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Properties; import javax.mail.Authenticator; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.naming.Context; import javax.naming.Name; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.naming.spi.ObjectFactory; import org.eclipse.jetty.util.security.Password; /** * MailSessionReference * * This is a subclass of javax.mail.Reference and an ObjectFactory for javax.mail.Session objects. * * The subclassing of Reference allows all of the setup for a javax.mail.Session * to be captured without necessitating first instantiating a Session object. The * reference is bound into JNDI and it is only when the reference is looked up that * this object factory will create an instance of javax.mail.Session using the * information captured in the Reference. * */ public class MailSessionReference extends Reference implements ObjectFactory { public static class PasswordAuthenticator extends Authenticator { PasswordAuthentication passwordAuthentication; private String user; private String password; public PasswordAuthenticator() { } public PasswordAuthenticator(String user, String password) { passwordAuthentication = new PasswordAuthentication (user, (password.startsWith(Password.__OBFUSCATE)?Password.deobfuscate(password):password)); } public PasswordAuthentication getPasswordAuthentication() { return passwordAuthentication; } public void setUser (String user) { this.user = user; } public String getUser () { return this.user; } public String getPassword () { return this.password; } public void setPassword(String password) { this.password = password; } }; /** * */ public MailSessionReference() { super ("javax.mail.Session", MailSessionReference.class.getName(), null); } /** * Create a javax.mail.Session instance based on the information passed in the Reference * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable) * @param ref the Reference * @param arg1 not used * @param arg2 not used * @param arg3 not used * @return the object found * @throws Exception */ public Object getObjectInstance(Object ref, Name arg1, Context arg2, Hashtable arg3) throws Exception { if (ref == null) return null; Reference reference = (Reference)ref; Properties props = new Properties(); String user = null; String password = null; Enumeration refs = reference.getAll(); while (refs.hasMoreElements()) { RefAddr refAddr = (RefAddr)refs.nextElement(); String name = refAddr.getType(); String value = (String)refAddr.getContent(); if (name.equalsIgnoreCase("user")) user = value; else if (name.equalsIgnoreCase("pwd")) password = value; else props.put(name, value); } if (password == null) return Session.getInstance(props); else return Session.getInstance(props, new PasswordAuthenticator(user, password)); } public void setUser (String user) { StringRefAddr addr = (StringRefAddr)get("user"); if (addr != null) { throw new RuntimeException ("user already set on SessionReference, can't be changed"); } add(new StringRefAddr("user", user)); } public void setPassword (String password) { StringRefAddr addr = (StringRefAddr)get("pwd"); if (addr != null) throw new RuntimeException ("password already set on SessionReference, can't be changed"); add(new StringRefAddr ("pwd", password)); } public void setProperties (Properties properties) { Iterator entries = properties.entrySet().iterator(); while (entries.hasNext()) { Map.Entry e = (Map.Entry)entries.next(); StringRefAddr sref = (StringRefAddr)get((String)e.getKey()); if (sref != null) throw new RuntimeException ("property "+e.getKey()+" already set on Session reference, can't be changed"); add(new StringRefAddr((String)e.getKey(), (String)e.getValue())); } } } jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/java/000077500000000000000000000000001174773561500247265ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/java/javaNameParser.java000066400000000000000000000032011174773561500304640ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jndi.java; import java.util.Properties; import javax.naming.CompoundName; import javax.naming.Name; import javax.naming.NameParser; import javax.naming.NamingException; /** * javaNameParser * */ public class javaNameParser implements NameParser { static Properties syntax = new Properties(); static { syntax.put("jndi.syntax.direction", "left_to_right"); syntax.put("jndi.syntax.separator", "/"); syntax.put("jndi.syntax.ignorecase", "false"); } /** * Parse a name into its components. * @param name The non-null string name to parse. * @return A non-null parsed form of the name using the naming convention * of this parser. * @exception NamingException If a naming exception was encountered. */ public Name parse(String name) throws NamingException { return new CompoundName(name, syntax); } } jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/java/javaRootURLContext.java000066400000000000000000000175611174773561500313200ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jndi.java; import java.util.Hashtable; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.StringRefAddr; import org.eclipse.jetty.jndi.ContextFactory; import org.eclipse.jetty.jndi.NamingContext; import org.eclipse.jetty.jndi.NamingUtil; import org.eclipse.jetty.util.log.Logger; /** javaRootURLContext *

    This is the root of the java: url namespace * *

    Notes

    *

    Thanks to Rickard Oberg for the idea of binding an ObjectFactory at "comp". * *

    Usage

    *
     */
    /*
    * 
    * * @see * * * @version 1.0 */ public class javaRootURLContext implements Context { private static Logger __log = NamingUtil.__log; public static final String URL_PREFIX = "java:"; protected Hashtable _env; protected static NamingContext __nameRoot; protected static NameParser __javaNameParser; static { try { __javaNameParser = new javaNameParser(); __nameRoot = new NamingContext(null,null,null,__javaNameParser); StringRefAddr parserAddr = new StringRefAddr("parser", __javaNameParser.getClass().getName()); Reference ref = new Reference ("javax.naming.Context", parserAddr, ContextFactory.class.getName(), (String)null); //bind special object factory at comp __nameRoot.bind ("comp", ref); } catch (Exception e) { __log.warn(e); } } /*------------------------------------------------*/ /** * Creates a new javaRootURLContext instance. * * @param env a Hashtable value */ public javaRootURLContext(Hashtable env) { _env = env; } public Object lookup(Name name) throws NamingException { return getRoot().lookup(stripProtocol(name)); } public Object lookup(String name) throws NamingException { return getRoot().lookup(stripProtocol(name)); } public void bind(Name name, Object obj) throws NamingException { getRoot().bind(stripProtocol(name), obj); } public void bind(String name, Object obj) throws NamingException { getRoot().bind(stripProtocol(name), obj); } public void unbind (String name) throws NamingException { getRoot().unbind(stripProtocol(name)); } public void unbind (Name name) throws NamingException { getRoot().unbind(stripProtocol(name)); } public void rename (String oldStr, String newStr) throws NamingException { getRoot().rename (stripProtocol(oldStr), stripProtocol(newStr)); } public void rename (Name oldName, Name newName) throws NamingException { getRoot().rename (stripProtocol(oldName), stripProtocol(newName)); } public void rebind (Name name, Object obj) throws NamingException { getRoot().rebind(stripProtocol(name), obj); } public void rebind (String name, Object obj) throws NamingException { getRoot().rebind(stripProtocol(name), obj); } public Object lookupLink (Name name) throws NamingException { return getRoot().lookupLink(stripProtocol(name)); } public Object lookupLink (String name) throws NamingException { return getRoot().lookupLink(stripProtocol(name)); } public Context createSubcontext (Name name) throws NamingException { return getRoot().createSubcontext(stripProtocol(name)); } public Context createSubcontext (String name) throws NamingException { return getRoot().createSubcontext(stripProtocol(name)); } public void destroySubcontext (Name name) throws NamingException { getRoot().destroySubcontext(stripProtocol(name)); } public void destroySubcontext (String name) throws NamingException { getRoot().destroySubcontext(stripProtocol(name)); } public NamingEnumeration list(Name name) throws NamingException { return getRoot().list(stripProtocol(name)); } public NamingEnumeration list(String name) throws NamingException { return getRoot().list(stripProtocol(name)); } public NamingEnumeration listBindings(Name name) throws NamingException { return getRoot().listBindings(stripProtocol(name)); } public NamingEnumeration listBindings(String name) throws NamingException { return getRoot().listBindings(stripProtocol(name)); } public Name composeName (Name name, Name prefix) throws NamingException { return getRoot().composeName(name, prefix); } public String composeName (String name, String prefix) throws NamingException { return getRoot().composeName(name, prefix); } public void close () throws NamingException { } public String getNameInNamespace () throws NamingException { return URL_PREFIX; } public NameParser getNameParser (Name name) throws NamingException { return __javaNameParser; } public NameParser getNameParser (String name) throws NamingException { return __javaNameParser; } public Object addToEnvironment(String propName, Object propVal) throws NamingException { return _env.put (propName,propVal); } public Object removeFromEnvironment(String propName) throws NamingException { return _env.remove (propName); } public Hashtable getEnvironment () { return _env; } public static NamingContext getRoot () { return __nameRoot; } protected Name stripProtocol (Name name) throws NamingException { if ((name != null) && (name.size() > 0)) { String head = name.get(0); if(__log.isDebugEnabled())__log.debug("Head element of name is: "+head); if (head.startsWith(URL_PREFIX)) { head = head.substring (URL_PREFIX.length()); name.remove(0); if (head.length() > 0) name.add(0, head); if(__log.isDebugEnabled())__log.debug("name modified to "+name.toString()); } } return name; } protected String stripProtocol (String name) { String newName = name; if ((name != null) && (!name.equals(""))) { if (name.startsWith(URL_PREFIX)) newName = name.substring(URL_PREFIX.length()); } return newName; } } jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/java/javaURLContextFactory.java000066400000000000000000000064461174773561500320040ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.jndi.java; import java.util.Hashtable; import javax.naming.Context; import javax.naming.Name; import javax.naming.NamingException; import javax.naming.spi.ObjectFactory; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /** javaURLContextFactory *

    This is the URL context factory for the java: URL. * *

    Notes

    *

    * *

    Usage

    *
     */
    public class javaURLContextFactory implements ObjectFactory 
    {
        private static final Logger LOG = Log.getLogger(javaURLContextFactory.class);
            
        /**
         * Either return a new context or the resolution of a url.
         *
         * @param url an Object value
         * @param name a Name value
         * @param ctx a Context value
         * @param env a Hashtable value
         * @return a new context or the resolved object for the url
         * @exception Exception if an error occurs
         */
        public Object getObjectInstance(Object url, Name name, Context ctx, Hashtable env)
            throws Exception 
        {
            // null object means return a root context for doing resolutions
            if (url == null)
            {
                if(LOG.isDebugEnabled())LOG.debug(">>> new root context requested ");
                return new javaRootURLContext(env);
            }
            
            // return the resolution of the url
            if (url instanceof String)
            {
                if(LOG.isDebugEnabled())LOG.debug(">>> resolution of url "+url+" requested");
                Context rootctx = new javaRootURLContext (env);
                return rootctx.lookup ((String)url);
            }
    
            // return the resolution of at least one of the urls
            if (url instanceof String[])
            {
                if(LOG.isDebugEnabled())LOG.debug(">>> resolution of array of urls requested");
                String[] urls = (String[])url; 
                Context rootctx = new javaRootURLContext (env);
                Object object = null;
                NamingException e = null;
                for (int i=0;(i< urls.length) && (object == null); i++)
                {
                    try
                    {
                        object = rootctx.lookup (urls[i]);
                    }
                    catch (NamingException x)
                    {
                        e = x;
                    }
                }
    
                if (object == null)
                    throw e;
                else
                    return object;
            }
    
            if(LOG.isDebugEnabled())LOG.debug(">>> No idea what to do, so return a new root context anyway");
            return new javaRootURLContext (env);
        }
    };
    jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/local/000077500000000000000000000000001174773561500250775ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/local/localContextRoot.java000066400000000000000000001017351174773561500312540ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) 2000-2009 Mort Bay Consulting Pty. Ltd.
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.jndi.local;
    
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Hashtable;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    
    import javax.naming.Binding;
    import javax.naming.CompoundName;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.LinkRef;
    import javax.naming.Name;
    import javax.naming.NameAlreadyBoundException;
    import javax.naming.NameClassPair;
    import javax.naming.NameNotFoundException;
    import javax.naming.NameParser;
    import javax.naming.NamingEnumeration;
    import javax.naming.NamingException;
    import javax.naming.NotContextException;
    import javax.naming.OperationNotSupportedException;
    import javax.naming.Reference;
    import javax.naming.Referenceable;
    import javax.naming.spi.NamingManager;
    
    import org.eclipse.jetty.jndi.BindingEnumeration;
    import org.eclipse.jetty.jndi.NameEnumeration;
    import org.eclipse.jetty.jndi.NamingContext;
    import org.eclipse.jetty.jndi.NamingUtil;
    import org.eclipse.jetty.util.log.Logger;
    
    /**
     * 
     * localContext
     * 
     * Implementation of the delegate for InitialContext for the local namespace. 
     * 
     * 
     * @version $Revision: 4780 $ $Date: 2009-03-17 16:36:08 +0100 (Tue, 17 Mar 2009) $
     * 
     */
    public class localContextRoot implements Context
    {
        private final static Logger __log=NamingUtil.__log;
        protected final static NamingContext __root = new NamingRoot();
        private final Hashtable _env;
      
    
        static class NamingRoot extends NamingContext
        {
            public NamingRoot()
            {
                super (null,null,null,new LocalNameParser());
            }
        }
        
        
    
        static class LocalNameParser implements NameParser
        {
            Properties syntax = new Properties();
    
            LocalNameParser()
            {
                syntax.put("jndi.syntax.direction", "left_to_right");
                syntax.put("jndi.syntax.separator", "/");
                syntax.put("jndi.syntax.ignorecase", "false");
            }
    
            public Name parse(String name) throws NamingException
            {
                return new CompoundName(name, syntax);
            }
        }
        
        
        /*
         * Root has to use the localContextRoot's  env for all operations.
         * So, if createSubcontext in the root, use the env of the localContextRoot.
         * If lookup binding in the root, use the env of the localContextRoot.
         * 
         */
        
      
        
        
       
    
        public static NamingContext getRoot()
        {
            return __root;
        }
    
        public localContextRoot(Hashtable env)
        {
            _env = new Hashtable(env);
        }
    
        /**
         * 
         * 
         * @see javax.naming.Context#close()
         */
        public void close() throws NamingException
        {
    
        }
    
        /**
         * 
         * 
         * @see javax.naming.Context#getNameInNamespace()
         */
        public String getNameInNamespace() throws NamingException
        {
            return "";
        }
    
        
        /**
         * 
         * 
         * @see javax.naming.Context#destroySubcontext(javax.naming.Name)
         */
        public void destroySubcontext(Name name) throws NamingException
        {
            synchronized (__root)
            {
                __root.destroySubcontext(getSuffix(name));   
            }
        }
        
        
        /**
         * 
         * 
         * @see javax.naming.Context#destroySubcontext(java.lang.String)
         */
        public void destroySubcontext(String name) throws NamingException
        {
            synchronized (__root)
            {
               
               destroySubcontext(__root.getNameParser("").parse(getSuffix(name)));
            }
        }
    
      
        /**
         * 
         * 
         * @see javax.naming.Context#getEnvironment()
         */
        public Hashtable getEnvironment() throws NamingException
        {
            return _env;
        }
    
     
    
        /**
         * 
         * 
         * @see javax.naming.Context#unbind(javax.naming.Name)
         */
        public void unbind(Name name) throws NamingException
        {
            synchronized (__root)
            {
                //__root.unbind(getSuffix(name));
                
                if (name.size() == 0)
                    return;
                
                
                if (__root.isLocked())
                    throw new NamingException ("This context is immutable");
    
                Name cname = __root.toCanonicalName(name);
    
                if (cname == null)
                    throw new NamingException ("Name is null");
                
                if (cname.size() == 0)
                    throw new NamingException ("Name is empty");
    
    
                //if no subcontexts, just unbind it
                if (cname.size() == 1)
                {         
                    __root.removeBinding (cname);
                }
                else
                { 
                    //walk down the subcontext hierarchy
                    if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0));
                            
                    String firstComponent = cname.get(0);
                    Object ctx = null;
    
                    
                    if (firstComponent.equals(""))
                        ctx = this;
                    else
                    {
                        Binding  binding = __root.getBinding (name.get(0));
                        if (binding == null)
                            throw new NameNotFoundException (name.get(0)+ " is not bound");
                    
                        ctx = binding.getObject();
    
                        if (ctx instanceof Reference)
                        {  
                            //deference the object
                            try
                            {
                                ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
                            }
                            catch (NamingException e)
                            {
                                throw e;
                            }
                            catch (Exception e)
                            {
                                __log.warn("",e);
                                throw new NamingException (e.getMessage());
                            }
                        }
                    }
    
                    if (ctx instanceof Context)
                    {
                        ((Context)ctx).unbind (cname.getSuffix(1));
                    }
                    else
                        throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
                } 
                
                
                
            }
        }
    
        /**
         * 
         * 
         * @see javax.naming.Context#unbind(java.lang.String)
         */
        public void unbind(String name) throws NamingException
        {
            unbind(__root.getNameParser("").parse(getSuffix(name)));
        }
    
        
    
        /**
         * 
         * 
         * @see javax.naming.Context#lookupLink(java.lang.String)
         */
        public Object lookupLink(String name) throws NamingException
        {
            synchronized (__root)
            {
                return lookupLink(__root.getNameParser("").parse(getSuffix(name)));
            }
        }
    
        /**
         * 
         * 
         * @see javax.naming.Context#lookupLink(javax.naming.Name)
         */
        public Object lookupLink(Name name) throws NamingException
        {
            synchronized (__root)
            {
                //return __root.lookupLink(getSuffix(name));
                
                
                Name cname = __root.toCanonicalName(name);
    
                if (cname == null)
                {
                    //If no name create copy of this context with same bindings, but with copy of the environment so it can be modified
                    NamingContext ctx = new NamingContext (_env, null, null, __root.getNameParser(""));
                    ctx.setBindings(__root.getBindings());
                    return ctx;
                }
                
                if (cname.size() == 0)
                    throw new NamingException ("Name is empty");
    
                if (cname.size() == 1)
                {
                    Binding binding = __root.getBinding (cname);
                    if (binding == null)
                        throw new NameNotFoundException();
    
                    Object o = binding.getObject();
    
                    //handle links by looking up the link
                    if (o instanceof Reference)
                    {
                        //deference the object
                        try
                        {
                            return NamingManager.getObjectInstance(o, cname.getPrefix(1), __root, _env);
                        }
                        catch (NamingException e)
                        {
                            throw e;
                        }
                        catch (Exception e)
                        {
                            __log.warn("",e);
                            throw new NamingException (e.getMessage());
                        }
                    }
                    else
                    {
                        //object is either a LinkRef which we don't dereference
                        //or a plain object in which case spec says we return it
                        return o;
                    }
                }
    
    
                //it is a multipart name, recurse to the first subcontext
                String firstComponent = cname.get(0);
                Object ctx = null;
                
                if (firstComponent.equals(""))
                    ctx = this;
                else
                {
                    Binding binding = __root.getBinding (firstComponent);
                    if (binding == null)
                        throw new NameNotFoundException ();
                    
                    ctx = binding.getObject();
    
                    if (ctx instanceof Reference)
                    {  
                        //deference the object
                        try
                        {
                            ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
                        }
                        catch (NamingException e)
                        {
                            throw e;
                        }
                        catch (Exception e)
                        {
                            __log.warn("",e);
                            throw new NamingException (e.getMessage());
                        }
                    }
                }
    
                if (!(ctx instanceof Context))
                    throw new NotContextException();
    
                return ((Context)ctx).lookup (cname.getSuffix(1)); 
                
                
            }
        }
    
        
        /**
         * 
         *       
         * @see javax.naming.Context#removeFromEnvironment(java.lang.String)
         */
        public Object removeFromEnvironment(String propName) throws NamingException
        {
            return _env.remove(propName);
        }
    
    
        /**
         * 
         * 
         * @see javax.naming.Context#lookup(javax.naming.Name)
         */
        public Object lookup(Name name) throws NamingException
        {
            synchronized (__root)
            {
                //return __root.lookup(getSuffix(name));
                
                if(__log.isDebugEnabled())__log.debug("Looking up name=\""+name+"\"");
                Name cname = __root.toCanonicalName(name);
    
                if ((cname == null) || (cname.size() == 0))
                {
                    __log.debug("Null or empty name, returning copy of this context");
                    NamingContext ctx = new NamingContext (_env, null, null, __root.getNameParser(""));
                    ctx.setBindings(__root.getBindings());
                    return ctx;
                }
    
            
              
                if (cname.size() == 1)
                {
                    Binding binding = __root.getBinding (cname);
                    if (binding == null)
                    {
                        NameNotFoundException nnfe = new NameNotFoundException();
                        nnfe.setRemainingName(cname);
                        throw nnfe;
                    }
                        
    
                    Object o = binding.getObject();
    
                    //handle links by looking up the link
                    if (o instanceof LinkRef)
                    {
                        //if link name starts with ./ it is relative to current context
                        String linkName = ((LinkRef)o).getLinkName();
                        if (linkName.startsWith("./"))
                            return lookup (linkName.substring(2));
                        else
                        {
                            //link name is absolute
                            InitialContext ictx = new InitialContext();
                            return ictx.lookup (linkName);
                        }
                    }
                    else if (o instanceof Reference)
                    {
                        //deference the object
                        try
                        {
                            return NamingManager.getObjectInstance(o, cname, __root, _env);
                        }
                        catch (NamingException e)
                        {
                            throw e;
                        }
                        catch (final Exception e)
                        {
                            throw new NamingException (e.getMessage()) 
                            {
                                { initCause(e);}
                            };
                        }
                    }
                    else
                        return o;
                }
    
                //it is a multipart name, get the first subcontext
           
                String firstComponent = cname.get(0);
                Object ctx = null;
    
                if (firstComponent.equals(""))
                    ctx = this;
                else
                {
                    
                    Binding binding = __root.getBinding (firstComponent);
                    if (binding == null)
                    {
                        NameNotFoundException nnfe = new NameNotFoundException();
                        nnfe.setRemainingName(cname);
                        throw nnfe;
                    }
                    
                    //as we have bound a reference to an object factory 
                    //for the component specific contexts
                    //at "comp" we need to resolve the reference
                    ctx = binding.getObject();
                    
                    if (ctx instanceof Reference)
                    {  
                        //deference the object
                        try
                        {
                            ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
                        }
                        catch (NamingException e)
                        {
                            throw e;
                        }
                        catch (Exception e)
                        {
                            __log.warn("",e);
                            throw new NamingException (e.getMessage());
                        }
                    }
                }
                if (!(ctx instanceof Context))
                    throw new NotContextException();
    
                return ((Context)ctx).lookup (cname.getSuffix(1));
                
            }
        }
    
        
        /**
         * 
         * 
         * @see javax.naming.Context#lookup(java.lang.String)
         */
        public Object lookup(String name) throws NamingException
        {
            synchronized (__root)
            {
                return lookup(__root.getNameParser("").parse(getSuffix(name)));
            }
        }
        
    
        /**
         * 
         * 
         * @see javax.naming.Context#bind(java.lang.String, java.lang.Object)
         */
        public void bind(String name, Object obj) throws NamingException
        {
            synchronized (__root)
            {
               bind(__root.getNameParser("").parse(getSuffix(name)), obj);
                
            }
        }
    
    
        /**
         * 
         * 
         * @see javax.naming.Context#bind(javax.naming.Name, java.lang.Object)
         */
        public void bind(Name name, Object obj) throws NamingException
        {
            synchronized (__root)
            {
               // __root.bind(getSuffix(name), obj);
                
                
                if (__root.isLocked())
                    throw new NamingException ("This context is immutable");
    
                Name cname = __root.toCanonicalName(name);
                
                if (cname == null)
                    throw new NamingException ("Name is null");
                
                if (cname.size() == 0)
                    throw new NamingException ("Name is empty");
    
    
                //if no subcontexts, just bind it
                if (cname.size() == 1)
                {
                    //get the object to be bound
                    Object objToBind = NamingManager.getStateToBind(obj, name,this, _env);
                    // Check for Referenceable
                    if (objToBind instanceof Referenceable) 
                    {
                        objToBind = ((Referenceable)objToBind).getReference();
                    }
                    
                    //anything else we should be able to bind directly    
                    __root.addBinding (cname, objToBind);
                }
                else
                {
                    if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0));
                  
                    //walk down the subcontext hierarchy       
                    //need to ignore trailing empty "" name components
                            
                    String firstComponent = cname.get(0);
                    Object ctx = null;
    
                    if (firstComponent.equals(""))
                        ctx = this;
                    else
                    {
    
                        Binding  binding = __root.getBinding (firstComponent);
                        if (binding == null)
                            throw new NameNotFoundException (firstComponent+ " is not bound");
                        
                        ctx = binding.getObject();
                        
                        if (ctx instanceof Reference)
                        {  
                            //deference the object
                            try
                            {
                                ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env);
                            }
                            catch (NamingException e)
                            {
                                throw e;
                            }
                            catch (Exception e)
                            {
                                __log.warn("",e);
                                throw new NamingException (e.getMessage());
                            }
                        }
                    }
    
    
                    if (ctx instanceof Context)
                    {
                        ((Context)ctx).bind (cname.getSuffix(1), obj);
                    }
                    else
                        throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
                }
            }
        }
    
        /**
         *
         * 
         * @see javax.naming.Context#rebind(javax.naming.Name, java.lang.Object)
         */
        public void rebind(Name name, Object obj) throws NamingException
        {
            synchronized (__root)
            {
                //__root.rebind(getSuffix(name), obj);
                
                
                if (__root.isLocked())
                    throw new NamingException ("This context is immutable");
    
                Name cname = __root.toCanonicalName(name);
    
                if (cname == null)
                    throw new NamingException ("Name is null");
                
                if (cname.size() == 0)
                    throw new NamingException ("Name is empty");
    
    
                //if no subcontexts, just bind it
                if (cname.size() == 1)
                {      
                    //check if it is a Referenceable
                    Object objToBind = NamingManager.getStateToBind(obj, name, __root, _env);
                    
                    if (objToBind instanceof Referenceable)
                    {
                        objToBind = ((Referenceable)objToBind).getReference();
                    }
                    __root.removeBinding(cname);
                    __root.addBinding (cname, objToBind);
                }
                else
                { 
                    //walk down the subcontext hierarchy
                    if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0));
                            
                    String firstComponent = cname.get(0);
                    Object ctx = null;
    
                    
                    if (firstComponent.equals(""))
                        ctx = this;
                    else
                    {
                        Binding  binding = __root.getBinding (name.get(0));
                        if (binding == null)
                            throw new NameNotFoundException (name.get(0)+ " is not bound");
                    
                        ctx = binding.getObject();
    
    
                        if (ctx instanceof Reference)
                        {  
                            //deference the object
                            try
                            {
                                ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
                            }
                            catch (NamingException e)
                            {
                                throw e;
                            }
                            catch (Exception e)
                            {
                                __log.warn("",e);
                                throw new NamingException (e.getMessage());
                            }
                        }
                    }
    
                    if (ctx instanceof Context)
                    {
                        ((Context)ctx).rebind (cname.getSuffix(1), obj);
                    }
                    else
                        throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
                }
            }
        }
    
        /**
         * 
         * 
         * @see javax.naming.Context#rebind(java.lang.String, java.lang.Object)
         */
        public void rebind(String name, Object obj) throws NamingException
        {
            synchronized (__root)
            {
                rebind(__root.getNameParser("").parse(getSuffix(name)), obj);
            }
        }
        /**
         * 
         * 
         * @see javax.naming.Context#rename(javax.naming.Name, javax.naming.Name)
         */
        public void rename(Name oldName, Name newName) throws NamingException
        {
            synchronized (__root)
            {
                throw new OperationNotSupportedException();
            }
        }
    
        /**
         * 
         * 
         * @see javax.naming.Context#rename(java.lang.String, java.lang.String)
         */
        public void rename(String oldName, String newName) throws NamingException
        {
            synchronized (__root)
            {
               throw new OperationNotSupportedException();
            }
        }
    
        /**
         * 
         * 
         * @see javax.naming.Context#createSubcontext(java.lang.String)
         */
        public Context createSubcontext(String name) throws NamingException
        {
            synchronized (__root)
            {
                //if the subcontext comes directly off the root, use the env of the InitialContext
                //as the root itself has no environment. Otherwise, it inherits the env of the parent
                //Context further down the tree.
                //NamingContext ctx = (NamingContext)__root.createSubcontext(name);
                //if (ctx.getParent() == __root)
                //    ctx.setEnv(_env);
                //return ctx;
                
                return createSubcontext(__root.getNameParser("").parse(name));
            }
        }
    
        /**
         * 
         * 
         * @see javax.naming.Context#createSubcontext(javax.naming.Name)
         */
        public Context createSubcontext(Name name) throws NamingException
        {
            synchronized (__root)
            {            
                //if the subcontext comes directly off the root, use the env of the InitialContext
                //as the root itself has no environment. Otherwise, it inherits the env of the parent
                //Context further down the tree.
                //NamingContext ctx = (NamingContext)__root.createSubcontext(getSuffix(name));
                //if (ctx.getParent() == __root)
                //    ctx.setEnv(_env);
                //return ctx;
                
                
                
                
                if (__root.isLocked())
                {
                    NamingException ne = new NamingException ("This context is immutable"); 
                    ne.setRemainingName(name);
                    throw ne;
                }
                
                Name cname = __root.toCanonicalName (name);
    
                if (cname == null)
                    throw new NamingException ("Name is null");
                if (cname.size() == 0)
                    throw new NamingException ("Name is empty");
    
                if (cname.size() == 1)
                {
                    //not permitted to bind if something already bound at that name
                    Binding binding = __root.getBinding (cname);
                    if (binding != null)
                        throw new NameAlreadyBoundException (cname.toString());
    
                    //make a new naming context with the root as the parent
                    Context ctx = new NamingContext ((Hashtable)_env.clone(), cname.get(0), __root,  __root.getNameParser(""));
                    __root.addBinding (cname, ctx);
                    return ctx;
                }
                
                    
                //If the name has multiple subcontexts, walk the hierarchy by
                //fetching the first one. All intermediate subcontexts in the 
                //name must already exist.
                String firstComponent = cname.get(0);
                Object ctx = null;
    
                if (firstComponent.equals(""))
                    ctx = this;
                else
                {
                    Binding binding = __root.getBinding (firstComponent);
                    if (binding == null)
                        throw new NameNotFoundException (firstComponent + " is not bound");
                    
                    ctx = binding.getObject();
                    
                    if (ctx instanceof Reference)
                    {  
                        //deference the object
                        if(__log.isDebugEnabled())__log.debug("Object bound at "+firstComponent +" is a Reference");
                        try
                        {
                            ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
                        }
                        catch (NamingException e)
                        {
                            throw e;
                        }
                        catch (Exception e)
                        {
                            __log.warn("",e);
                            throw new NamingException (e.getMessage());
                        }
                    }
                }
                
                if (ctx instanceof Context)
                {
                    return ((Context)ctx).createSubcontext (cname.getSuffix(1));
                }
                else
                    throw new NotContextException (firstComponent +" is not a Context");
            }
        }
    
      
        /**
         *
         * 
         * @see javax.naming.Context#getNameParser(java.lang.String)
         */
        public NameParser getNameParser(String name) throws NamingException
        {
            return __root.getNameParser(name);
        }
    
        /**
         * 
         * 
         * @see javax.naming.Context#getNameParser(javax.naming.Name)
         */
        public NameParser getNameParser(Name name) throws NamingException
        {
            return __root.getNameParser(name);
        }
    
        /**
         * 
         * 
         * @see javax.naming.Context#list(java.lang.String)
         */
        public NamingEnumeration list(String name) throws NamingException
        {
            synchronized (__root)
            {
                return list(__root.getNameParser("").parse(getSuffix(name)));
            }
        }
    
    
        /**
         *
         * 
         * @see javax.naming.Context#list(javax.naming.Name)
         */
        public NamingEnumeration list(Name name) throws NamingException
        {
            synchronized (__root)
            {
                //return __root.list(getSuffix(name));
                
               
                Name cname = __root.toCanonicalName(name);
    
                if (cname == null)
                {
                    List empty = Collections.emptyList();
                    return new NameEnumeration(empty.iterator());
                }
    
                
                if (cname.size() == 0)
                {
                   return new NameEnumeration (__root.getBindings().values().iterator()); 
                }
    
              
    
                //multipart name
                String firstComponent = cname.get(0);
                Object ctx = null;
    
                if (firstComponent.equals(""))
                    ctx = this;
                else
                {
                    Binding binding = __root.getBinding (firstComponent);
                    if (binding == null)
                        throw new NameNotFoundException ();
                    
                    ctx = binding.getObject();
                    
                    if (ctx instanceof Reference)
                    {  
                        //deference the object
                        if(__log.isDebugEnabled())__log.debug("Dereferencing Reference for "+name.get(0));
                        try
                        {
                            ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
                        }
                        catch (NamingException e)
                        {
                            throw e;
                        }
                        catch (Exception e)
                        {
                            __log.warn("",e);
                            throw new NamingException (e.getMessage());
                        }
                    }
                }
    
                if (!(ctx instanceof Context))
                    throw new NotContextException();
    
                return ((Context)ctx).list (cname.getSuffix(1));       
                
            }
        }
    
        /**
         *
         * 
         * @see javax.naming.Context#listBindings(javax.naming.Name)
         */
        public NamingEnumeration listBindings(Name name) throws NamingException
        {
            synchronized (__root)
            {
                //return __root.listBindings(getSuffix(name));
                
                Name cname = __root.toCanonicalName (name);
    
                if (cname == null)
                {
                    List empty = Collections.emptyList();
                    return new BindingEnumeration(empty.iterator());
                }
    
                if (cname.size() == 0)
                {
                   return new BindingEnumeration (__root.getBindings().values().iterator()); 
                }
    
              
                
                //multipart name
                String firstComponent = cname.get(0);
                Object ctx = null;
    
                //if a name has a leading "/" it is parsed as "" so ignore it by staying
                //at this level in the tree
                if (firstComponent.equals(""))
                    ctx = this;
                else
                {
                    //it is a non-empty name component
                    Binding binding = __root.getBinding (firstComponent);
                    if (binding == null)
                        throw new NameNotFoundException ();
                
                    ctx = binding.getObject();
    
                    if (ctx instanceof Reference)
                    {  
                        //deference the object
                        try
                        {
                            ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
                        }
                        catch (NamingException e)
                        {
                            throw e;
                        }
                        catch (Exception e)
                        {
                            __log.warn("",e);
                            throw new NamingException (e.getMessage());
                        }
                    }
                }
    
                if (!(ctx instanceof Context))
                    throw new NotContextException();
    
                return ((Context)ctx).listBindings (cname.getSuffix(1));
                
            }
        }
    
    
        /**
         *
         * 
         * @see javax.naming.Context#listBindings(java.lang.String)
         */
        public NamingEnumeration listBindings(String name) throws NamingException
        {
            synchronized (__root)
            {
                return listBindings(__root.getNameParser("").parse(getSuffix(name)));
            }
        }
        
        
        /**
         *
         * 
         * @see javax.naming.Context#addToEnvironment(java.lang.String,
         *      java.lang.Object)
         */
        public Object addToEnvironment(String propName, Object propVal)
                throws NamingException
        {
            return _env.put(propName, propVal);
        }
    
        /**
         *
         * 
         * @see javax.naming.Context#composeName(java.lang.String, java.lang.String)
         */
        public String composeName(String name, String prefix)
                throws NamingException
        {
            return __root.composeName(name, prefix);
        }
    
        /**
         *
         * 
         * @see javax.naming.Context#composeName(javax.naming.Name,
         *      javax.naming.Name)
         */
        public Name composeName(Name name, Name prefix) throws NamingException
        {
            return __root.composeName(name, prefix);
        }
    
        protected String getSuffix(String url) throws NamingException
        {
            return url;
        }
    
        protected Name getSuffix(Name name) throws NamingException
        {
            return name;
        }
    
    }
    jetty8-8.1.3/jetty-jndi/src/main/resources/000077500000000000000000000000001174773561500206005ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/main/resources/jndi.properties000066400000000000000000000001751174773561500236450ustar00rootroot00000000000000java.naming.factory.url.pkgs=org.eclipse.jetty.jndi
    java.naming.factory.initial=org.eclipse.jetty.jndi.InitialContextFactory
    jetty8-8.1.3/jetty-jndi/src/test/000077500000000000000000000000001174773561500166215ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/test/java/000077500000000000000000000000001174773561500175425ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/test/java/org/000077500000000000000000000000001174773561500203315ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/test/java/org/eclipse/000077500000000000000000000000001174773561500217555ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500231145ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/test/java/org/eclipse/jetty/jndi/000077500000000000000000000000001174773561500240405ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/test/java/org/eclipse/jetty/jndi/factories/000077500000000000000000000000001174773561500260175ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/test/java/org/eclipse/jetty/jndi/factories/TestMailSessionReference.java000066400000000000000000000053131174773561500335710ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd.
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses.
    // ========================================================================
    
    package org.eclipse.jetty.jndi.factories;
    
    import java.util.Properties;
    import javax.mail.Session;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.LinkRef;
    import javax.naming.Name;
    import javax.naming.NameParser;
    
    import org.eclipse.jetty.jndi.NamingUtil;
    import org.junit.Test;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertNotNull;
    import static org.junit.Assert.assertTrue;
    
    /**
     *
     */
    public class TestMailSessionReference
    {
        @Test
        public void testMailSessionReference () throws Exception
        {
            InitialContext icontext = new InitialContext();
            MailSessionReference sref = new MailSessionReference();
            sref.setUser("janb");
            sref.setPassword("OBF:1xmk1w261z0f1w1c1xmq");
            Properties props = new Properties ();
            props.put("mail.smtp.host", "xxx");
            props.put("mail.debug", "true");
            sref.setProperties(props);
            NamingUtil.bind(icontext, "mail/Session", sref);
            Object x = icontext.lookup("mail/Session");
            assertNotNull(x);
            assertTrue(x instanceof javax.mail.Session);
            javax.mail.Session session = (javax.mail.Session)x;
            Properties sessionProps =  session.getProperties();
            assertEquals(props, sessionProps);
            assertTrue (session.getDebug());
    
            Context foo = icontext.createSubcontext("foo");
            NameParser parser = icontext.getNameParser("");
            Name objectNameInNamespace = parser.parse(icontext.getNameInNamespace());
            objectNameInNamespace.addAll(parser.parse("mail/Session"));
    
            NamingUtil.bind(foo, "mail/Session", new LinkRef(objectNameInNamespace.toString()));
    
            Object o = foo.lookup("mail/Session");
            assertNotNull(o);
            Session fooSession = (Session)o;
            assertEquals(props, fooSession.getProperties());
            assertTrue(fooSession.getDebug());
    
            icontext.destroySubcontext("mail");
            icontext.destroySubcontext("foo");
        }
    }
    jetty8-8.1.3/jetty-jndi/src/test/java/org/eclipse/jetty/jndi/java/000077500000000000000000000000001174773561500247615ustar00rootroot00000000000000jetty8-8.1.3/jetty-jndi/src/test/java/org/eclipse/jetty/jndi/java/TestJNDI.java000066400000000000000000000265501174773561500272200ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd.
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses.
    // ========================================================================
    
    package org.eclipse.jetty.jndi.java;
    
    import java.net.URL;
    import java.net.URLClassLoader;
    import java.util.HashMap;
    import java.util.Hashtable;
    
    import javax.naming.Binding;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.LinkRef;
    import javax.naming.Name;
    import javax.naming.NameAlreadyBoundException;
    import javax.naming.NameClassPair;
    import javax.naming.NameNotFoundException;
    import javax.naming.NamingEnumeration;
    import javax.naming.NamingException;
    import javax.naming.Reference;
    import javax.naming.StringRefAddr;
    import javax.naming.spi.ObjectFactory;
    
    import org.eclipse.jetty.jndi.NamingContext;
    import org.eclipse.jetty.jndi.NamingUtil;
    import org.eclipse.jetty.jndi.local.localContextRoot;
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.log.Logger;
    import org.junit.Test;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertTrue;
    import static org.junit.Assert.fail;
    
    /**
     *
     */
    public class TestJNDI
    {
        private static final Logger LOG = Log.getLogger(TestJNDI.class);
    
        static
        {
            // NamingUtil.__log.setDebugEnabled(true);    
        }
        
        public static class MyObjectFactory implements ObjectFactory
        {
            public static String myString = "xxx";
    
            public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception
            {
                return myString;
            }
            
        }
    
        @Test
        public void testIt() throws Exception
        {
            try
            {
                //set up some classloaders
                Thread currentThread = Thread.currentThread();
                ClassLoader currentLoader = currentThread.getContextClassLoader();
                ClassLoader childLoader1 = new URLClassLoader(new URL[0], currentLoader);
                ClassLoader childLoader2 = new URLClassLoader(new URL[0], currentLoader);
    
                /*
                javaRootURLContext.getRoot().addListener(new NamingContext.Listener()
                {
                    public void unbind(NamingContext ctx, Binding binding)
                    {
                        System.err.println("java unbind "+binding+" from "+ctx.getName());
                    }
                    
                    public Binding bind(NamingContext ctx, Binding binding)
                    {
                        System.err.println("java bind "+binding+" to "+ctx.getName());
                        return binding;
                    }
                });
                
                localContextRoot.getRoot().addListener(new NamingContext.Listener()
                {
                    public void unbind(NamingContext ctx, Binding binding)
                    {
                        System.err.println("local unbind "+binding+" from "+ctx.getName());
                    }
                    
                    public Binding bind(NamingContext ctx, Binding binding)
                    {
                        System.err.println("local bind "+binding+" to "+ctx.getName());
                        return binding;
                    }
                });
                */
                
                
                //set the current thread's classloader
                currentThread.setContextClassLoader(childLoader1);
    
                InitialContext initCtxA = new InitialContext();
                initCtxA.bind ("blah", "123");
                assertEquals ("123", initCtxA.lookup("blah"));
    
                InitialContext initCtx = new InitialContext();
                Context sub0 = (Context)initCtx.lookup("java:");
    
                if(LOG.isDebugEnabled())LOG.debug("------ Looked up java: --------------");
    
                Name n = sub0.getNameParser("").parse("/red/green/");
    
                if(LOG.isDebugEnabled())LOG.debug("get(0)="+n.get(0));
                if(LOG.isDebugEnabled())LOG.debug("getPrefix(1)="+n.getPrefix(1));
                n = n.getSuffix(1);
                if(LOG.isDebugEnabled())LOG.debug("getSuffix(1)="+n);
                if(LOG.isDebugEnabled())LOG.debug("get(0)="+n.get(0));
                if(LOG.isDebugEnabled())LOG.debug("getPrefix(1)="+n.getPrefix(1));
                n = n.getSuffix(1);
                if(LOG.isDebugEnabled())LOG.debug("getSuffix(1)="+n);
                if(LOG.isDebugEnabled())LOG.debug("get(0)="+n.get(0));
                if(LOG.isDebugEnabled())LOG.debug("getPrefix(1)="+n.getPrefix(1));
                n = n.getSuffix(1);
                if(LOG.isDebugEnabled())LOG.debug("getSuffix(1)="+n);
    
                n = sub0.getNameParser("").parse("pink/purple/");
                if(LOG.isDebugEnabled())LOG.debug("get(0)="+n.get(0));
                if(LOG.isDebugEnabled())LOG.debug("getPrefix(1)="+n.getPrefix(1));
                n = n.getSuffix(1);
                if(LOG.isDebugEnabled())LOG.debug("getSuffix(1)="+n);
                if(LOG.isDebugEnabled())LOG.debug("get(0)="+n.get(0));
                if(LOG.isDebugEnabled())LOG.debug("getPrefix(1)="+n.getPrefix(1));
    
                NamingContext ncontext = (NamingContext)sub0;
    
                Name nn = ncontext.toCanonicalName(ncontext.getNameParser("").parse("/yellow/blue/"));
                LOG.debug(nn.toString());
                assertEquals (2, nn.size());
    
                nn = ncontext.toCanonicalName(ncontext.getNameParser("").parse("/yellow/blue"));
                LOG.debug(nn.toString());
                assertEquals (2, nn.size());
    
                nn = ncontext.toCanonicalName(ncontext.getNameParser("").parse("/"));
                if(LOG.isDebugEnabled())LOG.debug("/ parses as: "+nn+" with size="+nn.size());
                LOG.debug(nn.toString());
                assertEquals (1, nn.size());
    
                nn = ncontext.toCanonicalName(ncontext.getNameParser("").parse(""));
                LOG.debug(nn.toString());
                assertEquals (0, nn.size());
    
                Context fee = ncontext.createSubcontext("fee");
                fee.bind ("fi", "88");
                assertEquals("88", initCtxA.lookup("java:/fee/fi"));
                assertEquals("88", initCtxA.lookup("java:/fee/fi/"));
                assertTrue (initCtxA.lookup("java:/fee/") instanceof javax.naming.Context);
    
                try
                {
                    Context sub1 = sub0.createSubcontext ("comp");
                    fail("Comp should already be bound");
                }
                catch (NameAlreadyBoundException e)
                {
                    //expected exception
                }
    
                //check bindings at comp
                Context sub1 = (Context)initCtx.lookup("java:comp");
    
                Context sub2 = sub1.createSubcontext ("env");
    
                initCtx.bind ("java:comp/env/rubbish", "abc");
                assertEquals ("abc", initCtx.lookup("java:comp/env/rubbish"));
    
                //check binding LinkRefs
                LinkRef link = new LinkRef ("java:comp/env/rubbish");
                initCtx.bind ("java:comp/env/poubelle", link);
                assertEquals ("abc", initCtx.lookup("java:comp/env/poubelle"));
    
                //check binding References
                StringRefAddr addr = new StringRefAddr("blah", "myReferenceable");
                Reference ref = new Reference (java.lang.String.class.getName(),
                        addr,
                        MyObjectFactory.class.getName(),
                        null);
    
                initCtx.bind ("java:comp/env/quatsch", ref);
                assertEquals (MyObjectFactory.myString, initCtx.lookup("java:comp/env/quatsch"));
    
                //test binding something at java:
                Context sub3 = initCtx.createSubcontext("java:zero");
                initCtx.bind ("java:zero/one", "ONE");
                assertEquals ("ONE", initCtx.lookup("java:zero/one"));
    
                //change the current thread's classloader to check distinct naming
                currentThread.setContextClassLoader(childLoader2);
    
                Context otherSub1 = (Context)initCtx.lookup("java:comp");
                assertTrue (!(sub1 == otherSub1));
                try
                {
                    initCtx.lookup("java:comp/env/rubbish");
                }
                catch (NameNotFoundException e)
                {
                    //expected
                }
    
                //put the thread's classloader back
                currentThread.setContextClassLoader(childLoader1);
    
                //test rebind with existing binding
                initCtx.rebind("java:comp/env/rubbish", "xyz");
                assertEquals ("xyz", initCtx.lookup("java:comp/env/rubbish"));
    
                //test rebind with no existing binding
                initCtx.rebind ("java:comp/env/mullheim", "hij");
                assertEquals ("hij", initCtx.lookup("java:comp/env/mullheim"));
    
                //test that the other bindings are already there
                assertEquals ("xyz", initCtx.lookup("java:comp/env/poubelle"));
    
                //test java:/comp/env/stuff
                assertEquals ("xyz", initCtx.lookup("java:/comp/env/poubelle/"));
    
                //test list Names
                NamingEnumeration nenum = initCtx.list ("java:comp/env");
                HashMap results = new HashMap();
                while (nenum.hasMore())
                {
                    NameClassPair ncp = (NameClassPair)nenum.next();
                    results.put (ncp.getName(), ncp.getClassName());
                }
    
                assertEquals (4, results.size());
    
                assertEquals ("java.lang.String", results.get("rubbish"));
                assertEquals ("javax.naming.LinkRef", results.get("poubelle"));
                assertEquals ("java.lang.String", results.get("mullheim"));
                assertEquals ("javax.naming.Reference", results.get("quatsch"));
    
                //test list Bindings
                NamingEnumeration benum = initCtx.list("java:comp/env");
                assertEquals (4, results.size());
    
                //test NameInNamespace
                assertEquals ("comp/env", sub2.getNameInNamespace());
    
                //test close does nothing
                Context closeCtx = (Context)initCtx.lookup("java:comp/env");
                closeCtx.close();
    
    
                //test what happens when you close an initial context
                InitialContext closeInit = new InitialContext();
                closeInit.close();
    
                //check locking the context
                Context ectx = (Context)initCtx.lookup("java:comp");
                ectx.bind("crud", "xxx");
                ectx.addToEnvironment("org.eclipse.jndi.immutable", "TRUE");
                assertEquals ("xxx", initCtx.lookup("java:comp/crud"));
                try
                {
                    ectx.bind("crud2", "xxx2");
                }
                catch (NamingException ne)
                {
                    //expected failure to modify immutable context
                }
    
                System.err.println("java:"+javaRootURLContext.getRoot().dump());
                System.err.println("local:"+localContextRoot.getRoot().dump());
                
                //test what happens when you close an initial context that was used
                initCtx.close();
            }
            finally
            {
                InitialContext ic = new InitialContext();
                Context comp = (Context)ic.lookup("java:comp");
                comp.destroySubcontext("env");
            }
        }
    }
    jetty8-8.1.3/jetty-jndi/src/test/java/org/eclipse/jetty/jndi/java/TestLocalJNDI.java000066400000000000000000000153731174773561500301740ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses.
    // ========================================================================
    package org.eclipse.jetty.jndi.java;
    
    import java.util.Hashtable;
    
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.Name;
    import javax.naming.NameNotFoundException;
    import javax.naming.NameParser;
    import javax.naming.NamingException;
    import javax.naming.RefAddr;
    import javax.naming.Reference;
    import javax.naming.Referenceable;
    import javax.naming.StringRefAddr;
    import javax.naming.spi.ObjectFactory;
    
    import org.eclipse.jetty.jndi.NamingUtil;
    import org.junit.After;
    import org.junit.Test;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertNotNull;
    import static org.junit.Assert.fail;
    
    /**
     *
     */
    public class TestLocalJNDI
    {
        public static class FruitFactory implements ObjectFactory
        {
            public FruitFactory() 
            {
            }
            
            public Object getObjectInstance(Object obj, Name name, Context ctx, Hashtable env) throws Exception 
            {
                
                if (!env.containsKey("flavour"))
                    throw new Exception ("No flavour!");
                
                if (obj instanceof Reference) 
                {
                    Reference ref = (Reference)obj;
                    if (ref.getClassName().equals(Fruit.class.getName())) 
                    {
                        RefAddr addr = ref.get("fruit");
                        if (addr != null) 
                        {
                            return new Fruit((String)addr.getContent());
                        }
                    }
                }
                return null;
             }
        }
        
        
        public static class Fruit implements Referenceable 
        {
            String fruit;
            
            public Fruit(String f) 
            {
                fruit = f;
            }
            
            public Reference getReference() throws NamingException 
            {
                return new Reference(
                    Fruit.class.getName(),
                    new StringRefAddr("fruit", fruit),
                    FruitFactory.class.getName(),
                    null);          // Factory location
            }
    
            public String toString() 
            {
                return fruit;
            }
        }
        
        
        
        
        
        
        
        
        @After
        public void tearDown() throws Exception
        {
            InitialContext ic = new InitialContext();
            ic.destroySubcontext("a");
        }
        
        
        @Test
        public void testLocalReferenceable() throws Exception
        {
            Hashtable env1 = new Hashtable();
            env1.put("flavour", "orange");
            InitialContext ic1 = new InitialContext(env1);
            
            ic1.bind("valencia", new Fruit("orange"));
            
            Object o = ic1.lookup("valencia");
    
            Hashtable env2 = new Hashtable();
            InitialContext ic2 = new InitialContext(env2);
            try
            {
                o = ic2.lookup("valencia");
                fail("Constructed object from reference without correct environment");
            }
            catch (Exception e)
            {
                assertEquals("No flavour!", e.getMessage());
            }
        }
    
    
        @Test
        public void testLocalEnvironment() throws Exception
        {
            Hashtable env1 = new Hashtable();
            env1.put("make", "holden");
            env1.put("model", "commodore");
            
            Object car1 = new Object();
            
            InitialContext ic = new InitialContext(env1);
            ic.bind("car1", car1);
            assertNotNull(ic.lookup("car1"));
            assertEquals(car1, ic.lookup("car1"));
            
            Context carz = ic.createSubcontext("carz");
            assertNotNull(carz);
            Hashtable ht = carz.getEnvironment();
            assertNotNull(ht);
            assertEquals("holden", ht.get("make"));
            assertEquals("commodore", ht.get("model"));
            
            Hashtable env2 = new Hashtable();
            env2.put("flavour", "strawberry");
            InitialContext ic2 = new InitialContext(env2);
            assertEquals(car1, ic2.lookup("car1"));
            Context c = (Context)ic2.lookup("carz");
            assertNotNull(c);
            ht = c.getEnvironment();
            assertEquals("holden", ht.get("make"));
            assertEquals("commodore", ht.get("model"));
            
            Context icecreamz = ic2.createSubcontext("icecreamz");
            ht = icecreamz.getEnvironment();
            assertNotNull(ht);
            assertEquals("strawberry", ht.get("flavour"));
            
            Context hatchbackz = ic2.createSubcontext("carz/hatchbackz");
            assertNotNull(hatchbackz);
            ht = hatchbackz.getEnvironment();
            assertNotNull(ht);
            assertEquals("holden", ht.get("make"));
            assertEquals("commodore", ht.get("model"));
            assertEquals(null, ht.get("flavour"));
            
            c = (Context)ic.lookup("carz/hatchbackz");
            assertNotNull(c);
            assertEquals(hatchbackz, c);
            
        }
        
        
        
        
        @Test
        public void testLocal () throws Exception
        {
            InitialContext ic = new InitialContext();
            NameParser parser = ic.getNameParser("");
            ic.bind("foo", "xxx");
    
            Object o = ic.lookup("foo");
            assertNotNull(o);
            assertEquals("xxx", (String)o);
    
            ic.unbind("foo");
            try
            {
                ic.lookup("foo");
                fail("Foo exists");
            }
            catch (NameNotFoundException e)
            {
                //expected
            }
            Name name = parser.parse("a");
            name.addAll(parser.parse("b/c/d"));
            NamingUtil.bind(ic, name.toString(), "333");
            assertNotNull(ic.lookup("a"));
            assertNotNull(ic.lookup("a/b"));
            assertNotNull(ic.lookup("a/b/c"));
            Context c = (Context)ic.lookup("a/b/c");
            o = c.lookup("d");
            assertNotNull(o);
            assertEquals("333", (String)o);
            assertEquals("333", ic.lookup(name));
            ic.destroySubcontext("a");
    
            name = parser.parse("");
            name.add("x");
            Name suffix = parser.parse("y/z");
            name.addAll(suffix);
            NamingUtil.bind(ic, name.toString(), "555");
            assertEquals("555", ic.lookup(name));
            ic.destroySubcontext("x");
        }
    }
    jetty8-8.1.3/jetty-jsp/000077500000000000000000000000001174773561500147235ustar00rootroot00000000000000jetty8-8.1.3/jetty-jsp/pom.xml000066400000000000000000000037311174773561500162440ustar00rootroot00000000000000
      
        org.eclipse.jetty
        jetty-project
        8.1.3.v20120416
      
      4.0.0
      jetty-jsp
      Jetty :: JSP dependencies
      jar
      
      
    
      
        
        
          org.eclipse.jetty.orbit
          javax.servlet.jsp
          2.2.0.v201112011158
        
        
        
           org.eclipse.jetty.orbit
           org.apache.jasper.glassfish
           2.2.2.v201112011158
        
        
        
           org.eclipse.jetty.orbit
           javax.servlet.jsp.jstl
           1.2.0.v201105211821
        
        
        
           org.eclipse.jetty.orbit
           org.apache.taglibs.standard.glassfish
           1.2.0.v201112081803
        
        
        
          org.eclipse.jetty.orbit
          javax.el
          2.2.0.v201108011116
        
        
        
          org.eclipse.jetty.orbit
          com.sun.el
          2.2.0.v201108011116
        
        
        
          org.eclipse.jetty.orbit
          org.eclipse.jdt.core
          3.7.1
        
      
    
    jetty8-8.1.3/jetty-jsp/src/000077500000000000000000000000001174773561500155125ustar00rootroot00000000000000jetty8-8.1.3/jetty-jsp/src/main/000077500000000000000000000000001174773561500164365ustar00rootroot00000000000000jetty8-8.1.3/jetty-jsp/src/main/resources/000077500000000000000000000000001174773561500204505ustar00rootroot00000000000000jetty8-8.1.3/jetty-jsp/src/main/resources/readme.txt000066400000000000000000000005661174773561500224550ustar00rootroot00000000000000This jar file is purely to work around a problem with the Maven Dependency plugin.
    Several modules in jetty use the Dependency plugin to copy or unpack the dependencies of  other modules.
    However, the Dependency plugin is not capable of unpacking or copying a dependency of type 'pom', which
    this module is, as it consists purely of external dependencies needed to run jsp.
    jetty8-8.1.3/jetty-monitor/000077500000000000000000000000001174773561500156165ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/README.txt000066400000000000000000000016401174773561500173150ustar00rootroot00000000000000The ThreadMonitor is distributed as part of the jetty-monitor module. 
    
    In order to start ThreadMonitor when server starts up, the following command line should be used.
    
        java -jar start.jar OPTIONS=monitor jetty-monitor.xml
    
    To run ThreadMonitor on a Jetty installation that doesn't include jetty-monitor module, the jetty-monitor-[version].jar file needs to be copied into ${jetty.home}/lib/ext directory, and jetty-monitor.xml configuration file needs to be copied into ${jetty.home}/etc directory. Subsequently, the following command line should be used.
    
        java -jar start.jar etc/jetty-monitor.xml
    
    If running Jetty on Java VM version 1.5, the -Dcom.sun.management.jmxremote option should be added to the command lines above in order to enable the JMX agent.
    
    In order to log CPU utilization for threads that are above specified threshold, you need to follow instructions inside jetty-monitor.xml configuration file.jetty8-8.1.3/jetty-monitor/pom.xml000066400000000000000000000115401174773561500171340ustar00rootroot00000000000000
    
      
        org.eclipse.jetty
        jetty-project
        8.1.3.v20120416
      
      4.0.0
      jetty-monitor
      Jetty :: Monitoring
      Performance monitoring artifact for jetty.
      
        ${project.groupId}.monitor
      
      
        
          
            org.apache.felix
            maven-bundle-plugin
            true
            
              
                
                  manifest
                
                
                  
                    javax.management.*,*
                  
                
               
            
          
          
            
            org.apache.maven.plugins
            maven-jar-plugin
            
              
                ${project.build.outputDirectory}/META-INF/MANIFEST.MF
              
            
          
          
            org.apache.maven.plugins
            maven-assembly-plugin
            
              
                package
                
                  single
                
                
                  
                    config
                  
                
              
            
          
          
            org.apache.maven.plugins
            maven-surefire-plugin
            
              always
            
          
          
            org.codehaus.mojo
            findbugs-maven-plugin
            
              org.eclipse.jetty.monitor.*
            
          
        
      
      
        
          org.eclipse.jetty
          jetty-util
          ${project.version}
        
        
          org.eclipse.jetty
          jetty-io
          ${project.version}
        
        
          org.eclipse.jetty
          jetty-http
          ${project.version}
        
        
          org.eclipse.jetty
          jetty-xml
          ${project.version}
        
        
          org.eclipse.jetty
          jetty-client
          ${project.version}
        
        
          org.eclipse.jetty
          jetty-jmx
          ${project.version}
          test
        
        
          org.eclipse.jetty
          jetty-websocket
          ${project.version}
          test
        
        
          org.eclipse.jetty
          jetty-server
          ${project.version}
          test
        
        
          org.eclipse.jetty.toolchain
          jetty-test-helper
          test
        
        
          junit
          junit
          test
        
      
    
    jetty8-8.1.3/jetty-monitor/src/000077500000000000000000000000001174773561500164055ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/000077500000000000000000000000001174773561500173315ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/config/000077500000000000000000000000001174773561500205765ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/config/etc/000077500000000000000000000000001174773561500213515ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/config/etc/jetty-monitor.xml000066400000000000000000000022301174773561500247140ustar00rootroot00000000000000
    
    
    
      
      
        
          
            2000
            90
            3
            2
            
            
            
            
            
            
            
            
          
        
      
    
    
    jetty8-8.1.3/jetty-monitor/src/main/java/000077500000000000000000000000001174773561500202525ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/000077500000000000000000000000001174773561500210415ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/000077500000000000000000000000001174773561500224655ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500236245ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/000077500000000000000000000000001174773561500253135ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/JMXMonitor.java000066400000000000000000000117761174773561500302000ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor;
    
    import java.io.IOException;
    import java.util.HashSet;
    import java.util.Set;
    
    import javax.management.MBeanServerConnection;
    
    import org.eclipse.jetty.monitor.jmx.MonitorAction;
    import org.eclipse.jetty.monitor.jmx.MonitorTask;
    import org.eclipse.jetty.monitor.jmx.ServiceConnection;
    import org.eclipse.jetty.xml.XmlConfiguration;
    
    /* ------------------------------------------------------------ */
    /**
     * JMXMonitor
     *
     * Performs monitoring of the values of the attributes of MBeans
     * and executes specified actions as well as sends notifications
     * of the specified events that have occurred.
     */
    public class JMXMonitor
    {
        private static JMXMonitor __monitor = new JMXMonitor();
        
        private String _serverUrl;
        private ServiceConnection _serviceConnection;
    
        private Set _actions = new HashSet();
    
        /* ------------------------------------------------------------ */
        /**
         * Constructs a JMXMonitor instance. Used for XML Configuration.
         * 
         * !! DO NOT INSTANTIATE EXPLICITLY !!
         */
        public JMXMonitor() {}
    
        /* ------------------------------------------------------------ */
        /**
         * Adds monitor actions to the monitor
         *
         * @param actions monitor actions to add
         * @return true if successful
         */
        public boolean addActions(MonitorAction... actions)
        {
            return getInstance().add(actions);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Removes monitor actions from the monitor
         * 
         * @param actions monitor actions to remove
         * @return true if successful
         */
        public boolean removeActions(MonitorAction... actions)
        {
            return getInstance().remove(actions);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Sets the JMX server URL
         *
         * @param url URL of the JMX server
         */
        public void setUrl(String url)
         {
            getInstance().set(url);
        }
        
        public MBeanServerConnection getConnection()
            throws IOException
        {
            return getInstance().get();
        }
    
        public static JMXMonitor getInstance()
        {
            return __monitor;
        }
           
        public static boolean addMonitorActions(MonitorAction... actions)
        {
            return getInstance().add(actions);
        }
    
        public static boolean removeMonitorActions(MonitorAction... actions)
        {
            return getInstance().remove(actions);
        }
        
        public static void setServiceUrl(String url)
        {
            getInstance().set(url);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Retrieves a connection to JMX service
         *
         * @return server connection
         * @throws IOException
         */
        public static MBeanServerConnection getServiceConnection()
            throws IOException
        {
            return getInstance().getConnection();
        }
    
        public static void main(final String args[]) throws Exception
        {
            XmlConfiguration.main(args);
        }
        
        private synchronized boolean add(MonitorAction... actions)
        {
            boolean result = true;
    
            for (MonitorAction action : actions)
            {
                if (!_actions.add(action))
                {
                    result = false;
                }
                else
                {
                    MonitorTask.schedule(action);
                }
            }
            
            return result;
        }
        
        private synchronized boolean remove(MonitorAction... actions)
        {
            boolean result = true;
    
            for (MonitorAction action : actions)
            {
                if (!_actions.remove(action))
                {
                    result = false;
                }
    
                MonitorTask.cancel(action);
            }
            
            return result;
        }
        
        private synchronized void set(String url)
        {
            _serverUrl = url;
    
            if (_serviceConnection != null)
            {
                _serviceConnection.disconnect();
                _serviceConnection = null;
            }
        }
        
        private synchronized MBeanServerConnection get()
            throws IOException
        {
            if (_serviceConnection == null)
            {
                _serviceConnection = new ServiceConnection(_serverUrl);
                _serviceConnection.connect();
            }
            
            return _serviceConnection.getConnection();
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/ThreadMonitor.java000066400000000000000000000437131174773561500307450ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor;
    
    import java.lang.management.ManagementFactory;
    import java.lang.management.ThreadMXBean;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.eclipse.jetty.monitor.thread.ThreadMonitorException;
    import org.eclipse.jetty.monitor.thread.ThreadMonitorInfo;
    import org.eclipse.jetty.util.component.AbstractLifeCycle;
    import org.eclipse.jetty.util.component.Dumpable;
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.log.Logger;
    import org.eclipse.jetty.util.log.Logger;
    
    
    /* ------------------------------------------------------------ */
    public class ThreadMonitor extends AbstractLifeCycle implements Runnable
    {
        private static final Logger LOG = Log.getLogger(ThreadMonitor.class);
    
        private int _scanInterval;
        private int _logInterval;
        private int _busyThreshold;
        private int _logThreshold;
        private int _stackDepth;
        private int _trailLength;
        
        private ThreadMXBean _threadBean;
        
        private Thread _runner;
        private Logger _logger;
        private volatile boolean _done = true;
        private Dumpable _dumpable;
    
        private Map _monitorInfo;
        
        /* ------------------------------------------------------------ */
        /**
         * Instantiates a new thread monitor.
         *
         * @throws Exception
         */
        public ThreadMonitor() throws Exception
        {
            this(5000);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Instantiates a new thread monitor.
         *
         * @param intervalMs scan interval
         * @throws Exception
         */
        public ThreadMonitor(int intervalMs) throws Exception
        {
            this(intervalMs, 95);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Instantiates a new thread monitor.
         *
         * @param intervalMs scan interval
         * @param threshold busy threshold
         * @throws Exception
         */
        public ThreadMonitor(int intervalMs, int threshold) throws Exception
        {
            this(intervalMs, threshold, 3);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Instantiates a new thread monitor.
         *
         * @param intervalMs scan interval
         * @param threshold busy threshold
         * @param depth stack compare depth
         * @throws Exception
         */
        public ThreadMonitor(int intervalMs, int threshold, int depth) throws Exception
        {
            this(intervalMs, threshold, depth, 3);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Instantiates a new thread monitor.
         *
         * @param intervalMs scan interval
         * @param threshold busy threshold
         * @param depth stack compare depth
         * @param trail length of stack trail
         * @throws Exception
         */
        public ThreadMonitor(int intervalMs, int threshold, int depth, int trail) throws Exception
        {
            _scanInterval = intervalMs;
            _busyThreshold = threshold;
            _stackDepth = depth;
            _trailLength = trail;
            
            _logger = Log.getLogger(ThreadMonitor.class.getName());
            _monitorInfo = new HashMap();
           
            init();
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Gets the scan interval.
         *
         * @return the scan interval
         */
        public int getScanInterval()
        {
            return _scanInterval;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Sets the scan interval.
         *
         * @param ms the new scan interval
         */
        public void setScanInterval(int ms)
        {
            _scanInterval = ms;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Gets the log interval.
         *
         * @return the log interval
         */
        public int getLogInterval()
        {
            return _logInterval;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Sets the log interval.
         *
         * @param ms the new log interval
         */
        public void setLogInterval(int ms)
        {
            _logInterval = ms;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Gets the busy threshold.
         *
         * @return the busy threshold
         */
        public int getBusyThreshold()
        {
            return _busyThreshold;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Sets the busy threshold.
         *
         * @param percent the new busy threshold
         */
        public void setBusyThreshold(int percent)
        {
            _busyThreshold = percent;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Gets the log threshold.
         *
         * @return the log threshold
         */
        public int getLogThreshold()
        {
            return _logThreshold;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Sets the log threshold.
         *
         * @param percent the new log threshold
         */
        public void setLogThreshold(int percent)
        {
            _logThreshold = percent;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Gets the stack depth.
         *
         * @return the stack depth
         */
        public int getStackDepth()
        {
            return _stackDepth;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Sets the stack depth.
         *
         * @param stackDepth the new stack depth
         */
        public void setStackDepth(int stackDepth)
        {
            _stackDepth = stackDepth;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Sets the stack trace trail length.
         *
         * @param trailLength the new trail length
         */
        public void setTrailLength(int trailLength)
        {
            _trailLength = trailLength;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Gets the stack trace trail length.
         *
         * @return the trail length
         */
        public int getTrailLength()
        {
            return _trailLength;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Enable logging of CPU usage.
         *
         * @param frequencyMs the logging frequency 
         * @param thresholdPercent the logging threshold
         */
        public void logCpuUsage(int frequencyMs, int thresholdPercent)
        {
            setLogInterval(frequencyMs);
            setLogThreshold(thresholdPercent);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * @return A {@link Dumpable} that is dumped whenever spinning threads are detected
         */
        public Dumpable getDumpable()
        {
            return _dumpable;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @param dumpable A {@link Dumpable} that is dumped whenever spinning threads are detected
         */
        public void setDumpable(Dumpable dumpable)
        {
            _dumpable = dumpable;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
         */
        public void doStart()
        {
            _done = false;
            
            _runner = new Thread(this);
            _runner.setDaemon(true);
            _runner.start();
    
            LOG.info("Thread Monitor started successfully");
        }
        
        /* ------------------------------------------------------------ */
        /**
         * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
         */
        public void doStop()
        {
            if (_runner != null)
            {
                _done = true;
                try
                {
                    _runner.join();
                }
                catch (InterruptedException ex) {}
            }
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Retrieve all avaliable thread ids
         *
         * @return array of thread ids
         */
        protected long[] getAllThreadIds()
        {
            return _threadBean.getAllThreadIds();
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Retrieve the cpu time for specified thread.
         *
         * @param id thread id
         * @return cpu time of the thread
         */
        protected long getThreadCpuTime(long id)
        {
            return _threadBean.getThreadCpuTime(id);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Initialize JMX objects.
         */
        protected void init()
        {
            _threadBean = ManagementFactory.getThreadMXBean();
            if (_threadBean.isThreadCpuTimeSupported())
            {
                _threadBean.setThreadCpuTimeEnabled(true);
            }
        }
        
        /* ------------------------------------------------------------ */
        /**
         * @see java.lang.Runnable#run()
         */
        public void run()
        {
            // Initialize repeat flag
            boolean repeat = false;
            boolean scanNow, logNow;
    
            // Set next scan time and log time
            long nextScanTime = System.currentTimeMillis();
            long nextLogTime = nextScanTime + _logInterval;
            
            while (!_done)
            {
                long currTime = System.currentTimeMillis();
                scanNow = (currTime > nextScanTime);
                logNow = (_logInterval > 0 && currTime > nextLogTime);
                if (repeat || scanNow || logNow)
                {
                    repeat = collectThreadInfo();
                    logThreadInfo(logNow);
    
                    if (scanNow)
                    {
                        nextScanTime = System.currentTimeMillis() + _scanInterval;
                    }
                    if (logNow)
                    {
                        nextLogTime = System.currentTimeMillis() + _logInterval;
                    }
                }
    
                // Sleep only if not going to repeat scanning immediately
                if (!repeat)
                {
                    try
                    {
                        Thread.sleep(100);
                    }
                    catch (InterruptedException ex)
                    {
                        LOG.ignore(ex);
                    }
                }
            }
            
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Collect thread info.
         */
        private boolean collectThreadInfo()
        {
            boolean repeat = false;
            try
            {
                // Retrieve stack traces for all threads at once as it 
                // was proven to be an order of magnitude faster when
                // retrieving a single thread stack trace.
                Map all = Thread.getAllStackTraces();
                
                for (Map.Entry entry : all.entrySet())
                {
                    Thread thread = entry.getKey();
                    long threadId = thread.getId();
                    
                    // Skip our own runner thread
                    if (threadId == _runner.getId())
                    {
                        continue;
                    }
    
                    ThreadMonitorInfo currMonitorInfo = _monitorInfo.get(Long.valueOf(threadId));
                    if (currMonitorInfo == null)
                    {
                        // Create thread info object for a new thread 
                        currMonitorInfo = new ThreadMonitorInfo(thread);
                        currMonitorInfo.setStackTrace(entry.getValue());
                        currMonitorInfo.setCpuTime(getThreadCpuTime(threadId));
                        currMonitorInfo.setSampleTime(System.nanoTime());
                        _monitorInfo.put(Long.valueOf(threadId), currMonitorInfo);
                    }
                    else
                    {
                        // Update the existing thread info object
                        currMonitorInfo.setStackTrace(entry.getValue());
                        currMonitorInfo.setCpuTime(getThreadCpuTime(threadId));
                        currMonitorInfo.setSampleTime(System.nanoTime());
        
                        // Stack trace count holds logging state
                        int count = currMonitorInfo.getTraceCount();
                        if (count >= 0 && currMonitorInfo.isSpinning())
                        {
                            // Thread was spinning and was logged before
                            if (count < _trailLength) 
                            {
                                // Log another stack trace
                                currMonitorInfo.setTraceCount(count+1);
                                repeat = true;
                                continue;
                            }
                            
                            // Reset spin flag and trace count
                            currMonitorInfo.setSpinning(false);
                            currMonitorInfo.setTraceCount(-1);
                        }
                        if (currMonitorInfo.getCpuUtilization() > _busyThreshold)
                        {
                            // Thread is busy
                            StackTraceElement[] lastStackTrace = currMonitorInfo.getStackTrace();
        
                            if (lastStackTrace != null 
                            && matchStackTraces(lastStackTrace, entry.getValue()))
                            {
                                // Thread is spinning
                                currMonitorInfo.setSpinning(true);
                                if (count < 0)
                                {
                                    // Enable logging of spin status and stack traces 
                                    // only if the incoming trace count is negative
                                    // that indicates a new scan for this thread
                                    currMonitorInfo.setTraceCount(0);
                                    repeat = (_trailLength > 0);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LOG.debug(ex);
            }
            return repeat;
        }
    
        /* ------------------------------------------------------------ */
        protected void logThreadInfo(boolean logAll)
        {
            if (_monitorInfo.size() > 0)
            {
                // Select thread objects for all live threads
                long[] running = getAllThreadIds();
                List all = new ArrayList();
                for (int idx=0; idx()
                {
                    /* ------------------------------------------------------------ */
                    public int compare(ThreadMonitorInfo info1, ThreadMonitorInfo info2)
                    {
                        return (int)Math.signum(info2.getCpuUtilization()-info1.getCpuUtilization());
                    }
                });
                
                String format = "Thread '%2$s'[%3$s,id:%1$d,cpu:%4$.2f%%]%5$s";
                
                // Log thread information for threads that exceed logging threshold
                // or log spinning threads if their trace count is zero
                boolean spinning=false;
                for (ThreadMonitorInfo info : all)
                {
                    if (logAll && info.getCpuUtilization() > _logThreshold 
                    || info.isSpinning() && info.getTraceCount() == 0)
                    {
                        String message = String.format(format, 
                                info.getThreadId(), info.getThreadName(), 
                                info.getThreadState(), info.getCpuUtilization(),
                                info.isSpinning() ? " SPINNING" : "");
                       _logger.info(message);
                       spinning=true;
                    }
                }
                
                // Dump info
                if (spinning && _dumpable!=null)
                {
                    System.err.println(_dumpable.dump());
                }
    
                // Log stack traces for spinning threads with positive trace count
                for (ThreadMonitorInfo info : all)
                {
                    if (info.isSpinning() && info.getTraceCount() >= 0)
                    {
                        String message = String.format(format,
                                info.getThreadId(), info.getThreadName(), 
                                info.getThreadState(), info.getCpuUtilization(),
                                " STACK TRACE");
                        _logger.warn(new ThreadMonitorException(message, info.getStackTrace()));
                    }
                }
            }
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Match stack traces.
         *
         * @param lastStackTrace last stack trace
         * @param stackTrace current stack trace
         * @return true, if successful
         */
        private boolean matchStackTraces(StackTraceElement[] lastStackTrace, StackTraceElement[] stackTrace)
        {
            boolean match = true;
            int count = Math.min(_stackDepth, Math.min(lastStackTrace.length, stackTrace.length));
            
            for (int idx=0; idx < count; idx++)
            {
                if (!stackTrace[idx].equals(lastStackTrace[idx]))
                {
                    match = false;
                    break;
                }
            }
            return match;
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/integration/000077500000000000000000000000001174773561500276365ustar00rootroot00000000000000JavaMonitorAction.java000066400000000000000000000310241174773561500340110ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/integration// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.integration;
    
    import static java.lang.Integer.parseInt;
    import static java.lang.System.getProperty;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    import java.net.URL;
    import java.util.Collection;
    import java.util.Map;
    import java.util.Properties;
    import java.util.Set;
    
    import javax.management.MBeanServerConnection;
    import javax.management.MalformedObjectNameException;
    import javax.management.ObjectName;
    
    import org.eclipse.jetty.client.ContentExchange;
    import org.eclipse.jetty.client.HttpClient;
    import org.eclipse.jetty.http.HttpMethods;
    import org.eclipse.jetty.http.HttpStatus;
    import org.eclipse.jetty.io.ByteArrayBuffer;
    import org.eclipse.jetty.monitor.JMXMonitor;
    import org.eclipse.jetty.monitor.jmx.EventNotifier;
    import org.eclipse.jetty.monitor.jmx.EventState;
    import org.eclipse.jetty.monitor.jmx.EventState.TriggerState;
    import org.eclipse.jetty.monitor.jmx.EventTrigger;
    import org.eclipse.jetty.monitor.jmx.MonitorAction;
    import org.eclipse.jetty.monitor.triggers.AggregateEventTrigger;
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.log.Logger;
    
    
    /* ------------------------------------------------------------ */
    /**
     */
    public class JavaMonitorAction extends MonitorAction
    {
        private static final Logger LOG = Log.getLogger(JavaMonitorAction.class);
    
        private final HttpClient _client;
        
        private final String _url;
        private final String _uuid;
        private final String _appid;
        
        private String _srvip;
        private String _session;
        
        /* ------------------------------------------------------------ */
        /**
         * @param notifier
         * @param pollInterval
         * @throws Exception 
         * @throws MalformedObjectNameException 
         */
        public JavaMonitorAction(EventNotifier notifier, String url, String uuid, String appid, long pollInterval)
            throws Exception
        {
            super(new AggregateEventTrigger(),notifier,pollInterval);
            
            _url = url;
            _uuid = uuid;
            _appid = appid;
            
            _client = new HttpClient();
            _client.setTimeout(60000);
            _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
            
            try
            {
                _client.start();
                _srvip = getServerIP();
            }
            catch (Exception ex)
            {
                LOG.debug(ex);
            }
            
            sendData(new Properties());
         }
    
        /* ------------------------------------------------------------ */
        /**
         * @see org.eclipse.jetty.monitor.jmx.MonitorAction#execute(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
         */
        @Override
        public void execute(EventTrigger trigger, EventState state, long timestamp)
        {
            exec(trigger, state, timestamp);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @param trigger
         * @param state
         * @param timestamp
         */
        private  void exec(EventTrigger trigger, EventState state, long timestamp)
        {
            Collection> trs = state.values();
            
            Properties data = new Properties();
            for (TriggerState ts :  trs)
            {
                Object value = ts.getValue();
    
                StringBuffer buffer = new StringBuffer();
                buffer.append(value == null ? "" : value.toString());
                buffer.append("|");
                buffer.append(getClassID(value));
                buffer.append("||");
                buffer.append(ts.getDescription());
                
                data.setProperty(ts.getID(), buffer.toString());
                
                try
                {
                    sendData(data);
                }
                catch (Exception ex)
                {
                    LOG.debug(ex);
                }
            }
         }
        
        /* ------------------------------------------------------------ */
        /**
         * @param data
         * @throws Exception 
         */
        private void sendData(Properties data)
            throws Exception
        {
            data.put("account", _uuid);
            data.put("appserver", "Jetty");
            data.put("localIp", _srvip);
            if (_appid == null)
                data.put("lowestPort", getHttpPort());
            else
                data.put("lowestPort", _appid);
            if (_session != null)
                data.put("session", _session);
            
            Properties response = sendRequest(data);
            
            parseResponse(response);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @param request
         * @return
         * @throws Exception 
         */
        private Properties sendRequest(Properties request)
            throws Exception
        {
            ByteArrayOutputStream reqStream = null;
            ByteArrayInputStream resStream = null;
            Properties response = null;
        
            try {
                ContentExchange reqEx = new ContentExchange();
                reqEx.setURL(_url);
                reqEx.setMethod(HttpMethods.POST);
                reqEx.addRequestHeader("Connection","close");
                
                reqStream = new ByteArrayOutputStream();
                request.storeToXML(reqStream,null);
                ByteArrayBuffer reqBuff = new ByteArrayBuffer(reqStream.toByteArray());
    
                reqEx.setRequestContent(reqBuff);
                _client.send(reqEx);
            
                reqEx.waitForDone();
                
                if (reqEx.getResponseStatus() == HttpStatus.OK_200)
                {
                    response = new Properties();
                    resStream = new ByteArrayInputStream(reqEx.getResponseContentBytes());
                    response.loadFromXML(resStream);               
                }
            }
            finally
            {
                try
                {
                    if (reqStream != null)
                        reqStream.close();
                }
                catch (IOException ex)
                {
                    LOG.ignore(ex);
                }
                
                try
                {
                    if (resStream != null)
                        resStream.close();
                }
                catch (IOException ex)
                {
                    LOG.ignore(ex);
                }
            }
            
            return response;    
        }
        
        /* ------------------------------------------------------------ */
        private void parseResponse(Properties response)
        {
            if (response.get("onhold") != null)
                throw new Error("Suspended");
            
    
            if (response.get("session") != null)
            {
                _session = (String) response.remove("session");
    
                AggregateEventTrigger trigger = (AggregateEventTrigger)getTrigger();
    
                String queryString;
                ObjectName[] queryResults;
                for (Map.Entry entry : response.entrySet())
                {
                    String[] values = ((String) entry.getValue()).split("\\|");
    
                    queryString = values[0];
                    if (queryString.startsWith("com.javamonitor.openfire"))
                        continue;
                    
                    if (queryString.startsWith("com.javamonitor"))
                    {
                        queryString = "org.eclipse.jetty.monitor.integration:type=javamonitortools,id=0";
                    }
                    
                    queryResults = null;
                    try
                    {
                        queryResults = queryNames(queryString);
                    }
                    catch (IOException e)
                    {
                        LOG.debug(e);
                    }
                    catch (MalformedObjectNameException e)
                    {
                        LOG.debug(e);
                    }
                    
                    if (queryResults != null)
                    {
                        int idx = 0;
                        for(ObjectName objName : queryResults)
                        {
                            String id = entry.getKey().toString()+(idx == 0 ? "" : ":"+idx);
                            String name = queryString.equals(objName.toString()) ? "" : objName.toString();
                            boolean repeat = Boolean.parseBoolean(values[2]);
                            trigger.add(new JavaMonitorTrigger(objName, values[1], id, name, repeat));
                        }   
                    }
               }
            }
        }
        
        /* ------------------------------------------------------------ */
        /**
         * @param value
         * @return
         */
        private int getClassID(final Object value)
        {
            if (value == null)
                return 0;
            
            if (value instanceof Byte || 
                value instanceof Short ||
                value instanceof Integer ||
                value instanceof Long)
                return 1;
                
            if (value instanceof Float ||
                value instanceof Double)
                return 2;
            
            if (value instanceof Boolean)
                return 3;
    
            return 4; // String
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @return
         * @throws Exception 
         */
        private String getServerIP()
            throws Exception
        {
            Socket s = null;
            try {
                if (getProperty("http.proxyHost") != null)
                {
                    s = new Socket(getProperty("http.proxyHost"),
                                   parseInt(getProperty("http.proxyPort", "80")));
                } 
                else
                {
                    int port = 80;
                    
                    URL url = new URL(_url);
                    if (url.getPort() != -1) {
                        port = url.getPort();
                    }
                    s = new Socket(url.getHost(), port);
                }
                return s.getLocalAddress().getHostAddress();
            }
            finally
            {
                try
                {
                    if (s != null)
                        s.close();
                } 
                catch (IOException ex)
                {
                    LOG.ignore(ex);
                }
            }
        }
        
        /* ------------------------------------------------------------ */
        public Integer getHttpPort() 
        {       
            Collection connectors = null;
            MBeanServerConnection service;
            try
            {
                service = JMXMonitor.getServiceConnection();
    
                connectors = service.queryNames(new ObjectName("org.eclipse.jetty.nio:type=selectchannelconnector,*"), null);
                if (connectors != null && connectors.size() > 0)
                {
                    Integer lowest = Integer.MAX_VALUE;
                    for (final ObjectName connector : connectors) {
                        lowest = (Integer)service.getAttribute(connector, "port");
                    }
            
                    if (lowest < Integer.MAX_VALUE)
                        return lowest;
                }
            }
            catch (Exception ex)
            {
                LOG.debug(ex);
            }
            
            return 0;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @param param
         * @return
         * @throws IOException
         * @throws NullPointerException 
         * @throws MalformedObjectNameException 
         */
        private ObjectName[] queryNames(ObjectName param) 
            throws IOException, MalformedObjectNameException
        {
            ObjectName[] result = null;
            
            MBeanServerConnection connection = JMXMonitor.getServiceConnection();
            Set names = connection.queryNames(param, null);
            if (names != null && names.size() > 0)
            {
                result = new ObjectName[names.size()];
                
                int idx = 0;
                for(Object name : names)
                {
                    if (name instanceof ObjectName)
                        result[idx++] = (ObjectName)name;
                    else
                        result[idx++] = new ObjectName(name.toString());
                }
            }
            
            return result;
        }
        
        private ObjectName[] queryNames(String param) 
            throws IOException, MalformedObjectNameException
        {
            return queryNames(new ObjectName(param));
        }
    
     }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/integration/JavaMonitorTools.java000066400000000000000000000176571174773561500337730ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.integration;
    
    import java.lang.management.ManagementFactory;
    import java.lang.management.ThreadInfo;
    import java.lang.management.ThreadMXBean;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.security.Security;
    import java.util.HashMap;
    import java.util.Map;
    
    /* ------------------------------------------------------------ */
    /**
     * Derived from the JMX bean classes created by Kees Jan Koster for the java-monitor
     * J2EE probe http://code.google.com/p/java-monitor-probes/source/browse/.
     * 
     * @author kjkoster 
     */
    public class JavaMonitorTools
    {
        private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
    
        private static Method findDeadlockMethod = null;
    
        static
        {
            try
            {
                findDeadlockMethod = ThreadMXBean.class.getMethod("findDeadlockedThreads");
            }
            catch (Exception ignored)
            {
                // this is a 1.5 JVM
                try
                {
                    findDeadlockMethod = ThreadMXBean.class.getMethod("findMonitorDeadlockedThreads");
                }
                catch (SecurityException e)
                {
                    e.printStackTrace();
                }
                catch (NoSuchMethodException e)
                {
                    e.printStackTrace();
                }
            }
        }
    
        private ThreadInfo[] findDeadlock()
            throws IllegalAccessException, InvocationTargetException
        {
            final long[] threadIds = (long[])findDeadlockMethod.invoke(threadMXBean,(Object[])null);
    
            if (threadIds == null || threadIds.length < 1)
            {
                // no deadlock, we're done
                return null;
            }
    
            final ThreadInfo[] threads = threadMXBean.getThreadInfo(threadIds,Integer.MAX_VALUE);
            return threads;
        }
    
        public String getDeadlockStacktraces()
        {
            try
            {
                final ThreadInfo[] threads = findDeadlock();
                if (threads == null)
                {
                    // no deadlock, we're done
                    return null;
                }
    
                return stacktraces(threads,0);
            }
            catch (Exception e)
            {
                return e.getMessage();
            }
        }
    
        private static final int MAX_STACK = 10;
    
        private String stacktraces(final ThreadInfo[] threads, final int i)
        {
            if (i >= threads.length)
            {
                return "";
            }
            final ThreadInfo thread = threads[i];
    
            final StringBuilder trace = new StringBuilder();
            for (int stack_i = 0; stack_i < Math.min(thread.getStackTrace().length,MAX_STACK); stack_i++)
            {
                if (stack_i == (MAX_STACK - 1))
                {
                    trace.append("    ...");
                }
                else
                {
                    trace.append("    at ").append(thread.getStackTrace()[stack_i]).append("\n");
                }
            }
    
            return "\"" + thread.getThreadName() + "\", id " + thread.getThreadId() + " is " + thread.getThreadState() + " on " + thread.getLockName()
                    + ", owned by " + thread.getLockOwnerName() + ", id " + thread.getLockOwnerId() + "\n" + trace + "\n\n" + stacktraces(threads,i + 1);
        }
    
        /**
         * We keep track of the last time we sampled the thread states.
         * It is a crude optimization to avoid having to query for the
         * threads states very often.
         */
        private long lastSampled = 0L;
    
        private final Map states = new HashMap();
    
        public int getThreadsBlocked()
        {
            sampleThreads();
    
            return states.get(Thread.State.BLOCKED);
        }
    
        public int getThreadsNew()
        {
            sampleThreads();
    
            return states.get(Thread.State.NEW);
        }
    
        public int getThreadsTerminated()
        {
            sampleThreads();
    
            return states.get(Thread.State.TERMINATED);
        }
    
        public int getThreadsTimedWaiting()
        {
            sampleThreads();
    
            return states.get(Thread.State.TIMED_WAITING);
        }
    
        public int getThreadsWaiting()
        {
            sampleThreads();
    
            return states.get(Thread.State.WAITING);
        }
    
        public int getThreadsRunnable()
        {
            sampleThreads();
    
            return states.get(Thread.State.RUNNABLE);
        }
    
        private synchronized void sampleThreads()
        {
            if ((lastSampled + 50L) < System.currentTimeMillis())
            {
                lastSampled = System.currentTimeMillis();
                for (final Thread.State state : Thread.State.values())
                {
                    states.put(state,0);
                }
    
                for (final ThreadInfo thread : threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds()))
                {
                    if (thread != null)
                    {
                        final Thread.State state = thread.getThreadState();
                        states.put(state,states.get(state) + 1);
                    }
                    else
                    {
                        states.put(Thread.State.TERMINATED,states.get(Thread.State.TERMINATED) + 1);
                    }
                }
            }
        }
    
        private static final String POLICY = "sun.net.InetAddressCachePolicy";
    
        public int getCacheSeconds() throws ClassNotFoundException,
                IllegalAccessException, InvocationTargetException,
                NoSuchMethodException {
            final Class policy = Class.forName(POLICY);
            final Object returnValue = policy.getMethod("get", (Class[]) null)
                    .invoke(null, (Object[]) null);
            Integer seconds = (Integer) returnValue;
    
            return seconds.intValue();
        }
    
        public int getCacheNegativeSeconds() throws ClassNotFoundException,
                IllegalAccessException, InvocationTargetException,
                NoSuchMethodException {
            final Class policy = Class.forName(POLICY);
            final Object returnValue = policy.getMethod("getNegative",
                    (Class[]) null).invoke(null, (Object[]) null);
            Integer seconds = (Integer) returnValue;
    
            return seconds.intValue();
        }
    
        private static final String DEFAULT = "default";
    
        private static final String SECURITY = "security";
    
        private static final String SYSTEM = "system";
    
        private static final String BOTH = "both";
    
        private static final String SECURITY_TTL = "networkaddress.cache.ttl";
    
        private static final String SYSTEM_TTL = "sun.net.inetaddr.ttl";
    
        private static final String SECURITY_NEGATIVE_TTL = "networkaddress.cache.negative.ttl";
    
        private static final String SYSTEM_NEGATIVE_TTL = "sun.net.inetaddr.negative.ttl";
    
        public String getCacheTweakedFrom() {
            if (Security.getProperty(SECURITY_TTL) != null) {
                if (System.getProperty(SYSTEM_TTL) != null) {
                    return BOTH;
                }
    
                return SECURITY;
            }
    
            if (System.getProperty(SYSTEM_TTL) != null) {
                return SYSTEM;
            }
    
            return DEFAULT;
        }
    
        public String getCacheNegativeTweakedFrom() {
            if (Security.getProperty(SECURITY_NEGATIVE_TTL) != null) {
                if (System.getProperty(SYSTEM_NEGATIVE_TTL) != null) {
                    return BOTH;
                }
    
                return SECURITY;
            }
    
            if (System.getProperty(SYSTEM_NEGATIVE_TTL) != null) {
                return SYSTEM;
            }
    
            return DEFAULT;
        }
    }
    JavaMonitorTrigger.java000066400000000000000000000043551174773561500342060ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/integration// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.integration;
    
    import javax.management.MalformedObjectNameException;
    import javax.management.ObjectName;
    
    import org.eclipse.jetty.monitor.triggers.AttrEventTrigger;
    
    
    /* ------------------------------------------------------------ */
    /**
     */
    public class JavaMonitorTrigger >
        extends AttrEventTrigger
    {
        private final String _id;
        private final String _name;
        private final boolean _dynamic;
        private int _count;
        
        /* ------------------------------------------------------------ */
        /**
         * @param nameObject
         * @param attributeName
         * @param id
         * @param dynamic
         * @throws IllegalArgumentException
         */
        public JavaMonitorTrigger(ObjectName nameObject, String attributeName, String id, String name, boolean dynamic)
            throws IllegalArgumentException
        {   
            super(nameObject, attributeName);
          
            _id = id;
            _name = name;
            _dynamic = dynamic;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
         */
        @Override
        public boolean match(Comparable value)
        {
            return _dynamic ? true : (_count++ < 1);
        }
        
        protected boolean getSaveAll()
        {
            return false;
        }
        
        @Override
        public String getID()
        {
            return _id;
        }
        
        @Override
        public String getNameString()
        {
            return _name;
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/000077500000000000000000000000001174773561500261115ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/ConsoleNotifier.java000066400000000000000000000040351174773561500320600ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.jmx;
    
    
    /* ------------------------------------------------------------ */
    /**
     * ConsoleNotifier
     * 
     * Provides a way to output notification messages to the server console
     */
    public class ConsoleNotifier implements EventNotifier
    {
        String _messageFormat;
        
    
        /* ------------------------------------------------------------ */
        /**
         * Constructs a new notifier with specified format string
         * 
         * @param format the {@link java.util.Formatter format string}
         * @throws IllegalArgumentException
         */
        public ConsoleNotifier(String format)
            throws IllegalArgumentException
        {
            if (format == null)
                throw new IllegalArgumentException("Message format cannot be null");
            
            _messageFormat = format;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * @see org.eclipse.jetty.monitor.jmx.EventNotifier#notify(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
         */
        public void notify(EventTrigger trigger, EventState state, long timestamp)
        {
            String output = String.format("%1$tF %1$tT.%1$tL:NOTIFY::", timestamp);
            
            output += String.format(_messageFormat, state);         
            
            System.out.println(output);
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/EventNotifier.java000066400000000000000000000025211174773561500315350ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.jmx;
    
    
    /* ------------------------------------------------------------ */
    /**
     * EventNotifier
     * 
     * Interface for classes used to send event notifications
     */
    public interface EventNotifier
    {
    
        /* ------------------------------------------------------------ */
        /**
         * This method is called when a notification event is received by the containing object
         *  
         * @param state an {@link org.eclipse.jetty.monitor.jmx.EventState event state} 
         * @param timestamp time stamp of the event
         */
        public void notify(EventTrigger trigger, EventState state, long timestamp);
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/EventState.java000066400000000000000000000141561174773561500310450ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.jmx;
    
    import java.util.Collection;
    import java.util.Collections;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    
    /* ------------------------------------------------------------ */
    /**
     * EventState
     * 
     * Holds the state of one or more {@link org.eclipse.jetty.monitor.jmx.EventTrigger event trigger}
     * instances to be used when sending notifications as well as executing the actions
     */
    public class EventState
    {
        
        /* ------------------------------------------------------------ */
        /**
         * State
         * 
         * Holds the state of a single {@link org.eclipse.jetty.monitor.jmx.EventTrigger event trigger}
         */
        public static class TriggerState
        {
            private final String _id;
            private final String _desc;
            private final TYPE _value;
            
            /* ------------------------------------------------------------ */
            /**
             * Construct a trigger state 
             * 
             * @param id unique identification string of the associated event trigger
             * @param desc description of the associated event trigger
             * @param value effective value of the MXBean attribute (if applicable)
             */
            public TriggerState(String id, String desc, TYPE value)
            {
                _id = id;
                _desc = desc;
                _value = value;
            }
            
            /* ------------------------------------------------------------ */
            /**
             * Retrieve the identification string of associated event trigger
             * 
             * @return unique identification string
             */
            public String getID()
            {
                return _id;
            }
            
            /* ------------------------------------------------------------ */
            /**
             * Retrieve the description string set by event trigger
             * 
             * @return description string
             */
            public String getDescription()
            {
                return _desc;
            }
            
            /* ------------------------------------------------------------ */
            /**
             * Retrieve the effective value of the MXBean attribute (if applicable)
             * 
             * @return attribute value
             */
            public TYPE getValue()
            {
                return _value;
            }
            
            /* ------------------------------------------------------------ */
            /**
             * @return string representation of the state
             */
            public String toString()
            {
                StringBuilder result = new StringBuilder();
               
                result.append(_desc);
                result.append('=');
                result.append(_value);
                
                return result.toString();
            }
        }
        
        protected Map> _states;
        
        /* ------------------------------------------------------------ */
        /**
         * Constructs an empty event state
         */
        public EventState()
        {
            _states = new ConcurrentHashMap>();
        }
        
    
        /* ------------------------------------------------------------ */
        /**
         * Constructs an event state and adds a specified trigger state to it
         * 
         * @param id unique identification string of the associated event trigger
         * @param desc description of the associated event trigger
         * @param value effective value of the MXBean attribute (if applicable)
         */
        public EventState(String id, String desc, TYPE value)
        {
            this();
            
            add(new TriggerState(id, desc, value));
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Adds a trigger state to the event state
         * 
         * @param state trigger state to add
         */
        public void add(TriggerState state)
        {
            _states.put(state.getID(), state);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Adds a collection of trigger states to the event state
         * 
         * @param entries collection of trigger states to add
         */
        public void addAll(Collection> entries)
        {
            for (TriggerState entry : entries)
            {
                add(entry);
            }
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Retrieves a single trigger state
         * 
         * @param id unique identification string of the event trigger
         * @return requested trigger state or null if not found
         */
        public TriggerState get(String id)
        {
            return _states.get(id);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Retrieves a collection of all trigger states of the event state
         * 
         * @return collection of the trigger states
         */
        public Collection> values()
        {
            return Collections.unmodifiableCollection(_states.values());
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Returns a string representation of the event state
         * 
         * @return string representation of the event state
         */
        public String toString()
        {
            int cnt = 0;
            StringBuilder result = new StringBuilder();
            
            for (TriggerState value : _states.values())
            {
                result.append(cnt++>0?"#":"");
                result.append(value.toString());
            }
            
            return result.toString();
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/EventTrigger.java000066400000000000000000000044101174773561500313600ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.jmx;
    
    import static java.util.UUID.randomUUID;
    
    /* ------------------------------------------------------------ */
    /**
     * EventTrigger
     * 
     * Abstract base class for all EventTrigger implementations.
     * Used to determine whether the necessary conditions for  
     * triggering an event are present.
     */
    public abstract class EventTrigger
    {
        private final String _id;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct an event trigger
         */
        public EventTrigger()
        {
            _id = randomUUID().toString();
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Retrieve the identification string of the event trigger
         * 
         * @return unique identification string
         */
        public String getID()
        {
            return _id;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Abstract method to verify if the event trigger conditions
         * are in the appropriate state for an event to be triggered
         * 
         * @return true to trigger an event
         */
        public abstract boolean match(long timestamp) throws Exception;
    
        /* ------------------------------------------------------------ */
        /**
         * Retrieve the event state associated with specified invocation
         * of the event trigger match method
         * 
         * @param timestamp time stamp associated with invocation
         * @return event state or null if not found
         */
        public abstract EventState getState(long timestamp);
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/LoggingNotifier.java000066400000000000000000000041131174773561500320410ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.jmx;
    
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.log.Logger;
    
    
    /* ------------------------------------------------------------ */
    /**
     * ConsoleNotifier
     * 
     * Provides a way to output notification messages to a log file
     */
    public class LoggingNotifier implements EventNotifier
    {
        private static final Logger LOG = Log.getLogger(LoggingNotifier.class);
    
        String _messageFormat;
    
        /* ------------------------------------------------------------ */
        /**
         * Constructs a new notifier with specified format string
         * 
         * @param format the {@link java.util.Formatter format string}
         * @throws IllegalArgumentException
         */
        public LoggingNotifier(String format)
            throws IllegalArgumentException
        {
            if (format == null)
                throw new IllegalArgumentException("Message format cannot be null");
            
            _messageFormat = format;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * @see org.eclipse.jetty.monitor.jmx.EventNotifier#notify(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
         */
        public void notify(EventTrigger trigger, EventState state, long timestamp)
        {
            String output = String.format(_messageFormat, state);
            
            LOG.info(output);
        }
    
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/MonitorAction.java000066400000000000000000000134161174773561500315460ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.jmx;
    
    import static java.util.UUID.randomUUID;
    
    import java.security.InvalidParameterException;
    
    /* ------------------------------------------------------------ */
    /**
     * MonitorAction
     * 
     * Abstract base class for all MonitorAction implementations. 
     * Receives notification when an associated EventTrigger is matched.
     */
    public abstract class MonitorAction
        extends NotifierGroup
    {
        public static final int DEFAULT_POLL_INTERVAL = 5000;
        
        private final String _id;
        private final EventTrigger _trigger;
        private final EventNotifier _notifier;
        private final long _pollInterval;
        private final long _pollDelay;
    
        /* ------------------------------------------------------------ */
        /**
         * Creates a new monitor action 
         * 
         * @param trigger event trigger to be associated with this action
         * @throws InvalidParameterException
         */
        public MonitorAction(EventTrigger trigger)
            throws InvalidParameterException
        {
            this(trigger, null, 0, 0);
        }
        
        
        /* ------------------------------------------------------------ */
        /**
         * Creates a new monitor action 
         * 
         * @param trigger event trigger to be associated with this action
         * @param notifier event notifier to be associated with this action
         * @throws InvalidParameterException
         */
        public MonitorAction(EventTrigger trigger, EventNotifier notifier)
            throws InvalidParameterException
        {
            this(trigger, notifier, 0);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Creates a new monitor action 
         * 
         * @param trigger event trigger to be associated with this action
         * @param notifier event notifier to be associated with this action
         * @param pollInterval interval for polling of the JMX server
         * @throws InvalidParameterException
         */
        public MonitorAction(EventTrigger trigger, EventNotifier notifier, long pollInterval)
            throws InvalidParameterException
        {
            this(trigger, notifier, pollInterval, 0);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Creates a new monitor action 
         * 
         * @param trigger event trigger to be associated with this action
         * @param notifier event notifier to be associated with this action
         * @param pollInterval interval for polling of the JMX server
         * @param pollDelay delay before starting to poll the JMX server
         * @throws InvalidParameterException
         */
        public MonitorAction(EventTrigger trigger, EventNotifier notifier, long pollInterval, long pollDelay)
            throws InvalidParameterException
        {
            if (trigger == null)
                throw new InvalidParameterException("Trigger cannot be null");
            
            _id = randomUUID().toString();
            _trigger = trigger;
            _notifier = notifier;
            _pollInterval = pollInterval > 0 ? pollInterval : DEFAULT_POLL_INTERVAL;
            _pollDelay = pollDelay > 0 ? pollDelay : _pollInterval;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Retrieve the identification string of the monitor action
         * 
         * @return unique identification string
         */
    
        public final String getID()
        {
            return _id;
        }
        
       
        /* ------------------------------------------------------------ */
        /**
         * Retrieve the event trigger of the monitor action
         * 
         * @return associated event trigger
         */
        public EventTrigger getTrigger()
        {
            return _trigger;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Retrieve the poll interval
         * 
         * @return interval value (in milliseconds)
         */
        public long getPollInterval()
        {
            return _pollInterval;
        }
        
    
        /* ------------------------------------------------------------ */
        /** Retrieve the poll delay
         * @return delay value (in milliseconds)
         */
        public long getPollDelay()
        {
            return _pollDelay;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * This method will be called when event trigger associated
         * with this monitor action matches its conditions.
         * 
         * @param timestamp time stamp of the event
         */
        public final void doExecute(long timestamp)
        {
            EventState state =_trigger.getState(timestamp);
            if (_notifier != null)
                _notifier.notify(_trigger, state, timestamp);
            execute(_trigger, state, timestamp);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * This method will be called to allow subclass to execute
         * the desired action in response to the event.
         * 
         * @param trigger event trigger associated with this monitor action
         * @param state event state associated with current invocation of event trigger
         * @param timestamp time stamp of the current invocation of event trigger
         */
        public abstract void execute(EventTrigger trigger, EventState state, long timestamp);
     }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/MonitorTask.java000066400000000000000000000073111174773561500312300ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.jmx;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.TimeUnit;
    
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.log.Logger;
    import org.eclipse.jetty.util.thread.ExecutorThreadPool;
    import org.eclipse.jetty.util.thread.ThreadPool;
    
    /* ------------------------------------------------------------ */
    /**
     * MonitorTask
     * 
     * Invokes polling of the JMX server for the MBean attribute values
     * through executing timer task scheduled using java.util.Timer 
     * at specified poll interval following a specified delay.
     */
    public class MonitorTask extends TimerTask
    {
        private static final Logger LOG = Log.getLogger(MonitorTask.class);
    
        private static Timer __timer = new Timer(true);
        private static ThreadPool _callback = new ExecutorThreadPool(4,64,60,TimeUnit.SECONDS);;
        private static Map __tasks  = new HashMap();
    
        private final MonitorAction _action;
        
        /* ------------------------------------------------------------ */
        /**
         * Creates new instance of MonitorTask 
         * 
         * @param action instance of MonitorAction to use
         */
        private MonitorTask(MonitorAction action)
        {
            _action = action;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Schedule new timer task for specified monitor action
         * 
         * @param action monitor action
         */
        public static void schedule(MonitorAction action)
        {
            TimerTask task = new MonitorTask(action);
            __timer.scheduleAtFixedRate(task,
                                        action.getPollDelay(),
                                        action.getPollInterval());
            
            __tasks.put(action.getID(), task);
       }
        
        /* ------------------------------------------------------------ */
        /**
         * Cancel timer task for specified monitor action
         * 
         * @param action monitor action
         */
        public static void cancel(MonitorAction action)
        {
            TimerTask task = __tasks.remove(action.getID());
            if (task != null)
                task.cancel();
        }
    
        /* ------------------------------------------------------------ */
        /**
         * This method is invoked when poll interval has elapsed
         * to check if the event trigger conditions are satisfied
         * in order to fire event.
         *
         * @see java.util.TimerTask#run()
         */
        @Override
        public final void run()
        {
            final long timestamp = System.currentTimeMillis();
            final EventTrigger trigger = _action.getTrigger();
    
            _callback.dispatch(new Runnable() {
                public void run()
                {
                    try
                    {
                        if(trigger.match(timestamp))
                            _action.doExecute(timestamp);
                    }
                    catch (Exception ex)
                    {
                        LOG.debug(ex);
                    }
                }
            });
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/NotifierGroup.java000066400000000000000000000071331174773561500315540ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.jmx;
    
    import java.util.Collection;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Set;
    
    
    
    /* ------------------------------------------------------------ */
    /**
     * NotifierGroup
     * 
     * This class allows for grouping of the event notifiers 
     */
    public class NotifierGroup implements EventNotifier
    {
        private Set _group;
    
        /* ------------------------------------------------------------ */
        /**
         * Create a notifier group
         */
        public NotifierGroup()
        {
            _group = new HashSet();
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Retrieve all event notifier associated with this group
         * 
         * @return collection of event notifiers
         */    
        public Collection getNotifiers()
        {
            return Collections.unmodifiableSet(_group);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Add specified event notifier to event notifier group
         * 
         * @param notifier event notifier to be added
         * @return true if successful
         */
        public boolean addNotifier(EventNotifier notifier)
        {
            return _group.add(notifier);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Add a collection of event notifiers to event notifier group
         * 
         * @param notifiers collection of event notifiers to be added
         * @return true if successful
         */
        public boolean addNotifiers(Collection notifiers)
        {
            return _group.addAll(notifiers);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Remove event notifier from event notifier group
         * 
         * @param notifier event notifier to be removed
         * @return true if successful
         */
        public boolean removeNotifier(EventNotifier notifier)
        {
            return _group.remove(notifier);
        }
     
        /* ------------------------------------------------------------ */
        /**
         * Remove a collection of event notifiers from event notifier group
         * 
         * @param notifiers collection of event notifiers to be removed
         * @return true if successful
         */
        public boolean removeNotifiers(Collection notifiers)
        {
            return _group.removeAll(notifiers);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Invoke the notify() method of each of the notifiers in group
         * 
         * @see org.eclipse.jetty.monitor.jmx.EventNotifier#notify(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
         */
        public void notify(EventTrigger trigger, EventState state, long timestamp)
        {
            for (EventNotifier notifier: _group)
            {
                notifier.notify(trigger, state, timestamp);
            }
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/ServiceConnection.java000066400000000000000000000116531174773561500324020ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.jmx;
    
    import java.io.IOException;
    import java.lang.management.ManagementFactory;
    
    import javax.management.MBeanServer;
    import javax.management.MBeanServerConnection;
    import javax.management.remote.JMXConnector;
    import javax.management.remote.JMXConnectorFactory;
    import javax.management.remote.JMXConnectorServer;
    import javax.management.remote.JMXConnectorServerFactory;
    import javax.management.remote.JMXServiceURL;
    
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.log.Logger;
    
    
    /* ------------------------------------------------------------ */
    /**
     * ServerConnection
     * 
     * Provides ability to create a connection to either an external
     * JMX server, or a loopback connection to the internal one.
     */
    public class ServiceConnection
    {
        private static final Logger LOG = Log.getLogger(ServiceConnection.class);
    
        private String _serviceUrl;
        private MBeanServer _server;
        private JMXConnectorServer _connectorServer;
        private JMXConnector _serverConnector;
        private MBeanServerConnection _serviceConnection;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct a loopback connection to an internal server
         * 
         * @throws IOException
         */
        public ServiceConnection()
            throws IOException
        {
            this(null);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Construct a connection to specified server
         * 
         * @param url URL of JMX server
         * @throws IOException
         */
        public ServiceConnection(String url)
            throws IOException
        {
            _serviceUrl = url;
        }
        
        /**
         * Retrieve an external URL for the JMX server
         * 
         * @return service URL
         */
        public String getServiceUrl()
        {
        	return _serviceUrl;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Retrieve a connection to MBean server
         * 
         * @return connection to MBean server
         */
        public MBeanServerConnection getConnection()
        {
            return _serviceConnection;
        }
    
        public void connect()
            throws IOException
        {
            if (_serviceConnection == null)
            {
                if (_serviceUrl == null)
                    openLoopbackConnection();
                else
                    openServerConnection(_serviceUrl);
            }
        }
        /* ------------------------------------------------------------ */
        /**
         * Open a loopback connection to local JMX server
         * 
         * @throws IOException
         */
        private void openLoopbackConnection()
            throws IOException
        {
            _server = ManagementFactory.getPlatformMBeanServer();       
    
            JMXServiceURL serviceUrl = new JMXServiceURL("service:jmx:rmi://");
            _connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, null, _server);
            _connectorServer.start();
            
            _serviceUrl = _connectorServer.getAddress().toString();
            
            _serverConnector = JMXConnectorFactory.connect(_connectorServer.getAddress());      
            _serviceConnection = _serverConnector.getMBeanServerConnection();
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Open a connection to remote JMX server
         * 
         * @param url
         * @throws IOException
         */
        private void openServerConnection(String url)
            throws IOException
        {
            _serviceUrl = url;
            
            JMXServiceURL serviceUrl = new JMXServiceURL(_serviceUrl);
            _serverConnector = JMXConnectorFactory.connect(serviceUrl);
            _serviceConnection = _serverConnector.getMBeanServerConnection();
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Close the connections
         */
        public void disconnect()
        {
            try
            {
                if (_serverConnector != null)
                {
                    _serverConnector.close();
                    _serviceConnection = null;
                }
                if (_connectorServer != null)
                {
                    _connectorServer.stop();
                    _connectorServer = null;
                }
            }
            catch (Exception ex)
            {
                LOG.debug(ex);
            }
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/SimpleAction.java000066400000000000000000000030121174773561500313370ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.jmx;
    
    import java.security.InvalidParameterException;
    
    
    
    /* ------------------------------------------------------------ */
    /**
     */
    public class SimpleAction extends MonitorAction
    {
        public SimpleAction(EventTrigger trigger, EventNotifier notifier, long pollInterval)
            throws InvalidParameterException
        {
            super(trigger,notifier,pollInterval);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @see org.eclipse.jetty.monitor.jmx.MonitorAction#execute(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
         */
    
        @Override
        public void execute(EventTrigger trigger, EventState state, long timestamp)
        {
            System.out.printf("Action time: %tc%n", timestamp);
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/thread/000077500000000000000000000000001174773561500265625ustar00rootroot00000000000000ThreadMonitorException.java000066400000000000000000000021561174773561500340100ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/thread// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.thread;
    
    
    /* ------------------------------------------------------------ */
    /**
     */
    public class ThreadMonitorException extends Exception
    {
        private static final long serialVersionUID = -4345223166315716918L;
        
        public ThreadMonitorException(String message, StackTraceElement[] stackTrace)
        {
            super(message);
            setStackTrace(stackTrace);
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/thread/ThreadMonitorInfo.java000066400000000000000000000116641174773561500330300ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.thread;
    
    
    /* ------------------------------------------------------------ */
    /**
     */
    public class ThreadMonitorInfo
    {
        private Thread _thread;
        private StackTraceElement[] _stackTrace;
    
        private boolean _threadSpinning = false;
        private int _traceCount = -1;
    
        private long _prevCpuTime;
        private long _prevSampleTime;
        private long _currCpuTime;
        private long _currSampleTime;
    
        
        /* ------------------------------------------------------------ */
        /**
         * Instantiates a new thread monitor info.
         *
         * @param thread the thread this object is created for
         */
        public ThreadMonitorInfo(Thread thread)
        {
            _thread = thread;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @return Id of the thread
         */
        public long getThreadId()
        {
            return _thread.getId();
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Gets the thread name.
         *
         * @return the thread name
         */
        public String getThreadName()
        {
            return _thread.getName();
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Gets the thread state.
         *
         * @return the thread state
         */
        public String getThreadState()
        {
            return _thread.getState().toString();
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Gets the stack trace.
         *
         * @return the stack trace
         */
        public StackTraceElement[] getStackTrace()
        {
            return _stackTrace; 
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Sets the stack trace.
         *
         * @param stackTrace the new stack trace
         */
        public void setStackTrace(StackTraceElement[] stackTrace)
        {
            _stackTrace = stackTrace;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Checks if is spinning.
         *
         * @return true, if is spinning
         */
        public boolean isSpinning()
        {
            return _threadSpinning;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Sets the spinning flag.
         *
         * @param value the new value
         */
        public void setSpinning(boolean value)
        {
            _threadSpinning = value;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Sets the trace count.
         *
         * @param traceCount the new trace count
         */
        public void setTraceCount(int traceCount)
        {
            _traceCount = traceCount;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Gets the trace count.
         *
         * @return the trace count
         */
        public int getTraceCount()
        {
            return _traceCount;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @return the CPU time of the thread
         */
        public long getCpuTime()
        {
            return _currCpuTime;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Set the CPU time.
         *
         * @param ns new CPU time
         */
        public void setCpuTime(long ns)
        {
            _prevCpuTime = _currCpuTime;
            _currCpuTime = ns;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @return the time of sample  
         */
        public long getSampleTime()
        {
            return _currSampleTime;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Sets the sample time.
         *
         * @param ns the time of sample
         */
        public void setSampleTime(long ns)
        {
            _prevSampleTime = _currSampleTime;
            _currSampleTime = ns;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Gets the CPU utilization.
         *
         * @return the CPU utilization percentage
         */
        public float getCpuUtilization()
        {
            long elapsedCpuTime = _currCpuTime - _prevCpuTime;
            long elapsedNanoTime = _currSampleTime - _prevSampleTime;
    
            return elapsedNanoTime > 0 ? Math.min((elapsedCpuTime * 100.0f) / elapsedNanoTime, 100.0f) : 0; 
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/triggers/000077500000000000000000000000001174773561500271415ustar00rootroot00000000000000AggregateEventTrigger.java000066400000000000000000000115721174773561500341470ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/triggers// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.triggers;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    import org.eclipse.jetty.monitor.jmx.EventState;
    import org.eclipse.jetty.monitor.jmx.EventTrigger;
    
    
    /* ------------------------------------------------------------ */
    /**
     * AggregateEventTrigger
     * 
     * EventTrigger aggregation that executes every aggregated event
     * triggers in left to right order, and returns match if any one
     * of them have returned match.   
     */
    public class AggregateEventTrigger extends EventTrigger
    {
        protected final List _triggers;
    
        /* ------------------------------------------------------------ */
        /**
         * Construct an event trigger
         */
        public AggregateEventTrigger()
        {
            _triggers = new ArrayList();
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Construct an event trigger and associate the list 
         * of event triggers to be aggregated by this trigger
         * 
         * @param triggers list of event triggers to add
         */
        public AggregateEventTrigger(List triggers)
        {
            _triggers = new ArrayList(triggers);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Construct an event trigger and associate the array 
         * of event triggers to be aggregated by this trigger
         * 
         * @param triggers list of event triggers to add
         */
        public AggregateEventTrigger(EventTrigger... triggers)
        {
            _triggers = Arrays.asList(triggers);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * @param trigger
         */
        public void add(EventTrigger trigger)
        {
            _triggers.add(trigger);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * @param triggers
         */
        public void addAll(List triggers)
        {
            _triggers.addAll(triggers);
        }
            
        /* ------------------------------------------------------------ */
        /**
         * @param triggers
         */
        public void addAll(EventTrigger... triggers)
        {
            _triggers.addAll(Arrays.asList(triggers));
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Retrieve the event state associated with specified invocation
         * of the event trigger match method. This event trigger retrieves
         * the combined event state of all aggregated event triggers.
         * 
         * @param timestamp time stamp associated with invocation
         * @return event state or null if not found
         *
         * @see org.eclipse.jetty.monitor.jmx.EventTrigger#getState(long)
         */
        @Override
        public EventState getState(long timestamp)
        {
            EventState state = new EventState();
            
            for (EventTrigger trigger : _triggers)
            {
                EventState subState = trigger.getState(timestamp);
                if (subState != null)
                {
                    state.addAll(subState.values());
                }
            }
            
            return state;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * @see org.eclipse.jetty.monitor.jmx.EventTrigger#match(long)
         */
        @Override
        public boolean match(long timestamp) throws Exception
        {
            boolean result = false;
            for(EventTrigger trigger : _triggers)
            {
                result = trigger.match(timestamp) ? true : result;
            }
            return true;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "AND(triger1,trigger2,...)". 
         * 
         * @return string representation of the event trigger
         * 
         * @see java.lang.Object#toString()
         */
        public String toString()
        {
            int cnt = 0;
            StringBuilder result = new StringBuilder();
            
            result.append("ANY(");
            for (EventTrigger trigger : _triggers)
            {
                result.append(cnt++ > 0 ? "," : "");
                result.append(trigger);
            }
            result.append(')');
            
            return result.toString();
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/triggers/AndEventTrigger.java000066400000000000000000000100451174773561500330340ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.triggers;
    
    import java.util.Arrays;
    import java.util.List;
    
    import org.eclipse.jetty.monitor.jmx.EventState;
    import org.eclipse.jetty.monitor.jmx.EventTrigger;
    
    
    /* ------------------------------------------------------------ */
    /**
     * AndEventTrigger 
     *
     * EventTrigger aggregation using logical AND operation 
     * that executes matching of the aggregated event triggers
     * in left to right order  
     */
    public class AndEventTrigger extends EventTrigger
    {
        protected final List _triggers;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct an event trigger and associate the list 
         * of event triggers to be aggregated by this trigger
         * 
         * @param triggers list of event triggers to add
         */
        public AndEventTrigger(List triggers)
        {
            _triggers = triggers;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Construct an event trigger and associate the array 
         * of event triggers to be aggregated by this trigger
         * 
         * @param triggers array of event triggers to add
         */
        public AndEventTrigger(EventTrigger... triggers)
        {
            _triggers = Arrays.asList(triggers);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Verify if the event trigger conditions are in the 
         * appropriate state for an event to be triggered.
         * This event trigger will match if all aggregated 
         * event triggers would return a match.
         * 
         * @see org.eclipse.jetty.monitor.jmx.EventTrigger#match(long)
         */
        public boolean match(long timestamp)
            throws Exception
        {
            for(EventTrigger trigger : _triggers)
            {
                if (!trigger.match(timestamp))
                    return false;
            }
            return true;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Retrieve the event state associated with specified invocation
         * of the event trigger match method. This event trigger retrieves
         * the combined event state of all aggregated event triggers.
         * 
         * @param timestamp time stamp associated with invocation
         * @return event state or null if not found
         *
         * @see org.eclipse.jetty.monitor.jmx.EventTrigger#getState(long)
         */
        @Override
        public EventState getState(long timestamp)
        {
           EventState state = new EventState();
           
           for (EventTrigger trigger : _triggers)
           {
               EventState subState = trigger.getState(timestamp);
               state.addAll(subState.values());
           }
           
           return state;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "AND(triger1,trigger2,...)". 
         * 
         * @return string representation of the event trigger
         * 
         * @see java.lang.Object#toString()
         */
        public String toString()
        {
            int cnt = 0;
            StringBuilder result = new StringBuilder();
            
            result.append("AND(");
            for (EventTrigger trigger : _triggers)
            {
                result.append(cnt++ > 0 ? "," : "");
                result.append(trigger);
            }
            result.append(')');
            
            return result.toString();
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/triggers/AttrEventTrigger.java000066400000000000000000000177001174773561500332510ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.triggers;
    
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    import javax.management.MBeanServerConnection;
    import javax.management.MalformedObjectNameException;
    import javax.management.ObjectName;
    import javax.management.openmbean.CompositeData;
    
    import org.eclipse.jetty.monitor.JMXMonitor;
    import org.eclipse.jetty.monitor.jmx.EventState;
    import org.eclipse.jetty.monitor.jmx.EventTrigger;
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.log.Logger;
    
    
    /* ------------------------------------------------------------ */
    /**
     * AttrEventTrigger
     * 
     * Event trigger that polls a value of an MXBean attribute
     * and matches every invocation of this trigger. It can be
     * used to send notifications of the value of an attribute
     * of the MXBean being polled at a certain interval, or as
     * a base class for the event triggers that match the 
     * value of an attribute of the MXBean being polled against
     * some specified criteria.
     */
    public class AttrEventTrigger> 
        extends EventTrigger
    {
        private static final Logger LOG = Log.getLogger(AttrEventTrigger.class);
       
        private final ObjectName _nameObject;
    
        protected final String _objectName;
        protected final String _attributeName;
        protected Map> _states;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct event trigger and specify the MXBean attribute
         * that will be polled by this event trigger.
         * 
         * @param objectName object name of an MBean to be polled
         * @param attributeName name of an MBean attribute to be polled
         * 
         * @throws MalformedObjectNameException
         * @throws IllegalArgumentException
         */
        public AttrEventTrigger(String objectName, String attributeName)
            throws MalformedObjectNameException, IllegalArgumentException
        {
            if (objectName == null)
                throw new IllegalArgumentException("Object name cannot be null");
            if (attributeName == null)
                throw new IllegalArgumentException("Attribute name cannot be null");
            
            _states =  new ConcurrentHashMap>();
            
            _objectName = objectName;
            _attributeName = attributeName;
            
            _nameObject = new ObjectName(_objectName);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Construct event trigger and specify the MXBean attribute
         * that will be polled by this event trigger.
         * 
         * @param nameObject object name of an MBean to be polled
         * @param attributeName name of an MBean attribute to be polled
         * 
         * @throws IllegalArgumentException
         */
        public AttrEventTrigger(ObjectName nameObject, String attributeName)
            throws IllegalArgumentException
        {
            if (nameObject == null)
                throw new IllegalArgumentException("Object name cannot be null");
            if (attributeName == null)
                throw new IllegalArgumentException("Attribute name cannot be null");
            
            _states =  new ConcurrentHashMap>();
            
            _objectName = nameObject.toString();
            _attributeName = attributeName;
            
            _nameObject = nameObject;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Verify if the event trigger conditions are in the 
         * appropriate state for an event to be triggered.
         * This event trigger uses the match(Comparable)
         * method to compare the value of the MXBean attribute
         * to the conditions specified by the subclasses.
         * 
         * @see org.eclipse.jetty.monitor.jmx.EventTrigger#match(long)
         */
        @SuppressWarnings("unchecked")
        public final boolean match(long timestamp) 
            throws Exception
        {
            MBeanServerConnection serverConnection = JMXMonitor.getServiceConnection();
    
            TYPE value = null;
            try
            {
                int pos = _attributeName.indexOf('.');
                if (pos < 0)
                    value = (TYPE)serverConnection.getAttribute(_nameObject,_attributeName);
                else
                    value =  getValue((CompositeData)serverConnection.getAttribute(_nameObject, _attributeName.substring(0, pos)),
                                      _attributeName.substring(pos+1));
            }
            catch (Exception ex)
            {
                LOG.debug(ex);
            }
    
            boolean result = false;
            if (value != null)
            {
                result = match(value);
                
                if (result || getSaveAll())
                {
                    _states.put(timestamp, 
                                new EventState(this.getID(), this.getNameString(), value));
                }
            }
                
            return result;
        }
        
        
        /* ------------------------------------------------------------ */
        /**
         * Verify if the event trigger conditions are in the 
         * appropriate state for an event to be triggered.
         * Allows subclasses to override the default behavior
         * that matches every invocation of this trigger
         */
        public boolean match(Comparable value)
        {
            return true;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Retrieve the event state associated with specified invocation
         * of the event trigger match method. 
         * 
         * @param timestamp time stamp associated with invocation
         * @return event state or null if not found
         *
         * @see org.eclipse.jetty.monitor.jmx.EventTrigger#getState(long)
         */
        @Override
        public final EventState getState(long timestamp)
        {
            return _states.get(timestamp);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "[object_name:attribute_name]". 
         * 
         * @return string representation of the event trigger
         * 
         * @see java.lang.Object#toString()
         */
        public String toString()
        {
            return getNameString();
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "[object_name:attribute_name]". Allows
         * subclasses to override the name string used to identify
         * this event trigger in the event state object as well as
         * string representation of the subclasses.
         * 
         * @return string representation of the event trigger
         */
        protected String getNameString()
        {
            StringBuilder result = new StringBuilder();
            
            result.append('[');
            result.append(_objectName);
            result.append(":");
            result.append(_attributeName);
            result.append("]");
            
            return result.toString();
        }
    
        protected boolean getSaveAll()
        {
            return true;
        }
        
        protected TYPE getValue(CompositeData compValue, String fieldName)
        {
            int pos = fieldName.indexOf('.');
            if (pos < 0)
                return (TYPE)compValue.get(fieldName);
            else
                return getValue((CompositeData)compValue.get(fieldName.substring(0, pos)), 
                                fieldName.substring(pos+1));
              
        }
    }
    EqualToAttrEventTrigger.java000066400000000000000000000055671174773561500344750ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/triggers// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.triggers;
    
    import javax.management.MalformedObjectNameException;
    
    
    /* ------------------------------------------------------------ */
    /**
     * EqualToAttrEventTrigger
     * 
     * Event trigger that polls a value of an MXBean attribute and
     * checks if it is equal to specified value. 
     */
    public class EqualToAttrEventTrigger> extends AttrEventTrigger
    {
        protected final TYPE _value;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct event trigger and specify the MXBean attribute
         * that will be polled by this event trigger as well as the
         * target value of the attribute.
         * 
         * @param objectName object name of an MBean to be polled
         * @param attributeName name of an MBean attribute to be polled
         * @param value target value of the attribute
         * 
         * @throws MalformedObjectNameException
         * @throws IllegalArgumentException
         */
        public EqualToAttrEventTrigger(String objectName, String attributeName, TYPE value)
            throws MalformedObjectNameException, IllegalArgumentException
        {
            super(objectName,attributeName);
            
            if (value == null)
                throw new IllegalArgumentException("Value cannot be null");
    
            _value = value;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Compare the value of the MXBean attribute being polling
         * to check if it is equal to the specified value.
         */
        @Override
        public boolean match(Comparable value)
        {
            return (value.compareTo(_value) == 0);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "name=value". 
         * 
         * @return string representation of the event trigger
         * 
         * @see java.lang.Object#toString()
         */
        public String toString()
        {
            StringBuilder result = new StringBuilder();
            
            result.append(getNameString());
            result.append("==");
            result.append(_value);
            
            return result.toString();
        }
    }
    GreaterThanAttrEventTrigger.java000066400000000000000000000057221174773561500353200ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/triggers// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.triggers;
    
    import javax.management.MalformedObjectNameException;
    
    
    /* ------------------------------------------------------------ */
    /**
     * GreaterThanAttrEventTrigger
     * 
     * Event trigger that polls a value of an MXBean attribute and
     * checks if it is greater than specified min value. 
     */
    public class GreaterThanAttrEventTrigger> extends AttrEventTrigger
    {
        protected final TYPE _min;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct event trigger and specify the MXBean attribute
         * that will be polled by this event trigger as well as min
         * value of the attribute.
         * 
         * @param objectName object name of an MBean to be polled
         * @param attributeName name of an MBean attribute to be polled
         * @param min minimum value of the attribute
         * 
         * @throws MalformedObjectNameException
         * @throws IllegalArgumentException
         */
        public GreaterThanAttrEventTrigger(String objectName, String attributeName, TYPE min)
            throws MalformedObjectNameException, IllegalArgumentException
        {
            super(objectName,attributeName);
            
            if (min == null)
                throw new IllegalArgumentException("Value cannot be null");
    
            _min = min;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Compare the value of the MXBean attribute being polling
         * to check if it is greater than the min value.
         * 
         * @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
         */
        @Override
        public boolean match(Comparable value)
        {
            return (value.compareTo(_min) > 0);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "min> extends AttrEventTrigger
    {
        protected final TYPE _min;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct event trigger and specify the MXBean attribute
         * that will be polled by this event trigger as well as min
         * value of the attribute.
         * 
         * @param objectName object name of an MBean to be polled
         * @param attributeName name of an MBean attribute to be polled
         * @param min minimum value of the attribute
         * 
         * @throws MalformedObjectNameException
         * @throws IllegalArgumentException
         */
        public GreaterThanOrEqualToAttrEventTrigger(String objectName, String attributeName, TYPE min)
            throws MalformedObjectNameException, IllegalArgumentException
        {
            super(objectName,attributeName);
            
            if (min == null)
                throw new IllegalArgumentException("Value cannot be null");
    
            _min = min;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Compare the value of the MXBean attribute being polling
         * to check if it is greater than or equal to the min value.
         * 
         * @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
         */
        @Override
        public boolean match(Comparable value)
        {
            return (value.compareTo(_min) >= 0);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "min<=name". 
         * 
         * @return string representation of the event trigger
         * 
         * @see java.lang.Object#toString()
         */
        public String toString()
        {
            StringBuilder result = new StringBuilder();
            
            result.append(_min);
            result.append("<=");
            result.append(getNameString());
            
            return result.toString();
        }
    }
    LessThanAttrEventTrigger.java000066400000000000000000000057071174773561500346400ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/triggers// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.triggers;
    
    import javax.management.MalformedObjectNameException;
    
    
    /* ------------------------------------------------------------ */
    /**
     * LessThanAttrEventTrigger
     * 
     * Event trigger that polls a value of an MXBean attribute and
     * checks if it is greater than specified max value. 
     */
    public class LessThanAttrEventTrigger> extends AttrEventTrigger
    {
        protected final TYPE _max;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct event trigger and specify the MXBean attribute
         * that will be polled by this event trigger as well as max
         * value of the attribute.
         * 
         * @param objectName object name of an MBean to be polled
         * @param attributeName name of an MBean attribute to be polled
         * @param max maximum value of the attribute
         * 
         * @throws MalformedObjectNameException
         * @throws IllegalArgumentException
         */
        public LessThanAttrEventTrigger(String objectName, String attributeName, TYPE max)
            throws MalformedObjectNameException, IllegalArgumentException
        {
            super(objectName,attributeName);
            
            if (max == null)
                throw new IllegalArgumentException("Value cannot be null");
    
            _max = max;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Compare the value of the MXBean attribute being polling
         * to check if it is less than the min value.
         * 
         * @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
         */
        @Override
        public boolean match(Comparable value)
        {
            return (value.compareTo(_max) < 0);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "name> extends AttrEventTrigger
    {
        protected final TYPE _max;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct event trigger and specify the MXBean attribute
         * that will be polled by this event trigger as well as max
         * value of the attribute.
         * 
         * @param objectName object name of an MBean to be polled
         * @param attributeName name of an MBean attribute to be polled
         * @param max maximum value of the attribute
         * 
         * @throws MalformedObjectNameException
         * @throws IllegalArgumentException
         */
        public LessThanOrEqualToAttrEventTrigger(String objectName, String attributeName, TYPE max)
            throws MalformedObjectNameException, IllegalArgumentException
        {
            super(objectName,attributeName);
            
            if (max == null)
                throw new IllegalArgumentException("Value cannot be null");
    
            _max = max;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Compare the value of the MXBean attribute being polling
         * to check if it is less than or equal to the max value.
         * 
         * @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
         */
        @Override
        public boolean match(Comparable value)
        {
            return (value.compareTo(_max) <= 0);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "name<=max". 
         * 
         * @return string representation of the event trigger
         * 
         * @see java.lang.Object#toString()
         */
        public String toString()
        {
            StringBuilder result = new StringBuilder();
            
            result.append(getNameString());
            result.append("<=");
            result.append(_max);
            
            return result.toString();
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/triggers/OrEventTrigger.java000066400000000000000000000102121174773561500327060ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor.triggers;
    
    import java.util.Arrays;
    import java.util.List;
    
    import org.eclipse.jetty.monitor.jmx.EventState;
    import org.eclipse.jetty.monitor.jmx.EventTrigger;
    
    
    /* ------------------------------------------------------------ */
    /**
     * AndEventTrigger 
     *
     * EventTrigger aggregation using logical OR operation 
     * that executes matching of the aggregated event triggers
     * in left to right order  
     */
    public class OrEventTrigger
        extends EventTrigger
    {
        private final List _triggers;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct an event trigger and associate the list 
         * of event triggers to be aggregated by this trigger
         * 
         * @param triggers list of event triggers to add
         */
        public OrEventTrigger(List triggers)
        {
            _triggers = triggers;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Construct an event trigger and associate the array 
         * of event triggers to be aggregated by this trigger
         * 
         * @param triggers array of event triggers to add
         */
        public OrEventTrigger(EventTrigger... triggers)
        {
            _triggers = Arrays.asList(triggers);
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Verify if the event trigger conditions are in the 
         * appropriate state for an event to be triggered.
         * This event trigger will match if any of aggregated 
         * event triggers would return a match.
         * 
         * @see org.eclipse.jetty.monitor.jmx.EventTrigger#match(long)
         */
        public boolean match(long timestamp)
            throws Exception
        {
            for(EventTrigger trigger : _triggers)
            {
                if (trigger.match(timestamp))
                    return true;
            }
            return false;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Retrieve the event state associated with specified invocation
         * of the event trigger match method. This event trigger retrieves
         * the combined event state of all aggregated event triggers.
         * 
         * @param timestamp time stamp associated with invocation
         * @return event state or null if not found
         *
         * @see org.eclipse.jetty.monitor.jmx.EventTrigger#getState(long)
         */
        @Override
        @SuppressWarnings("unchecked")
        public EventState getState(long timestamp)
        {
           EventState state = new EventState();
           
           for (EventTrigger trigger : _triggers)
           {
               EventState subState = trigger.getState(timestamp);
               if (subState!=null)
               {
                   state.addAll(subState.values());
               }
           }
           
           return state;
        }
        
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "OR(triger1,trigger2,...)". 
         * 
         * @return string representation of the event trigger
         * 
         * @see java.lang.Object#toString()
         */
        public String toString()
        {
            int cnt = 0;
            StringBuilder result = new StringBuilder();
            
            result.append("OR(");
            for (EventTrigger trigger : _triggers)
            {
                result.append(cnt++ > 0 ? "," : "");
                result.append(trigger);
            }
            result.append(')');
            
            return result.toString();
        }
    }
    RangeAttrEventTrigger.java000066400000000000000000000064671174773561500341570ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/triggers// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor.triggers;
    
    import javax.management.MalformedObjectNameException;
    
    
    /* ------------------------------------------------------------ */
    /**
     * RangeAttrEventTrigger
     * 
     * Event trigger that polls a value of an MXBean attribute and
     * checks if it is in a range from specified min value to
     * specified max value. 
     */
    public class RangeAttrEventTrigger> extends AttrEventTrigger
    {
        protected final TYPE _min;
        protected final TYPE _max;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct event trigger and specify the MXBean attribute
         * that will be polled by this event trigger as well as min
         * and max value of the attribute.
         * 
         * @param objectName object name of an MBean to be polled
         * @param attributeName name of an MBean attribute to be polled
         * @param min minimum value of the attribute
         * @param max maximum value of the attribute
         * 
         * @throws MalformedObjectNameException
         * @throws IllegalArgumentException
         */
        public RangeAttrEventTrigger(String objectName, String attributeName,TYPE min, TYPE max)
            throws MalformedObjectNameException, IllegalArgumentException
        {
            super(objectName,attributeName);
            
            if (min == null)
                throw new IllegalArgumentException("Value cannot be null");
            if (max == null)
                throw new IllegalArgumentException("Value cannot be null");
    
            _min = min;
            _max = max;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Compare the value of the MXBean attribute being polling
         * to check if it is in a range from specified min value to
         * specified max value. 
         * 
         * @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
         */
        @Override
        public boolean match(Comparable value)
        {
            return (value.compareTo(_min) > 0) &&(value.compareTo(_max) < 0);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "min> extends AttrEventTrigger
    {
        protected final TYPE _min;
        protected final TYPE _max;
        
        /* ------------------------------------------------------------ */
        /**
         * Construct event trigger and specify the MXBean attribute
         * that will be polled by this event trigger as well as min
         * and max value of the attribute.
         * 
         * @param objectName object name of an MBean to be polled
         * @param attributeName name of an MBean attribute to be polled
         * @param min minimum value of the attribute
         * @param max maximum value of the attribute
         * 
         * @throws MalformedObjectNameException
         * @throws IllegalArgumentException
         */
        public RangeInclAttrEventTrigger(String objectName, String attributeName,TYPE min, TYPE max)
            throws MalformedObjectNameException, IllegalArgumentException
        {
            super(objectName,attributeName);
            
            if (min == null)
                throw new IllegalArgumentException("Value cannot be null");
            if (max == null)
                throw new IllegalArgumentException("Value cannot be null");
    
            _min = min;
            _max = max;
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Compare the value of the MXBean attribute being polling
         * to check if it is in a range from specified min value to
         * specified max value including the range bounds. 
         * 
         * @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
         */
        @Override
        public boolean match(Comparable value)
        {
            return (value.compareTo(_min) >= 0) &&(value.compareTo(_max) <= 0);
        }
    
        /* ------------------------------------------------------------ */
        /**
         * Returns the string representation of this event trigger
         * in the format "min<=name<=max". 
         * 
         * @return string representation of the event trigger
         * 
         * @see java.lang.Object#toString()
         */
        public String toString()
        {
            StringBuilder result = new StringBuilder();
            
            result.append(_min);
            result.append("<=");
            result.append(getNameString());
            result.append("<=");
            result.append(_max);
            
            return result.toString();
        }
    }
    jetty8-8.1.3/jetty-monitor/src/main/resources/000077500000000000000000000000001174773561500213435ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/resources/org/000077500000000000000000000000001174773561500221325ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/resources/org/eclipse/000077500000000000000000000000001174773561500235565ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/resources/org/eclipse/jetty/000077500000000000000000000000001174773561500247155ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/resources/org/eclipse/jetty/monitor/000077500000000000000000000000001174773561500264045ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/resources/org/eclipse/jetty/monitor/integration/000077500000000000000000000000001174773561500307275ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/resources/org/eclipse/jetty/monitor/integration/jmx/000077500000000000000000000000001174773561500315255ustar00rootroot00000000000000JavaMonitorTools-mbean.properties000066400000000000000000000014151174773561500401170ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/resources/org/eclipse/jetty/monitor/integration/jmxJavaMonitorTools: Retrieves additional information required by java-monitor
    DeadlockStacktraces: RO:Detailed report on the deadlocked threads.
    ThreadsNew: RO:Number of new threads
    ThreadsRunnable: RO:Number of runnable threads
    ThreadsBlocked: RO:Number of blocked threads
    ThreadsWaiting: RO:Number of waiting threads
    ThreadsTimedWaiting: RO:Number of sleeping and waiting threads
    ThreadsTerminated: RO:Number of terminated threads
    CacheSeconds: RO:Amount of time successful DNS queries are cached for
    CacheTweakedFrom: RO:Cache policy for successful DNS lookups was changed from the hard-coded default
    CacheNegativeSeconds: RO:Amount of time failed DNS queries are cached for
    CacheNegativeTweakedFrom: RO:Cache policy for failed DNS lookups was changed from the hard-coded default
    jetty8-8.1.3/jetty-monitor/src/main/resources/org/eclipse/jetty/monitor/jmx/000077500000000000000000000000001174773561500272025ustar00rootroot00000000000000ThreadMonitor-mbean.properties000066400000000000000000000001011174773561500350700ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/main/resources/org/eclipse/jetty/monitor/jmxThreadMonitor: Detect and report spinning and deadlocked threads
    jetty8-8.1.3/jetty-monitor/src/test/000077500000000000000000000000001174773561500173645ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/java/000077500000000000000000000000001174773561500203055ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/java/org/000077500000000000000000000000001174773561500210745ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/java/org/eclipse/000077500000000000000000000000001174773561500225205ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500236575ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/java/org/eclipse/jetty/monitor/000077500000000000000000000000001174773561500253465ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/java/org/eclipse/jetty/monitor/AttrEventTriggerTest.java000066400000000000000000000405311174773561500323140ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses.
    // ========================================================================
    
    package org.eclipse.jetty.monitor;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.lang.management.ManagementFactory;
    import java.util.Collection;
    import java.util.Iterator;
    import java.util.TreeSet;
    import javax.management.MBeanServer;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.eclipse.jetty.client.ContentExchange;
    import org.eclipse.jetty.client.HttpClient;
    import org.eclipse.jetty.client.security.Realm;
    import org.eclipse.jetty.client.security.SimpleRealmResolver;
    import org.eclipse.jetty.http.HttpMethods;
    import org.eclipse.jetty.http.HttpStatus;
    import org.eclipse.jetty.jmx.MBeanContainer;
    import org.eclipse.jetty.monitor.jmx.ConsoleNotifier;
    import org.eclipse.jetty.monitor.jmx.EventNotifier;
    import org.eclipse.jetty.monitor.jmx.EventState;
    import org.eclipse.jetty.monitor.jmx.EventState.TriggerState;
    import org.eclipse.jetty.monitor.jmx.EventTrigger;
    import org.eclipse.jetty.monitor.jmx.MonitorAction;
    import org.eclipse.jetty.monitor.triggers.AndEventTrigger;
    import org.eclipse.jetty.monitor.triggers.AttrEventTrigger;
    import org.eclipse.jetty.monitor.triggers.EqualToAttrEventTrigger;
    import org.eclipse.jetty.monitor.triggers.GreaterThanAttrEventTrigger;
    import org.eclipse.jetty.monitor.triggers.GreaterThanOrEqualToAttrEventTrigger;
    import org.eclipse.jetty.monitor.triggers.LessThanAttrEventTrigger;
    import org.eclipse.jetty.monitor.triggers.LessThanOrEqualToAttrEventTrigger;
    import org.eclipse.jetty.monitor.triggers.OrEventTrigger;
    import org.eclipse.jetty.monitor.triggers.RangeAttrEventTrigger;
    import org.eclipse.jetty.monitor.triggers.RangeInclAttrEventTrigger;
    import org.eclipse.jetty.server.Request;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.handler.AbstractHandler;
    import org.eclipse.jetty.server.nio.SelectChannelConnector;
    import org.eclipse.jetty.util.log.Log;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import static org.junit.Assert.assertEquals;
    
    
    /* ------------------------------------------------------------ */
    /**
     */
    public class AttrEventTriggerTest
    {
        private Server _server;
        private TestHandler _handler;
        private RequestCounter _counter;
        private JMXMonitor _monitor;
        private HttpClient _client;
        private String _requestUrl;
    
        @Before
        public void setUp()
            throws Exception
        {
            File docRoot = new File("target/test-output/docroot/");
            docRoot.mkdirs();
            docRoot.deleteOnExit();
    
            System.setProperty("org.eclipse.jetty.util.log.DEBUG","");
            _server = new Server();
    
            SelectChannelConnector connector = new SelectChannelConnector();
            _server.addConnector(connector);
    
            _handler = new TestHandler();
            _server.setHandler(_handler);
    
            MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
            MBeanContainer mBeanContainer = new MBeanContainer(mBeanServer);
            mBeanContainer.addBean(Log.getLog());
    
            _counter = _handler.getRequestCounter();
            mBeanContainer.addBean(_counter);
    
            _server.addBean(mBeanContainer, true);
            _server.getContainer().addEventListener(mBeanContainer);
            _server.start();
    
            startClient(null);
    
            _monitor = new JMXMonitor();
    
            int port = connector.getLocalPort();
            _requestUrl = "http://localhost:"+port+ "/";
        }
    
        @After
        public void tearDown()
            throws Exception
        {
            stopClient();
    
            if (_server != null)
            {
                _server.stop();
                _server = null;
            }
        }
    
        @Test
        public void testNoCondition()
            throws Exception
        {
            long requestCount = 10;
    
            AttrEventTrigger trigger =
                new AttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter");
    
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet(1,requestCount);
            assertEquals(result, action.getHits());
        }
    
        @Test
        public void testEqual_TRUE()
            throws Exception
        {
            long requestCount = 10;
            long testValue = 5;
    
            EqualToAttrEventTrigger trigger =
                new EqualToAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",testValue);
    
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet(testValue);
            assertEquals(result, action.getHits());
        }
    
        @Test
        public void testEqual_FALSE()
            throws Exception
        {
            long requestCount = 10;
            long testValue = 11;
    
            EqualToAttrEventTrigger trigger =
                new EqualToAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                  testValue);
    
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet();
            assertEquals(result, action.getHits());
       }
    
        @Test
        public void testLowerLimit()
            throws Exception
        {
            long requestCount = 10;
            long testRangeLow = 5;
    
            GreaterThanAttrEventTrigger trigger =
                new GreaterThanAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                      testRangeLow);
    
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet(6,10);
            assertEquals(result, action.getHits());
        }
    
        @Test
        public void testLowerLimitIncl()
            throws Exception
        {
            long requestCount = 10;
            long testRangeLow = 5;
    
            GreaterThanOrEqualToAttrEventTrigger trigger =
                new GreaterThanOrEqualToAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                      testRangeLow);
    
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet(5,10);
            assertEquals(result, action.getHits());
        }
    
        @Test
        public void testUpperLimit()
            throws Exception
        {
            long requestCount = 10;
            long testRangeHigh = 5;
    
            LessThanAttrEventTrigger trigger =
                new LessThanAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                      testRangeHigh);
    
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet(1,4);
            assertEquals(result, action.getHits());
        }
    
    
        @Test
        public void testUpperLimitIncl()
            throws Exception
        {
            long requestCount = 10;
            long testRangeHigh = 5;
    
            LessThanOrEqualToAttrEventTrigger trigger =
                new LessThanOrEqualToAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                      testRangeHigh);
    
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet(1,5);
            assertEquals(result, action.getHits());
        }
    
        @Test
        public void testRangeInclusive()
            throws Exception
        {
            long requestCount = 10;
            long testRangeLow  = 3;
            long testRangeHigh = 8;
    
            RangeInclAttrEventTrigger trigger =
                new RangeInclAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                    testRangeLow, testRangeHigh);
    
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet(testRangeLow,testRangeHigh);
            assertEquals(result, action.getHits());
        }
    
        @Test
        public void testInsideRangeExclusive()
            throws Exception
        {
            long requestCount = 10;
            long testRangeLow  = 3;
            long testRangeHigh = 8;
    
            RangeAttrEventTrigger trigger =
                new RangeAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                testRangeLow, testRangeHigh);
    
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet(testRangeLow+1,testRangeHigh-1);
            assertEquals(result, action.getHits());
        }
    
        @Test
        public void testRangeComposite()
            throws Exception
        {
            long requestCount = 10;
            long testRangeLow  = 4;
            long testRangeHigh = 7;
    
            GreaterThanAttrEventTrigger trigger1 =
                new GreaterThanAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                    testRangeLow);
            LessThanOrEqualToAttrEventTrigger trigger2 =
                new LessThanOrEqualToAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                    testRangeHigh);
            AndEventTrigger trigger = new AndEventTrigger(trigger1, trigger2);
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet(testRangeLow+1,testRangeHigh);
            assertEquals(result, action.getHits());
        }
    
        @Test
        public void testRangeOuter()
            throws Exception
        {
            long requestCount = 10;
            long testRangeLow  = 4;
            long testRangeHigh = 7;
    
            LessThanOrEqualToAttrEventTrigger trigger1 =
                new LessThanOrEqualToAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                    testRangeLow);
            GreaterThanAttrEventTrigger trigger2 =
                new GreaterThanAttrEventTrigger("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
                                                    testRangeHigh);
            OrEventTrigger trigger = new OrEventTrigger(trigger1, trigger2);
            EventNotifier notifier = new ConsoleNotifier("%s");
            CounterAction action = new CounterAction(trigger, notifier, 500, 100);
    
            performTest(action, requestCount, 1000);
    
            ResultSet result = new ResultSet(1,testRangeLow,testRangeHigh+1, requestCount);
            assertEquals(result, action.getHits());
        }
    
        protected void performTest(MonitorAction action, long count, long interval)
            throws Exception
        {
            _monitor.addActions(action);
    
            for (long cnt=0; cnt < count; cnt++)
            {
                try
                {
                    ContentExchange getExchange = new ContentExchange();
                    getExchange.setURL(_requestUrl);
                    getExchange.setMethod(HttpMethods.GET);
    
                    _client.send(getExchange);
                    int state = getExchange.waitForDone();
    
                    String content = "";
                    int responseStatus = getExchange.getResponseStatus();
                    if (responseStatus == HttpStatus.OK_200)
                    {
                        content = getExchange.getResponseContent();
                    }
    
                    assertEquals(HttpStatus.OK_200,responseStatus);
                    Thread.sleep(interval);
                }
                catch (InterruptedException ex)
                {
                    break;
                }
            }
    
            Thread.sleep(interval);
    
            _monitor.removeActions(action);
        }
    
        protected void startClient(Realm realm)
            throws Exception
        {
            _client = new HttpClient();
            _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
            if (realm != null)
                _client.setRealmResolver(new SimpleRealmResolver(realm));
            _client.start();
        }
    
        protected void stopClient()
            throws Exception
        {
            if (_client != null)
            {
                _client.stop();
                _client = null;
            }
        }
    
        protected static class TestHandler
            extends AbstractHandler
        {
            private RequestCounter _counter = new RequestCounter();
    
            public void handle(String target, Request baseRequest,
                    HttpServletRequest request, HttpServletResponse response)
                throws IOException, ServletException
            {
                if (baseRequest.isHandled()) {
                    return;
                }
                _counter.increment();
    
                response.setContentType("text/plain");
                response.setStatus(HttpServletResponse.SC_OK);
                PrintWriter writer = response.getWriter();
                writer.println("===TEST RESPONSE===");
                baseRequest.setHandled(true);
            }
    
            public RequestCounter getRequestCounter()
            {
                return _counter;
            }
        }
    
        protected static class ResultSet extends TreeSet
        {
            public ResultSet() {}
    
            public ResultSet(long value)
            {
                add(value);
            }
    
            public ResultSet(long start, long end)
            {
                addEntries(start, end);
            }
    
            public ResultSet(long start, long pause, long resume, long end)
            {
                addEntries(start, pause);
                addEntries(resume, end);
            }
    
            public void addEntries(long start, long stop)
            {
                if (start > 0 && stop > 0)
                {
                    for(long idx=start; idx <= stop; idx++)
                    {
                        add(idx);
                    }
                }
            }
    
            public boolean equals(ResultSet set)
            {
                return (this.size() == set.size()) && containsAll(set);
            }
        }
    
        protected static class CounterAction
            extends MonitorAction
        {
            private ResultSet _hits = new ResultSet();
    
            public CounterAction(EventTrigger trigger, EventNotifier notifier, long interval, long delay)
            {
                super(trigger, notifier, interval, delay);
            }
    
            public void execute(EventTrigger trigger, EventState state, long timestamp)
            {
                if (trigger != null && state != null)
                {
                    Collection values = state.values();
    
                    Iterator it = values.iterator();
                    while(it.hasNext())
                    {
                        TriggerState entry = (TriggerState)it.next();
                        Object value = entry.getValue();
                        if (value != null)
                        {
                            _hits.add((Long)value);
                        }
                    }
                }
            }
    
            public ResultSet getHits()
            {
                return _hits;
            }
        }
    }
    jetty8-8.1.3/jetty-monitor/src/test/java/org/eclipse/jetty/monitor/RequestCounter.java000066400000000000000000000020411174773561500311760ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    package org.eclipse.jetty.monitor;
    
    
    public class RequestCounter
    {  
        public long _counter;
        
        public synchronized long getCounter()
        {
            return _counter;
        }
        
        public synchronized void increment()
        {
            _counter++;
        }
    
        public synchronized void reset()
        {
            _counter = 0;
        }
    }
    jetty8-8.1.3/jetty-monitor/src/test/java/org/eclipse/jetty/monitor/ThreadMonitorTest.java000066400000000000000000000111351174773561500316310ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) Webtide LLC
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    
    
    package org.eclipse.jetty.monitor;
    
    import static org.junit.Assert.assertTrue;
    
    import java.io.IOException;
    import java.util.Random;
    import java.util.concurrent.atomic.AtomicInteger;
    
    import org.eclipse.jetty.util.component.Dumpable;
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.log.StdErrLog;
    import org.junit.Test;
    
    
    /* ------------------------------------------------------------ */
    /**
     */
    public class ThreadMonitorTest
    {
        public final static int DURATION=4000;
        
        @Test
        public void monitorTest() throws Exception
        {
            ((StdErrLog)Log.getLogger(ThreadMonitor.class.getName())).setHideStacks(true);
            ((StdErrLog)Log.getLogger(ThreadMonitor.class.getName())).setSource(false);
            
            final AtomicInteger countLogs=new AtomicInteger(0);
            final AtomicInteger countSpin=new AtomicInteger(0);
            
            ThreadMonitor monitor = new ThreadMonitor(1000,50,1,1)
            {
                @Override
                protected void logThreadInfo(boolean logAll)
                {
                    if (logAll)
                        countLogs.incrementAndGet();
                    else
                        countSpin.incrementAndGet();
                    super.logThreadInfo(logAll);
                }
            };
            monitor.setDumpable(new Dumpable()
            {
                public void dump(Appendable out, String indent) throws IOException
                {
                    out.append(dump());
                }
                
                public String dump()
                {
                    return "Dump Spinning";
                }
            });
            
            monitor.logCpuUsage(2000,0);
            monitor.start();
            
            Random rnd = new Random();
            for (long cnt=0; cnt<100; cnt++)
            {
                long value = rnd.nextLong() % 50 + 50;
                Sleeper sleeper = new Sleeper(value);
                Thread runner = new Thread(sleeper);
                runner.setDaemon(true);
                runner.start();
            }
            
            Spinner spinner = new Spinner();
            Thread runner = new Thread(spinner);
            runner.start();
            
            Thread.sleep(DURATION);
                    
            spinner.setDone();
            monitor.stop();
            
            assertTrue(countLogs.get() >= 1);
            assertTrue(countSpin.get() >= 2);
        }
    
    
        private class Spinner implements Runnable
        {
            private volatile boolean done = false;
    
            /* ------------------------------------------------------------ */
            public void setDone()
            {
                done = true;
            }
    
            /* ------------------------------------------------------------ */
            public void run()
            {
                spin();
            }
    
            /* ------------------------------------------------------------ */
            public void spin()
            {
                long result=-1;
                long end=System.currentTimeMillis()+DURATION+1000;
                while (!done && System.currentTimeMillis() 1 ? fn(value-1) : 1;
                
                Thread.sleep(50);
                
                return result;
            }
        }
    }
    jetty8-8.1.3/jetty-monitor/src/test/resources/000077500000000000000000000000001174773561500213765ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/resources/org/000077500000000000000000000000001174773561500221655ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/resources/org/eclipse/000077500000000000000000000000001174773561500236115ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/resources/org/eclipse/jetty/000077500000000000000000000000001174773561500247505ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/resources/org/eclipse/jetty/monitor/000077500000000000000000000000001174773561500264375ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/resources/org/eclipse/jetty/monitor/jmx/000077500000000000000000000000001174773561500272355ustar00rootroot00000000000000RequestCounter-mbean.properties000066400000000000000000000001501174773561500353400ustar00rootroot00000000000000jetty8-8.1.3/jetty-monitor/src/test/resources/org/eclipse/jetty/monitor/jmxRequestCounter: Request counter
    counter: current value of the counter
    increment(): increment the counterjetty8-8.1.3/jetty-nested/000077500000000000000000000000001174773561500154115ustar00rootroot00000000000000jetty8-8.1.3/jetty-nested/pom.xml000066400000000000000000000040641174773561500167320ustar00rootroot00000000000000
    
      4.0.0
      
        org.eclipse.jetty
        jetty-project
        8.1.3.v20120416
      
      jetty-nested
      Jetty :: Nested
      jar
      Local Servlet Connector for jetty.
      
        ${project.groupId}.nested
      
      
        
          
            org.apache.felix
            maven-bundle-plugin
            true
            
              
                
                  manifest
                
                
                  
                    javax.servlet.*;version="2.6.0",*
                  
                
               
            
          
          
            
            org.apache.maven.plugins
            maven-jar-plugin
            
              
                ${project.build.outputDirectory}/META-INF/MANIFEST.MF
              
            
          
          
            org.codehaus.mojo
            findbugs-maven-plugin
            
              org.eclipse.jetty.nested.*
            
          
        
      
      
        
          org.eclipse.jetty
          jetty-server
          ${project.version}
        
      
    
    jetty8-8.1.3/jetty-nested/src/000077500000000000000000000000001174773561500162005ustar00rootroot00000000000000jetty8-8.1.3/jetty-nested/src/main/000077500000000000000000000000001174773561500171245ustar00rootroot00000000000000jetty8-8.1.3/jetty-nested/src/main/java/000077500000000000000000000000001174773561500200455ustar00rootroot00000000000000jetty8-8.1.3/jetty-nested/src/main/java/org/000077500000000000000000000000001174773561500206345ustar00rootroot00000000000000jetty8-8.1.3/jetty-nested/src/main/java/org/eclipse/000077500000000000000000000000001174773561500222605ustar00rootroot00000000000000jetty8-8.1.3/jetty-nested/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500234175ustar00rootroot00000000000000jetty8-8.1.3/jetty-nested/src/main/java/org/eclipse/jetty/nested/000077500000000000000000000000001174773561500247015ustar00rootroot00000000000000jetty8-8.1.3/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedConnection.java000066400000000000000000000102321174773561500310040ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd.
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    package org.eclipse.jetty.nested;
    
    import java.io.IOException;
    import java.util.Enumeration;
    
    import javax.servlet.DispatcherType;
    import javax.servlet.ServletException;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.eclipse.jetty.http.HttpFields;
    import org.eclipse.jetty.http.HttpURI;
    import org.eclipse.jetty.io.Connection;
    import org.eclipse.jetty.server.AbstractHttpConnection;
    
    
    public class NestedConnection extends AbstractHttpConnection
    {
        protected NestedConnection(final NestedConnector connector, final NestedEndPoint endp, final HttpServletRequest outerRequest, HttpServletResponse outerResponse,String nestedIn)
            throws IOException
        {
            super(connector,
                  endp,
                  connector.getServer(),
                  new NestedParser(),
                  new NestedGenerator(connector.getResponseBuffers(),endp,outerResponse,nestedIn),
                  new NestedRequest(outerRequest));
    
            ((NestedRequest)_request).setConnection(this);
            
            // Set the request line
            _request.setDispatcherType(DispatcherType.REQUEST);
            _request.setScheme(outerRequest.getScheme());
            _request.setMethod(outerRequest.getMethod());
            String uri=outerRequest.getQueryString()==null?outerRequest.getRequestURI():(outerRequest.getRequestURI()+"?"+outerRequest.getQueryString());
            _request.setUri(new HttpURI(uri));
            _request.setPathInfo(outerRequest.getRequestURI());
            _request.setQueryString(outerRequest.getQueryString());
            _request.setProtocol(outerRequest.getProtocol());
            
            // Set the headers
            HttpFields fields = getRequestFields();
            for (Enumeration e=outerRequest.getHeaderNames();e.hasMoreElements();)
            {
                String header=e.nextElement();
                String value=outerRequest.getHeader(header);
                fields.add(header,value);
            }
            
            // Let outer parse the cookies
            _request.setCookies(outerRequest.getCookies());
            
            // copy request attributes
            for (Enumeration e=outerRequest.getAttributeNames();e.hasMoreElements();)
            {
                String attr=e.nextElement();
                _request.setAttribute(attr,outerRequest.getAttribute(attr));
            }
            
            // customize the request
            connector.customize(endp,_request);
            
            // System.err.println(_request.getMethod()+" "+_request.getUri()+" "+_request.getProtocol());
            // System.err.println(fields.toString());
        }
    
        void service() throws IOException, ServletException
        {
            setCurrentConnection(this);
            try
            {
                getServer().handle(this);
                completeResponse();
                while (!_generator.isComplete() && _endp.isOpen())
                    _generator.flushBuffer();
                _endp.flush();
            }
            finally
            {
                setCurrentConnection(null);
            }
        }
    
        /* (non-Javadoc)
         * @see org.eclipse.jetty.server.HttpConnection#getInputStream()
         */
        @Override
        public ServletInputStream getInputStream() throws IOException
        {
            return ((NestedEndPoint)_endp).getServletInputStream();
        }
    
        /* (non-Javadoc)
         * @see org.eclipse.jetty.server.HttpConnection#handle()
         */
        @Override
        public Connection handle() throws IOException
        {
            throw new IllegalStateException();
        }
    
    }
    jetty8-8.1.3/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedConnector.java000066400000000000000000000054311174773561500306440ustar00rootroot00000000000000// ========================================================================
    // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd.
    // ------------------------------------------------------------------------
    // All rights reserved. This program and the accompanying materials
    // are made available under the terms of the Eclipse Public License v1.0
    // and Apache License v2.0 which accompanies this distribution.
    // The Eclipse Public License is available at 
    // http://www.eclipse.org/legal/epl-v10.html
    // The Apache License v2.0 is available at
    // http://www.opensource.org/licenses/apache2.0.php
    // You may elect to redistribute this code under either of these licenses. 
    // ========================================================================
    package org.eclipse.jetty.nested;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.eclipse.jetty.io.EndPoint;
    import org.eclipse.jetty.server.AbstractConnector;
    import org.eclipse.jetty.server.Connector;
    import org.eclipse.jetty.server.Request;
    
    /**
     * Nested Jetty Connector
     * 

    * This Jetty {@link Connector} allows a jetty instance to be nested inside another servlet container. * Requests received by the outer servlet container should be passed to jetty using the {@link #service(ServletRequest, ServletResponse)} method of this connector. * */ public class NestedConnector extends AbstractConnector { String _serverInfo; public NestedConnector() { setAcceptors(0); setForwarded(true); } public void open() throws IOException { } public void close() throws IOException { } public int getLocalPort() { return -1; } public Object getConnection() { return null; } @Override protected void accept(int acceptorID) throws IOException, InterruptedException { throw new IllegalStateException(); } /** * Service a request of the outer servlet container by passing it to the nested instance of Jetty. * @param outerRequest * @param outerResponse * @throws IOException * @throws ServletException */ public void service(ServletRequest outerRequest, ServletResponse outerResponse) throws IOException, ServletException { HttpServletRequest outerServletRequest = (HttpServletRequest)outerRequest; HttpServletResponse outerServletResponse = (HttpServletResponse)outerResponse; NestedConnection connection=new NestedConnection(this,new NestedEndPoint(outerServletRequest,outerServletResponse),outerServletRequest,outerServletResponse,_serverInfo); connection.service(); } } jetty8-8.1.3/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedEndPoint.java000066400000000000000000000040651174773561500304340ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.nested; import java.io.IOException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.io.bio.StreamEndPoint; public class NestedEndPoint extends StreamEndPoint { private final HttpServletRequest _outerRequest; public NestedEndPoint(HttpServletRequest outerRequest, HttpServletResponse outerResponse) throws IOException { super(outerRequest.getInputStream(),outerResponse.getOutputStream()); _outerRequest=outerRequest; } public ServletInputStream getServletInputStream() { return (ServletInputStream)getInputStream(); } @Override public String getLocalAddr() { return _outerRequest.getLocalAddr(); } @Override public String getLocalHost() { return _outerRequest.getLocalName(); } @Override public int getLocalPort() { return _outerRequest.getLocalPort(); } @Override public String getRemoteAddr() { return _outerRequest.getRemoteAddr(); } @Override public String getRemoteHost() { return _outerRequest.getRemoteHost(); } @Override public int getRemotePort() { return _outerRequest.getRemotePort(); } } jetty8-8.1.3/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedGenerator.java000066400000000000000000000203451174773561500306410ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.nested; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.AbstractGenerator; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.http.HttpVersions; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public class NestedGenerator extends AbstractGenerator { private static final Logger LOG = Log.getLogger(NestedGenerator.class); final HttpServletResponse _response; final String _nestedIn; public NestedGenerator(Buffers buffers, EndPoint io, HttpServletResponse response, String nestedIn) { super(buffers,io); _response=response; _nestedIn=nestedIn; } public void addContent(Buffer content, boolean last) throws IOException { LOG.debug("addContent {} {}",content.length(),last); if (_noContent) { content.clear(); return; } if (content.isImmutable()) throw new IllegalArgumentException("immutable"); if (_last || _state == STATE_END) { LOG.debug("Ignoring extra content {}", content); content.clear(); return; } _last = last; if(!_endp.isOpen()) { _state = STATE_END; return; } // Handle any unfinished business? if (_content != null && _content.length() > 0) { flushBuffer(); if (_content != null && _content.length() > 0) throw new IllegalStateException("FULL"); } _content = content; _contentWritten += content.length(); // Handle the _content if (_head) { content.clear(); _content = null; } else if (!last || _buffer!=null) { // Yes - so we better check we have a buffer initBuffer(); // Copy _content to buffer; int len = 0; len = _buffer.put(_content); // make sure there is space for a trailing null (???) if (len > 0 && _buffer.space() == 0) { len--; _buffer.setPutIndex(_buffer.putIndex() - 1); } LOG.debug("copied {} to buffer",len); _content.skip(len); if (_content.length() == 0) _content = null; } } public boolean addContent(byte b) throws IOException { // LOG.debug("addContent 1"); if (_noContent) return false; if (_last || _state == STATE_END) throw new IllegalStateException("Closed"); if(!_endp.isOpen()) { _state = STATE_END; return false; } // Handle any unfinished business? if (_content != null && _content.length() > 0) { flushBuffer(); if (_content != null && _content.length() > 0) throw new IllegalStateException("FULL"); } _contentWritten++; // Handle the _content if (_head) return false; // we better check we have a buffer initBuffer(); // Copy _content to buffer; _buffer.put(b); return _buffer.space() <= 1; } /* ------------------------------------------------------------ */ private void initBuffer() throws IOException { if (_buffer == null) { // LOG.debug("initContent"); _buffer = _buffers.getBuffer(); } } /* ------------------------------------------------------------ */ @Override public boolean isRequest() { return false; } /* ------------------------------------------------------------ */ @Override public boolean isResponse() { return true; } /* ------------------------------------------------------------ */ @Override public int prepareUncheckedAddContent() throws IOException { initBuffer(); return _buffer.space(); } /* ------------------------------------------------------------ */ @Override public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException { if (LOG.isDebugEnabled()) LOG.debug("completeHeader: {}",fields.toString().trim().replace("\r\n","|")); if (_state != STATE_HEADER) return; if (_last && !allContentAdded) throw new IllegalStateException("last?"); _last = _last | allContentAdded; if (_persistent==null) _persistent=(_version > HttpVersions.HTTP_1_0_ORDINAL); if (_reason == null) _response.setStatus(_status); else _response.setStatus(_status,_reason.toString()); if (_status == 100 || _status == 204 || _status == 304) { _noContent = true; _content = null; } boolean has_server = false; if (fields != null) { // Add headers int s=fields.size(); for (int f=0;f 100 && getSendServerVersion()) _response.setHeader(HttpHeaders.SERVER,"Jetty("+Server.getVersion()+",nested in "+_nestedIn+")"); _state = STATE_CONTENT; } /* ------------------------------------------------------------ */ /** * Complete the message. * * @throws IOException */ @Override public void complete() throws IOException { if (_state == STATE_END) return; super.complete(); if (_state < STATE_FLUSHING) _state = STATE_FLUSHING; flushBuffer(); } /* ------------------------------------------------------------ */ @Override public int flushBuffer() throws IOException { if (_state == STATE_HEADER) throw new IllegalStateException("State==HEADER"); int len = 0; if (_buffer==null) { if (_content!=null && _content.length()>0) { // flush content directly len = _endp.flush(_content); if (len>0) _content.skip(len); } } else { if (_buffer.length()==0 && _content!=null && _content.length()>0) { // Copy content to buffer _content.skip(_buffer.put(_content)); } int size=_buffer.length(); len =_endp.flush(_buffer); LOG.debug("flushBuffer {} of {}",len,size); if (len>0) _buffer.skip(len); } if (_content!=null && _content.length()==0) _content=null; if (_buffer!=null && _buffer.length()==0 && _content==null) { _buffers.returnBuffer(_buffer); _buffer=null; } if (_state==STATE_FLUSHING && _buffer==null && _content==null) _state=STATE_END; return len; } } jetty8-8.1.3/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedParser.java000066400000000000000000000027531174773561500301520ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.nested; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import org.eclipse.jetty.http.Parser; public class NestedParser implements Parser { public NestedParser() { } public void reset() { } public void returnBuffers() { } public boolean isComplete() { return false; } public boolean parseAvailable() throws IOException { return false; } public boolean isMoreInBuffer() throws IOException { return false; } public boolean isIdle() { return false; } public boolean isPersistent() { return false; } public void setPersistent(boolean persistent) { } } jetty8-8.1.3/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedRequest.java000066400000000000000000000024701174773561500303420ustar00rootroot00000000000000// ======================================================================== // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.nested; import javax.servlet.http.HttpServletRequest; import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.server.Request; public class NestedRequest extends Request { private final HttpServletRequest _outer; public NestedRequest(HttpServletRequest outer) { _outer=outer; } void setConnection(NestedConnection connection) { super.setConnection(connection); } public boolean isSecure() { return _outer.isSecure() || HttpSchemes.HTTPS.equals(getScheme()); } } jetty8-8.1.3/jetty-nosql/000077500000000000000000000000001174773561500152635ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/pom.xml000066400000000000000000000057111174773561500166040ustar00rootroot00000000000000 org.eclipse.jetty jetty-project 8.1.3.v20120416 4.0.0 jetty-nosql Jetty :: NoSQL Session Managers ${project.groupId}.nosql install org.apache.felix maven-bundle-plugin javax.servlet.*;version="2.6.0",org.eclipse.jetty.server.session.jmx;version="8.0.0";resolution:=optional,,org.eclipse.jetty.*;version="8.0.0",* true manifest org.apache.maven.plugins maven-jar-plugin artifact-jar jar ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.eclipse.jetty jetty-server ${project.version} junit junit test org.eclipse.jetty jetty-jmx ${project.version} true org.mongodb mongo-java-driver 2.6.1 jar compile org.eclipse.jetty.tests test-sessions-common ${project.version} test jetty8-8.1.3/jetty-nosql/src/000077500000000000000000000000001174773561500160525ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/000077500000000000000000000000001174773561500167765ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/java/000077500000000000000000000000001174773561500177175ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/java/org/000077500000000000000000000000001174773561500205065ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/java/org/eclipse/000077500000000000000000000000001174773561500221325ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500232715ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/000077500000000000000000000000001174773561500244255ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSession.java000066400000000000000000000122321174773561500276700ustar00rootroot00000000000000package org.eclipse.jetty.nosql; //======================================================================== //Copyright (c) 2011 Intalio, Inc. //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html //The Apache License v2.0 is available at //http://www.opensource.org/licenses/apache2.0.php //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.http.HttpServletRequest; import org.eclipse.jetty.server.session.AbstractSession; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ public class NoSqlSession extends AbstractSession { private final static Logger __log = Log.getLogger("org.eclipse.jetty.server.session"); private final NoSqlSessionManager _manager; private Set _dirty; private final AtomicInteger _active = new AtomicInteger(); private Object _version; private long _lastSync; /* ------------------------------------------------------------ */ public NoSqlSession(NoSqlSessionManager manager, HttpServletRequest request) { super(manager, request); _manager=manager; save(true); _active.incrementAndGet(); } /* ------------------------------------------------------------ */ public NoSqlSession(NoSqlSessionManager manager, long created, long accessed, String clusterId, Object version) { super(manager, created,accessed,clusterId); _manager=manager; _version=version; } /* ------------------------------------------------------------ */ @Override public Object doPutOrRemove(String name, Object value) { synchronized (this) { if (_dirty==null) _dirty=new HashSet(); _dirty.add(name); Object old = super.doPutOrRemove(name,value); if (_manager.getSavePeriod()==-2) save(true); return old; } } /* ------------------------------------------------------------ */ @Override protected void checkValid() throws IllegalStateException { super.checkValid(); } /* ------------------------------------------------------------ */ @Override protected boolean access(long time) { __log.debug("NoSqlSession:access:active "+_active); if (_active.incrementAndGet()==1) { long period=_manager.getStalePeriod()*1000L; if (period==0) refresh(); else if (period>0) { long stale=time-_lastSync; __log.debug("NoSqlSession:access:stale "+stale); if (stale>period) refresh(); } } return super.access(time); } /* ------------------------------------------------------------ */ @Override protected void complete() { super.complete(); if(_active.decrementAndGet()==0) { switch(_manager.getSavePeriod()) { case 0: save(isValid()); break; case 1: if (isDirty()) save(isValid()); break; } } } /* ------------------------------------------------------------ */ @Override protected void doInvalidate() throws IllegalStateException { super.doInvalidate(); save(false); } /* ------------------------------------------------------------ */ protected void save(boolean activateAfterSave) { synchronized (this) { _version=_manager.save(this,_version,activateAfterSave); _lastSync=getAccessed(); } } /* ------------------------------------------------------------ */ protected void refresh() { synchronized (this) { _version=_manager.refresh(this,_version); } } /* ------------------------------------------------------------ */ public boolean isDirty() { synchronized (this) { return _dirty!=null && !_dirty.isEmpty(); } } /* ------------------------------------------------------------ */ public Set takeDirty() { synchronized (this) { Set dirty=_dirty; if (dirty==null) dirty= new HashSet(); else _dirty=null; return dirty; } } /* ------------------------------------------------------------ */ public Object getVersion() { return _version; } } jetty8-8.1.3/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSessionManager.java000066400000000000000000000276541174773561500312010ustar00rootroot00000000000000package org.eclipse.jetty.nosql; //======================================================================== //Copyright (c) 2011 Intalio, Inc. //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html //The Apache License v2.0 is available at //http://www.opensource.org/licenses/apache2.0.php //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.util.ArrayList; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.servlet.http.HttpServletRequest; import org.eclipse.jetty.server.SessionManager; import org.eclipse.jetty.server.session.AbstractSession; import org.eclipse.jetty.server.session.AbstractSessionManager; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; public abstract class NoSqlSessionManager extends AbstractSessionManager implements SessionManager { private final static Logger __log = Log.getLogger("org.eclipse.jetty.server.session"); protected final ConcurrentMap _sessions=new ConcurrentHashMap(); private int _stalePeriod=0; private int _savePeriod=0; private int _idlePeriod=-1; private boolean _invalidateOnStop; private boolean _saveAllAttributes; /* ------------------------------------------------------------ */ /* (non-Javadoc) * @see org.eclipse.jetty.server.session.AbstractSessionManager#doStart() */ @Override public void doStart() throws Exception { super.doStart(); } /* ------------------------------------------------------------ */ @Override protected void addSession(AbstractSession session) { if (isRunning()) _sessions.put(session.getClusterId(),(NoSqlSession)session); } /* ------------------------------------------------------------ */ @Override public AbstractSession getSession(String idInCluster) { NoSqlSession session = _sessions.get(idInCluster); __log.debug("getSession: " + session ); if (session==null) { session=loadSession(idInCluster); if (session!=null) { NoSqlSession race=_sessions.putIfAbsent(idInCluster,session); if (race!=null) { session.willPassivate(); session.clearAttributes(); session=race; } } } return session; } /* ------------------------------------------------------------ */ @Override protected void invalidateSessions() throws Exception { // Invalidate all sessions to cause unbind events ArrayList sessions=new ArrayList(_sessions.values()); int loop=100; while (sessions.size()>0 && loop-->0) { // If we are called from doStop if (isStopping()) { // Then we only save and remove the session - it is not invalidated. for (NoSqlSession session : sessions) { session.save(false); removeSession(session,false); } } else { for (NoSqlSession session : sessions) session.invalidate(); } // check that no new sessions were created while we were iterating sessions=new ArrayList(_sessions.values()); } } /* ------------------------------------------------------------ */ @Override protected AbstractSession newSession(HttpServletRequest request) { long created=System.currentTimeMillis(); return new NoSqlSession(this,request); } /* ------------------------------------------------------------ */ @Override protected boolean removeSession(String idInCluster) { synchronized (this) { NoSqlSession session = _sessions.remove(idInCluster); try { if (session != null) { return remove(session); } } catch (Exception e) { __log.warn("Problem deleting session id=" + idInCluster,e); } return session != null; } } /* ------------------------------------------------------------ */ protected void invalidateSession( String idInCluster ) { synchronized (this) { NoSqlSession session = _sessions.remove(idInCluster); try { if (session != null) { remove(session); } } catch (Exception e) { __log.warn("Problem deleting session id=" + idInCluster,e); } } /* * ought we not go to cluster and mark it invalid? */ } /* ------------------------------------------------------------ */ /** * The State Period is the maximum time in seconds that an in memory session is allows to be stale: *

      *
    • If this period is exceeded, the DB will be checked to see if a more recent version is available.
    • *
    • If the state period is set to a value < 0, then no staleness check will be made.
    • *
    • If the state period is set to 0, then a staleness check is made whenever the active request count goes from 0 to 1.
    • *
    * @return the stalePeriod in seconds */ public int getStalePeriod() { return _stalePeriod; } /* ------------------------------------------------------------ */ /** * The State Period is the maximum time in seconds that an in memory session is allows to be stale: *
      *
    • If this period is exceeded, the DB will be checked to see if a more recent version is available.
    • *
    • If the state period is set to a value < 0, then no staleness check will be made.
    • *
    • If the state period is set to 0, then a staleness check is made whenever the active request count goes from 0 to 1.
    • *
    * @param stalePeriod the stalePeriod in seconds */ public void setStalePeriod(int stalePeriod) { _stalePeriod = stalePeriod; } /* ------------------------------------------------------------ */ /** * The Save Period is the time in seconds between saves of a dirty session to the DB. * When this period is exceeded, the a dirty session will be written to the DB:
      *
    • a save period of -2 means the session is written to the DB whenever setAttribute is called.
    • *
    • a save period of -1 means the session is never saved to the DB other than on a shutdown
    • *
    • a save period of 0 means the session is written to the DB whenever the active request count goes from 1 to 0.
    • *
    • a save period of 1 means the session is written to the DB whenever the active request count goes from 1 to 0 and the session is dirty.
    • *
    • a save period of > 1 means the session is written after that period in seconds of being dirty.
    • *
    * @return the savePeriod -2,-1,0,1 or the period in seconds >=2 */ public int getSavePeriod() { return _savePeriod; } /* ------------------------------------------------------------ */ /** * The Save Period is the time in seconds between saves of a dirty session to the DB. * When this period is exceeded, the a dirty session will be written to the DB:
      *
    • a save period of -2 means the session is written to the DB whenever setAttribute is called.
    • *
    • a save period of -1 means the session is never saved to the DB other than on a shutdown
    • *
    • a save period of 0 means the session is written to the DB whenever the active request count goes from 1 to 0.
    • *
    • a save period of 1 means the session is written to the DB whenever the active request count goes from 1 to 0 and the session is dirty.
    • *
    • a save period of > 1 means the session is written after that period in seconds of being dirty.
    • *
    * @param savePeriod the savePeriod -2,-1,0,1 or the period in seconds >=2 */ public void setSavePeriod(int savePeriod) { _savePeriod = savePeriod; } /* ------------------------------------------------------------ */ /** * The Idle Period is the time in seconds before an in memory session is passivated. * When this period is exceeded, the session will be passivated and removed from memory. If the session was dirty, it will be written to the DB. * If the idle period is set to a value < 0, then the session is never idled. * If the save period is set to 0, then the session is idled whenever the active request count goes from 1 to 0. * @return the idlePeriod */ public int getIdlePeriod() { return _idlePeriod; } /* ------------------------------------------------------------ */ /** * The Idle Period is the time in seconds before an in memory session is passivated. * When this period is exceeded, the session will be passivated and removed from memory. If the session was dirty, it will be written to the DB. * If the idle period is set to a value < 0, then the session is never idled. * If the save period is set to 0, then the session is idled whenever the active request count goes from 1 to 0. * @param idlePeriod the idlePeriod in seconds */ public void setIdlePeriod(int idlePeriod) { _idlePeriod = idlePeriod; } /* ------------------------------------------------------------ */ /** * Invalidate sessions when the session manager is stopped otherwise save them to the DB. * @return the invalidateOnStop */ public boolean isInvalidateOnStop() { return _invalidateOnStop; } /* ------------------------------------------------------------ */ /** * Invalidate sessions when the session manager is stopped otherwise save them to the DB. * @param invalidateOnStop the invalidateOnStop to set */ public void setInvalidateOnStop(boolean invalidateOnStop) { _invalidateOnStop = invalidateOnStop; } /* ------------------------------------------------------------ */ /** * Save all attributes of a session or only update the dirty attributes. * @return the saveAllAttributes */ public boolean isSaveAllAttributes() { return _saveAllAttributes; } /* ------------------------------------------------------------ */ /** * Save all attributes of a session or only update the dirty attributes. * @param saveAllAttributes the saveAllAttributes to set */ public void setSaveAllAttributes(boolean saveAllAttributes) { _saveAllAttributes = saveAllAttributes; } /* ------------------------------------------------------------ */ abstract protected NoSqlSession loadSession(String clusterId); /* ------------------------------------------------------------ */ abstract protected Object save(NoSqlSession session,Object version, boolean activateAfterSave); /* ------------------------------------------------------------ */ abstract protected Object refresh(NoSqlSession session, Object version); /* ------------------------------------------------------------ */ abstract protected boolean remove(NoSqlSession session); } jetty8-8.1.3/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/000077500000000000000000000000001174773561500260525ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionIdManager.java000066400000000000000000000423421174773561500331150ustar00rootroot00000000000000package org.eclipse.jetty.nosql.mongodb; //======================================================================== //Copyright (c) 2011 Intalio, Inc. //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html //The Apache License v2.0 is available at //http://www.opensource.org/licenses/apache2.0.php //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.net.UnknownHostException; import java.util.HashSet; import java.util.Random; import java.util.Set; import java.util.Timer; import java.util.TimerTask; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.SessionManager; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.session.AbstractSessionIdManager; import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import com.mongodb.BasicDBObject; import com.mongodb.BasicDBObjectBuilder; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.Mongo; import com.mongodb.MongoException; /** * Based partially on the jdbc session id manager... * * Theory is that we really only need the session id manager for the local * instance so we have something to scavenge on, namely the list of known ids * * this class has a timer that runs at the scavenge delay that runs a query * for all id's known to this node and that have and old accessed value greater * then the scavengeDelay. * * these found sessions are then run through the invalidateAll(id) method that * is a bit hinky but is supposed to notify all handlers this id is now DOA and * ought to be cleaned up. this ought to result in a save operation on the session * that will change the valid field to false (this conjecture is unvalidated atm) */ public class MongoSessionIdManager extends AbstractSessionIdManager { private final static Logger __log = Log.getLogger("org.eclipse.jetty.server.session"); final static DBObject __version_1 = new BasicDBObject(MongoSessionManager.__VERSION,1); final static DBObject __valid_false = new BasicDBObject(MongoSessionManager.__VALID,false); final static DBObject __valid_true = new BasicDBObject(MongoSessionManager.__VALID,true); final DBCollection _sessions; protected Server _server; private Timer _scavengeTimer; private Timer _purgeTimer; private TimerTask _scavengerTask; private TimerTask _purgeTask; private long _scavengeDelay = 30 * 60 * 1000; // every 30 minutes private long _scavengePeriod = 10 * 6 * 1000; // wait at least 10 minutes /** * purge process is enabled by default */ private boolean _purge = true; /** * purge process would run daily by default */ private long _purgeDelay = 24 * 60 * 60 * 1000; // every day /** * how long do you want to persist sessions that are no longer * valid before removing them completely */ private long _purgeInvalidAge = 24 * 60 * 60 * 1000; // default 1 day /** * how long do you want to leave sessions that are still valid before * assuming they are dead and removing them */ private long _purgeValidAge = 7 * 24 * 60 * 60 * 1000; // default 1 week /** * the collection of session ids known to this manager * * TODO consider if this ought to be concurrent or not */ protected final Set _sessionsIds = new HashSet(); /* ------------------------------------------------------------ */ public MongoSessionIdManager(Server server) throws UnknownHostException, MongoException { this(server, new Mongo().getDB("HttpSessions").getCollection("sessions")); } /* ------------------------------------------------------------ */ public MongoSessionIdManager(Server server, DBCollection sessions) { super(new Random()); _server = server; _sessions = sessions; _sessions.ensureIndex( BasicDBObjectBuilder.start().add("id",1).get(), BasicDBObjectBuilder.start().add("unique",true).add("sparse",false).get()); _sessions.ensureIndex( BasicDBObjectBuilder.start().add("id",1).add("version",1).get(), BasicDBObjectBuilder.start().add("unique",true).add("sparse",false).get()); } /* ------------------------------------------------------------ */ /** * Scavenge is a process that periodically checks the tracked session * ids of this given instance of the session id manager to see if they * are past the point of expiration. */ protected void scavenge() { __log.debug("SessionIdManager:scavenge:called with delay" + _scavengeDelay); synchronized (_sessionsIds) { /* * run a query returning results that: * - are in the known list of sessionIds * - have an accessed time less then current time - the scavenger period * * we limit the query to return just the __ID so we are not sucking back full sessions */ BasicDBObject query = new BasicDBObject(); query.put(MongoSessionManager.__ID,new BasicDBObject("$in", _sessionsIds )); query.put(MongoSessionManager.__ACCESSED, new BasicDBObject("$lt",System.currentTimeMillis() - _scavengeDelay)); DBCursor checkSessions = _sessions.find(query, new BasicDBObject(MongoSessionManager.__ID, 1)); for ( DBObject session : checkSessions ) { __log.debug("SessionIdManager:scavenge: invalidating " + (String)session.get(MongoSessionManager.__ID)); invalidateAll((String)session.get(MongoSessionManager.__ID)); } } } /* ------------------------------------------------------------ */ /** * ScavengeFully is a process that periodically checks the tracked session * ids of this given instance of the session id manager to see if they * are past the point of expiration. * * NOTE: this is potentially devastating and may lead to serious session * coherence issues, not to be used in a running cluster */ protected void scavengeFully() { __log.debug("SessionIdManager:scavengeFully"); DBCursor checkSessions = _sessions.find(); for (DBObject session : checkSessions) { invalidateAll((String)session.get(MongoSessionManager.__ID)); } } /* ------------------------------------------------------------ */ /** * Purge is a process that cleans the mongodb cluster of old sessions that are no * longer valid. * * There are two checks being done here: * * - if the accessed time is older then the current time minus the purge invalid age * and it is no longer valid then remove that session * - if the accessed time is older then the current time minus the purge valid age * then we consider this a lost record and remove it * * NOTE: if your system supports long lived sessions then the purge valid age should be * set to zero so the check is skipped. * * The second check was added to catch sessions that were being managed on machines * that might have crashed without marking their sessions as 'valid=false' */ protected void purge() { BasicDBObject invalidQuery = new BasicDBObject(); invalidQuery.put(MongoSessionManager.__ACCESSED, new BasicDBObject("$lt",System.currentTimeMillis() - _purgeInvalidAge)); invalidQuery.put(MongoSessionManager.__VALID, __valid_false); DBCursor oldSessions = _sessions.find(invalidQuery, new BasicDBObject(MongoSessionManager.__ID, 1)); for (DBObject session : oldSessions) { String id = (String)session.get("id"); __log.debug("MongoSessionIdManager:purging invalid " + id); _sessions.remove(session); } if (_purgeValidAge != 0) { BasicDBObject validQuery = new BasicDBObject(); validQuery.put(MongoSessionManager.__ACCESSED,new BasicDBObject("$lt",System.currentTimeMillis() - _purgeValidAge)); validQuery.put(MongoSessionManager.__VALID, __valid_false); oldSessions = _sessions.find(invalidQuery,new BasicDBObject(MongoSessionManager.__ID,1)); for (DBObject session : oldSessions) { String id = (String)session.get(MongoSessionManager.__ID); __log.debug("MongoSessionIdManager:purging valid " + id); _sessions.remove(session); } } } /* ------------------------------------------------------------ */ /** * Purge is a process that cleans the mongodb cluster of old sessions that are no * longer valid. * */ protected void purgeFully() { BasicDBObject invalidQuery = new BasicDBObject(); invalidQuery.put(MongoSessionManager.__VALID, false); DBCursor oldSessions = _sessions.find(invalidQuery, new BasicDBObject(MongoSessionManager.__ID, 1)); for (DBObject session : oldSessions) { String id = (String)session.get(MongoSessionManager.__ID); __log.debug("MongoSessionIdManager:purging invalid " + id); _sessions.remove(session); } } /* ------------------------------------------------------------ */ public DBCollection getSessions() { return _sessions; } /* ------------------------------------------------------------ */ public boolean isPurgeEnabled() { return _purge; } /* ------------------------------------------------------------ */ public void setPurge(boolean purge) { this._purge = purge; } /* ------------------------------------------------------------ */ /** * sets the scavengeDelay */ public void setScavengeDelay(long scavengeDelay) { this._scavengeDelay = scavengeDelay; } /* ------------------------------------------------------------ */ public void setScavengePeriod(long scavengePeriod) { this._scavengePeriod = scavengePeriod; } /* ------------------------------------------------------------ */ public void setPurgeDelay(long purgeDelay) { if ( isRunning() ) { throw new IllegalStateException(); } this._purgeDelay = purgeDelay; } /* ------------------------------------------------------------ */ public long getPurgeInvalidAge() { return _purgeInvalidAge; } /* ------------------------------------------------------------ */ /** * sets how old a session is to be persisted past the point it is * no longer valid */ public void setPurgeInvalidAge(long purgeValidAge) { this._purgeInvalidAge = purgeValidAge; } /* ------------------------------------------------------------ */ public long getPurgeValidAge() { return _purgeValidAge; } /* ------------------------------------------------------------ */ /** * sets how old a session is to be persist past the point it is * considered no longer viable and should be removed * * NOTE: set this value to 0 to disable purging of valid sessions */ public void setPurgeValidAge(long purgeValidAge) { this._purgeValidAge = purgeValidAge; } /* ------------------------------------------------------------ */ @Override protected void doStart() throws Exception { __log.debug("MongoSessionIdManager:starting"); /* * setup the scavenger thread */ if (_scavengeDelay > 0) { _scavengeTimer = new Timer("MongoSessionIdScavenger",true); synchronized (this) { if (_scavengerTask != null) { _scavengerTask.cancel(); } _scavengerTask = new TimerTask() { @Override public void run() { scavenge(); } }; _scavengeTimer.schedule(_scavengerTask,_scavengeDelay,_scavengePeriod); } } /* * if purging is enabled, setup the purge thread */ if ( _purge ) { _purgeTimer = new Timer("MongoSessionPurger", true); synchronized (this) { if (_purgeTask != null) { _purgeTask.cancel(); } _purgeTask = new TimerTask() { @Override public void run() { purge(); } }; _purgeTimer.schedule(_purgeTask,_purgeDelay); } } } /* ------------------------------------------------------------ */ @Override protected void doStop() throws Exception { if (_scavengeTimer != null) { _scavengeTimer.cancel(); _scavengeTimer = null; } if (_purgeTimer != null) { _purgeTimer.cancel(); _purgeTimer = null; } super.doStop(); } /* ------------------------------------------------------------ */ /** * is the session id known to mongo, and is it valid */ public boolean idInUse(String sessionId) { /* * optimize this query to only return the valid variable */ DBObject o = _sessions.findOne(new BasicDBObject("id",sessionId), __valid_true); if ( o != null ) { Boolean valid = (Boolean)o.get(MongoSessionManager.__VALID); if ( valid == null ) { return false; } return valid; } return false; } /* ------------------------------------------------------------ */ public void addSession(HttpSession session) { if (session == null) { return; } /* * already a part of the index in mongo... */ __log.debug("MongoSessionIdManager:addSession:" + session.getId()); synchronized (_sessionsIds) { _sessionsIds.add(session.getId()); } } /* ------------------------------------------------------------ */ public void removeSession(HttpSession session) { if (session == null) { return; } synchronized (_sessionsIds) { _sessionsIds.remove(session.getId()); } } /* ------------------------------------------------------------ */ public void invalidateAll(String sessionId) { synchronized (_sessionsIds) { _sessionsIds.remove(sessionId); //tell all contexts that may have a session object with this id to //get rid of them Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class); for (int i=0; contexts!=null && i0)?nodeId.substring(0,dot):nodeId; } /* ------------------------------------------------------------ */ // TODO not sure if this is correct public String getNodeId(String clusterId, HttpServletRequest request) { if (_workerName!=null) return clusterId+'.'+_workerName; return clusterId; } } jetty8-8.1.3/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java000066400000000000000000000455601174773561500326450ustar00rootroot00000000000000package org.eclipse.jetty.nosql.mongodb; //======================================================================== //Copyright (c) 2011 Intalio, Inc. //------------------------------------------------------------------------ //All rights reserved. This program and the accompanying materials //are made available under the terms of the Eclipse Public License v1.0 //and Apache License v2.0 which accompanies this distribution. //The Eclipse Public License is available at //http://www.eclipse.org/legal/epl-v10.html //The Apache License v2.0 is available at //http://www.opensource.org/licenses/apache2.0.php //You may elect to redistribute this code under either of these licenses. //======================================================================== import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.UnknownHostException; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.eclipse.jetty.nosql.NoSqlSession; import org.eclipse.jetty.nosql.NoSqlSessionManager; import org.eclipse.jetty.server.SessionIdManager; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import com.mongodb.BasicDBObject; import com.mongodb.DBCollection; import com.mongodb.DBObject; import com.mongodb.MongoException; public class MongoSessionManager extends NoSqlSessionManager { private static final Logger LOG = Log.getLogger(MongoSessionManager.class); private final static Logger __log = Log.getLogger("org.eclipse.jetty.server.session"); /* * strings used as keys or parts of keys in mongo */ private final static String __METADATA = "__metadata__"; public final static String __ID = "id"; private final static String __CREATED = "created"; public final static String __VALID = "valid"; public final static String __INVALIDATED = "invalidated"; public final static String __ACCESSED = "accessed"; private final static String __CONTEXT = "context"; public final static String __VERSION = __METADATA + ".version"; /** * the context id is only set when this class has been started */ private String _contextId = null; private DBCollection _sessions; private DBObject __version_1; /* ------------------------------------------------------------ */ public MongoSessionManager() throws UnknownHostException, MongoException { } /*------------------------------------------------------------ */ @Override public void doStart() throws Exception { super.doStart(); String[] hosts = getContextHandler().getVirtualHosts(); if (hosts == null || hosts.length == 0) hosts = getContextHandler().getConnectorNames(); if (hosts == null || hosts.length == 0) hosts = new String[] { "::" }; // IPv6 equiv of 0.0.0.0 String contextPath = getContext().getContextPath(); if (contextPath == null || "".equals(contextPath)) { contextPath = "*"; } _contextId = createContextId(hosts,contextPath); __version_1 = new BasicDBObject(getContextKey(__VERSION),1); } /* ------------------------------------------------------------ */ /* (non-Javadoc) * @see org.eclipse.jetty.server.session.AbstractSessionManager#setSessionIdManager(org.eclipse.jetty.server.SessionIdManager) */ @Override public void setSessionIdManager(SessionIdManager metaManager) { MongoSessionIdManager msim = (MongoSessionIdManager)metaManager; _sessions=msim.getSessions(); super.setSessionIdManager(metaManager); } /* ------------------------------------------------------------ */ @Override protected synchronized Object save(NoSqlSession session, Object version, boolean activateAfterSave) { try { __log.debug("MongoSessionManager:save:" + session); session.willPassivate(); // Form query for upsert BasicDBObject key = new BasicDBObject(__ID,session.getClusterId()); // Form updates BasicDBObject update = new BasicDBObject(); boolean upsert = false; BasicDBObject sets = new BasicDBObject(); BasicDBObject unsets = new BasicDBObject(); // handle new or existing if (version == null) { // New session upsert = true; version = new Long(1); sets.put(__CREATED,session.getCreationTime()); sets.put(__VALID,true); sets.put(getContextKey(__VERSION),version); } else { version = new Long(((Long)version).intValue() + 1); update.put("$inc",__version_1); } // handle valid or invalid if (session.isValid()) { sets.put(__ACCESSED,session.getAccessed()); Set names = session.takeDirty(); if (isSaveAllAttributes() || upsert) { names.addAll(session.getNames()); // note dirty may include removed names } for (String name : names) { Object value = session.getAttribute(name); if (value == null) unsets.put(getContextKey() + "." + encodeName(name),1); else sets.put(getContextKey() + "." + encodeName(name),encodeName(value)); } } else { sets.put(__VALID,false); sets.put(__INVALIDATED, System.currentTimeMillis()); unsets.put(getContextKey(),1); } // Do the upsert if (!sets.isEmpty()) update.put("$set",sets); if (!unsets.isEmpty()) update.put("$unset",unsets); _sessions.update(key,update,upsert,false); __log.debug("MongoSessionManager:save:db.sessions.update(" + key + "," + update + ",true)"); if (activateAfterSave) session.didActivate(); return version; } catch (Exception e) { LOG.warn(e); } return null; } /*------------------------------------------------------------ */ @Override protected Object refresh(NoSqlSession session, Object version) { __log.debug("MongoSessionManager:refresh " + session); // check if our in memory version is the same as what is on the disk if (version != null) { DBObject o = _sessions.findOne(new BasicDBObject(__ID,session.getClusterId()),__version_1); if (o != null) { Object saved = getNestedValue(o, getContextKey(__VERSION)); if (saved != null && saved.equals(version)) { __log.debug("MongoSessionManager:refresh not needed"); return version; } version = saved; } } // If we are here, we have to load the object DBObject o = _sessions.findOne(new BasicDBObject(__ID,session.getClusterId())); // If it doesn't exist, invalidate if (o == null) { __log.debug("MongoSessionManager:refresh:marking invalid, no object"); session.invalidate(); return null; } // If it has been flagged invalid, invalidate Boolean valid = (Boolean)o.get(__VALID); if (valid == null || !valid) { __log.debug("MongoSessionManager:refresh:marking invalid, valid flag " + valid); session.invalidate(); return null; } // We need to update the attributes. We will model this as a passivate, // followed by bindings and then activation. session.willPassivate(); try { session.clearAttributes(); DBObject attrs = (DBObject)getNestedValue(o,getContextKey()); if (attrs != null) { for (String name : attrs.keySet()) { if (__METADATA.equals(name)) { continue; } String attr = decodeName(name); Object value = decodeValue(attrs.get(name)); if (attrs.keySet().contains(name)) { session.doPutOrRemove(attr,value); session.bindValue(attr,value); } else { session.doPutOrRemove(attr,value); } } // cleanup, remove values from session, that don't exist in data anymore: for (String name : session.getNames()) { if (!attrs.keySet().contains(name)) { session.doPutOrRemove(name,null); session.unbindValue(name,session.getAttribute(name)); } } } session.didActivate(); return version; } catch (Exception e) { LOG.warn(e); } return null; } /*------------------------------------------------------------ */ @Override protected synchronized NoSqlSession loadSession(String clusterId) { DBObject o = _sessions.findOne(new BasicDBObject(__ID,clusterId)); __log.debug("MongoSessionManager:loaded " + o); if (o == null) { return null; } Boolean valid = (Boolean)o.get(__VALID); if (valid == null || !valid) { return null; } try { Object version = o.get(getContextKey(__VERSION)); Long created = (Long)o.get(__CREATED); Long accessed = (Long)o.get(__ACCESSED); NoSqlSession session = new NoSqlSession(this,created,accessed,clusterId,version); // get the attributes for the context DBObject attrs = (DBObject)getNestedValue(o,getContextKey()); __log.debug("MongoSessionManager:attrs: " + attrs); if (attrs != null) { for (String name : attrs.keySet()) { if ( __METADATA.equals(name) ) { continue; } String attr = decodeName(name); Object value = decodeValue(attrs.get(name)); session.doPutOrRemove(attr,value); session.bindValue(attr,value); } } session.didActivate(); return session; } catch (Exception e) { LOG.warn(e); } return null; } /*------------------------------------------------------------ */ @Override protected boolean remove(NoSqlSession session) { __log.debug("MongoSessionManager:remove:session " + session.getClusterId()); /* * Check if the session exists and if it does remove the context * associated with this session */ BasicDBObject key = new BasicDBObject(__ID,session.getClusterId()); DBObject o = _sessions.findOne(key,__version_1); if (o != null) { BasicDBObject remove = new BasicDBObject(); BasicDBObject unsets = new BasicDBObject(); unsets.put(getContextKey(),1); remove.put("$unset",unsets); _sessions.update(key,remove); return true; } else { return false; } } /*------------------------------------------------------------ */ @Override protected void invalidateSession(String idInCluster) { __log.debug("MongoSessionManager:invalidateSession:invalidating " + idInCluster); super.invalidateSession(idInCluster); /* * pull back the 'valid' value, we can check if its false, if is we don't need to * reset it to false */ DBObject validKey = new BasicDBObject(__VALID, true); DBObject o = _sessions.findOne(new BasicDBObject(__ID,idInCluster), validKey); if (o != null && (Boolean)o.get(__VALID)) { BasicDBObject update = new BasicDBObject(); BasicDBObject sets = new BasicDBObject(); sets.put(__VALID,false); sets.put(__INVALIDATED, System.currentTimeMillis()); update.put("$set",sets); BasicDBObject key = new BasicDBObject(__ID,idInCluster); _sessions.update(key,update); } } /*------------------------------------------------------------ */ protected String encodeName(String name) { return name.replace("%","%25").replace(".","%2E"); } /*------------------------------------------------------------ */ protected String decodeName(String name) { return name.replace("%2E",".").replace("%25","%"); } /*------------------------------------------------------------ */ protected Object encodeName(Object value) throws IOException { if (value instanceof Number || value instanceof String || value instanceof Boolean || value instanceof Date) { return value; } else if (value.getClass().equals(HashMap.class)) { BasicDBObject o = new BasicDBObject(); for (Map.Entry entry : ((Map)value).entrySet()) { if (!(entry.getKey() instanceof String)) { o = null; break; } o.append(encodeName(entry.getKey().toString()),encodeName(entry.getValue())); } if (o != null) return o; } ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bout); out.reset(); out.writeUnshared(value); out.flush(); return bout.toByteArray(); } /*------------------------------------------------------------ */ protected Object decodeValue(final Object valueToDecode) throws IOException, ClassNotFoundException { if (valueToDecode == null || valueToDecode instanceof Number || valueToDecode instanceof String || valueToDecode instanceof Boolean || valueToDecode instanceof Date) { return valueToDecode; } else if (valueToDecode instanceof byte[]) { final byte[] decodeObject = (byte[])valueToDecode; final ByteArrayInputStream bais = new ByteArrayInputStream(decodeObject); final ClassLoadingObjectInputStream objectInputStream = new ClassLoadingObjectInputStream(bais); return objectInputStream.readUnshared(); } else if (valueToDecode instanceof DBObject) { Map map = new HashMap(); for (String name : ((DBObject)valueToDecode).keySet()) { String attr = decodeName(name); map.put(attr,decodeValue(((DBObject)valueToDecode).get(name))); } return map; } else { throw new IllegalStateException(valueToDecode.getClass().toString()); } } /*------------------------------------------------------------ */ private String getContextKey() { return __CONTEXT + "." + _contextId; } /*------------------------------------------------------------ */ private String getContextKey(String keybit) { return __CONTEXT + "." + _contextId + "." + keybit; } public void purge() { ((MongoSessionIdManager)_sessionIdManager).purge(); } public void purgeFully() { ((MongoSessionIdManager)_sessionIdManager).purgeFully(); } public void scavenge() { ((MongoSessionIdManager)_sessionIdManager).scavenge(); } public void scavengeFully() { ((MongoSessionIdManager)_sessionIdManager).scavengeFully(); } /*------------------------------------------------------------ */ /** * returns the total number of session objects in the session store * * the count() operation itself is optimized to perform on the server side * and avoid loading to client side. */ public long getSessionStoreCount() { return _sessions.find().count(); } /*------------------------------------------------------------ */ /** * MongoDB keys are . delimited for nesting so .'s are protected characters * * @param virtualHosts * @param contextPath * @return */ private String createContextId(String[] virtualHosts, String contextPath) { String contextId = virtualHosts[0] + contextPath; contextId.replace('/', '_'); contextId.replace('.','_'); contextId.replace('\\','_'); return contextId; } /** * Dig through a given dbObject for the nested value */ private Object getNestedValue(DBObject dbObject, String nestedKey) { String[] keyChain = nestedKey.split("\\."); DBObject temp = dbObject; for (int i = 0; i < keyChain.length - 1; ++i) { temp = (DBObject)temp.get(keyChain[i]); if ( temp == null ) { return null; } } return temp.get(keyChain[keyChain.length - 1]); } /** * ClassLoadingObjectInputStream * * */ protected class ClassLoadingObjectInputStream extends ObjectInputStream { public ClassLoadingObjectInputStream(java.io.InputStream in) throws IOException { super(in); } public ClassLoadingObjectInputStream () throws IOException { super(); } @Override public Class resolveClass (java.io.ObjectStreamClass cl) throws IOException, ClassNotFoundException { try { return Class.forName(cl.getName(), false, Thread.currentThread().getContextClassLoader()); } catch (ClassNotFoundException e) { return super.resolveClass(cl); } } } } jetty8-8.1.3/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/000077500000000000000000000000001174773561500266505ustar00rootroot00000000000000MongoSessionManagerMBean.java000066400000000000000000000030241174773561500342540ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmxpackage org.eclipse.jetty.nosql.mongodb.jmx; import org.eclipse.jetty.nosql.mongodb.MongoSessionManager; import org.eclipse.jetty.server.handler.AbstractHandlerContainer; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.session.AbstractSessionManager; import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.server.session.jmx.AbstractSessionManagerMBean; public class MongoSessionManagerMBean extends AbstractSessionManagerMBean { public MongoSessionManagerMBean(Object managedObject) { super(managedObject); } /* ------------------------------------------------------------ */ public String getObjectContextBasis() { if (_managed != null && _managed instanceof MongoSessionManager) { MongoSessionManager manager = (MongoSessionManager)_managed; String basis = null; SessionHandler handler = manager.getSessionHandler(); if (handler != null) { ContextHandler context = AbstractHandlerContainer.findContainerOf(handler.getServer(), ContextHandler.class, handler); if (context != null) basis = getContextName(context); } if (basis != null) return basis; } return super.getObjectContextBasis(); } } jetty8-8.1.3/jetty-nosql/src/main/resources/000077500000000000000000000000001174773561500210105ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/resources/org/000077500000000000000000000000001174773561500215775ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/resources/org/eclipse/000077500000000000000000000000001174773561500232235ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/resources/org/eclipse/jetty/000077500000000000000000000000001174773561500243625ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/resources/org/eclipse/jetty/nosql/000077500000000000000000000000001174773561500255165ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/resources/org/eclipse/jetty/nosql/mongodb/000077500000000000000000000000001174773561500271435ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/resources/org/eclipse/jetty/nosql/mongodb/jmx/000077500000000000000000000000001174773561500277415ustar00rootroot00000000000000MongoSessionManager-mbean.properties000066400000000000000000000006541174773561500370030ustar00rootroot00000000000000jetty8-8.1.3/jetty-nosql/src/main/resources/org/eclipse/jetty/nosql/mongodb/jmxMongoSessionManager: Mongo Session Manager sessionStoreCount: total number of known sessions in the store purge(): force a purge() of invalid sessions in the session store based on normal criteria purgeFully(): force a full purge of invalid sessions in the session store scavenge(): force a scavenge() of sessions known to this manager in the session store scavengeFully(): force a scavenge of all sessions in the session store jetty8-8.1.3/jetty-npn/000077500000000000000000000000001174773561500147225ustar00rootroot00000000000000jetty8-8.1.3/jetty-npn/pom.xml000066400000000000000000000026721174773561500162460ustar00rootroot00000000000000 org.eclipse.jetty jetty-parent 19 4.0.0 org.eclipse.jetty.npn npn-api 1.0.1-SNAPSHOT Jetty :: Next Protocol Negotiation :: API scm:git:http://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git scm:git:ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/jetty-npn org.apache.maven.plugins maven-release-plugin 2.2.1 false deploy -Peclipse-release clean install jetty8-8.1.3/jetty-npn/src/000077500000000000000000000000001174773561500155115ustar00rootroot00000000000000jetty8-8.1.3/jetty-npn/src/main/000077500000000000000000000000001174773561500164355ustar00rootroot00000000000000jetty8-8.1.3/jetty-npn/src/main/java/000077500000000000000000000000001174773561500173565ustar00rootroot00000000000000jetty8-8.1.3/jetty-npn/src/main/java/org/000077500000000000000000000000001174773561500201455ustar00rootroot00000000000000jetty8-8.1.3/jetty-npn/src/main/java/org/eclipse/000077500000000000000000000000001174773561500215715ustar00rootroot00000000000000jetty8-8.1.3/jetty-npn/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500227305ustar00rootroot00000000000000jetty8-8.1.3/jetty-npn/src/main/java/org/eclipse/jetty/npn/000077500000000000000000000000001174773561500235235ustar00rootroot00000000000000jetty8-8.1.3/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java000066400000000000000000000157361174773561500271550ustar00rootroot00000000000000/* * Copyright (c) 2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.eclipse.jetty.npn; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.WeakHashMap; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSocket; /** *

    {@link NextProtoNego} provides an API to applications that want to make use of the * Next Protocol Negotiation.

    *

    The NPN extension is only available when using the TLS protocol, therefore applications must * ensure that the TLS protocol is used:

    *
     * SSLContext context = SSLContext.getInstance("TLSv1");
     * 
    *

    Refer to the * list * of standard SSLContext protocol names for further information on TLS protocol versions supported.

    *

    Applications must register instances of either {@link SSLSocket} or {@link SSLEngine} with a * {@link ClientProvider} or with a {@link ServerProvider}, depending whether they are on client or * server side.

    *

    The NPN implementation will invoke the provider callbacks to allow applications to interact * with the negotiation of the next protocol.

    *

    Client side typical usage:

    *
     * SSLSocket sslSocket = ...;
     * NextProtoNego.put(sslSocket, new NextProtoNego.ClientProvider()
     * {
     *     @Override
     *     public boolean supports()
     *     {
     *         return true;
     *     }
     *
     *     @Override
     *     public void unsupported()
     *     {
     *     }
     *
     *     @Override
     *     public String selectProtocol(List<String> protocols)
     *     {
     *         return protocols.get(0);
     *     }
     *  });
     * 
    *

    Server side typical usage:

    *
     * SSLSocket sslSocket = ...;
     * NextProtoNego.put(sslSocket, new NextProtoNego.ServerProvider()
     * {
     *     @Override
     *     public void unsupported()
     *     {
     *     }
     *
     *     @Override
     *     public List protocols()
     *     {
     *         return Arrays.asList("http/1.1");
     *     }
     *
     *     @Override
     *     public void protocolSelected(String protocol)
     *     {
     *         System.out.println("Protocol Selected is: " + protocol);
     *     }
     *  });
     * 
    *

    There is no need to unregister {@link SSLSocket} or {@link SSLEngine} instances, as they * are kept in a {@link WeakHashMap} and will be garbage collected when the application does not * hard reference them anymore.

    *

    In order to help application development, you can set the {@link NextProtoNego#debug} field * to {@code true} to have debug code printed to {@link System#err}.

    */ public class NextProtoNego { /** *

    Enables debug logging on {@link System#err}.

    */ public static boolean debug = false; private static Map objects = Collections.synchronizedMap(new WeakHashMap()); private NextProtoNego() { } /** *

    Registers a SSLSocket with a provider.

    * * @param socket the socket to register with the provider * @param provider the provider to register with the socket */ public static void put(SSLSocket socket, Provider provider) { objects.put(socket, provider); } /** * @param socket a socket registered with {@link #put(SSLSocket, Provider)} * @return the provider registered with the given socket */ public static Provider get(SSLSocket socket) { return objects.get(socket); } /** *

    Registers a SSLEngine with a provider.

    * * @param engine the engine to register with the provider * @param provider the provider to register with the engine */ public static void put(SSLEngine engine, Provider provider) { objects.put(engine, provider); } /** * * @param engine an engine registered with {@link #put(SSLEngine, Provider)} * @return the provider registered with the given engine */ public static Provider get(SSLEngine engine) { return objects.get(engine); } /** *

    Base, empty, interface for providers.

    */ public interface Provider { } /** *

    The client-side provider interface that applications must implement to interact * with the negotiation of the next protocol.

    */ public interface ClientProvider extends Provider { /** *

    Callback invoked to let the implementation know whether an * empty NPN extension should be added to a ClientHello SSL message.

    * * @return true to add the NPN extension, false otherwise */ public boolean supports(); /** *

    Callback invoked to let the application know that the server does * not support NPN.

    */ public void unsupported(); /** *

    Callback invoked to let the application select a protocol * among the ones sent by the server.

    * * @param protocols the protocols sent by the server * @return the protocol selected by the application, or null if the * NextProtocol SSL message should not be sent to the server */ public String selectProtocol(List protocols); } /** *

    The server-side provider interface that applications must implement to interact * with the negotiation of the next protocol.

    */ public interface ServerProvider extends Provider { /** *

    Callback invoked to let the application know that the client does not * support NPN.

    */ public void unsupported(); /** *

    Callback invoked to let the implementation know the list * of protocols that should be added to an NPN extension in a * ServerHello SSL message.

    *

    This callback is invoked only if the client sent a NPN extension.

    * * @return the list of protocols, or null if no NPN extension * should be sent to the client */ public List protocols(); /** *

    Callback invoked to let the application know the protocol selected * by the client.

    *

    This callback is invoked only if the client sent a NextProtocol SSL message.

    * * @param protocol the selected protocol */ public void protocolSelected(String protocol); } } jetty8-8.1.3/jetty-osgi/000077500000000000000000000000001174773561500150705ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/000077500000000000000000000000001174773561500207215ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/META-INF/000077500000000000000000000000001174773561500220615ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/META-INF/MANIFEST.MF000066400000000000000000000065231174773561500235210ustar00rootroot00000000000000Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Jetty-OSGi-Jasper integration Fragment-Host: org.eclipse.jetty.osgi.boot Bundle-SymbolicName: org.eclipse.jetty.osgi.boot.jsp Bundle-Version: 8.1.3.qualifier Bundle-Vendor: Mort Bay Consulting Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Import-Package: com.sun.el;version="2.2.0";resolution:=optional, javax.el;version="2.2.0";resolution:=optional, javax.servlet.jsp;version="2.2.0", javax.servlet.jsp.el;version="2.2.0", javax.servlet.jsp.jstl.core;version="1.2.0";resolution:=optional, javax.servlet.jsp.jstl.fmt;version="1.2.0";resolution:=optional, javax.servlet.jsp.jstl.sql;version="1.2.0";resolution:=optional, javax.servlet.jsp.jstl.tlv;version="1.2.0";resolution:=optional, javax.servlet.jsp.resources;version="2.1.0", javax.servlet.jsp.tagext;version="2.1.0", javax.servlet.resources;version="2.6.0", org.apache.jasper;version="2.2.2";resolution:=optional, org.apache.jasper.compiler;version="2.2.2";resolution:=optional, org.apache.jasper.compiler.tagplugin;version="2.2.2";resolution:=optional, org.apache.jasper.runtime;version="2.2.2";resolution:=optional, org.apache.jasper.security;version="2.2.2";resolution:=optional, org.apache.jasper.servlet;version="2.2.2";resolution:=optional, org.apache.jasper.tagplugins.jstl;version="2.2.2";resolution:=optional, org.apache.jasper.util;version="2.2.2";resolution:=optional, org.apache.jasper.xmlparser;version="2.2.2";resolution:=optional, org.apache.taglibs.standard;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.extra.spath;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.functions;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.lang.jstl;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.lang.jstl.parser;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.lang.jstl.test;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.lang.jstl.test.beans;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.lang.support;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.resources;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.common.core;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.common.fmt;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.common.sql;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.common.xml;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.el.core;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.el.fmt;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.el.sql;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.el.xml;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.rt.core;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.rt.fmt;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.rt.sql;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tag.rt.xml;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tei;version="1.2.0";resolution:=optional, org.apache.taglibs.standard.tlv;version="1.2.0";resolution:=optional, org.glassfish.jsp.api;version="2.2.2";resolution:=optional DynamicImport-Package: org.apache.jasper.*;version="2.2.2" jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/build.properties000066400000000000000000000001721174773561500241360ustar00rootroot00000000000000source.. = src/main/java/ output.. = target/classes/ bin.includes = META-INF/,\ . src.includes = META-INF/ jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/pom.xml000066400000000000000000000062161174773561500222430ustar00rootroot00000000000000 org.eclipse.jetty.osgi jetty-osgi-project 8.1.3.v20120416 ../pom.xml 4.0.0 jetty-osgi-boot-jsp Jetty :: OSGi :: Boot JSP Jetty OSGi Boot JSP bundle ${project.groupId}.boot.jsp org.eclipse.jetty jetty-deploy org.eclipse.jetty.osgi jetty-osgi-boot ${project.version} provided org.eclipse.osgi org.eclipse.osgi org.eclipse.osgi org.eclipse.osgi.services org.eclipse.jetty.orbit javax.servlet org.eclipse.jetty jetty-jsp ${project.version} maven-antrun-plugin process-resources run org.apache.maven.plugins maven-jar-plugin artifact-jar jar test-jar test-jar target/classes/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.osgi.boot.jasper.*,org.eclipse.jetty.osgi.boot.jsp.* jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/000077500000000000000000000000001174773561500215105ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/000077500000000000000000000000001174773561500224345ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/000077500000000000000000000000001174773561500233555ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/000077500000000000000000000000001174773561500241445ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/000077500000000000000000000000001174773561500255705ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500267275ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/000077500000000000000000000000001174773561500276705ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/000077500000000000000000000000001174773561500306335ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/000077500000000000000000000000001174773561500321175ustar00rootroot00000000000000PluggableWebAppRegistrationCustomizerImpl.java000066400000000000000000000146701174773561500432160ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper// ======================================================================== // Copyright (c) 2009-2010 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.jasper; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.StringTokenizer; import org.eclipse.jetty.osgi.boot.OSGiAppProvider; import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper; import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; /** * Plug bundles that contains tld files so that jasper will discover them and * set them up in jetty. * * For example: * -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet * ,com.opensymphony.module.sitemesh Otherwise use an attribute to the * WebAppDeployer <New * class="org.eclipse.jetty.deploy.providers.WebAppProvider"> .... <Set * name="tldBundles"><Property name="org.eclipse.jetty.osgi.tldsbundles" * default="" /></Set> <New> */ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistrationCustomizer { /** * To plug into jasper bundles that contain tld files please use a list of * bundle's symbolic names: * -Djetty.osgi.tldbundles=org.springframework.web.servlet * ,com.opensymphony.module.sitemesh */ public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles"; /** * Union of the tld bundles defined system wide and the one defines as an * attribute of the AppProvider. * * @param provider * @return */ private static Collection getTldBundles(OSGiAppProvider provider) { String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES); String att = (String) provider.getTldBundles(); if (sysprop == null && att == null) { return Collections.emptySet(); } if (att == null) { att = sysprop; } else if (sysprop != null) { att = att + "," + sysprop; } Collection tldbundles = new HashSet(); StringTokenizer tokenizer = new StringTokenizer(att, ", \n\r\t", false); while (tokenizer.hasMoreTokens()) { tldbundles.add(tokenizer.nextToken()); } return tldbundles; } /** * @return The location of the jars that contain tld files. Jasper will * discover them. */ public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception { List urls = new ArrayList(); // naive way of finding those bundles. // lots of assumptions: for example we assume a single version of each // bundle that would contain tld files. // this is probably good enough as those tlds are loaded system-wide on // jetty. // to do better than this we need to do it on a per webapp basis. // probably using custom properties in the ContextHandler service // and mirroring those in the MANIFEST.MF Bundle[] bundles = FrameworkUtil.getBundle(PluggableWebAppRegistrationCustomizerImpl.class).getBundleContext().getBundles(); Collection tldbundles = getTldBundles(provider); for (Bundle bundle : bundles) { if (tldbundles.contains(bundle.getSymbolicName())) { registerTldBundle(locatorHelper, bundle, urls); } } return urls.toArray(new URL[urls.size()]); } /** * Resolves the bundle that contains tld files as a set of URLs that will be * passed to jasper as a URLClassLoader later on. Usually that would be a * single URL per bundle. But we do some more work if there are jars * embedded in the bundle. * * The jasper TldScanner expects a URLClassloader to parse a jar for the * /META-INF/*.tld it may contain. We place the bundles that we know contain * such tag-libraries. Please note that it will work if and only if the * bundle is a jar (!) Currently we just hardcode the bundle that contains * the jstl implemenation. * * A workaround when the tld cannot be parsed with this method is to copy * and paste it inside the WEB-INF of the webapplication where it is used. * * Support only 2 types of packaging for the bundle: - the bundle is a jar * (recommended for runtime.) - the bundle is a folder and contain jars in * the root and/or in the lib folder (nice for PDE developement situations) * Unsupported: the bundle is a jar that embeds more jars. * * @param locatorHelper * @param bundle * @param urls * @throws Exception */ private void registerTldBundle(BundleFileLocatorHelper locatorHelper, Bundle bundle, List urls) throws Exception { File jasperLocation = locatorHelper.getBundleInstallLocation(bundle); if (jasperLocation.isDirectory()) { for (File f : jasperLocation.listFiles()) { if (f.getName().endsWith(".jar") && f.isFile()) { urls.add(f.toURI().toURL()); } else if (f.isDirectory() && f.getName().equals("lib")) { for (File f2 : jasperLocation.listFiles()) { if (f2.getName().endsWith(".jar") && f2.isFile()) { urls.add(f2.toURI().toURL()); } } } } urls.add(jasperLocation.toURI().toURL()); } else { urls.add(jasperLocation.toURI().toURL()); } } }WebappRegistrationCustomizerImpl.java000066400000000000000000000250341174773561500414270ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper// ======================================================================== // Copyright (c) 2009-2010 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.jasper; import java.io.File; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import javax.servlet.Servlet; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspFactory; import org.apache.jasper.Constants; import org.apache.jasper.compiler.Localizer; import org.apache.jasper.xmlparser.ParserUtils; import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator; import org.eclipse.jetty.osgi.boot.OSGiAppProvider; import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper; import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Fix various shortcomings with the way jasper parses the tld files. Plugs the * JSTL tlds assuming that they are packaged with the bundle that contains the * JSTL classes. *

    * Pluggable tlds at the server level are handled by * {@link PluggableWebAppRegistrationCustomizerImpl}. *

    */ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCustomizer { /** * Default name of a class that belongs to the jstl bundle. From that class * we locate the corresponding bundle and register it as a bundle that * contains tld files. */ private static String DEFAULT_JSTL_BUNDLE_CLASS = "org.apache.taglibs.standard.tag.el.core.WhenTag"; // used to be "org.apache.jasper.runtime.JspFactoryImpl" but now // the standard tag library implementation are stored in a separate bundle. // DISABLED please use the tld bundle argument for the OSGiAppProvider // /** // * Default name of a class that belongs to the bundle where the Java // server Faces tld files are defined. // * This is the sun's reference implementation. // */ // private static String DEFAUT_JSF_IMPL_CLASS = // "com.sun.faces.config.ConfigureListener"; /** * Default jsp factory implementation. Idally jasper is osgified and we can * use services. In the mean time we statically set the jsp factory * implementation. bug #299733 */ private static String DEFAULT_JSP_FACTORY_IMPL_CLASS = "org.apache.jasper.runtime.JspFactoryImpl"; public WebappRegistrationCustomizerImpl() { fixupDtdResolution(); try { // sanity check: Class cl = getClass().getClassLoader().loadClass("org.apache.jasper.servlet.JspServlet"); // System.err.println("found the jsp servlet: " + cl.getName()); } catch (Exception e) { System.err.println("Unable to locate the JspServlet: jsp support unavailable."); e.printStackTrace(); return; } try { // bug #299733 JspFactory fact = JspFactory.getDefaultFactory(); if (fact == null) { // bug #299733 // JspFactory does a simple // Class.getForName("org.apache.jasper.runtime.JspFactoryImpl") // however its bundles does not import the jasper package // so it fails. let's help things out: fact = (JspFactory) JettyBootstrapActivator.class.getClassLoader().loadClass(DEFAULT_JSP_FACTORY_IMPL_CLASS).newInstance(); JspFactory.setDefaultFactory(fact); } } catch (Exception e) { System.err.println("Unable to set the JspFactory: jsp support incomplete."); e.printStackTrace(); } } /** * The jasper TldScanner expects a URLClassloader to parse a jar for the * /META-INF/*.tld it may contain. We place the bundles that we know contain * such tag-libraries. Please note that it will work if and only if the * bundle is a jar (!) Currently we just hardcode the bundle that contains * the jstl implemenation. * * A workaround when the tld cannot be parsed with this method is to copy * and paste it inside the WEB-INF of the webapplication where it is used. * * Support only 2 types of packaging for the bundle: - the bundle is a jar * (recommended for runtime.) - the bundle is a folder and contain jars in * the root and/or in the lib folder (nice for PDE developement situations) * Unsupported: the bundle is a jar that embeds more jars. * * @return array of URLs * @throws Exception */ public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception { HashSet> classesToAddToTheTldBundles = new HashSet>(); // Look for the jstl bundle // We assume the jstl's tlds are defined there. // We assume that the jstl bundle is imported by this bundle // So we can look for this class using this bundle's classloader: Class jstlClass = WebappRegistrationCustomizerImpl.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS); classesToAddToTheTldBundles.add(jstlClass); ArrayList urls = new ArrayList(); for (Class cl : classesToAddToTheTldBundles) { Bundle tldBundle = FrameworkUtil.getBundle(cl); File tldBundleLocation = locatorHelper.getBundleInstallLocation(tldBundle); if (tldBundleLocation != null && tldBundleLocation.isDirectory()) { // try to find the jar files inside this folder for (File f : tldBundleLocation.listFiles()) { if (f.getName().endsWith(".jar") && f.isFile()) { urls.add(f.toURI().toURL()); } else if (f.isDirectory() && f.getName().equals("lib")) { for (File f2 : tldBundleLocation.listFiles()) { if (f2.getName().endsWith(".jar") && f2.isFile()) { urls.add(f2.toURI().toURL()); } } } } } else if (tldBundleLocation != null) { urls.add(tldBundleLocation.toURI().toURL()); } } return urls.toArray(new URL[urls.size()]); } /** * Jasper resolves the dtd when it parses a taglib descriptor. It uses this * code to do that: * ParserUtils.getClass().getResourceAsStream(resourcePath); where * resourcePath is for example: * /javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd Unfortunately, the * dtd file is not in the exact same classloader as ParserUtils class and * the dtds are packaged in 2 separate bundles. OSGi does not look in the * dependencies' classloader when a resource is searched. *

    * The workaround consists of setting the entity resolver. That is a patch * added to the version of glassfish-jasper-jetty. IT is also present in the * latest version of glassfish jasper. Could not use introspection to set * new value on a static friendly field :( *

    */ void fixupDtdResolution() { try { ParserUtils.setEntityResolver(new MyFixedupEntityResolver()); } catch (Exception e) { e.printStackTrace(); } } /** * Instead of using the ParserUtil's classloader, we use a class that is * indeed next to the resource for sure. */ static class MyFixedupEntityResolver implements EntityResolver { /** * Same values than in ParserUtils... */ static final String[] CACHED_DTD_PUBLIC_IDS = { Constants.TAGLIB_DTD_PUBLIC_ID_11, Constants.TAGLIB_DTD_PUBLIC_ID_12, Constants.WEBAPP_DTD_PUBLIC_ID_22, Constants.WEBAPP_DTD_PUBLIC_ID_23, }; static final String[] CACHED_DTD_RESOURCE_PATHS = { Constants.TAGLIB_DTD_RESOURCE_PATH_11, Constants.TAGLIB_DTD_RESOURCE_PATH_12, Constants.WEBAPP_DTD_RESOURCE_PATH_22, Constants.WEBAPP_DTD_RESOURCE_PATH_23, }; static final String[] CACHED_SCHEMA_RESOURCE_PATHS = { Constants.TAGLIB_SCHEMA_RESOURCE_PATH_20, Constants.TAGLIB_SCHEMA_RESOURCE_PATH_21, Constants.WEBAPP_SCHEMA_RESOURCE_PATH_24, Constants.WEBAPP_SCHEMA_RESOURCE_PATH_25, }; public InputSource resolveEntity(String publicId, String systemId) throws SAXException { for (int i = 0; i < CACHED_DTD_PUBLIC_IDS.length; i++) { String cachedDtdPublicId = CACHED_DTD_PUBLIC_IDS[i]; if (cachedDtdPublicId.equals(publicId)) { String resourcePath = CACHED_DTD_RESOURCE_PATHS[i]; InputStream input = null; input = Servlet.class.getResourceAsStream(resourcePath); if (input == null) { input = JspContext.class.getResourceAsStream(resourcePath); if (input == null) { // if that failed try again with the original code: // although it is likely not changed. input = this.getClass().getResourceAsStream(resourcePath); } } if (input == null) { throw new SAXException(Localizer.getMessage("jsp.error.internal.filenotfound", resourcePath)); } InputSource isrc = new InputSource(input); return isrc; } } return null; } } } jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/000077500000000000000000000000001174773561500314275ustar00rootroot00000000000000FragmentActivator.java000066400000000000000000000041441174773561500356360ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.jsp; import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleDeployerHelper; import org.eclipse.jetty.osgi.boot.jasper.PluggableWebAppRegistrationCustomizerImpl; import org.eclipse.jetty.osgi.boot.jasper.WebappRegistrationCustomizerImpl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; /** * Pseudo fragment activator. Called by the main org.eclipse.jetty.osgi.boot * bundle. Please note: this is not a real BundleActivator. Simply something * called back by the host bundle. *

    * It must be placed in the org.eclipse.jetty.osgi.boot.jsp package: this is * because org.eclipse.jetty.osgi.boot.jsp is the sympbolic-name of this * fragment. From that name, the PackageadminTracker will call this class. IN a * different package it won't be called. *

    */ public class FragmentActivator implements BundleActivator { /** * */ public void start(BundleContext context) throws Exception { System.setProperty("org.apache.jasper.compiler.disablejsr199", Boolean.TRUE.toString()); WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new WebappRegistrationCustomizerImpl()); WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new PluggableWebAppRegistrationCustomizerImpl()); } /** * */ public void stop(BundleContext context) throws Exception { } } TagLibOSGiConfiguration.java000066400000000000000000000155371174773561500366420ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp// ======================================================================== // Copyright (c) 2004-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.jsp; import java.io.IOException; import java.net.URL; import java.util.Collection; import java.util.Enumeration; import java.util.LinkedHashSet; import org.eclipse.jetty.osgi.boot.OSGiWebappConstants; import org.eclipse.jetty.osgi.boot.utils.internal.DefaultFileLocatorHelper; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.TagLibConfiguration; import org.eclipse.jetty.webapp.WebAppContext; import org.osgi.framework.Bundle; import org.osgi.framework.BundleReference; import org.osgi.service.packageadmin.PackageAdmin; import org.osgi.util.tracker.ServiceTracker; /** *

    * Replacement for {@link TagLibConfiguration} for the OSGi integration. *

    *

    * In the case of a WAB, tlds can be located in OSGi bundles that are * dependencies of the WAB. It is expected that each WAB lists the * symbolic-names of the bundles that contain tld files. The list is defined as * the value of the header 'Require-TldBundle' *

    *

    * Discussions about this are logged in * https://bugs.eclipse.org/bugs/show_bug.cgi?id=306971 *

    */ public class TagLibOSGiConfiguration extends TagLibConfiguration { private static final Logger LOG = Log.getLogger(TagLibOSGiConfiguration.class); private ServiceTracker packageAdminServiceTracker = null; /** * Override the preConfigure; locates the bundles that contain tld files * according to the value of the manifest header Require-TldBundle. *

    * Set or add to the property TldProcessor.TLDResources the list of located * jars so that the super class will scan those. *

    */ public void preConfigure(WebAppContext context) throws Exception { String requireTldBundle = (String) context.getAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE); if (requireTldBundle != null) { Collection resources = getRequireTldBundleAsJettyResources(context, requireTldBundle); if (resources != null && !resources.isEmpty()) { Collection previouslySet = (Collection) context.getAttribute(TagLibConfiguration.TLD_RESOURCES); if (previouslySet != null) { resources.addAll(previouslySet); } context.setAttribute(TagLibConfiguration.TLD_RESOURCES, resources); } } super.preConfigure(context); } /** * @param requireTldBundle The comma separated list of bundles' symbolic * names that contain tld for this osgi webapp. * @return The collection of jars or folders that match those bundles. */ private Collection getRequireTldBundleAsJettyResources(WebAppContext context, String requireTldBundle) { Bundle bundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE); PackageAdmin packAdmin = getBundleAdmin(); String[] symbNames = requireTldBundle.split(", "); Collection tlds = new LinkedHashSet(); for (String symbName : symbNames) { Bundle[] bs = packAdmin.getBundles(symbName, null); if (bs == null || bs.length == 0) { throw new IllegalArgumentException("Unable to locate the bundle '" + symbName + "' specified in the " + OSGiWebappConstants.REQUIRE_TLD_BUNDLE + " of the manifest of " + bundle.getSymbolicName()); } // take the first one as it is the most recent version? Enumeration en = bs[0].findEntries("META-INF", "*.tld", false); boolean atLeastOneTldFound = false; while (en.hasMoreElements()) { atLeastOneTldFound = true; URL oriUrl = en.nextElement(); URL url = DefaultFileLocatorHelper.getLocalURL(oriUrl); Resource tldResource; try { tldResource = Resource.newResource(url); } catch (IOException e) { throw new IllegalArgumentException("Unable to locate the " + "tld resource in '" + url.toString() + "' in the bundle '" + bs[0].getSymbolicName() + "' while registering the " + OSGiWebappConstants.REQUIRE_TLD_BUNDLE + " of the manifest of " + bundle.getSymbolicName(), e); } tlds.add(tldResource); } if (!atLeastOneTldFound) { LOG.warn("No '/META-INF/*.tld' resources were found " + " in the bundle '" + bs[0].getSymbolicName() + "' while registering the " + OSGiWebappConstants.REQUIRE_TLD_BUNDLE + " of the manifest of " + bundle.getSymbolicName()); } } return tlds; } private PackageAdmin getBundleAdmin() { if (packageAdminServiceTracker == null) { Bundle bootBundle = ((BundleReference) OSGiWebappConstants.class.getClassLoader()).getBundle(); packageAdminServiceTracker = new ServiceTracker(bootBundle.getBundleContext(), PackageAdmin.class.getName(), null); packageAdminServiceTracker.open(); } return (PackageAdmin) packageAdminServiceTracker.getService(); } } jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-logback/000077500000000000000000000000001174773561500215275ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-logback/META-INF/000077500000000000000000000000001174773561500226675ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-logback/META-INF/MANIFEST.MF000066400000000000000000000012771174773561500243300ustar00rootroot00000000000000Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Jetty-OSGi-Logback integration Fragment-Host: org.eclipse.jetty.osgi.boot Bundle-SymbolicName: org.eclipse.jetty.osgi.boot.logback;singleton:=true Bundle-Version: 8.1.3.qualifier Bundle-Vendor: Mort Bay Consulting Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: ch.qos.logback.classic, ch.qos.logback.classic.joran, ch.qos.logback.core, ch.qos.logback.core.joran, ch.qos.logback.core.joran.spi, ch.qos.logback.core.spi, ch.qos.logback.core.util, ch.qos.logback.access.jetty.v7;resolution:=optional, org.apache.commons.logging;resolution:=optional, org.apache.log4j;resolution:=optional, org.osgi.framework, org.slf4j jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/000077500000000000000000000000001174773561500214415ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/META-INF/000077500000000000000000000000001174773561500226015ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/META-INF/MANIFEST.MF000066400000000000000000000006611174773561500242360ustar00rootroot00000000000000Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Support for rfc66 war url scheme Bundle-SymbolicName: org.eclipse.jetty.osgi.boot.warurl;singleton:=true Bundle-Version: 8.1.3.qualifier Bundle-Activator: org.eclipse.jetty.osgi.boot.warurl.WarUrlActivator Bundle-Vendor: Mort Bay Consulting Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Import-Package: org.eclipse.jetty.util, org.osgi.framework, org.osgi.service.url jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/build.properties000066400000000000000000000001721174773561500246560ustar00rootroot00000000000000source.. = src/main/java/ output.. = target/classes/ bin.includes = META-INF/,\ . src.includes = META-INF/ jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/pom.xml000066400000000000000000000047071174773561500227660ustar00rootroot00000000000000 org.eclipse.jetty.osgi jetty-osgi-project 8.1.3.v20120416 ../pom.xml 4.0.0 jetty-osgi-boot-warurl Jetty :: OSGi :: Boot :: Warurl Jetty OSGi Boot-Warurl bundle ${project.groupId}.boot.warurl org.eclipse.jetty jetty-util org.eclipse.osgi org.eclipse.osgi maven-antrun-plugin process-resources run org.apache.maven.plugins maven-jar-plugin artifact-jar jar test-jar test-jar target/classes/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.osgi.boot.warurl.* jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/000077500000000000000000000000001174773561500222305ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/000077500000000000000000000000001174773561500231545ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/000077500000000000000000000000001174773561500240755ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/000077500000000000000000000000001174773561500246645ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/000077500000000000000000000000001174773561500263105ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500274475ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/000077500000000000000000000000001174773561500304105ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/000077500000000000000000000000001174773561500313535ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/000077500000000000000000000000001174773561500326675ustar00rootroot00000000000000WarUrlActivator.java000066400000000000000000000043071174773561500365500ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.warurl; import java.util.Dictionary; import java.util.Hashtable; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import org.osgi.service.url.URLConstants; import org.osgi.service.url.URLStreamHandlerService; /** * Register the factory to handle the war scheme specified by rfc66 * when the bundle is activated. */ public class WarUrlActivator implements BundleActivator { private ServiceRegistration _reg; /** * Register the url stream handler factory. * * @param context */ @SuppressWarnings("unchecked") public void start(BundleContext context) throws Exception { Dictionary props = new Hashtable(); props.put(URLConstants.URL_HANDLER_PROTOCOL,new String[] {"war"}); context.registerService(URLStreamHandlerService.class.getName(), new WarUrlStreamHandler(), props); } /** * Remove the url stream handler. (probably not required, * as osgi might shutdown every registered service * by default: need test) */ public void stop(BundleContext context) throws Exception { try { if (_reg != null) { _reg.unregister(); } } catch (Exception e) { e.printStackTrace(); } } } WarUrlStreamHandler.java000066400000000000000000000066621174773561500373530ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.warurl; import java.io.File; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.jar.Manifest; import org.eclipse.jetty.osgi.boot.warurl.internal.WarBundleManifestGenerator; import org.eclipse.jetty.osgi.boot.warurl.internal.WarURLConnection; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.resource.Resource; import org.osgi.service.url.AbstractURLStreamHandlerService; /** * RFC-66: support for the "war" protocol We are reusing the parsing of the * query string from jetty. If we wanted to not depend on jetty at all we could * duplicate that method here */ public class WarUrlStreamHandler extends AbstractURLStreamHandlerService { /** * @param url The url with a war scheme */ @Override public URLConnection openConnection(URL url) throws IOException { // remove the war scheme. URL actual = new URL(url.toString().substring("war:".length())); // let's do some basic tests: see if this is a folder or not. // if it is a folder. we will try to support it. if (actual.getProtocol().equals("file")) { File file = new File(URIUtil.encodePath(actual.getPath())); if (file.exists()) { if (file.isDirectory()) { // TODO (not mandatory for rfc66 though) } } } // if (actual.toString().startsWith("file:/") && ! actual.to) URLConnection ori = (URLConnection) actual.openConnection(); ori.setDefaultUseCaches(Resource.getDefaultUseCaches()); JarURLConnection jarOri = null; try { if (ori instanceof JarURLConnection) { jarOri = (JarURLConnection) ori; } else { jarOri = (JarURLConnection) new URL("jar:" + actual.toString() + "!/").openConnection(); jarOri.setDefaultUseCaches(Resource.getDefaultUseCaches()); } Manifest mf = WarBundleManifestGenerator.createBundleManifest(jarOri.getManifest(), url, jarOri.getJarFile()); try { jarOri.getJarFile().close(); jarOri = null; } catch (Throwable t) { } return new WarURLConnection(actual, mf); } finally { if (jarOri != null) try { jarOri.getJarFile().close(); } catch (Throwable t) { } } } } 000077500000000000000000000000001174773561500344245ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/internalWarBundleManifestGenerator.java000066400000000000000000000247461174773561500425250ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/internal// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.warurl.internal; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.UrlEncoded; import org.osgi.framework.Constants; public class WarBundleManifestGenerator { /** missing version in the url and in the manifest * use this one. */ private static final String MISSING_VERSION = "0.0.1.unknown"; private static final String MISSING_MANIFEST_VERSION = "2"; public static Manifest createBundleManifest(Manifest originalManifest, URL url, JarFile jarFile) { Manifest res = new Manifest(); res.getMainAttributes().putAll( createBundleManifest(originalManifest.getMainAttributes(), url.toString(), jarFile)); return res; } private static Attributes createBundleManifest(Attributes originalManifest, String url, JarFile jarFile) { HashMap res = new HashMap(); for (Entry entries : originalManifest.entrySet()) { res.put(entries.getKey().toString(),String.valueOf(entries.getValue())); } MultiMap params = parseQueryString(url); //follow RFC66 documentation: //#1 Bundle-Version String version = params.getString(Constants.BUNDLE_VERSION); if (version != null) { res.put(Constants.BUNDLE_VERSION, version); } else { String versionInManifest = (String) res.get(Constants.BUNDLE_VERSION); if (versionInManifest == null) { res.put(Constants.BUNDLE_VERSION, MISSING_VERSION); } } //#2 Bundle_ManifestVersion String manversion = params.getString(Constants.BUNDLE_MANIFESTVERSION); if (manversion != null) { res.put(Constants.BUNDLE_MANIFESTVERSION, manversion); } else { int manv = 2; try { String versionInManifest = (String) res.get(Constants.BUNDLE_MANIFESTVERSION); if (versionInManifest != null) { manv = Integer.parseInt(versionInManifest.trim()); } } catch (NumberFormatException nfe) { } res.put(Constants.BUNDLE_MANIFESTVERSION, String.valueOf( manv < 2 ? 2 : manv )); } //#3 Bundle-SymbolicName String symbname = params.getString(Constants.BUNDLE_SYMBOLICNAME); if (symbname != null) { res.put(Constants.BUNDLE_SYMBOLICNAME, symbname); } else { symbname = (String) res.get(Constants.BUNDLE_SYMBOLICNAME); if (symbname == null) { //derive the symbolic name from the url. int lastSlash = url.lastIndexOf('/'); int beforeQueryString = url.indexOf(lastSlash, '?'); if (beforeQueryString == -1) { beforeQueryString = url.indexOf(lastSlash, '#'); if (beforeQueryString == -1) { beforeQueryString = url.length(); } } symbname = url.substring(lastSlash+1, beforeQueryString); //todo: something better probably. res.put(Constants.BUNDLE_SYMBOLICNAME, symbname); } } //#4 Bundle-Classpath String extraBundleClasspath = params.getString(Constants.BUNDLE_CLASSPATH); String alreadyBundleClasspath = res.get(Constants.BUNDLE_CLASSPATH); if (alreadyBundleClasspath == null) { StringBuilder bundleClasspath = new StringBuilder(); if (jarFile == null || jarFile.getJarEntry("WEB-INF/classes/") != null) { bundleClasspath.append("WEB-INF/classes"); } if (jarFile != null) { List libs = getJarsInWebInfLib(jarFile); if (extraBundleClasspath != null) { libs.add(extraBundleClasspath); } for (String lib : libs) { if (bundleClasspath.length() != 0) { bundleClasspath.append(","); } bundleClasspath.append(lib); } } alreadyBundleClasspath = bundleClasspath.toString(); } //if there is already a manifest and it specifies the Bundle-Classpath. //for now let's trust that one. //please note that the draft of the spec implies that we should be parsing the existing //header and merge it with the missing stuff so this does not follow the spec yet. res.put(Constants.BUNDLE_CLASSPATH, alreadyBundleClasspath + (extraBundleClasspath == null ? "" : "," + extraBundleClasspath )); //#5 Import-Package String extraImportPackage = params.getString(Constants.IMPORT_PACKAGE); String alreadyImportPackage = res.get(Constants.IMPORT_PACKAGE); if (alreadyImportPackage == null) {//The spec does not specify that the jsp imports are optional //kind of nice to have them optional so we can run simple wars in //simple environments. alreadyImportPackage = "javax.servlet; version=\"2.5\"," + "javax.servlet.http;version=\"2.5\"," + "javax.el;version=\"1.0\"" + "javax.jsp;version=\"2.1\";resolution:=optional," + "javax.jsp.tagext;version=\"2.1\";resolution:=optional"; } if (extraImportPackage != null) { //if there is already a manifest and it specifies the Bundle-Classpath. //for now let's trust that one. //please note that the draft of the spec implies that we should be parsing the existing //header and merge it with the missing stuff so this does not follow the spec yet. res.put(Constants.IMPORT_PACKAGE, (alreadyImportPackage == null ? "" : alreadyImportPackage + ",") + extraImportPackage); } //#6 Export-Package String extraExportPackage = params.getString(Constants.EXPORT_PACKAGE); String alreadyExportPackage = res.get(Constants.EXPORT_PACKAGE); if (extraExportPackage != null) { //if there is already a manifest and it specifies the Bundle-Classpath. //for now let's trust that one. //please note that the draft of the spec implies that we should be parsing the existing //header and merge it with the missing stuff so this does not follow the spec yet. res.put(Constants.EXPORT_PACKAGE, (alreadyExportPackage == null ? "" : alreadyExportPackage + ",") + extraImportPackage); } //#7 Web-ContextPath String webContextPath = params.getString("Web-ContextPath"); if (webContextPath != null) { res.put("Web-ContextPath", webContextPath); } else { webContextPath = res.get("Web-ContextPath"); if (webContextPath == null) { //we choose to use the symbolic name as the default context path. if (symbname.endsWith(".war")) { webContextPath = "/" + symbname.substring(0, symbname.length()-".war".length()); } else { webContextPath = "/" + symbname; } res.put("Web-ContextPath", webContextPath); } } //#8 Web-JSPExtractLocation String jspExtractLocation = params.getString("Web-JSPExtractLocation"); if (jspExtractLocation != null) { res.put("Web-JSPExtractLocation", jspExtractLocation); } else { //nothing to do. } Attributes newAttrs = new Attributes(); for (Entry e : res.entrySet()) { newAttrs.putValue(e.getKey(),e.getValue()); } return newAttrs; } /** * @return The key values pairs that are in the query string of this url. */ private static MultiMap parseQueryString(String url) { MultiMap res = new MultiMap(); int questionMarkIndex = url.indexOf('?'); if (questionMarkIndex == -1) { return res; } int poundIndex = url.indexOf('#'); if (poundIndex == -1) { poundIndex = url.length(); } UrlEncoded.decodeUtf8To(url.getBytes(), questionMarkIndex+1, poundIndex - questionMarkIndex - 1, res); return res; } private static List getJarsInWebInfLib(JarFile jarFile) { List res = new ArrayList(); Enumeration en = jarFile.entries(); while (en.hasMoreElements()) { JarEntry e = en.nextElement(); if (e.getName().startsWith("WEB-INF/lib/") && e.getName().endsWith(".jar")) { res.add(e.getName()); } } return res; } } WarURLConnection.java000066400000000000000000000176111174773561500404310ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot-warurl/src/main/java/org/eclipse/jetty/osgi/boot/warurl/internal// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.warurl.internal; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.net.URL; import java.net.URLConnection; import java.security.Permission; import java.util.List; import java.util.Map; import java.util.jar.JarFile; import java.util.jar.JarInputStream; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import java.util.zip.ZipEntry; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.resource.Resource; /** * Facade for a URLConnection that will read a jar and substitute its * manifest by the manifest provided here. *

    * Use Piped streams to avoid having to create temporary files. *

    */ public class WarURLConnection extends URLConnection { /** * Use PipedOuputStream and PipedInputStream to do the transformation without making * a new temporary file ust to replace the manifest. * @param newmanifest The new manifest * @param rawIn The file input stream or equivalent. not the jar input stream. */ public static InputStream substitueManifest(final Manifest newmanifest, final InputStream rawIn) throws IOException { final PipedOutputStream pOut = new PipedOutputStream(); PipedInputStream pIn = new PipedInputStream(pOut); Runnable run = new Runnable() { public void run() { JarInputStream jin = null; JarOutputStream dest = null; try { jin = new JarInputStream(rawIn, false); dest = new JarOutputStream(pOut, newmanifest); ZipEntry next = jin.getNextEntry(); while (next != null) { if (next.getName().equalsIgnoreCase(JarFile.MANIFEST_NAME)) { continue; } dest.putNextEntry(next); if (next.getSize() > 0) { IO.copy(jin,dest,next.getSize()); } next = jin.getNextJarEntry(); } } catch (IOException ioe) { ioe.printStackTrace(); } finally { if (dest != null) IO.close(dest); if (jin != null) IO.close(jin); IO.close(pOut); } } }; Thread th = new Thread(run); th.start(); return pIn; } private Manifest _mf; private URLConnection _conn; /** * @param url The file url (for example) * @param mf The manifest to use as a replacement to the jar file inside * the file url. */ public WarURLConnection(URL url, Manifest mf) throws IOException { super(url); _conn = url.openConnection(); _conn.setDefaultUseCaches(Resource.getDefaultUseCaches()); _mf = mf; } @Override public void connect() throws IOException { _conn.connect(); } public InputStream getInputStream() throws IOException { return substitueManifest(_mf, _conn.getInputStream()); } public void addRequestProperty(String key, String value) { _conn.addRequestProperty(key,value); } public boolean equals(Object obj) { return _conn.equals(obj); } public boolean getAllowUserInteraction() { return _conn.getAllowUserInteraction(); } public int getConnectTimeout() { return _conn.getConnectTimeout(); } public Object getContent() throws IOException { return _conn.getContent(); } public Object getContent(Class[] classes) throws IOException { return _conn.getContent(classes); } public String getContentEncoding() { return _conn.getContentEncoding(); } public int getContentLength() { return _conn.getContentLength(); } public String getContentType() { return _conn.getContentType(); } public long getDate() { return _conn.getDate(); } public boolean getDefaultUseCaches() { return _conn.getDefaultUseCaches(); } public boolean getDoInput() { return _conn.getDoInput(); } public boolean getDoOutput() { return _conn.getDoOutput(); } public long getExpiration() { return _conn.getExpiration(); } public String getHeaderField(int n) { return _conn.getHeaderField(n); } public String getHeaderField(String name) { return _conn.getHeaderField(name); } public long getHeaderFieldDate(String name, long Default) { return _conn.getHeaderFieldDate(name,Default); } public int getHeaderFieldInt(String name, int Default) { return _conn.getHeaderFieldInt(name,Default); } public String getHeaderFieldKey(int n) { return _conn.getHeaderFieldKey(n); } public Map> getHeaderFields() { return _conn.getHeaderFields(); } public long getIfModifiedSince() { return _conn.getIfModifiedSince(); } public long getLastModified() { return _conn.getLastModified(); } public OutputStream getOutputStream() throws IOException { return _conn.getOutputStream(); } public Permission getPermission() throws IOException { return _conn.getPermission(); } public int getReadTimeout() { return _conn.getReadTimeout(); } public Map> getRequestProperties() { return _conn.getRequestProperties(); } public String getRequestProperty(String key) { return _conn.getRequestProperty(key); } public URL getURL() { return _conn.getURL(); } public boolean getUseCaches() { return _conn.getUseCaches(); } public void setAllowUserInteraction(boolean allowuserinteraction) { _conn.setAllowUserInteraction(allowuserinteraction); } public void setConnectTimeout(int timeout) { _conn.setConnectTimeout(timeout); } public void setDefaultUseCaches(boolean defaultusecaches) { _conn.setDefaultUseCaches(defaultusecaches); } public void setDoInput(boolean doinput) { _conn.setDoInput(doinput); } public void setDoOutput(boolean dooutput) { _conn.setDoOutput(dooutput); } public void setIfModifiedSince(long ifmodifiedsince) { _conn.setIfModifiedSince(ifmodifiedsince); } public void setReadTimeout(int timeout) { _conn.setReadTimeout(timeout); } public void setRequestProperty(String key, String value) { _conn.setRequestProperty(key,value); } public void setUseCaches(boolean usecaches) { _conn.setUseCaches(usecaches); } } jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/000077500000000000000000000000001174773561500201275ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/META-INF/000077500000000000000000000000001174773561500212675ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/META-INF/MANIFEST.MF000066400000000000000000000041121174773561500227170ustar00rootroot00000000000000Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Jetty OSGi bootstrap Bundle-SymbolicName: org.eclipse.jetty.osgi.boot Bundle-Vendor: Mort Bay Consulting Bundle-Version: 8.1.3.qualifier Bundle-Activator: org.eclipse.jetty.osgi.boot.JettyBootstrapActivator Import-Package: javax.mail;version="1.4.0";resolution:=optional, javax.mail.event;version="1.4.0";resolution:=optional, javax.mail.internet;version="1.4.0";resolution:=optional, javax.mail.search;version="1.4.0";resolution:=optional, javax.mail.util;version="1.4.0";resolution:=optional, javax.servlet;version="2.6", javax.servlet.http;version="2.6", javax.transaction;version="1.1.0";resolution:=optional, javax.transaction.xa;version="1.1.0";resolution:=optional, org.eclipse.jetty.annotations;version="8.1.3";resolution:=optional, org.eclipse.jetty.deploy;version="8.1.3", org.eclipse.jetty.deploy.providers;version="8.1.3", org.eclipse.jetty.http;version="8.1.3", org.eclipse.jetty.nested;version="8.1.3";resolution:=optional, org.eclipse.jetty.server;version="8.1.3", org.eclipse.jetty.server.handler;version="8.1.3", org.eclipse.jetty.servlet;version="8.1.3", org.eclipse.jetty.util;version="8.1.3", org.eclipse.jetty.util.component;version="8.1.3", org.eclipse.jetty.util.log;version="8.1.3", org.eclipse.jetty.util.resource;version="8.1.3", org.eclipse.jetty.webapp;version="8.1.3", org.eclipse.jetty.xml;version="8.1.3", org.osgi.framework, org.osgi.service.cm;version="1.2.0", org.osgi.service.packageadmin, org.osgi.service.startlevel;version="1.0", org.osgi.service.url;version="1.0.0", org.osgi.util.tracker;version="1.3.0", org.slf4j;resolution:=optional, org.slf4j.helpers;resolution:=optional, org.slf4j.spi;resolution:=optional, org.xml.sax, org.xml.sax.helpers Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-Classpath: . Export-Package: org.eclipse.jetty.osgi.boot;version="8.1.3", org.eclipse.jetty.osgi.nested;version="8.1.3", org.eclipse.jetty.osgi.boot.utils;version="8.1.3", org.eclipse.jetty.osgi.annotations;version="8.1.3" DynamicImport-Package: org.eclipse.jetty.*;version="[8.1,9)" jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/build.properties000066400000000000000000000003341174773561500233440ustar00rootroot00000000000000source.. = src/main/java/ output.. = target/classes/ bin.includes = META-INF/,\ .,\ jettyhome/ bin.excludes = jettyhome/logs/*.log,\ jettyhome/lib/* src.includes = jettyhome/ jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/000077500000000000000000000000001174773561500221375ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/contexts/000077500000000000000000000000001174773561500240065ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/contexts/README000066400000000000000000000002031174773561500246610ustar00rootroot00000000000000Default locations for standard context definitions. Those applications are unlikely to have access to the OSGi framework currently.jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/etc/000077500000000000000000000000001174773561500227125ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/etc/README000066400000000000000000000002501174773561500235670ustar00rootroot00000000000000This folder contains the default jetty configurations file for the server. In production, it is likely to be a different folder outside of the jetty's bootstrap plugin.jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty-osgi-default.xml000066400000000000000000000132241174773561500271560ustar00rootroot00000000000000 10 200 false 300000 2 false 8443 20000 5000 org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern .*/servlet-api-[^/]*\.jar$ 5 /contexts true true true 1000 false false java.naming.factory.initial java.naming.factory.url.pkgs jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty-osgi-nested-default.xml000066400000000000000000000122671174773561500304440ustar00rootroot00000000000000 false true x-forwarded_for sslclientcipher sslsessionid org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern .*/servlet-api-[^/]*\.jar$ 5 /contexts true true true 1000 false false java.naming.factory.initial java.naming.factory.url.pkgs jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/etc/webdefault.xml000066400000000000000000000570111174773561500255620ustar00rootroot00000000000000 Default web.xml file. This file is applied to a Web application before it's own WEB_INF/web.xml file default org.eclipse.jetty.servlet.DefaultServlet acceptRanges true dirAllowed true welcomeServlets false redirectWelcome false maxCacheSize 256000000 maxCachedFileSize 10000000 maxCachedFiles 1000 cacheType both gzip true useFileMappedBuffer true 0 default / jsp org.apache.jasper.servlet.JspServlet logVerbosityLevel DEBUG fork false xpoweredBy false 0 jsp *.jsp *.jspf *.jspx *.xsp *.JSP *.JSPF *.JSPX *.XSP 30 index.html index.htm index.jsp arISO-8859-6 beISO-8859-5 bgISO-8859-5 caISO-8859-1 csISO-8859-2 daISO-8859-1 deISO-8859-1 elISO-8859-7 enISO-8859-1 esISO-8859-1 etISO-8859-1 fiISO-8859-1 frISO-8859-1 hrISO-8859-2 huISO-8859-2 isISO-8859-1 itISO-8859-1 iwISO-8859-8 jaShift_JIS koEUC-KR ltISO-8859-2 lvISO-8859-2 mkISO-8859-5 nlISO-8859-1 noISO-8859-1 plISO-8859-2 ptISO-8859-1 roISO-8859-2 ruISO-8859-5 shISO-8859-5 skISO-8859-2 slISO-8859-2 sqISO-8859-2 srISO-8859-5 svISO-8859-1 trISO-8859-9 ukISO-8859-5 zhGB2312 zh_TWBig5 Disable TRACE / TRACE jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/lib/000077500000000000000000000000001174773561500227055ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/lib/ext/000077500000000000000000000000001174773561500235055ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/lib/ext/README000066400000000000000000000002301174773561500243600ustar00rootroot00000000000000Place here the jars that are inserted in the jetty classloader. As similar as possible as what this folder was for in the classical jetty installation. jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/logs/000077500000000000000000000000001174773561500231035ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/logs/README000066400000000000000000000002761174773561500237700ustar00rootroot00000000000000This folder contains the logs by default during development time. In production or outside the eclipse PDE, it is likely that a different jetty.home was set or jetty.log so it won't be here.jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/resources/000077500000000000000000000000001174773561500241515ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/resources/README000066400000000000000000000001741174773561500250330ustar00rootroot00000000000000This folder is part of the class-loader shared by the webapps run in jetty. Typically it contains log4j configuration files.jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/webapps/000077500000000000000000000000001174773561500236005ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/jettyhome/webapps/README000066400000000000000000000002001174773561500244500ustar00rootroot00000000000000Default locations for standard web-applications. Those applications are unlikely to have access to the OSGi framework currently.jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/pom.xml000066400000000000000000000146141174773561500214520ustar00rootroot00000000000000 org.eclipse.jetty.osgi jetty-osgi-project 8.1.3.v20120416 ../pom.xml 4.0.0 jetty-osgi-boot Jetty :: OSGi :: Boot Jetty OSGi Boot bundle ${project.groupId}.boot org.eclipse.jetty jetty-annotations org.eclipse.jetty jetty-webapp org.eclipse.jetty jetty-deploy org.eclipse.jetty jetty-jmx org.eclipse.jetty jetty-nested org.eclipse.osgi org.eclipse.osgi org.eclipse.osgi org.eclipse.osgi.services maven-antrun-plugin process-resources run org.apache.maven.plugins maven-jar-plugin artifact-jar jar test-jar test-jar target/classes/META-INF/MANIFEST.MF org.apache.felix maven-bundle-plugin true bundle-manifest process-classes manifest org.eclipse.jetty.osgi.boot org.eclipse.jetty.osgi.boot;version="${parsedVersion.osgiVersion}",org.eclipse.jetty.osgi.boot.utils,org.eclipse.jetty.osgi.nested;version="${parsedVersion.osgiVersion}" org.eclipse.jetty.osgi.boot.JettyBootstrapActivator <_nouses>true javax.mail;version="1.4.0";resolution:=optional, javax.mail.event;version="1.4.0";resolution:=optional, javax.mail.internet;version="1.4.0";resolution:=optional, javax.mail.search;version="1.4.0";resolution:=optional, javax.mail.util;version="1.4.0";resolution:=optional, javax.servlet;version="2.6.0", javax.servlet.http;version="2.6.0", javax.transaction;version="1.1.0";resolution:=optional, javax.transaction.xa;version="1.1.0";resolution:=optional, org.eclipse.jetty.nested;version="8.0.0";resolution:=optional, org.eclipse.jetty.annotations;version="8.0.0";resolution:=optional, org.osgi.framework, org.osgi.service.cm;version="1.2.0", org.osgi.service.packageadmin, org.osgi.service.startlevel;version="1.0.o", org.osgi.service.url;version="1.0.0", org.osgi.util.tracker;version="1.3.0", org.slf4j;resolution:=optional, org.slf4j.spi;resolution:=optional, org.slf4j.helpers;resolution:=optional, org.xml.sax, org.xml.sax.helpers, * org.eclipse.jetty.*;version="[8.0.0,9.0.0)" JavaSE-1.6 org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.osgi.boot.* jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/000077500000000000000000000000001174773561500207165ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/000077500000000000000000000000001174773561500216425ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/000077500000000000000000000000001174773561500225635ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/000077500000000000000000000000001174773561500233525ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/000077500000000000000000000000001174773561500247765ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500261355ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/000077500000000000000000000000001174773561500270765ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/000077500000000000000000000000001174773561500314335ustar00rootroot00000000000000AnnotationConfiguration.java000066400000000000000000000170171174773561500370670ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations// ======================================================================== // Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.annotations; import java.util.ArrayList; import java.util.List; import org.eclipse.jetty.annotations.ClassNameResolver; import org.eclipse.jetty.osgi.boot.OSGiWebappConstants; import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.DiscoveredAnnotation; import org.eclipse.jetty.webapp.WebAppContext; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; /** * Extend the AnnotationConfiguration to support OSGi: * Look for annotations inside WEB-INF/lib and also in the fragments and required bundles. * Discover them using a scanner adapted to OSGi instead of the jarscanner. */ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.AnnotationConfiguration { /** * This parser scans the bundles using the OSGi APIs instead of assuming a jar. */ @Override protected org.eclipse.jetty.annotations.AnnotationParser createAnnotationParser() { return new AnnotationParser(); } /** * Here is the order in which jars and osgi artifacts are scanned for discoverable annotations. *
      *
    1. The container jars are scanned.
    2. *
    3. The WEB-INF/classes are scanned
    4. *
    5. The osgi fragment to the web bundle are parsed.
    6. *
    7. The WEB-INF/lib are scanned
    8. *
    9. The required bundles are parsed
    10. *
    */ @Override public void parseWebInfLib (WebAppContext context, org.eclipse.jetty.annotations.AnnotationParser parser) throws Exception { AnnotationParser oparser = (AnnotationParser)parser; Bundle webbundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE); Bundle[] fragAndRequiredBundles = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(webbundle); if (fragAndRequiredBundles != null) { //index: for (Bundle bundle : fragAndRequiredBundles) { Resource bundleRes = oparser.indexBundle(bundle); if (!context.getMetaData().getWebInfJars().contains(bundleRes)) { context.getMetaData().addWebInfJar(bundleRes); } } //scan the fragments for (Bundle fragmentBundle : fragAndRequiredBundles) { if (fragmentBundle.getHeaders().get(Constants.FRAGMENT_HOST) != null) { //a fragment indeed: parseFragmentBundle(context,oparser,webbundle,fragmentBundle); } } } //scan ourselves parseWebBundle(context,oparser,webbundle); //scan the WEB-INF/lib super.parseWebInfLib(context,parser); if (fragAndRequiredBundles != null) { //scan the required bundles for (Bundle requiredBundle : fragAndRequiredBundles) { if (requiredBundle.getHeaders().get(Constants.FRAGMENT_HOST) == null) { //a bundle indeed: parseRequiredBundle(context,oparser,webbundle,requiredBundle); } } } } /** * Scan a fragment bundle for servlet annotations * @param context The webapp context * @param parser The parser * @param webbundle The current webbundle * @param fragmentBundle The OSGi fragment bundle to scan * @throws Exception */ protected void parseFragmentBundle(WebAppContext context, AnnotationParser parser, Bundle webbundle, Bundle fragmentBundle) throws Exception { parseBundle(context,parser,webbundle,fragmentBundle); } /** * Scan a bundle required by the webbundle for servlet annotations * @param context The webapp context * @param parser The parser * @param webbundle The current webbundle * @param fragmentBundle The OSGi required bundle to scan * @throws Exception */ protected void parseWebBundle(WebAppContext context, AnnotationParser parser, Bundle webbundle) throws Exception { parseBundle(context,parser,webbundle,webbundle); } /** * Scan a bundle required by the webbundle for servlet annotations * @param context The webapp context * @param parser The parser * @param webbundle The current webbundle * @param fragmentBundle The OSGi required bundle to scan * @throws Exception */ protected void parseRequiredBundle(WebAppContext context, AnnotationParser parser, Bundle webbundle, Bundle requiredBundle) throws Exception { parseBundle(context,parser,webbundle,requiredBundle); } protected void parseBundle(WebAppContext context, AnnotationParser parser, Bundle webbundle, Bundle bundle) throws Exception { Resource bundleRes = parser.getResource(bundle); parser.parse(bundle,createClassNameResolver(context)); List annotations = new ArrayList(); gatherAnnotations(annotations, parser.getAnnotationHandlers()); if (webbundle == bundle) { //just like the super with its question about annotations in WEB-INF/classes: //"TODO - where to set the annotations discovered from WEB-INF/classes?" context.getMetaData().addDiscoveredAnnotations(annotations); } else { context.getMetaData().addDiscoveredAnnotations(bundleRes, annotations); } } /** * Returns the same classname resolver than for the webInfjar scanner * @param context * @return */ protected ClassNameResolver createClassNameResolver(final WebAppContext context) { return createClassNameResolver(context,true,false,false,false); } protected ClassNameResolver createClassNameResolver(final WebAppContext context, final boolean excludeSysClass, final boolean excludeServerClass, final boolean excludeEverythingElse, final boolean overrideIsParenLoaderIsPriority) { return new ClassNameResolver () { public boolean isExcluded (String name) { if (context.isSystemClass(name)) return excludeSysClass; if (context.isServerClass(name)) return excludeServerClass; return excludeEverythingElse; } public boolean shouldOverride (String name) { //looking at system classpath if (context.isParentLoaderPriority()) return overrideIsParenLoaderIsPriority; return !overrideIsParenLoaderIsPriority; } }; } } AnnotationParser.java000066400000000000000000000150211174773561500355050ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.annotations; import java.io.File; import java.net.URI; import java.net.URL; import java.util.Comparator; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.TreeSet; import org.eclipse.jetty.annotations.ClassNameResolver; import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper; import org.eclipse.jetty.util.resource.Resource; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; /** * */ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationParser { private Set _alreadyParsed = new HashSet(); private Map _uriToBundle = new HashMap(); private Map _resourceToBundle = new HashMap(); private Map _bundleToUri = new HashMap(); /** * Keep track of a jetty URI Resource and its associated OSGi bundle. * @param uri * @param bundle * @throws Exception */ protected Resource indexBundle(Bundle bundle) throws Exception { File bundleFile = BundleFileLocatorHelper.DEFAULT.getBundleInstallLocation(bundle); Resource resource = Resource.newResource(bundleFile.toURI()); URI uri = resource.getURI(); _uriToBundle.put(uri,bundle); _bundleToUri.put(bundle,uri); _resourceToBundle.put(bundle,resource); return resource; } protected URI getURI(Bundle bundle) { return _bundleToUri.get(bundle); } protected Resource getResource(Bundle bundle) { return _resourceToBundle.get(bundle); } /** * */ @Override public void parse (URI[] uris, ClassNameResolver resolver) throws Exception { for (URI uri : uris) { Bundle associatedBundle = _uriToBundle.get(uri); if (associatedBundle == null) { if (!_alreadyParsed.add(uri)) { continue; } //a jar in WEB-INF/lib or the WEB-INF/classes //use the behavior of the super class for a standard jar. super.parse(new URI[] {uri},resolver); } else { parse(associatedBundle,resolver); } } } protected void parse(Bundle bundle, ClassNameResolver resolver) throws Exception { URI uri = _bundleToUri.get(bundle); if (!_alreadyParsed.add(uri)) { return; } String bundleClasspath = (String)bundle.getHeaders().get(Constants.BUNDLE_CLASSPATH); if (bundleClasspath == null) { bundleClasspath = "."; } //order the paths first by the number of tokens in the path second alphabetically. TreeSet paths = new TreeSet( new Comparator() { public int compare(String o1, String o2) { int paths1 = new StringTokenizer(o1,"/",false).countTokens(); int paths2 = new StringTokenizer(o2,"/",false).countTokens(); if (paths1 == paths2) { return o1.compareTo(o2); } return paths2 - paths1; } }); boolean hasDotPath = false; StringTokenizer tokenizer = new StringTokenizer(bundleClasspath, ",;", false); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken().trim(); if (!token.startsWith("/")) { token = "/" + token; } if (token.equals("/.")) { hasDotPath = true; } else if (!token.endsWith(".jar") && !token.endsWith("/")) { paths.add(token+"/"); } else { paths.add(token); } } //support the development environment: maybe the classes are inside bin or target/classes //this is certainly not useful in production. //however it makes our life so much easier during development. if (bundle.getEntry("/.classpath") != null) { if (bundle.getEntry("/bin/") != null) { paths.add("/bin/"); } else if (bundle.getEntry("/target/classes/") != null) { paths.add("/target/classes/"); } } Enumeration classes = bundle.findEntries("/","*.class",true); if (classes == null) { return; } while (classes.hasMoreElements()) { URL classUrl = (URL) classes.nextElement(); String path = classUrl.getPath(); //remove the longest path possible: String name = null; for (String prefixPath : paths) { if (path.startsWith(prefixPath)) { name = path.substring(prefixPath.length()); break; } } if (name == null && hasDotPath) { //remove the starting '/' name = path.substring(1); } //transform into a classname to pass to the resolver String shortName = name.replace('/', '.').substring(0,name.length()-6); if ((resolver == null)|| (!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName)))) scanClass(classUrl.openStream()); } } } jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/000077500000000000000000000000001174773561500300415ustar00rootroot00000000000000JettyBootstrapActivator.java000066400000000000000000000303101174773561500354740ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot; import java.util.Dictionary; import java.util.Hashtable; import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper; import org.eclipse.jetty.osgi.boot.internal.serverfactory.JettyServerServiceTracker; import org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper; import org.eclipse.jetty.osgi.boot.internal.webapp.JettyContextHandlerServiceTracker; import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer; import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.webapp.WebAppContext; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceRegistration; import org.osgi.util.tracker.BundleTracker; /** * Experiment: bootstrap jetty's complete distrib from an OSGi bundle. Progress: *
      *
    1. basic servlet [ok]
    2. *
    3. basic jetty.xml [ok]
    4. *
    5. basic jetty.xml and jetty-plus.xml [ok]
    6. *
    7. basic jsp [ok with modifications] *
        *
      • Needed to modify the headers of jdt.core-3.1.1 so that its dependency on * eclipse.runtime, eclipse.resources and eclipse.text are optional. Also we * should depend on the latest jdt.core from eclipse-3.5 not from eclipse-3.1.1 * although that will require actual changes to jasper as some internal APIs of * jdt.core have changed.
      • *
      • Modifications to org.mortbay.jetty.jsp-2.1-glassfish: made all imports to * ant, xalan and sun packages optional.
      • *
      *
    8. *
    9. jsp with tag-libs [ok]
    10. *
    11. test-jndi with atomikos and derby inside ${jetty.home}/lib/ext [ok]
    12. * */ public class JettyBootstrapActivator implements BundleActivator { private static JettyBootstrapActivator INSTANCE = null; public static JettyBootstrapActivator getInstance() { return INSTANCE; } private ServiceRegistration _registeredServer; private Server _server; private JettyContextHandlerServiceTracker _jettyContextHandlerTracker; private PackageAdminServiceTracker _packageAdminServiceTracker; private BundleTracker _webBundleTracker; private BundleContext _bundleContext; // private ServiceRegistration _jettyServerFactoryService; private JettyServerServiceTracker _jettyServerServiceTracker; /** * Setup a new jetty Server, registers it as a service. Setup the Service * tracker for the jetty ContextHandlers that are in charge of deploying the * webapps. Setup the BundleListener that supports the extender pattern for * the jetty ContextHandler. * * @param context */ public void start(BundleContext context) throws Exception { INSTANCE = this; _bundleContext = context; // track other bundles and fragments attached to this bundle that we // should activate. _packageAdminServiceTracker = new PackageAdminServiceTracker(context); _jettyServerServiceTracker = new JettyServerServiceTracker(); context.addServiceListener(_jettyServerServiceTracker, "(objectclass=" + Server.class.getName() + ")"); // Register the Jetty Server Factory as a ManagedServiceFactory: // Properties jettyServerMgdFactoryServiceProps = new Properties(); // jettyServerMgdFactoryServiceProps.put("pid", // OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID); // _jettyServerFactoryService = context.registerService( // ManagedServiceFactory.class.getName(), new // JettyServersManagedFactory(), // jettyServerMgdFactoryServiceProps); _jettyContextHandlerTracker = new JettyContextHandlerServiceTracker(_jettyServerServiceTracker); // the tracker in charge of the actual deployment // and that will configure and start the jetty server. context.addServiceListener(_jettyContextHandlerTracker, "(objectclass=" + ContextHandler.class.getName() + ")"); // see if we shoult start a default jetty instance right now. DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context); // now ready to support the Extender pattern: _webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, new WebBundleTrackerCustomizer()); _webBundleTracker.open(); } /* * (non-Javadoc) * * @see * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { try { if (_webBundleTracker != null) { _webBundleTracker.close(); _webBundleTracker = null; } if (_jettyContextHandlerTracker != null) { _jettyContextHandlerTracker.stop(); context.removeServiceListener(_jettyContextHandlerTracker); _jettyContextHandlerTracker = null; } if (_jettyServerServiceTracker != null) { _jettyServerServiceTracker.stop(); context.removeServiceListener(_jettyServerServiceTracker); _jettyServerServiceTracker = null; } if (_packageAdminServiceTracker != null) { _packageAdminServiceTracker.stop(); context.removeServiceListener(_packageAdminServiceTracker); _packageAdminServiceTracker = null; } if (_registeredServer != null) { try { _registeredServer.unregister(); } catch (IllegalArgumentException ill) { // already unregistered. } finally { _registeredServer = null; } } // if (_jettyServerFactoryService != null) // { // try // { // _jettyServerFactoryService.unregister(); // } // catch (IllegalArgumentException ill) // { // // already unregistered. // } // finally // { // _jettyServerFactoryService = null; // } // } } finally { if (_server != null) { _server.stop(); } INSTANCE = null; } } /** * Helper method that creates a new org.jetty.webapp.WebAppContext and * registers it as an OSGi service. The tracker * {@link JettyContextHandlerServiceTracker} will do the actual deployment. * * @param contributor The bundle * @param webappFolderPath The path to the root of the webapp. Must be a * path relative to bundle; either an absolute path. * @param contextPath The context path. Must start with "/" * @throws Exception */ public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath) throws Exception { checkBundleActivated(); WebAppContext contextHandler = new WebAppContext(); Dictionary dic = new Hashtable(); dic.put(OSGiWebappConstants.SERVICE_PROP_WAR, webappFolderPath); dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH, contextPath); String requireTldBundle = (String) contributor.getHeaders().get(OSGiWebappConstants.REQUIRE_TLD_BUNDLE); if (requireTldBundle != null) { dic.put(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE, requireTldBundle); } contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic); } /** * Helper method that creates a new org.jetty.webapp.WebAppContext and * registers it as an OSGi service. The tracker * {@link JettyContextHandlerServiceTracker} will do the actual deployment. * * @param contributor The bundle * @param webappFolderPath The path to the root of the webapp. Must be a * path relative to bundle; either an absolute path. * @param contextPath The context path. Must start with "/" * @param dic TODO: parameter description * @throws Exception */ public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath, Dictionary dic) throws Exception { checkBundleActivated(); WebAppContext contextHandler = new WebAppContext(); dic.put(OSGiWebappConstants.SERVICE_PROP_WAR, webappFolderPath); dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH, contextPath); contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic); } /** * Helper method that creates a new skeleton of a ContextHandler and * registers it as an OSGi service. The tracker * {@link JettyContextHandlerServiceTracker} will do the actual deployment. * * @param contributor The bundle that registers a new context * @param contextFilePath The path to the file inside the bundle that * defines the context. * @throws Exception */ public static void registerContext(Bundle contributor, String contextFilePath) throws Exception { registerContext(contributor, contextFilePath, new Hashtable()); } /** * Helper method that creates a new skeleton of a ContextHandler and * registers it as an OSGi service. The tracker * {@link JettyContextHandlerServiceTracker} will do the actual deployment. * * @param contributor The bundle that registers a new context * @param contextFilePath The path to the file inside the bundle that * defines the context. * @param dic TODO: parameter description * @throws Exception */ public static void registerContext(Bundle contributor, String contextFilePath, Dictionary dic) throws Exception { checkBundleActivated(); ContextHandler contextHandler = new ContextHandler(); dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH, contextFilePath); dic.put(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE, Boolean.TRUE.toString()); contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic); } public static void unregister(String contextPath) { // todo } /** * Since org.eclipse.jetty.osgi.boot does not have a lazy activation policy * when one fo the static methods to register a webapp is called we should * make sure that the bundle is started. */ private static void checkBundleActivated() { if (INSTANCE == null) { Bundle thisBundle = FrameworkUtil.getBundle(JettyBootstrapActivator.class); try { thisBundle.start(); } catch (BundleException e) { // nevermind. } } } /** * @return The bundle context for this bundle. */ public static BundleContext getBundleContext() { checkBundleActivated(); return INSTANCE._bundleContext; } } OSGiAppProvider.java000066400000000000000000000541451174773561500336130ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot// ======================================================================== // Copyright (c) 2009-2010 Mortbay, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Greg Wilkins - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Map.Entry; import java.util.Set; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppProvider; import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.deploy.providers.ContextProvider; import org.eclipse.jetty.deploy.providers.ScanningAppProvider; import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.Scanner; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.WebAppContext; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.Constants; /** * AppProvider for OSGi. Supports the configuration of ContextHandlers and * WebApps. Extends the AbstractAppProvider to support the scanning of context * files located outside of the bundles. *

      * This provider must not be called outside of jetty.boot: it should always be * called via the OSGi service listener. *

      *

      * This provider supports the same set of parameters than the WebAppProvider as * it supports the deployment of WebAppContexts. Except for the scanning of the * webapps directory. *

      *

      * When the parameter autoInstallOSGiBundles is set to true, OSGi bundles that * are located in the monitored directory are installed and started after the * framework as finished auto-starting all the other bundles. * Warning: only use this for development. *

      */ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider { private static final Logger LOG = Log.getLogger(OSGiAppProvider.class); private boolean _extractWars = true; private boolean _parentLoaderPriority = false; private String _defaultsDescriptor; private String _tldBundles; private String[] _configurationClasses; private boolean _autoInstallOSGiBundles = true; //Keep track of the bundles that were installed and that are waiting for the //framework to complete its initialization. Set _pendingBundlesToStart = null; /** * When a context file corresponds to a deployed bundle and is changed we * reload the corresponding bundle. */ private static class Filter implements FilenameFilter { OSGiAppProvider _enclosedInstance; public boolean accept(File dir, String name) { File file = new File(dir,name); if (fileMightBeAnOSGiBundle(file)) { return true; } if (!file.isDirectory()) { String contextName = getDeployedAppName(name); if (contextName != null) { App app = _enclosedInstance.getDeployedApps().get(contextName); return app != null; } } return false; } } /** * @param contextFileName * for example myContext.xml * @return The context, for example: myContext; null if this was not a * suitable contextFileName. */ private static String getDeployedAppName(String contextFileName) { String lowername = contextFileName.toLowerCase(); if (lowername.endsWith(".xml")) { String contextName = contextFileName.substring(0,lowername.length() - ".xml".length()); return contextName; } return null; } /** * Reading the display name of a webapp is really not sufficient for indexing the various * deployed ContextHandlers. * * @param context * @return */ private String getContextHandlerAppName(ContextHandler context) { String appName = context.getDisplayName(); if (appName == null || appName.length() == 0 || getDeployedApps().containsKey(appName)) { if (context instanceof WebAppContext) { appName = ((WebAppContext)context).getContextPath(); if (getDeployedApps().containsKey(appName)) { appName = "noDisplayName"+context.getClass().getSimpleName()+context.hashCode(); } } else { appName = "noDisplayName"+context.getClass().getSimpleName()+context.hashCode(); } } return appName; } /** * Default OSGiAppProvider consutructed when none are defined in the * jetty.xml configuration. */ public OSGiAppProvider() { super(new Filter()); ((Filter)super._filenameFilter)._enclosedInstance = this; } /** * Default OSGiAppProvider consutructed when none are defined in the * jetty.xml configuration. * * @param contextsDir */ public OSGiAppProvider(File contextsDir) throws IOException { this(); setMonitoredDirResource(Resource.newResource(contextsDir.toURI())); } /** * Returns the ContextHandler that was created by WebappRegistractionHelper * * @see AppProvider */ public ContextHandler createContextHandler(App app) throws Exception { // return pre-created Context ContextHandler wah = app.getContextHandler(); if (wah == null) { // for some reason it was not defined when the App was constructed. // we don't support this situation at this point. // once the WebAppRegistrationHelper is refactored, the code // that creates the ContextHandler will actually be here. throw new IllegalStateException("The App must be passed the " + "instance of the ContextHandler when it is construsted"); } if (_configurationClasses != null && wah instanceof WebAppContext) { ((WebAppContext)wah).setConfigurationClasses(_configurationClasses); } if (_defaultsDescriptor != null) ((WebAppContext)wah).setDefaultsDescriptor(_defaultsDescriptor); return app.getContextHandler(); } /** * @see AppProvider */ @Override public void setDeploymentManager(DeploymentManager deploymentManager) { // _manager=deploymentManager; super.setDeploymentManager(deploymentManager); } private static String getOriginId(Bundle contributor, String pathInBundle) { return contributor.getSymbolicName() + "-" + contributor.getVersion().toString() + (pathInBundle.startsWith("/") ? pathInBundle : "/" + pathInBundle); } /** * @param context * @throws Exception */ public void addContext(Bundle contributor, String pathInBundle, ContextHandler context) throws Exception { addContext(getOriginId(contributor, pathInBundle), context); } /** * @param context * @throws Exception */ public void addContext(String originId, ContextHandler context) throws Exception { // TODO apply configuration specific to this provider if (context instanceof WebAppContext) { ((WebAppContext)context).setExtractWAR(isExtract()); } // wrap context as an App App app = new App(getDeploymentManager(),this,originId,context); String appName = getContextHandlerAppName(context); getDeployedApps().put(appName,app); getDeploymentManager().addApp(app); } /** * Called by the scanner of the context files directory. If we find the * corresponding deployed App we reload it by returning the App. Otherwise * we return null and nothing happens: presumably the corresponding OSGi * webapp is not ready yet. * * @return the corresponding already deployed App so that it will be * reloaded. Otherwise returns null. */ @Override protected App createApp(String filename) { // find the corresponding bundle and ContextHandler or WebAppContext // and reload the corresponding App. // see the 2 pass of the refactoring of the WebAppRegistrationHelper. String name = getDeployedAppName(filename); if (name != null) { return getDeployedApps().get(name); } return null; } public void removeContext(ContextHandler context) throws Exception { String appName = getContextHandlerAppName(context); App app = getDeployedApps().remove(context.getDisplayName()); if (app == null) { //try harder to undeploy this context handler. //see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=330098 appName = null; for (Entry deployedApp : getDeployedApps().entrySet()) { if (deployedApp.getValue().getContextHandler() == context) { app = deployedApp.getValue(); appName = deployedApp.getKey(); break; } } if (appName != null) { getDeployedApps().remove(appName); } } if (app != null) { getDeploymentManager().removeApp(app); } } // //copied from WebAppProvider as the parameters are identical. // //only removed the parameer related to extractWars. /* ------------------------------------------------------------ */ /** * Get the parentLoaderPriority. * * @return the parentLoaderPriority */ public boolean isParentLoaderPriority() { return _parentLoaderPriority; } /* ------------------------------------------------------------ */ /** * Set the parentLoaderPriority. * * @param parentLoaderPriority * the parentLoaderPriority to set */ public void setParentLoaderPriority(boolean parentLoaderPriority) { _parentLoaderPriority = parentLoaderPriority; } /* ------------------------------------------------------------ */ /** * Get the defaultsDescriptor. * * @return the defaultsDescriptor */ public String getDefaultsDescriptor() { return _defaultsDescriptor; } /* ------------------------------------------------------------ */ /** * Set the defaultsDescriptor. * * @param defaultsDescriptor * the defaultsDescriptor to set */ public void setDefaultsDescriptor(String defaultsDescriptor) { _defaultsDescriptor = defaultsDescriptor; } /** * The context xml directory. In fact it is the directory watched by the * scanner. */ public File getContextXmlDirAsFile() { try { Resource monitoredDir = getMonitoredDirResource(); if (monitoredDir == null) return null; return monitoredDir.getFile(); } catch (IOException e) { LOG.warn(e); return null; } } /* ------------------------------------------------------------ */ /** * The context xml directory. In fact it is the directory watched by the * scanner. */ public String getContextXmlDir() { try { Resource monitoredDir = getMonitoredDirResource(); if (monitoredDir == null) return null; return monitoredDir.getFile().toURI().toString(); } catch (IOException e) { LOG.warn(e); return null; } } public boolean isExtract() { return _extractWars; } public void setExtract(boolean extract) { _extractWars=extract; } /** * @return true when this app provider locates osgi bundles and features in * its monitored directory and installs them. By default true if there is a folder to monitor. */ public boolean isAutoInstallOSGiBundles() { return _autoInstallOSGiBundles; } /** * <autoInstallOSGiBundles>true</autoInstallOSGiBundles> * @param installingOSGiBundles */ public void setAutoInstallOSGiBundles(boolean installingOSGiBundles) { _autoInstallOSGiBundles=installingOSGiBundles; } /* ------------------------------------------------------------ */ /** * Set the directory in which to look for context XML files. *

      * If a webapp call "foo/" or "foo.war" is discovered in the monitored * directory, then the ContextXmlDir is examined to see if a foo.xml file * exists. If it does, then this deployer will not deploy the webapp and the * ContextProvider should be used to act on the foo.xml file. *

      *

      * Also if this directory contains some osgi bundles, it will install them. *

      * * @see ContextProvider * @param contextsDir */ public void setContextXmlDir(String contextsDir) { setMonitoredDirName(contextsDir); } /** * @param tldBundles Comma separated list of bundles that contain tld jars * that should be setup on the jetty instances created here. */ public void setTldBundles(String tldBundles) { _tldBundles = tldBundles; } /** * @return The list of bundles that contain tld jars that should be setup * on the jetty instances created here. */ public String getTldBundles() { return _tldBundles; } /** * @param configurations The configuration class names. */ public void setConfigurationClasses(String[] configurations) { _configurationClasses = configurations==null?null:(String[])configurations.clone(); } /* ------------------------------------------------------------ */ /** * */ public String[] getConfigurationClasses() { return _configurationClasses; } /** * Overridden to install the OSGi bundles found in the monitored folder. */ @Override protected void doStart() throws Exception { if (isAutoInstallOSGiBundles()) { if (getMonitoredDirResource() == null) { setAutoInstallOSGiBundles(false); LOG.info("Disable autoInstallOSGiBundles as there is not contexts folder to monitor."); } else { File scandir = null; try { scandir = getMonitoredDirResource().getFile(); if (!scandir.exists() || !scandir.isDirectory()) { setAutoInstallOSGiBundles(false); LOG.warn("Disable autoInstallOSGiBundles as the contexts folder '" + scandir.getAbsolutePath() + " does not exist."); scandir = null; } } catch (IOException ioe) { setAutoInstallOSGiBundles(false); LOG.warn("Disable autoInstallOSGiBundles as the contexts folder '" + getMonitoredDirResource().getURI() + " does not exist."); scandir = null; } if (scandir != null) { for (File file : scandir.listFiles()) { if (fileMightBeAnOSGiBundle(file)) { installBundle(file, false); } } } } } super.doStart(); if (isAutoInstallOSGiBundles()) { Scanner.ScanCycleListener scanCycleListner = new AutoStartWhenFrameworkHasCompleted(this); super.addScannerListener(scanCycleListner); } } /** * When the file is a jar or a folder, we look if it looks like an OSGi bundle. * In that case we install it and start it. *

      * Really a simple trick to get going quickly with development. *

      */ @Override protected void fileAdded(String filename) throws Exception { File file = new File(filename); if (isAutoInstallOSGiBundles() && file.exists() && fileMightBeAnOSGiBundle(file)) { installBundle(file, true); } else { super.fileAdded(filename); } } /** * @param file * @return */ private static boolean fileMightBeAnOSGiBundle(File file) { if (file.isDirectory()) { if (new File(file,"META-INF/MANIFEST.MF").exists()) { return true; } } else if (file.getName().endsWith(".jar")) { return true; } return false; } @Override protected void fileChanged(String filename) throws Exception { File file = new File(filename); if (isAutoInstallOSGiBundles() && fileMightBeAnOSGiBundle(file)) { updateBundle(file); } else { super.fileChanged(filename); } } @Override protected void fileRemoved(String filename) throws Exception { File file = new File(filename); if (isAutoInstallOSGiBundles() && fileMightBeAnOSGiBundle(file)) { uninstallBundle(file); } else { super.fileRemoved(filename); } } /** * Returns a bundle according to its location. * In the version 1.6 of org.osgi.framework, BundleContext.getBundle(String) is what we want. * However to support older versions of OSGi. We use our own local refrence mechanism. * @param location * @return */ protected Bundle getBundle(BundleContext bc, String location) { //not available in older versions of OSGi: //return bc.getBundle(location); for (Bundle b : bc.getBundles()) { if (b.getLocation().equals(location)) { return b; } } return null; } protected synchronized Bundle installBundle(File file, boolean start) { try { BundleContext bc = JettyBootstrapActivator.getBundleContext(); String location = file.toURI().toString(); Bundle b = getBundle(bc, location); if (b == null) { b = bc.installBundle(location); } if (b == null) { //not sure we will ever be here, //most likely a BundleException was thrown LOG.warn("The file " + location + " is not an OSGi bundle."); return null; } if (start && b.getHeaders().get(Constants.FRAGMENT_HOST) == null) {//not a fragment, try to start it. if the framework has finished auto-starting. if (!PackageAdminServiceTracker.INSTANCE.frameworkHasCompletedAutostarts()) { if (_pendingBundlesToStart == null) { _pendingBundlesToStart = new HashSet(); } _pendingBundlesToStart.add(b); return null; } else { b.start(); } } return b; } catch (BundleException e) { LOG.warn("Unable to " + (start? "start":"install") + " the bundle " + file.getAbsolutePath(), e); } return null; } protected void uninstallBundle(File file) { try { Bundle b = getBundle(JettyBootstrapActivator.getBundleContext(), file.toURI().toString()); b.stop(); b.uninstall(); } catch (BundleException e) { LOG.warn("Unable to uninstall the bundle " + file.getAbsolutePath(), e); } } protected void updateBundle(File file) { try { Bundle b = getBundle(JettyBootstrapActivator.getBundleContext(), file.toURI().toString()); if (b == null) { installBundle(file, true); } else if (b.getState() == Bundle.ACTIVE) { b.update(); } else { b.start(); } } catch (BundleException e) { LOG.warn("Unable to update the bundle " + file.getAbsolutePath(), e); } } } /** * At the end of each scan, if there are some bundles to be started, * look if the framework has completed its autostart. In that case start those bundles. */ class AutoStartWhenFrameworkHasCompleted implements Scanner.ScanCycleListener { private static final Logger LOG = Log.getLogger(AutoStartWhenFrameworkHasCompleted.class); private final OSGiAppProvider _appProvider; AutoStartWhenFrameworkHasCompleted(OSGiAppProvider appProvider) { _appProvider = appProvider; } public void scanStarted(int cycle) throws Exception { } public void scanEnded(int cycle) throws Exception { if (_appProvider._pendingBundlesToStart != null && PackageAdminServiceTracker.INSTANCE.frameworkHasCompletedAutostarts()) { Iterator it = _appProvider._pendingBundlesToStart.iterator(); while (it.hasNext()) { Bundle b = it.next(); if (b.getHeaders().get(Constants.FRAGMENT_HOST) != null) { continue; } try { b.start(); } catch (BundleException e) { LOG.warn("Unable to start the bundle " + b.getLocation(), e); } } _appProvider._pendingBundlesToStart = null; } } } OSGiServerConstants.java000066400000000000000000000043521174773561500345160ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot; /** * Name of the properties that configure a jetty Server OSGi service. */ public class OSGiServerConstants { //for managed jetty instances, name of the configuration parameters /** * PID of the jetty servers's ManagedFactory */ public static final String MANAGED_JETTY_SERVER_FACTORY_PID = "org.eclipse.jetty.osgi.boot.managedserverfactory"; /** * The associated value of that configuration parameter is the name under which this * instance of the jetty server is tracked. * When a ContextHandler is deployed and it specifies the managedServerName property, it is deployed * on the corresponding jetty managed server or it throws an exception: jetty server not available. */ public static final String MANAGED_JETTY_SERVER_NAME = "managedServerName"; /** * Name of the 'default' jetty server instance. * Usually the first one to be created. */ public static final String MANAGED_JETTY_SERVER_DEFAULT_NAME = "defaultJettyServer"; /** * List of URLs to the jetty.xml files that configure th server. */ public static final String MANAGED_JETTY_XML_CONFIG_URLS = "jetty.etc.config.urls"; /** * List of URLs to the folders where the legacy J2EE shared libraries are stored aka lib/ext, lib/jsp etc. */ public static final String MANAGED_JETTY_SHARED_LIB_FOLDER_URLS = "managedJettySharedLibFolderUrls"; } OSGiWebappConstants.java000066400000000000000000000104021174773561500344570ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot; /** * Name of the service properties for a ContextHandler that configure a webapp deployed on jetty OSGi. */ public class OSGiWebappConstants { /** url scheme to deploy war file as bundled webapp */ public static final String RFC66_WAR_URL_SCHEME = "war"; /** * Name of the header that defines the context path for the embedded webapp. */ public static final String RFC66_WEB_CONTEXTPATH = "Web-ContextPath"; /** * Name of the header that defines the path to the folder where the jsp * files are extracted. */ public static final String RFC66_JSP_EXTRACT_LOCATION = "Jsp-ExtractLocation"; /** Name of the servlet context attribute that points to the bundle context. */ public static final String RFC66_OSGI_BUNDLE_CONTEXT = "osgi-bundlecontext"; /** Name of the servlet context attribute that points to the bundle object. * We can't always rely on the bundle-context as there might be no such thing. */ public static final String JETTY_OSGI_BUNDLE = "osgi-bundle"; /** List of relative pathes within the bundle to the jetty context files. */ public static final String JETTY_CONTEXT_FILE_PATH = "Jetty-ContextFilePath"; /** path within the bundle to the folder that contains the basic resources. */ public static final String JETTY_WAR_FOLDER_PATH = "Jetty-WarFolderPath"; /** path within a fragment hosted by a web-bundle to a folder that contains basic resources. * the path is appended to the lookup path where jetty locates static resources */ public static final String JETTY_WAR_FRAGMENT_FOLDER_PATH = "Jetty-WarFragmentFolderPath"; /** path within a fragment hosted by a web-bundle to a folder that contains basic resources. * The path is prefixed to the lookup path where jetty locates static resources: * this will override static resources with the same name in the web-bundle. */ public static final String JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH = "Jetty-WarPatchFragmentFolderPath"; // OSGi ContextHandler service properties. /** web app context path */ public static final String SERVICE_PROP_CONTEXT_PATH = "contextPath"; /** Path to the web application base folderr */ public static final String SERVICE_PROP_WAR = "war"; /** Extra classpath */ public static final String SERVICE_PROP_EXTRA_CLASSPATH = "extraClasspath"; /** jetty context file path */ public static final String SERVICE_PROP_CONTEXT_FILE_PATH = "contextFilePath"; /** web.xml file path */ public static final String SERVICE_PROP_WEB_XML_PATH = "webXmlFilePath"; /** defaultweb.xml file path */ public static final String SERVICE_PROP_DEFAULT_WEB_XML_PATH = "defaultWebXmlFilePath"; /** * path to the base folder that overrides the computed bundle installation * location if not null useful to install webapps or jetty context files * that are in fact not embedded in a bundle */ public static final String SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE = "thisBundleInstall"; /** * Comma separated list of bundles that contain tld file used by the webapp. */ public static final String REQUIRE_TLD_BUNDLE = "Require-TldBundle"; /** * Comma separated list of bundles that contain tld file used by the webapp. * Both the name of the manifest header and the name of the service property. */ public static final String SERVICE_PROP_REQUIRE_TLD_BUNDLE = REQUIRE_TLD_BUNDLE; } jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/000077500000000000000000000000001174773561500316555ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/000077500000000000000000000000001174773561500324515ustar00rootroot00000000000000TldLocatableURLClassloader.java000066400000000000000000000034111174773561500403260ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.jsp; import java.net.URL; import java.net.URLClassLoader; /** * Tricky url classloader. In fact we don't want a real URLClassLoader: we want * OSGi to provide its classloader and let it does. But to let * {@link org.apache.jasper.compiler.TldLocationsCache} find the core tlds * inside the jars we must be a URLClassLoader that returns an array of jars * where tlds are stored when the method getURLs is called. */ public class TldLocatableURLClassloader extends URLClassLoader { private URL[] _jarsWithTldsInside; public TldLocatableURLClassloader(ClassLoader osgiClassLoader, URL[] jarsWithTldsInside) { super(new URL[] {},osgiClassLoader); _jarsWithTldsInside = jarsWithTldsInside; } /** * @return the jars that contains tlds so that TldLocationsCache or * TldScanner can find them. */ @Override public URL[] getURLs() { return _jarsWithTldsInside; } } TldLocatableURLClassloaderWithInsertedJettyClassloader.java000066400000000000000000000043271174773561500460640ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.jsp; import java.net.URL; /** * Add a classloader to the * org.apache.jasper.compiler.TldLocatableURLClassloader. Hopefuly not * necessary: still experimenting. * * @see TldLocatableURLClassloader */ public class TldLocatableURLClassloaderWithInsertedJettyClassloader extends TldLocatableURLClassloader { private ClassLoader _internalClassLoader; /** * * @param osgiClassLoaderParent * The parent classloader * @param internalClassLoader * The classloader that will be at the same level than the * jarsWithTldsInside * @param jarsWithTldsInside * jars that are scanned for tld files. */ public TldLocatableURLClassloaderWithInsertedJettyClassloader(ClassLoader osgiClassLoaderParent, ClassLoader internalClassLoader, URL[] jarsWithTldsInside) { super(osgiClassLoaderParent,jarsWithTldsInside); _internalClassLoader = internalClassLoader; } protected Class findClass(String name) throws ClassNotFoundException { try { return super.findClass(name); } catch (ClassNotFoundException cne) { if (_internalClassLoader != null) { return _internalClassLoader.loadClass(name); } else { throw cne; } } } } 000077500000000000000000000000001174773561500344745ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactoryDefaultJettyAtJettyHomeHelper.java000066400000000000000000000306441174773561500432300ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory// ======================================================================== // Copyright (c) 2010 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.serverfactory; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.Dictionary; import java.util.Enumeration; import java.util.Hashtable; import java.util.StringTokenizer; import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator; import org.eclipse.jetty.osgi.boot.OSGiServerConstants; import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; /** * Called by the {@link JettyBootstrapActivator} during the starting of the bundle. * If the system property 'jetty.home' is defined and points to a folder, * then setup the corresponding jetty server and starts it. */ public class DefaultJettyAtJettyHomeHelper { private static final Logger LOG = Log.getLogger(DefaultJettyAtJettyHomeHelper.class); /** * contains a comma separated list of pathes to the etc/jetty-*.xml files * used to configure jetty. By default the value is 'etc/jetty.xml' when the * path is relative the file is resolved relatively to jettyhome. */ public static final String SYS_PROP_JETTY_ETC_FILES = OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS; /** * Usual system property used as the hostname for a typical jetty configuration. */ public static final String SYS_PROP_JETTY_HOME = "jetty.home"; /** * System property to point to a bundle that embeds a jetty configuration * and that jetty configuration should be the default jetty server. * First we look for jetty.home. If we don't find it then we look for this property. */ public static final String SYS_PROP_JETTY_HOME_BUNDLE = "jetty.home.bundle"; /** * Usual system property used as the hostname for a typical jetty configuration. */ public static final String SYS_PROP_JETTY_HOST = "jetty.host"; /** * Usual system property used as the port for http for a typical jetty configuration. */ public static final String SYS_PROP_JETTY_PORT = "jetty.port"; /** * Usual system property used as the port for https for a typical jetty configuration. */ public static final String SYS_PROP_JETTY_PORT_SSL = "jetty.port.ssl"; /** * Called by the JettyBootStrapActivator. * If the system property jetty.home is defined and points to a folder, * deploys the corresponding jetty server. *

      * If the system property jetty.home.bundle is defined and points to a bundle. * Look for the configuration of jetty inside that bundle and deploys the corresponding bundle. *

      *

      * In both cases reads the system property 'jetty.etc.config.urls' to locate the configuration * files for the deployed jetty. It is a comma spearate list of URLs or relative paths inside the bundle or folder * to the config files. If underfined it defaults to 'etc/jetty.xml'. *

      *

      * In both cases the system properties jetty.host, jetty.port and jetty.port.ssl are passed to the configuration files * that might use them as part of their properties. *

      */ public static void startJettyAtJettyHome(BundleContext bundleContext) throws Exception { String jettyHomeSysProp = System.getProperty(SYS_PROP_JETTY_HOME); String jettyHomeBundleSysProp = System.getProperty(SYS_PROP_JETTY_HOME_BUNDLE); File jettyHome = null; Bundle jettyHomeBundle = null; if (jettyHomeSysProp != null) { jettyHomeSysProp = resolvePropertyValue(jettyHomeSysProp); //bug 329621 if (jettyHomeSysProp.startsWith("\"") && jettyHomeSysProp.endsWith("\"") || (jettyHomeSysProp.startsWith("'") && jettyHomeSysProp.endsWith("'"))) { jettyHomeSysProp = jettyHomeSysProp.substring(1, jettyHomeSysProp.length() - 1); } if (jettyHomeBundleSysProp != null) { LOG.warn("Both the jetty.home property and the jetty.home.bundle property are defined." + " jetty.home.bundle is not taken into account."); } jettyHome = new File(jettyHomeSysProp); if (!jettyHome.exists() || !jettyHome.isDirectory()) { LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp); return; } } else if (jettyHomeBundleSysProp != null) { jettyHomeBundleSysProp = resolvePropertyValue(jettyHomeBundleSysProp); for (Bundle b : bundleContext.getBundles()) { if (b.getSymbolicName().equals(jettyHomeBundleSysProp)) { jettyHomeBundle = b; break; } } if (jettyHomeBundle == null) { LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp); return; } } if (jettyHome == null && jettyHomeBundle == null) { LOG.warn("No default jetty started."); return; } Server server = new Server(); Dictionary properties = new Hashtable(); properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME); String configURLs = jettyHome != null ? getJettyConfigurationURLs(jettyHome) : getJettyConfigurationURLs(jettyHomeBundle); properties.put(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS, configURLs); LOG.info("Configuring the default jetty server with " + configURLs); //these properties usually are the ones passed to this type of configuration. setProperty(properties,SYS_PROP_JETTY_HOME,System.getProperty(SYS_PROP_JETTY_HOME)); setProperty(properties,SYS_PROP_JETTY_HOST,System.getProperty(SYS_PROP_JETTY_HOST)); setProperty(properties,SYS_PROP_JETTY_PORT,System.getProperty(SYS_PROP_JETTY_PORT)); setProperty(properties,SYS_PROP_JETTY_PORT_SSL,System.getProperty(SYS_PROP_JETTY_PORT_SSL)); bundleContext.registerService(Server.class.getName(), server, properties); // hookNestedConnectorToBridgeServlet(server); } /** * Minimum setup for the location of the configuration files given a jettyhome folder. * Reads the system property jetty.etc.config.urls and look for the corresponding jetty * configuration files that will be used to setup the jetty server. * @param jettyhome * @return */ private static String getJettyConfigurationURLs(File jettyhome) { String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES, "etc/jetty.xml"); StringTokenizer tokenizer = new StringTokenizer(jettyetc, ";,", false); StringBuilder res = new StringBuilder(); while (tokenizer.hasMoreTokens()) { String next = tokenizer.nextToken().trim(); if (!next.startsWith("/") && next.indexOf(':') == -1) { try { next = new File(jettyhome, next).toURI().toURL().toString(); } catch (MalformedURLException e) { LOG.warn(e); continue; } } appendToCommaSeparatedList(res, next); } return res.toString(); } /** * Minimum setup for the location of the configuration files given a configuration * embedded inside a bundle. * Reads the system property jetty.etc.config.urls and look for the corresponding jetty * configuration files that will be used to setup the jetty server. * @param jettyhome * @return */ private static String getJettyConfigurationURLs(Bundle configurationBundle) { String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml"); StringTokenizer tokenizer = new StringTokenizer(jettyetc,";,", false); StringBuilder res = new StringBuilder(); while (tokenizer.hasMoreTokens()) { String etcFile = tokenizer.nextToken().trim(); if (etcFile.startsWith("/") || etcFile.indexOf(":") != -1) { appendToCommaSeparatedList(res, etcFile); } else { Enumeration enUrls = BundleFileLocatorHelper.DEFAULT .findEntries(configurationBundle, etcFile); //default for org.eclipse.osgi.boot where we look inside jettyhome for the default embedded configuration. //default inside jettyhome. this way fragments to the bundle can define their own configuration. if ((enUrls == null || !enUrls.hasMoreElements()) && etcFile.endsWith("etc/jetty.xml")) { enUrls = BundleFileLocatorHelper.DEFAULT .findEntries(configurationBundle, "/jettyhome/etc/jetty-osgi-default.xml"); System.err.println("Configuring jetty with the default embedded configuration:" + "bundle: " + configurationBundle.getSymbolicName() + " config: /jettyhome/etc/jetty-osgi-default.xml"); } if (enUrls == null || !enUrls.hasMoreElements()) { LOG.warn("Unable to locate a jetty configuration file for " + etcFile); } if (enUrls != null) { while (enUrls.hasMoreElements()) { appendToCommaSeparatedList(res, enUrls.nextElement().toString()); } } } } return res.toString(); } private static void appendToCommaSeparatedList(StringBuilder buffer, String value) { if (buffer.length() != 0) { buffer.append(","); } buffer.append(value); } private static void setProperty(Dictionary properties, String key, String value) { if (value != null) { properties.put(key, value); } } /** * recursively substitute the ${sysprop} by their actual system property. * ${sysprop,defaultvalue} will use 'defaultvalue' as the value if no sysprop is defined. * Not the most efficient code but we are shooting for simplicity and speed of development here. * * @param value * @return */ public static String resolvePropertyValue(String value) { int ind = value.indexOf("${"); if (ind == -1) { return value; } int ind2 = value.indexOf('}', ind); if (ind2 == -1) { return value; } String sysprop = value.substring(ind+2, ind2); String defaultValue = null; int comma = sysprop.indexOf(','); if (comma != -1 && comma+1 != sysprop.length()) { defaultValue = sysprop.substring(comma+1); defaultValue = resolvePropertyValue(defaultValue); sysprop = sysprop.substring(0,comma); } else { defaultValue = "${" + sysprop + "}"; } String v = System.getProperty(sysprop); String reminder = value.length() > ind2 + 1 ? value.substring(ind2+1) : ""; reminder = resolvePropertyValue(reminder); if (v != null) { return value.substring(0, ind) + v + reminder; } else { return value.substring(0, ind) + defaultValue + reminder; } } } IManagedJettyServerRegistry.java000066400000000000000000000023041174773561500427430ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory// ======================================================================== // Copyright (c) 2010 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.serverfactory; /** * Keeps track of the running jetty servers. They are named. */ public interface IManagedJettyServerRegistry { /** * @param managedServerName The server name * @return the corresponding jetty server wrapped with its deployment properties. */ public ServerInstanceWrapper getServerInstanceWrapper(String managedServerName); } JettyServerServiceTracker.java000066400000000000000000000132311174773561500424620ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory// ======================================================================== // Copyright (c) 2009-2010 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.serverfactory; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.eclipse.jetty.osgi.boot.OSGiServerConstants; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.osgi.framework.Bundle; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; /** * Deploy the jetty server instances when they are registered as an OSGi * service. */ public class JettyServerServiceTracker implements ServiceListener, IManagedJettyServerRegistry { private static Logger LOG = Log.getLogger(JettyServerServiceTracker.class.getName()); /** * Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin * service. */ private Map _serversIndexedByName = new HashMap(); /** The context-handler to deactivate indexed by ServerInstanceWrapper */ private Map _indexByServiceReference = new HashMap(); /** * Stops each one of the registered servers. */ public void stop() { // not sure that this is really useful but here we go. for (ServerInstanceWrapper wrapper : _serversIndexedByName.values()) { try { wrapper.stop(); } catch (Throwable t) { LOG.warn(t); } } } /** * Receives notification that a service has had a lifecycle change. * * @param ev The ServiceEvent object. */ public void serviceChanged(ServiceEvent ev) { ServiceReference sr = ev.getServiceReference(); switch (ev.getType()) { case ServiceEvent.MODIFIED: case ServiceEvent.UNREGISTERING: { ServerInstanceWrapper instance = unregisterInIndex(ev.getServiceReference()); if (instance != null) { try { instance.stop(); } catch (Exception e) { LOG.warn(e); } } } if (ev.getType() == ServiceEvent.UNREGISTERING) { break; } else { // modified, meaning: we reload it. now that we stopped it; // we can register it. } case ServiceEvent.REGISTERED: { try { Bundle contributor = sr.getBundle(); Server server = (Server) contributor.getBundleContext().getService(sr); ServerInstanceWrapper wrapper = registerInIndex(server, sr); Properties props = new Properties(); for (String key : sr.getPropertyKeys()) { Object value = sr.getProperty(key); props.put(key, value); } wrapper.start(server, props); } catch (Exception e) { LOG.warn(e); } break; } } } private ServerInstanceWrapper registerInIndex(Server server, ServiceReference sr) { String name = (String) sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME); if (name == null) { throw new IllegalArgumentException("The property " + OSGiServerConstants.MANAGED_JETTY_SERVER_NAME + " is mandatory"); } ServerInstanceWrapper wrapper = new ServerInstanceWrapper(name); _indexByServiceReference.put(sr, wrapper); _serversIndexedByName.put(name, wrapper); return wrapper; } /** * Returns the ContextHandler to stop. * * @param reg * @return the ContextHandler to stop. */ private ServerInstanceWrapper unregisterInIndex(ServiceReference sr) { ServerInstanceWrapper handler = _indexByServiceReference.remove(sr); if (handler == null) { // a warning? return null; } String name = handler.getManagedServerName(); if (name != null) { _serversIndexedByName.remove(name); } return handler; } /** * @param managedServerName The server name * @return the corresponding jetty server wrapped with its deployment * properties. */ public ServerInstanceWrapper getServerInstanceWrapper(String managedServerName) { return _serversIndexedByName.get(managedServerName == null ? OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME : managedServerName); } } JettyServersManagedFactory.java000066400000000000000000000167771174773561500426370ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.serverfactory; import java.net.URL; import java.util.Dictionary; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.StringTokenizer; import org.eclipse.jetty.osgi.boot.OSGiServerConstants; import org.eclipse.jetty.osgi.boot.OSGiWebappConstants; import org.eclipse.jetty.server.Server; import org.osgi.framework.Bundle; import org.osgi.framework.ServiceReference; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedServiceFactory; /** * Manages the deployment of jetty server instances. * Not sure this is bringing much compared to the JettyServerServiceTracker. * * @author hmalphettes */ public class JettyServersManagedFactory implements ManagedServiceFactory, IManagedJettyServerRegistry { /** * key to configure the server according to a jetty home folder. the value * is the corresponding java.io.File */ public static final String JETTY_HOME = "jettyhome"; /** key to configure the server according to a jetty.xml file */ public static final String JETTY_CONFIG_XML = "jettyxml"; /** * invoke jetty-factory class. the value of this property is the instance of * that class to call back. */ public static final String JETTY_FACTORY = "jettyfactory"; /** * default property in jetty.xml that is used as the value of the http port. */ public static final String JETTY_HTTP_PORT = "jetty.http.port"; /** * default property in jetty.xml that is used as the value of the https * port. */ public static final String JETTY_HTTPS_PORT = "jetty.http.port"; /** * Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin service. */ private Map _serversIndexedByPID = new HashMap(); /** * PID -> {@link OSGiWebappConstants#MANAGED_JETTY_SERVER_NAME} */ private Map _serversNameIndexedByPID = new HashMap(); /** * {@link OSGiWebappConstants#MANAGED_JETTY_SERVER_NAME} -> PID */ private Map _serversPIDIndexedByName = new HashMap(); /** * Return a descriptive name of this factory. * * @return the name for the factory, which might be localized */ public String getName() { return getClass().getName(); } public void updated(String pid, Dictionary properties) throws ConfigurationException { ServerInstanceWrapper serverInstanceWrapper = getServerByPID(pid); deleted(pid); // do we need to collect the currently deployed http services and // webapps // to be able to re-deploy them later? // probably not. simply restart and see the various service trackers // do everything that is needed. String name = (String)properties.get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME); if (name == null) { throw new ConfigurationException(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, "The name of the server is mandatory"); } serverInstanceWrapper = new ServerInstanceWrapper(name); _serversIndexedByPID.put(pid, serverInstanceWrapper); _serversNameIndexedByPID.put(pid, name); _serversPIDIndexedByName.put(name, pid); try { serverInstanceWrapper.start(new Server(), properties); } catch (Exception e) { throw new ConfigurationException(null, "Error starting jetty server instance", e); } } public synchronized void deleted(String pid) { ServerInstanceWrapper server = (ServerInstanceWrapper)_serversIndexedByPID.remove(pid); String name = _serversNameIndexedByPID.remove(pid); if (name != null) { _serversPIDIndexedByName.remove(name); } else { //something incorrect going on. } if (server != null) { try { server.stop(); } catch (Exception e) { e.printStackTrace(); } } } public synchronized ServerInstanceWrapper getServerByPID(String pid) { return _serversIndexedByPID.get(pid); } /** * @param managedServerName The server name * @return the corresponding jetty server wrapped with its deployment properties. */ public ServerInstanceWrapper getServerInstanceWrapper(String managedServerName) { String pid = _serversPIDIndexedByName.get(managedServerName); return pid != null ? _serversIndexedByPID.get(pid) : null; } /** * Helper method to create and configure a new Jetty Server via the ManagedServiceFactory * @param contributor * @param serverName * @param urlsToJettyXml * @throws Exception */ public static void createNewServer(Bundle contributor, String serverName, String urlsToJettyXml) throws Exception { ServiceReference configurationAdminReference = contributor.getBundleContext().getServiceReference( ConfigurationAdmin.class.getName() ); ConfigurationAdmin confAdmin = (ConfigurationAdmin) contributor.getBundleContext() .getService( configurationAdminReference ); Configuration configuration = confAdmin.createFactoryConfiguration( OSGiServerConstants.MANAGED_JETTY_SERVER_FACTORY_PID, contributor.getLocation() ); Dictionary properties = new Hashtable(); properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, serverName); StringBuilder actualBundleUrls = new StringBuilder(); StringTokenizer tokenizer = new StringTokenizer(urlsToJettyXml, ",", false); while (tokenizer.hasMoreTokens()) { if (actualBundleUrls.length() != 0) { actualBundleUrls.append(","); } String token = tokenizer.nextToken(); if (token.indexOf(':') != -1) { //a complete url. no change needed: actualBundleUrls.append(token); } else if (token.startsWith("/")) { //url relative to the contributor bundle: URL url = contributor.getEntry(token); if (url == null) { actualBundleUrls.append(token); } else { actualBundleUrls.append(url.toString()); } } } properties.put(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS, actualBundleUrls.toString()); configuration.update(properties); } } ServerInstanceWrapper.java000066400000000000000000000362361174773561500416450ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.serverfactory; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import org.eclipse.jetty.deploy.AppProvider; import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator; import org.eclipse.jetty.osgi.boot.OSGiAppProvider; import org.eclipse.jetty.osgi.boot.OSGiServerConstants; import org.eclipse.jetty.osgi.boot.internal.jsp.TldLocatableURLClassloader; import org.eclipse.jetty.osgi.boot.internal.webapp.LibExtClassLoaderHelper; import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleDeployerHelper; import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer; import org.eclipse.jetty.osgi.boot.utils.internal.DefaultFileLocatorHelper; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.xml.XmlConfiguration; import org.xml.sax.SAXParseException; /** * Exposes a Jetty Server to be managed by an OSGi ManagedServiceFactory * Configure and start it. Can also be used from the ManagedServiceFactory */ public class ServerInstanceWrapper { /** * The value of this property points to the parent director of the jetty.xml * configuration file currently executed. Everything is passed as a URL to * support the case where the bundle is zipped. */ public static final String PROPERTY_THIS_JETTY_XML_FOLDER_URL = "this.jetty.xml.parent.folder.url"; private static Logger LOG = Log.getLogger(ServerInstanceWrapper.class.getName()); private final String _managedServerName; /** * The managed jetty server */ private Server _server; private ContextHandlerCollection _ctxtHandler; /** * This is the class loader that should be the parent classloader of any * webapp classloader. It is in fact the _libExtClassLoader with a trick to * let the TldScanner find the jars where the tld files are. */ private ClassLoader _commonParentClassLoaderForWebapps; private DeploymentManager _deploymentManager; private OSGiAppProvider _provider; private WebBundleDeployerHelper _webBundleDeployerHelper; public ServerInstanceWrapper(String managedServerName) { _managedServerName = managedServerName; } public String getManagedServerName() { return _managedServerName; } /** * The classloader that should be the parent classloader for each webapp * deployed on this server. * * @return */ public ClassLoader getParentClassLoaderForWebapps() { return _commonParentClassLoaderForWebapps; } /** * @return The deployment manager registered on this server. */ public DeploymentManager getDeploymentManager() { return _deploymentManager; } /** * @return The app provider registered on this server. */ public OSGiAppProvider getOSGiAppProvider() { return _provider; } public Server getServer() { return _server; } public WebBundleDeployerHelper getWebBundleDeployerHelp() { return _webBundleDeployerHelper; } /** * @return The collection of context handlers */ public ContextHandlerCollection getContextHandlerCollection() { return _ctxtHandler; } public void start(Server server, Dictionary props) throws Exception { _server = server; ClassLoader contextCl = Thread.currentThread().getContextClassLoader(); try { // passing this bundle's classloader as the context classlaoder // makes sure there is access to all the jetty's bundles ClassLoader libExtClassLoader = null; String sharedURLs = (String) props.get(OSGiServerConstants.MANAGED_JETTY_SHARED_LIB_FOLDER_URLS); List shared = sharedURLs != null ? extractFiles(sharedURLs) : null; libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(shared, null, server, JettyBootstrapActivator.class.getClassLoader()); Thread.currentThread().setContextClassLoader(libExtClassLoader); configure(server, props); init(); // now that we have an app provider we can call the registration // customizer. URL[] jarsWithTlds = getJarsWithTlds(); _commonParentClassLoaderForWebapps = jarsWithTlds == null ? libExtClassLoader : new TldLocatableURLClassloader(libExtClassLoader, jarsWithTlds); server.start(); _webBundleDeployerHelper = new WebBundleDeployerHelper(this); } catch (Exception e) { if (server != null) { try { server.stop(); } catch (Exception x) { LOG.ignore(x); } } throw e; } finally { Thread.currentThread().setContextClassLoader(contextCl); } } public void stop() { try { if (_server.isRunning()) { _server.stop(); } } catch (Exception e) { LOG.warn(e); } } /** * TODO: right now only the jetty-jsp bundle is scanned for common taglibs. * Should support a way to plug more bundles that contain taglibs. * * The jasper TldScanner expects a URLClassloader to parse a jar for the * /META-INF/*.tld it may contain. We place the bundles that we know contain * such tag-libraries. Please note that it will work if and only if the * bundle is a jar (!) Currently we just hardcode the bundle that contains * the jstl implemenation. * * A workaround when the tld cannot be parsed with this method is to copy * and paste it inside the WEB-INF of the webapplication where it is used. * * Support only 2 types of packaging for the bundle: - the bundle is a jar * (recommended for runtime.) - the bundle is a folder and contain jars in * the root and/or in the lib folder (nice for PDE developement situations) * Unsupported: the bundle is a jar that embeds more jars. * * @return * @throws Exception */ private URL[] getJarsWithTlds() throws Exception { ArrayList res = new ArrayList(); WebBundleDeployerHelper.staticInit();// that is not looking great. for (WebappRegistrationCustomizer regCustomizer : WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS) { URL[] urls = regCustomizer.getJarsWithTlds(_provider, WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER); for (URL url : urls) { if (!res.contains(url)) res.add(url); } } if (!res.isEmpty()) return res.toArray(new URL[res.size()]); else return null; } private void configure(Server server, Dictionary props) throws Exception { String jettyConfigurationUrls = (String) props.get(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS); List jettyConfigurations = jettyConfigurationUrls != null ? extractResources(jettyConfigurationUrls) : null; if (jettyConfigurations == null || jettyConfigurations.isEmpty()) { return; } Map id_map = new HashMap(); id_map.put("Server", server); Map properties = new HashMap(); Enumeration en = props.keys(); while (en.hasMoreElements()) { Object key = en.nextElement(); Object value = props.get(key); properties.put(String.valueOf(key), String.valueOf(value)); } for (URL jettyConfiguration : jettyConfigurations) { InputStream is = null; try { // Execute a Jetty configuration file Resource r = Resource.newResource(jettyConfiguration); is = r.getInputStream(); XmlConfiguration config = new XmlConfiguration(is); config.getIdMap().putAll(id_map); // #334062 compute the URL of the folder that contains the // jetty.xml conf file // and set it as a property so we can compute relative paths // from it. String urlPath = jettyConfiguration.toString(); int lastSlash = urlPath.lastIndexOf('/'); if (lastSlash > 4) { urlPath = urlPath.substring(0, lastSlash); Map properties2 = new HashMap(properties); properties2.put(PROPERTY_THIS_JETTY_XML_FOLDER_URL, urlPath); config.getProperties().putAll(properties2); } else { config.getProperties().putAll(properties); } config.configure(); id_map = config.getIdMap(); } catch (SAXParseException saxparse) { LOG.warn("Unable to configure the jetty/etc file " + jettyConfiguration, saxparse); throw saxparse; } finally { IO.close(is); } } } /** * Must be called after the server is configured. * * Locate the actual instance of the ContextDeployer and WebAppDeployer that * was created when configuring the server through jetty.xml. If there is no * such thing it won't be possible to deploy webapps from a context and we * throw IllegalStateExceptions. */ private void init() { // Get the context handler _ctxtHandler = (ContextHandlerCollection) _server.getChildHandlerByClass(ContextHandlerCollection.class); // get a deployerManager List deployers = _server.getBeans(DeploymentManager.class); if (deployers != null && !deployers.isEmpty()) { _deploymentManager = deployers.get(0); for (AppProvider provider : _deploymentManager.getAppProviders()) { if (provider instanceof OSGiAppProvider) { _provider = (OSGiAppProvider) provider; break; } } if (_provider == null) { // create it on the fly with reasonable default values. try { _provider = new OSGiAppProvider(); _provider.setMonitoredDirResource(Resource.newResource(getDefaultOSGiContextsHome(new File(System.getProperty("jetty.home"))).toURI())); } catch (IOException e) { LOG.warn(e); } _deploymentManager.addAppProvider(_provider); } } if (_ctxtHandler == null || _provider == null) throw new IllegalStateException("ERROR: No ContextHandlerCollection or OSGiAppProvider configured"); } /** * @return The default folder in which the context files of the osgi bundles * are located and watched. Or null when the system property * "jetty.osgi.contexts.home" is not defined. If the configuration * file defines the OSGiAppProvider's context. This will not be * taken into account. */ File getDefaultOSGiContextsHome(File jettyHome) { String jettyContextsHome = System.getProperty("jetty.osgi.contexts.home"); if (jettyContextsHome != null) { File contextsHome = new File(jettyContextsHome); if (!contextsHome.exists() || !contextsHome.isDirectory()) { throw new IllegalArgumentException( "the ${jetty.osgi.contexts.home} '" + jettyContextsHome + " must exist and be a folder"); } return contextsHome; } return new File(jettyHome, "/contexts"); } File getOSGiContextsHome() { return _provider.getContextXmlDirAsFile(); } /** * @return the urls in this string. */ private List extractResources(String propertyValue) { StringTokenizer tokenizer = new StringTokenizer(propertyValue, ",;", false); List urls = new ArrayList(); while (tokenizer.hasMoreTokens()) { String tok = tokenizer.nextToken(); try { urls.add(((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getLocalURL(new URL(tok))); } catch (Throwable mfe) { LOG.warn(mfe); } } return urls; } /** * Get the folders that might contain jars for the legacy J2EE shared * libraries */ private List extractFiles(String propertyValue) { StringTokenizer tokenizer = new StringTokenizer(propertyValue, ",;", false); List files = new ArrayList(); while (tokenizer.hasMoreTokens()) { String tok = tokenizer.nextToken(); try { URL url = new URL(tok); url = ((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getFileURL(url); if (url.getProtocol().equals("file")) { Resource res = Resource.newResource(url); File folder = res.getFile(); if (folder != null) { files.add(folder); } } } catch (Throwable mfe) { LOG.warn(mfe); } } return files; } } jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/000077500000000000000000000000001174773561500331335ustar00rootroot00000000000000IWebBundleDeployerHelper.java000066400000000000000000000070361174773561500405510ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp// ======================================================================== // Copyright (c) 2010 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.webapp; import org.eclipse.jetty.deploy.ContextDeployer; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.webapp.WebAppContext; import org.osgi.framework.Bundle; /** * Internal interface for the class that deploys a webapp on a server. * Used as we migrate from the single instance of the jety server to multiple jetty servers. */ public interface IWebBundleDeployerHelper { /** when this property is present, the type of context handler registered is not * known in advance. */ public static final String INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE = "unknownContextHandlerType"; /** * Deploy a new web application on the jetty server. * * @param bundle * The bundle * @param webappFolderPath * The path to the root of the webapp. Must be a path relative to * bundle; either an absolute path. * @param contextPath * The context path. Must start with "/" * @param extraClasspath * @param overrideBundleInstallLocation * @param requireTldBundle The list of bundles's symbolic names that contain * tld files that are required by this WAB. * @param webXmlPath * @param defaultWebXmlPath * TODO: parameter description * @return The contexthandler created and started * @throws Exception */ public abstract WebAppContext registerWebapplication(Bundle bundle, String webappFolderPath, String contextPath, String extraClasspath, String overrideBundleInstallLocation, String requireTldBundle, String webXmlPath, String defaultWebXmlPath, WebAppContext webAppContext) throws Exception; /** * Stop a ContextHandler and remove it from the collection. * * @see ContextDeployer#undeploy * @param contextHandler * @throws Exception */ public abstract void unregister(ContextHandler contextHandler) throws Exception; /** * This type of registration relies on jetty's complete context xml file. * Context encompasses jndi and all other things. This makes the definition * of the webapp a lot more self-contained. * * @param contributor * @param contextFileRelativePath * @param extraClasspath * @param overrideBundleInstallLocation * @param requireTldBundle The list of bundles'symbolic name that contain tld files for this webapp. * @param handler the context handler passed in the server * reference that will be configured, deployed and started. * @return The contexthandler created and started * @throws Exception */ public abstract ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath, String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception; }JettyContextHandlerServiceTracker.java000066400000000000000000000404001174773561500425140ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.webapp; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator; import org.eclipse.jetty.osgi.boot.OSGiServerConstants; import org.eclipse.jetty.osgi.boot.OSGiWebappConstants; import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper; import org.eclipse.jetty.osgi.boot.internal.serverfactory.IManagedJettyServerRegistry; import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.Scanner; import org.eclipse.jetty.webapp.WebAppContext; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; /** * When a {@link ContextHandler} service is activated we look into it and if the * corresponding webapp is actually not configured then we go and register it. *

      * The idea is to always go through this class when we deploy a new webapp on * jetty. *

      *

      * We are exposing each web-application as an OSGi service. This lets us update * the webapps and stop/start them directly at the OSGi layer. It also give us * many ways to declare those services: Declarative Services for example.
      * It is a bit different from the way the HttpService works where we would have * a WebappService and we woud register a webapp onto it.
      * It does not go against RFC-66 nor does it prevent us from supporting the * WebappContainer semantics. *

      */ public class JettyContextHandlerServiceTracker implements ServiceListener { private static Logger __logger = Log.getLogger(WebBundleDeployerHelper.class.getName()); /** New style: ability to manage multiple jetty instances */ private final IManagedJettyServerRegistry _registry; /** The context-handler to deactivate indexed by context handler */ private Map _indexByServiceReference = new HashMap(); /** * The index is the bundle-symbolic-name/path/to/context/file when there is * such thing */ private Map _indexByContextFile = new HashMap(); /** in charge of detecting changes in the osgi contexts home folder. */ private Scanner _scanner; /** * @param registry */ public JettyContextHandlerServiceTracker(IManagedJettyServerRegistry registry) throws Exception { _registry = registry; } public void stop() throws Exception { if (_scanner != null) { _scanner.stop(); } // the class that created the server is also in charge of stopping it. // nothing to stop in the WebappRegistrationHelper } /** * @param contextHome Parent folder where the context files can override the * context files defined in the web bundles: equivalent to the * contexts folder in a traditional jetty installation. when * null, just do nothing. */ protected void setupContextHomeScanner(File contextHome) throws IOException { if (contextHome == null) { return; } final String osgiContextHomeFolderCanonicalPath = contextHome.getCanonicalPath(); _scanner = new Scanner(); _scanner.setRecursive(true); _scanner.setReportExistingFilesOnStartup(false); _scanner.addListener(new Scanner.DiscreteListener() { public void fileAdded(String filename) throws Exception { // adding a file does not create a new app, // it just reloads it with the new custom file. // well, if the file does not define a context handler, // then in fact it does remove it. reloadJettyContextHandler(filename, osgiContextHomeFolderCanonicalPath); } public void fileChanged(String filename) throws Exception { reloadJettyContextHandler(filename, osgiContextHomeFolderCanonicalPath); } public void fileRemoved(String filename) throws Exception { // removing a file does not remove the app: // it just goes back to the default embedded in the bundle. // well, if there was no default then it does remove it. reloadJettyContextHandler(filename, osgiContextHomeFolderCanonicalPath); } }); } /** * Receives notification that a service has had a lifecycle change. * * @param ev The ServiceEvent object. */ public void serviceChanged(ServiceEvent ev) { ServiceReference sr = ev.getServiceReference(); switch (ev.getType()) { case ServiceEvent.MODIFIED: case ServiceEvent.UNREGISTERING: { ContextHandler ctxtHandler = unregisterInIndex(ev.getServiceReference()); if (ctxtHandler != null && !ctxtHandler.isStopped()) { try { getWebBundleDeployerHelp(sr).unregister(ctxtHandler); } catch (Exception e) { __logger.warn(e); } } } if (ev.getType() == ServiceEvent.UNREGISTERING) { break; } else { // modified, meaning: we reload it. now that we stopped it; // we can register it. } case ServiceEvent.REGISTERED: { Bundle contributor = sr.getBundle(); BundleContext context = FrameworkUtil.getBundle(JettyBootstrapActivator.class).getBundleContext(); ContextHandler contextHandler = (ContextHandler) context.getService(sr); if (contextHandler.getServer() != null) { // is configured elsewhere. return; } String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); if (contextHandler instanceof WebAppContext && contextFilePath == null) // it could be a web-application that will in fact be configured // via a context file. // that case is identified by the fact that the contextFilePath // is not null // in that case we must use the register context methods. { WebAppContext webapp = (WebAppContext) contextHandler; String contextPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH); if (contextPath == null) { contextPath = webapp.getContextPath(); } String webXmlPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH); if (webXmlPath == null) { webXmlPath = webapp.getDescriptor(); } String defaultWebXmlPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH); if (defaultWebXmlPath == null) { String jettyHome = System.getProperty(DefaultJettyAtJettyHomeHelper.SYS_PROP_JETTY_HOME); if (jettyHome != null) { File etc = new File(jettyHome, "etc"); if (etc.exists() && etc.isDirectory()) { File webDefault = new File(etc, "webdefault.xml"); if (webDefault.exists()) defaultWebXmlPath = webDefault.getAbsolutePath(); else defaultWebXmlPath = webapp.getDefaultsDescriptor(); } else defaultWebXmlPath = webapp.getDefaultsDescriptor(); } } String war = (String) sr.getProperty("war"); try { IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr); if (deployerHelper == null) { } else { WebAppContext handler = deployerHelper.registerWebapplication(contributor, war, contextPath, (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH), (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE), (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE), webXmlPath, defaultWebXmlPath, webapp); if (handler != null) { registerInIndex(handler, sr); } } } catch (Throwable e) { __logger.warn(e); } } else { // consider this just an empty skeleton: if (contextFilePath == null) { throw new IllegalArgumentException("the property contextFilePath is required"); } try { IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr); if (deployerHelper == null) { // more warnings? } else { if (Boolean.TRUE.toString().equals(sr.getProperty(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE))) { contextHandler = null; } ContextHandler handler = deployerHelper.registerContext(contributor, contextFilePath, (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH), (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE), (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE), contextHandler); if (handler != null) { registerInIndex(handler, sr); } } } catch (Throwable e) { __logger.warn(e); } } } break; } } private void registerInIndex(ContextHandler handler, ServiceReference sr) { _indexByServiceReference.put(sr, handler); String key = getSymbolicNameAndContextFileKey(sr); if (key != null) { _indexByContextFile.put(key, sr); } } /** * Returns the ContextHandler to stop. * * @param reg * @return the ContextHandler to stop. */ private ContextHandler unregisterInIndex(ServiceReference sr) { ContextHandler handler = _indexByServiceReference.remove(sr); String key = getSymbolicNameAndContextFileKey(sr); if (key != null) { _indexByContextFile.remove(key); } if (handler == null) { // a warning? return null; } return handler; } /** * @param sr * @return The key for a context file within the osgi contexts home folder. */ private String getSymbolicNameAndContextFileKey(ServiceReference sr) { String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); if (contextFilePath != null) { return sr.getBundle().getSymbolicName() + "/" + contextFilePath; } return null; } /** * Called by the scanner when one of the context files is changed. * * @param contextFileFully */ public void reloadJettyContextHandler(String canonicalNameOfFileChanged, String osgiContextHomeFolderCanonicalPath) { String key = getNormalizedRelativePath(canonicalNameOfFileChanged, osgiContextHomeFolderCanonicalPath); if (key == null) { return; } ServiceReference sr = _indexByContextFile.get(key); if (sr == null) { // nothing to do? return; } serviceChanged(new ServiceEvent(ServiceEvent.MODIFIED, sr)); } /** * @param canFilename * @return */ private String getNormalizedRelativePath(String canFilename, String osgiContextHomeFolderCanonicalPath) { if (!canFilename.startsWith(osgiContextHomeFolderCanonicalPath)) { // why are we here: this does not look like a child of the osgi // contexts home. // warning? return null; } return canFilename.substring(osgiContextHomeFolderCanonicalPath.length()).replace('\\', '/'); } /** * @return The server on which this webapp is meant to be deployed */ private ServerInstanceWrapper getServerInstanceWrapper(String managedServerName) { if (_registry == null) { return null; } if (managedServerName == null) { managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME; } ServerInstanceWrapper wrapper = _registry.getServerInstanceWrapper(managedServerName); // System.err.println("Returning " + managedServerName + " = " + // wrapper); return wrapper; } private IWebBundleDeployerHelper getWebBundleDeployerHelp(ServiceReference sr) { if (_registry == null) { return null; } String managedServerName = (String) sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME); ServerInstanceWrapper wrapper = getServerInstanceWrapper(managedServerName); return wrapper != null ? wrapper.getWebBundleDeployerHelp() : null; } } LibExtClassLoaderHelper.java000066400000000000000000000207131174773561500403660ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.webapp; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.webapp.WebAppContext; /** * Helper to create a URL class-loader with the jars inside * ${jetty.home}/lib/ext and ${jetty.home}/resources. In an ideal world, every * library is an OSGi bundle that does loads nicely. To support standard jars or * bundles that cannot be loaded in the current OSGi environment, we support * inserting the jars in the usual jetty/lib/ext folders in the proper classpath * for the webapps. *

      * Also the folder resources typically contains central configuration files for * things like: log config and others. We enable fragments to register classes * that are called back and passed those resources to do what they need to do. *

      *

      * For example the test-jndi webapplication depends on derby, derbytools, * atomikos none of them are osgi bundles. we can either re-package them or we * can place them in the usual lib/ext.
      * In fact jasper's jsp libraries should maybe place in lib/ext too. *

      *

      * The drawback is that those libraries will not be available in the OSGi * classloader. Note that we could have setup those jars as embedded jars of the * current bundle. However, we would need to know in advance what are those jars * which was not acceptable. Also having those jars in a URLClassLoader seem to * be required for some cases. For example jaspers' TldLocationsCache (replaced * by TldScanner for servlet-3.0).
      * Also all the dependencies of those libraries must be resolvable directly from * the JettyBooStrapper bundle as it is set as the parent classloader. For * example: if atomikos is placed in lib/ext it will work if and only if * JettyBootStrapper import the necessary packages from javax.naming*, * javax.transaction*, javax.mail* etc Most of the common cases of javax are * added as optional import packages into jetty bootstrapper plugin. When there * are not covered: please make a request or create a fragment or register a * bundle with a buddy-policy onto the jetty bootstrapper.. *

      *

      * Alternatives to placing jars in lib/ext *

        *
      1. Bundle the jars in an osgi bundle. Have the webapp(s) that context * depends on them depend on that bundle. Things will go well for jetty.
      2. *
      3. Bundle those jars in an osgi bundle-fragment that targets the * jetty-bootstrap bundle
      4. *
      5. Use equinox Buddy-Policy: register a buddy of the jetty bootstrapper * bundle. (least favorite: it will work only on equinox)
      6. *
      *

      */ public class LibExtClassLoaderHelper { /** * Class called back */ public interface IFilesInJettyHomeResourcesProcessor { void processFilesInResourcesFolder(File jettyHome, Map filesInResourcesFolder); } public static Set registeredFilesInJettyHomeResourcesProcessors = new HashSet(); /** * @param server * @return a url classloader with the jars of resources, lib/ext and the * jars passed in the other argument. The parent classloader usually * is the JettyBootStrapper (an osgi classloader. * @throws MalformedURLException */ public static ClassLoader createLibEtcClassLoader(File jettyHome, Server server, ClassLoader parentClassLoader) throws MalformedURLException { if (jettyHome == null) { return parentClassLoader; } ArrayList urls = new ArrayList(); File jettyResources = new File(jettyHome,"resources"); if (jettyResources.exists()) { // make sure it contains something else than README: Map jettyResFiles = new HashMap(); for (File f : jettyResources.listFiles()) { jettyResFiles.put(f.getName(),f); if (f.getName().toLowerCase().startsWith("readme")) { continue; } else { if (urls.isEmpty()) { urls.add(jettyResources.toURI().toURL()); } } } processFilesInResourcesFolder(jettyHome,jettyResFiles); } File libExt = new File(jettyHome,"lib/ext"); if (libExt.exists()) { for (File f : libExt.listFiles()) { if (f.getName().endsWith(".jar")) { // cheap to tolerate folders so let's do it. URL url = f.toURI().toURL(); if (f.isFile()) {// is this necessary anyways? url = new URL("jar:" + url.toString() + "!/"); } urls.add(url); } } } return new URLClassLoader(urls.toArray(new URL[urls.size()]),parentClassLoader); } /** * @param server * @return a url classloader with the jars of resources, lib/ext and the * jars passed in the other argument. The parent classloader usually * is the JettyBootStrapper (an osgi classloader). * If there was no extra jars to insert, then just return the parentClassLoader. * @throws MalformedURLException */ public static ClassLoader createLibExtClassLoader(List jarsContainerOrJars, List otherJarsOrFolder, Server server, ClassLoader parentClassLoader) throws MalformedURLException { if (jarsContainerOrJars == null && otherJarsOrFolder == null) { return parentClassLoader; } List urls = new ArrayList(); if (otherJarsOrFolder != null) { urls.addAll(otherJarsOrFolder); } if (jarsContainerOrJars != null) { for (File libExt : jarsContainerOrJars) { if (libExt.isDirectory()) { for (File f : libExt.listFiles()) { if (f.getName().endsWith(".jar")) { // cheap to tolerate folders so let's do it. URL url = f.toURI().toURL(); if (f.isFile()) {// is this necessary anyways? url = new URL("jar:" + url.toString() + "!/"); } urls.add(url); } } } } } return new URLClassLoader(urls.toArray(new URL[urls.size()]),parentClassLoader); } /** * When we find files typically used for central logging configuration we do * what it takes in this method to do what the user expects. Without * depending too much directly on a particular logging framework. *

      * We can afford to do some implementation specific code for a logging * framework only in a fragment.
      * Trying to configure log4j and logback in here. *

      *

      * We recommend that slf4j jars are all placed in the osgi framework. And a * single implementation if possible packaged as an osgi bundle is there. *

      */ protected static void processFilesInResourcesFolder(File jettyHome, Map childrenFiles) { for (IFilesInJettyHomeResourcesProcessor processor : registeredFilesInJettyHomeResourcesProcessors) { processor.processFilesInResourcesFolder(jettyHome,childrenFiles); } } } OSGiWebappClassLoader.java000066400000000000000000000220441174773561500377760ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.webapp; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.StringTokenizer; import java.util.jar.JarFile; import javax.servlet.http.HttpServlet; import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.WebAppClassLoader; import org.eclipse.jetty.webapp.WebAppContext; import org.osgi.framework.Bundle; import org.osgi.framework.BundleReference; /** * Extends the webappclassloader to insert the classloader provided by the osgi * bundle at the same level than any other jars palced in the webappclassloader. */ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleReference { private Logger __logger = Log.getLogger(OSGiWebappClassLoader.class.getName().toString()); /** * when a logging framework is setup in the osgi classloaders, it can access * this and register the classes that must not be found in the jar. */ public static Set JAR_WITH_SUCH_CLASS_MUST_BE_EXCLUDED = new HashSet(); public static void addClassThatIdentifiesAJarThatMustBeRejected(Class zclass) { JAR_WITH_SUCH_CLASS_MUST_BE_EXCLUDED.add(zclass.getName().replace('.','/') + ".class"); } public static void addClassThatIdentifiesAJarThatMustBeRejected(String zclassName) { JAR_WITH_SUCH_CLASS_MUST_BE_EXCLUDED.add(zclassName.replace('.','/') + ".class"); } static { addClassThatIdentifiesAJarThatMustBeRejected(HttpServlet.class); } private ClassLoader _osgiBundleClassLoader; private Bundle _contributor; private boolean _lookInOsgiFirst = true; private Set _libsAlreadyInManifest = new HashSet(); /** * @param parent The parent classloader. In this case * @param context The WebAppContext * @param contributor The bundle that defines this web-application. * @throws IOException */ public OSGiWebappClassLoader(ClassLoader parent, WebAppContext context, Bundle contributor, BundleClassLoaderHelper bundleClassLoaderHelper) throws IOException { super(parent,context); _contributor = contributor; _osgiBundleClassLoader = bundleClassLoaderHelper.getBundleClassLoader(contributor); } /** * Returns the Bundle that defined this web-application. * * @return The Bundle object associated with this * BundleReference. */ public Bundle getBundle() { return _contributor; } /** * Reads the manifest. If the manifest is already configured to loads a few * libs we should not add them to the classpath of the webapp. Not really * important as we resolve classes through the osgi classloader first and * then default on the libs of the webapp. */ private void computeLibsAlreadyInOSGiClassLoader() { // TODO } @Override public Enumeration getResources(String name) throws IOException { Enumeration osgiUrls = _osgiBundleClassLoader.getResources(name); Enumeration urls = super.getResources(name); if (_lookInOsgiFirst) { return Collections.enumeration(toList(osgiUrls, urls)); } else { return Collections.enumeration(toList(urls, osgiUrls)); } } @Override public URL getResource(String name) { if (_lookInOsgiFirst) { URL url = _osgiBundleClassLoader.getResource(name); return url != null ? url : super.getResource(name); } else { URL url = super.getResource(name); return url != null ? url : _osgiBundleClassLoader.getResource(name); } } private List toList(Enumeration e, Enumeration e2) { List list = new ArrayList(); while (e!=null && e.hasMoreElements()) list.add(e.nextElement()); while (e2!=null && e2.hasMoreElements()) list.add(e2.nextElement()); return list; } /** * */ protected Class findClass(String name) throws ClassNotFoundException { try { return _lookInOsgiFirst?_osgiBundleClassLoader.loadClass(name):super.findClass(name); } catch (ClassNotFoundException cne) { try { return _lookInOsgiFirst?super.findClass(name):_osgiBundleClassLoader.loadClass(name); } catch (ClassNotFoundException cne2) { throw cne; } } } /** * Parse the classpath ourselves to be able to filter things. This is a * derivative work of the super class */ @Override public void addClassPath(String classPath) throws IOException { StringTokenizer tokenizer = new StringTokenizer(classPath,",;"); while (tokenizer.hasMoreTokens()) { String path = tokenizer.nextToken(); Resource resource = getContext().newResource(path); // Resolve file path if possible File file = resource.getFile(); if (file != null && isAcceptableLibrary(file,JAR_WITH_SUCH_CLASS_MUST_BE_EXCLUDED)) { super.addClassPath(path); } else { __logger.info("Did not add " + path + " to the classloader of the webapp " + getContext()); } } } /** * @param lib * @return true if the lib should be included in the webapp classloader. */ private boolean isAcceptableLibrary(File file, Set pathToClassFiles) { try { if (file.isDirectory()) { for (String criteria : pathToClassFiles) { if (new File(file,criteria).exists()) { return false; } } } else { JarFile jar = null; try { jar = new JarFile(file); for (String criteria : pathToClassFiles) { if (jar.getEntry(criteria) != null) { return false; } } } finally { if (jar != null) try { jar.close(); } catch (IOException ioe) { } } } } catch (IOException e) { // nevermind. just trying our best __logger.ignore(e); } return true; } private static Field _contextField; /** * In the case of the generation of a webapp via a jetty context file we * need a proper classloader to setup the app before we have the * WebappContext So we place a fake one there to start with. We replace it * with the actual webapp context with this method. We also apply the * extraclasspath there at the same time. */ public void setWebappContext(WebAppContext webappContext) { try { if (_contextField == null) { _contextField = WebAppClassLoader.class.getDeclaredField("_context"); _contextField.setAccessible(true); } _contextField.set(this,webappContext); if (webappContext.getExtraClasspath() != null) { addClassPath(webappContext.getExtraClasspath()); } } catch (Throwable t) { // humf that will hurt if it does not work. __logger.warn("Unable to set webappcontext", t); } } } WebBundleDeployerHelper.java000066400000000000000000001214451174773561500404410ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.webapp; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.TreeMap; import org.eclipse.jetty.deploy.ContextDeployer; import org.eclipse.jetty.osgi.boot.OSGiWebappConstants; import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper; import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper; import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper; import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer; import org.eclipse.jetty.osgi.boot.utils.internal.DefaultBundleClassLoaderHelper; import org.eclipse.jetty.osgi.boot.utils.internal.DefaultFileLocatorHelper; import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.webapp.FragmentConfiguration; import org.eclipse.jetty.webapp.TagLibConfiguration; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebInfConfiguration; import org.eclipse.jetty.xml.XmlConfiguration; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleReference; import org.osgi.service.packageadmin.PackageAdmin; import org.osgi.util.tracker.ServiceTracker; import org.xml.sax.SAXException; /** * Bridges the jetty deployers with the OSGi lifecycle where applications are * managed inside OSGi-bundles. *

      * This class should be called as a consequence of the activation of a new * service that is a ContextHandler.
      * This way the new webapps are exposed as OSGi services. *

      *

      * Helper methods to register a bundle that is a web-application or a context. *

      * Limitations: *
        *
      • support for jarred webapps is somewhat limited.
      • *
      */ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper { private static Logger __logger = Log.getLogger(WebBundleDeployerHelper.class.getName()); private static boolean INITIALIZED = false; /** * By default set to: {@link DefaultBundleClassLoaderHelper}. It supports * equinox and apache-felix fragment bundles that are specific to an OSGi * implementation should set a different implementation. */ public static BundleClassLoaderHelper BUNDLE_CLASS_LOADER_HELPER = null; /** * By default set to: {@link DefaultBundleClassLoaderHelper}. It supports * equinox and apache-felix fragment bundles that are specific to an OSGi * implementation should set a different implementation. */ public static BundleFileLocatorHelper BUNDLE_FILE_LOCATOR_HELPER = null; /** * By default set to: {@link DefaultBundleClassLoaderHelper}. It supports * equinox and apache-felix fragment bundles that are specific to an OSGi * implementation should set a different implementation. *

      * Several of those objects can be added here: For example we could have an * optional fragment that setups a specific implementation of JSF for the * whole of jetty-osgi. *

      */ public static Collection JSP_REGISTRATION_HELPERS = new ArrayList(); /** * this class loader loads the jars inside {$jetty.home}/lib/ext it is meant * as a migration path and for jars that are not OSGi ready. also gives * access to the jsp jars. */ // private URLClassLoader _libExtClassLoader; private ServerInstanceWrapper _wrapper; public WebBundleDeployerHelper(ServerInstanceWrapper wrapper) { staticInit(); _wrapper = wrapper; } // Inject the customizing classes that might be defined in fragment bundles. public static synchronized void staticInit() { if (!INITIALIZED) { INITIALIZED = true; // setup the custom BundleClassLoaderHelper try { BUNDLE_CLASS_LOADER_HELPER = (BundleClassLoaderHelper) Class.forName(BundleClassLoaderHelper.CLASS_NAME).newInstance(); } catch (Throwable t) { // System.err.println("support for equinox and felix"); BUNDLE_CLASS_LOADER_HELPER = new DefaultBundleClassLoaderHelper(); } // setup the custom FileLocatorHelper try { BUNDLE_FILE_LOCATOR_HELPER = (BundleFileLocatorHelper) Class.forName(BundleFileLocatorHelper.CLASS_NAME).newInstance(); } catch (Throwable t) { // System.err.println("no jsp/jasper support"); BUNDLE_FILE_LOCATOR_HELPER = new DefaultFileLocatorHelper(); } } } /** * Deploy a new web application on the jetty server. * * @param bundle The bundle * @param webappFolderPath The path to the root of the webapp. Must be a * path relative to bundle; either an absolute path. * @param contextPath The context path. Must start with "/" * @param extraClasspath * @param overrideBundleInstallLocation * @param requireTldBundle The list of bundles's symbolic names that contain * tld files that are required by this WAB. * @param webXmlPath * @param defaultWebXmlPath TODO: parameter description * @return The contexthandler created and started * @throws Exception */ public WebAppContext registerWebapplication(Bundle bundle, String webappFolderPath, String contextPath, String extraClasspath, String overrideBundleInstallLocation, String requireTldBundle, String webXmlPath, String defaultWebXmlPath, WebAppContext webAppContext) throws Exception { File bundleInstall = overrideBundleInstallLocation == null ? BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle) : new File( overrideBundleInstallLocation); File webapp = null; URL baseWebappInstallURL = null; if (webappFolderPath != null && webappFolderPath.length() != 0 && !webappFolderPath.equals(".")) { if (webappFolderPath.startsWith("/") || webappFolderPath.startsWith("file:")) { webapp = new File(webappFolderPath); } else if (bundleInstall != null && bundleInstall.isDirectory()) { webapp = new File(bundleInstall, webappFolderPath); } else if (bundleInstall != null) { Enumeration urls = BUNDLE_FILE_LOCATOR_HELPER.findEntries(bundle, webappFolderPath); if (urls != null && urls.hasMoreElements()) { baseWebappInstallURL = urls.nextElement(); } } } else { webapp = bundleInstall; } if (baseWebappInstallURL == null && (webapp == null || !webapp.exists())) { throw new IllegalArgumentException( "Unable to locate " + webappFolderPath + " inside " + (bundleInstall != null ? bundleInstall.getAbsolutePath() : "unlocated bundle '" + bundle.getSymbolicName() + "'")); } if (baseWebappInstallURL == null && webapp != null) { baseWebappInstallURL = webapp.toURI().toURL(); } return registerWebapplication(bundle, webappFolderPath, baseWebappInstallURL, contextPath, extraClasspath, bundleInstall, requireTldBundle, webXmlPath, defaultWebXmlPath, webAppContext); } /* * (non-Javadoc) * * @see * org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper# * registerWebapplication(org.osgi.framework.Bundle, java.lang.String, * java.io.File, java.lang.String, java.lang.String, java.io.File, * java.lang.String, java.lang.String) */ private WebAppContext registerWebapplication(Bundle contributor, String pathInBundleToWebApp, URL baseWebappInstallURL, String contextPath, String extraClasspath, File bundleInstall, String requireTldBundle, String webXmlPath, String defaultWebXmlPath, WebAppContext context) throws Exception { ClassLoader contextCl = Thread.currentThread().getContextClassLoader(); String[] oldServerClasses = null; try { //apply any META-INF/context.xml file that is found to configure the webapp first applyMetaInfContextXml (contributor, context); // make sure we provide access to all the jetty bundles by going // through this bundle. OSGiWebappClassLoader composite = createWebappClassLoader(contributor); // configure with access to all jetty classes and also all the // classes // that the contributor gives access to. Thread.currentThread().setContextClassLoader(composite); context.setWar(baseWebappInstallURL.toString()); context.setContextPath(contextPath); context.setExtraClasspath(extraClasspath); if (webXmlPath != null && webXmlPath.length() != 0) { File webXml = null; if (webXmlPath.startsWith("/") || webXmlPath.startsWith("file:/")) { webXml = new File(webXmlPath); } else { webXml = new File(bundleInstall, webXmlPath); } if (webXml.exists()) { context.setDescriptor(webXml.getAbsolutePath()); } } if (defaultWebXmlPath == null || defaultWebXmlPath.length() == 0) { // use the one defined by the OSGiAppProvider. defaultWebXmlPath = _wrapper.getOSGiAppProvider().getDefaultsDescriptor(); } if (defaultWebXmlPath != null && defaultWebXmlPath.length() != 0) { File defaultWebXml = null; if (defaultWebXmlPath.startsWith("/") || defaultWebXmlPath.startsWith("file:/")) { defaultWebXml = new File(defaultWebXmlPath); } else { defaultWebXml = new File(bundleInstall, defaultWebXmlPath); } if (defaultWebXml.exists()) { context.setDefaultsDescriptor(defaultWebXml.getAbsolutePath()); } } // other parameters that might be defines on the OSGiAppProvider: context.setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority()); configureWebappClassLoader(contributor, context, composite, requireTldBundle); configureWebAppContext(context, contributor, requireTldBundle); // @see // org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext) // during initialization of the webapp all the jetty packages are // visible // through the webapp classloader. oldServerClasses = context.getServerClasses(); context.setServerClasses(null); _wrapper.getOSGiAppProvider().addContext(contributor, pathInBundleToWebApp, context); // support for patch resources. ideally this should be done inside a // configurator. List patchResources = (List) context.getAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch"); if (patchResources != null) { LinkedList resourcesPath = new LinkedList(); // place the patch resources at the beginning of the lookup // path. resourcesPath.addAll(patchResources); // then place the ones from the host web bundle. Resource hostResources = context.getBaseResource(); if (hostResources instanceof ResourceCollection) { for (Resource re : ((ResourceCollection) hostResources).getResources()) { resourcesPath.add(re); } } else { resourcesPath.add(hostResources); } ResourceCollection rc = new ResourceCollection(resourcesPath.toArray(new Resource[resourcesPath.size()])); context.setBaseResource(rc); } return context; } finally { if (context != null && oldServerClasses != null) { context.setServerClasses(oldServerClasses); } Thread.currentThread().setContextClassLoader(contextCl); } } /* * (non-Javadoc) * * @see * org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper# * unregister(org.eclipse.jetty.server.handler.ContextHandler) */ public void unregister(ContextHandler contextHandler) throws Exception { _wrapper.getOSGiAppProvider().removeContext(contextHandler); } /* * (non-Javadoc) * * @see * org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper# * registerContext(org.osgi.framework.Bundle, java.lang.String, * java.lang.String, java.lang.String) */ public ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath, String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception { File contextsHome = _wrapper.getOSGiAppProvider().getContextXmlDirAsFile(); if (contextsHome != null) { File prodContextFile = new File(contextsHome, contributor.getSymbolicName() + "/" + contextFileRelativePath); if (prodContextFile.exists()) { return registerContext(contributor, contextFileRelativePath, prodContextFile, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler); } } File rootFolder = overrideBundleInstallLocation != null ? Resource.newResource(overrideBundleInstallLocation).getFile() : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(contributor); File contextFile = rootFolder != null ? new File(rootFolder, contextFileRelativePath) : null; if (contextFile != null && contextFile.exists()) { return registerContext(contributor, contextFileRelativePath, contextFile, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler); } else { if (contextFileRelativePath.startsWith("./")) { contextFileRelativePath = contextFileRelativePath.substring(1); } if (!contextFileRelativePath.startsWith("/")) { contextFileRelativePath = "/" + contextFileRelativePath; } URL contextURL = contributor.getEntry(contextFileRelativePath); if (contextURL != null) { Resource r = Resource.newResource(contextURL); return registerContext(contributor, contextFileRelativePath, r.getInputStream(), extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler); } throw new IllegalArgumentException("Could not find the context " + "file " + contextFileRelativePath + " for the bundle " + contributor.getSymbolicName() + (overrideBundleInstallLocation != null ? " using the install location " + overrideBundleInstallLocation : "")); } } /** * This type of registration relies on jetty's complete context xml file. * Context encompasses jndi and all other things. This makes the definition * of the webapp a lot more self-contained. * * @param webapp * @param contextPath * @param classInBundle * @throws Exception */ private ContextHandler registerContext(Bundle contributor, String pathInBundle, File contextFile, String extraClasspath, String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception { InputStream contextFileInputStream = null; try { contextFileInputStream = new BufferedInputStream(new FileInputStream(contextFile)); return registerContext(contributor, pathInBundle, contextFileInputStream, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler); } finally { IO.close(contextFileInputStream); } } /** * @param contributor * @param contextFileInputStream * @return The ContextHandler created and registered or null if it did not * happen. * @throws Exception */ private ContextHandler registerContext(Bundle contributor, String pathInsideBundle, InputStream contextFileInputStream, String extraClasspath, String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception { ClassLoader contextCl = Thread.currentThread().getContextClassLoader(); String[] oldServerClasses = null; WebAppContext webAppContext = null; try { // make sure we provide access to all the jetty bundles by going // through this bundle. OSGiWebappClassLoader composite = createWebappClassLoader(contributor); // configure with access to all jetty classes and also all the // classes // that the contributor gives access to. Thread.currentThread().setContextClassLoader(composite); ContextHandler context = createContextHandler(handler, contributor, contextFileInputStream, extraClasspath, overrideBundleInstallLocation, requireTldBundle); if (context == null) { return null;// did not happen } // ok now register this webapp. we checked when we started jetty // that there // was at least one such handler for webapps. // the actual registration must happen via the new Deployment API. // _ctxtHandler.addHandler(context); configureWebappClassLoader(contributor, context, composite, requireTldBundle); if (context instanceof WebAppContext) { webAppContext = (WebAppContext) context; // @see // org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext) oldServerClasses = webAppContext.getServerClasses(); webAppContext.setServerClasses(null); } _wrapper.getOSGiAppProvider().addContext(contributor, pathInsideBundle, context); return context; } finally { if (webAppContext != null) { webAppContext.setServerClasses(oldServerClasses); } Thread.currentThread().setContextClassLoader(contextCl); } } /** * Applies the properties of WebAppDeployer as defined in jetty.xml. * * @see {WebAppDeployer#scan} around the comment * // configure it */ protected void configureWebAppContext(ContextHandler wah, Bundle contributor, String requireTldBundle) throws IOException { // rfc66 wah.setAttribute(OSGiWebappConstants.RFC66_OSGI_BUNDLE_CONTEXT, contributor.getBundleContext()); // spring-dm-1.2.1 looks for the BundleContext as a different attribute. // not a spec... but if we want to support // org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext // then we need to do this to: wah.setAttribute("org.springframework.osgi.web." + BundleContext.class.getName(), contributor.getBundleContext()); // also pass the bundle directly. sometimes a bundle does not have a // bundlecontext. // it is still useful to have access to the Bundle from the servlet // context. wah.setAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE, contributor); // pass the value of the require tld bundle so that the // TagLibOSGiConfiguration // can pick it up. wah.setAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE, requireTldBundle); Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(contributor); if (fragments != null && fragments.length != 0) { // sorted extra resource base found in the fragments. // the resources are either overriding the resourcebase found in the // web-bundle // or appended. // amongst each resource we sort them according to the alphabetical // order // of the name of the internal folder and the symbolic name of the // fragment. // this is useful to make sure that the lookup path of those // resource base defined by fragments is always the same. // This natural order could be abused to define the order in which // the base resources are // looked up. TreeMap patchResourcesPath = new TreeMap(); TreeMap appendedResourcesPath = new TreeMap(); for (Bundle frag : fragments) { String fragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH); String patchFragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH); if (fragFolder != null) { URL fragUrl = frag.getEntry(fragFolder); if (fragUrl == null) { throw new IllegalArgumentException("Unable to locate " + fragFolder + " inside " + " the fragment '" + frag.getSymbolicName() + "'"); } fragUrl = DefaultFileLocatorHelper.getLocalURL(fragUrl); String key = fragFolder.startsWith("/") ? fragFolder.substring(1) : fragFolder; appendedResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(fragUrl)); } if (patchFragFolder != null) { URL patchFragUrl = frag.getEntry(patchFragFolder); if (patchFragUrl == null) { throw new IllegalArgumentException("Unable to locate " + patchFragUrl + " inside " + " the fragment '" + frag.getSymbolicName() + "'"); } patchFragUrl = DefaultFileLocatorHelper.getLocalURL(patchFragUrl); String key = patchFragFolder.startsWith("/") ? patchFragFolder.substring(1) : patchFragFolder; patchResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(patchFragUrl)); } } if (!appendedResourcesPath.isEmpty()) { wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList(appendedResourcesPath.values())); } if (!patchResourcesPath.isEmpty()) { wah.setAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch", new ArrayList(patchResourcesPath.values())); } if (wah instanceof WebAppContext) { // This is the equivalent of what MetaInfConfiguration does. For // OSGi bundles without the JarScanner WebAppContext webappCtxt = (WebAppContext) wah; // take care of the web-fragments, meta-inf resources and tld // resources: // similar to what MetaInfConfiguration does. List frags = (List) wah.getAttribute(FragmentConfiguration.FRAGMENT_RESOURCES); List resfrags = (List) wah.getAttribute(WebInfConfiguration.RESOURCE_URLS); List tldfrags = (List) wah.getAttribute(TagLibConfiguration.TLD_RESOURCES); for (Bundle frag : fragments) { URL webFrag = frag.getEntry("/META-INF/web-fragment.xml"); Enumeration resEnum = frag.findEntries("/META-INF/resources", "*", true); Enumeration tldEnum = frag.findEntries("/META-INF", "*.tld", false); if (webFrag != null || (resEnum != null && resEnum.hasMoreElements()) || (tldEnum != null && tldEnum.hasMoreElements())) { try { File fragFile = BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(frag); // add it to the webinf jars collection: // no need to check that it was not there yet: it // was not there yet for sure. Resource fragFileAsResource = Resource.newResource(fragFile.toURI()); webappCtxt.getMetaData().addWebInfJar(fragFileAsResource); if (webFrag != null) { if (frags == null) { frags = new ArrayList(); wah.setAttribute(FragmentConfiguration.FRAGMENT_RESOURCES, frags); } frags.add(fragFileAsResource); } if (resEnum != null && resEnum.hasMoreElements()) { URL resourcesEntry = frag.getEntry("/META-INF/resources/"); if (resourcesEntry == null) { // probably we found some fragments to a // bundle. // those are already contributed. // so we skip this. } else { if (resfrags == null) { resfrags = new ArrayList(); wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, resfrags); } resfrags.add(Resource.newResource(DefaultFileLocatorHelper.getLocalURL(resourcesEntry))); } } if (tldEnum != null && tldEnum.hasMoreElements()) { if (tldfrags == null) { tldfrags = new ArrayList(); wah.setAttribute(TagLibConfiguration.TLD_RESOURCES, tldfrags); } while (tldEnum.hasMoreElements()) { URL tldUrl = tldEnum.nextElement(); tldfrags.add(Resource.newResource(DefaultFileLocatorHelper.getLocalURL(tldUrl))); } } } catch (Exception e) { __logger.warn("Unable to locate the bundle " + frag.getBundleId(), e); } } } } } } /** * @See {@link ContextDeployer#scan} * @param contextFile * @return */ protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, Bundle bundle, File contextFile, String extraClasspath, String overrideBundleInstallLocation, String requireTldBundle) { try { return createContextHandler(handlerToConfigure, bundle, new BufferedInputStream(new FileInputStream(contextFile)), extraClasspath, overrideBundleInstallLocation, requireTldBundle); } catch (FileNotFoundException e) { __logger.warn(e); } return null; } /** * @See {@link ContextDeployer#scan} * @param contextFile * @return */ @SuppressWarnings("unchecked") protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, Bundle bundle, InputStream contextInputStream, String extraClasspath, String overrideBundleInstallLocation, String requireTldBundle) { /* * Do something identical to what the ContextProvider would have done: * XmlConfiguration xmlConfiguration=new * XmlConfiguration(resource.getURL()); HashMap properties = new * HashMap(); properties.put("Server", _contexts.getServer()); if * (_configMgr!=null) properties.putAll(_configMgr.getProperties()); * * xmlConfiguration.setProperties(properties); ContextHandler * context=(ContextHandler)xmlConfiguration.configure(); * context.setAttributes(new AttributesMap(_contextAttributes)); */ try { XmlConfiguration xmlConfiguration = new XmlConfiguration(contextInputStream); HashMap properties = new HashMap(); properties.put("Server", _wrapper.getServer()); // insert the bundle's location as a property. setThisBundleHomeProperty(bundle, properties, overrideBundleInstallLocation); xmlConfiguration.getProperties().putAll(properties); ContextHandler context = null; if (handlerToConfigure == null) { context = (ContextHandler) xmlConfiguration.configure(); } else { xmlConfiguration.configure(handlerToConfigure); context = handlerToConfigure; } if (context instanceof WebAppContext) { ((WebAppContext) context).setExtraClasspath(extraClasspath); ((WebAppContext) context).setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority()); if (_wrapper.getOSGiAppProvider().getDefaultsDescriptor() != null && _wrapper.getOSGiAppProvider().getDefaultsDescriptor().length() != 0) { ((WebAppContext) context).setDefaultsDescriptor(_wrapper.getOSGiAppProvider().getDefaultsDescriptor()); } } configureWebAppContext(context, bundle, requireTldBundle); return context; } catch (FileNotFoundException e) { return null; } catch (SAXException e) { __logger.warn(e); } catch (IOException e) { __logger.warn(e); } catch (Throwable e) { __logger.warn(e); } finally { IO.close(contextInputStream); } return null; } /** * Configure a classloader onto the context. If the context is a * WebAppContext, build a WebAppClassLoader that has access to all the jetty * classes thanks to the classloader of the JettyBootStrapper bundle and * also has access to the classloader of the bundle that defines this * context. *

      * If the context is not a WebAppContext, same but with a simpler * URLClassLoader. Note that the URLClassLoader is pretty much fake: it * delegate all actual classloading to the parent classloaders. *

      *

      * The URL[] returned by the URLClassLoader create contained specifically * the jars that some j2ee tools expect and look into. For example the jars * that contain tld files for jasper's jstl support. *

      *

      * Also as the jars in the lib folder and the classes in the classes folder * might already be in the OSGi classloader we filter them out of the * WebAppClassLoader *

      * * @param context * @param contributor * @param webapp * @param contextPath * @param classInBundle * @throws Exception */ protected void configureWebappClassLoader(Bundle contributor, ContextHandler context, OSGiWebappClassLoader webappClassLoader, String requireTldBundle) throws Exception { if (context instanceof WebAppContext) { WebAppContext webappCtxt = (WebAppContext) context; context.setClassLoader(webappClassLoader); webappClassLoader.setWebappContext(webappCtxt); String pathsToRequiredBundles = getPathsToRequiredBundles(context, requireTldBundle); if (pathsToRequiredBundles != null) webappClassLoader.addClassPath(pathsToRequiredBundles); } else { context.setClassLoader(webappClassLoader); } } /** * No matter what the type of webapp, we create a WebappClassLoader. */ protected OSGiWebappClassLoader createWebappClassLoader(Bundle contributor) throws Exception { // we use a temporary WebAppContext object. // if this is a real webapp we will set it on it a bit later: once we // know. OSGiWebappClassLoader webappClassLoader = new OSGiWebappClassLoader(_wrapper.getParentClassLoaderForWebapps(), new WebAppContext(), contributor, BUNDLE_CLASS_LOADER_HELPER); return webappClassLoader; } protected void applyMetaInfContextXml (Bundle bundle, ContextHandler contextHandler) throws Exception { if (bundle == null) return; if (contextHandler == null) return; ClassLoader cl = Thread.currentThread().getContextClassLoader(); __logger.info("Context classloader = "+cl); try { Thread.currentThread().setContextClassLoader(_wrapper.getParentClassLoaderForWebapps()); //find if there is a META-INF/context.xml file URL contextXmlUrl = bundle.getEntry("/META-INF/jetty-webapp-context.xml"); if (contextXmlUrl == null) return; //Apply it just as the standard jetty ContextProvider would do __logger.info("Applying "+contextXmlUrl+" to "+contextHandler); XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXmlUrl); HashMap properties = new HashMap(); properties.put("Server", _wrapper.getServer()); xmlConfiguration.getProperties().putAll(properties); xmlConfiguration.configure(contextHandler); } finally { Thread.currentThread().setContextClassLoader(cl); } } /** * Set the property "this.bundle.install" to point to the location * of the bundle. Useful when is * used. */ private void setThisBundleHomeProperty(Bundle bundle, HashMap properties, String overrideBundleInstallLocation) { try { File location = overrideBundleInstallLocation != null ? new File(overrideBundleInstallLocation) : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle); properties.put("this.bundle.install", location.getCanonicalPath()); properties.put("this.bundle.install.url", bundle.getEntry("/").toString()); } catch (Throwable t) { __logger.warn("Unable to set 'this.bundle.install' " + " for the bundle " + bundle.getSymbolicName(), t); } } private String getPathsToRequiredBundles(ContextHandler context, String requireTldBundle) throws Exception { if (requireTldBundle == null) return null; StringBuilder paths = new StringBuilder(); Bundle bundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE); PackageAdmin packAdmin = getBundleAdmin(); DefaultFileLocatorHelper fileLocatorHelper = new DefaultFileLocatorHelper(); String[] symbNames = requireTldBundle.split(", "); for (String symbName : symbNames) { Bundle[] bs = packAdmin.getBundles(symbName, null); if (bs == null || bs.length == 0) { throw new IllegalArgumentException("Unable to locate the bundle '" + symbName + "' specified in the " + OSGiWebappConstants.REQUIRE_TLD_BUNDLE + " of the manifest of " + bundle.getSymbolicName()); } File f = fileLocatorHelper.getBundleInstallLocation(bs[0]); if (paths.length() > 0) paths.append(", "); __logger.debug("getPathsToRequiredBundles: bundle path=" + bs[0].getLocation() + " uri=" + f.toURI()); paths.append(f.toURI().toURL().toString()); } return paths.toString(); } private PackageAdmin getBundleAdmin() { Bundle bootBundle = ((BundleReference) OSGiWebappConstants.class.getClassLoader()).getBundle(); ServiceTracker serviceTracker = new ServiceTracker(bootBundle.getBundleContext(), PackageAdmin.class.getName(), null); serviceTracker.open(); return (PackageAdmin) serviceTracker.getService(); } } WebBundleTrackerCustomizer.java000066400000000000000000000246161174773561500412000ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp// ======================================================================== // Copyright (c) 2009-2010 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.internal.webapp; import java.net.URL; import java.util.Dictionary; import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator; import org.eclipse.jetty.osgi.boot.OSGiWebappConstants; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.osgi.framework.Bundle; import org.osgi.framework.BundleEvent; import org.osgi.util.tracker.BundleTracker; import org.osgi.util.tracker.BundleTrackerCustomizer; /** * Support bundles that declare the webapp directly through headers in their * manifest. *

      * Those headers will define a new WebApplication: *

        *
      • Web-ContextPath
      • *
      • Jetty-WarFolderPath
      • *
      *

      *

      * Those headers will define a new app started via a jetty-context or a list of * them. ',' column is the separator between the various context files. *

        *
      • Jetty-ContextFilePath
      • *
      *

      * And generate a jetty WebAppContext or another ContextHandler then registers * it as service. Kind of simpler than declarative services and their xml files. * Also avoid having the contributing bundle depend on jetty's package for * WebApp. * * @author hmalphettes */ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer { private static final Logger LOG = Log.getLogger(WebBundleTrackerCustomizer.class); /** * A bundle is being added to the BundleTracker. * *

      * This method is called before a bundle which matched the search parameters * of the BundleTracker is added to the * BundleTracker. This method should return the object to be * tracked for the specified Bundle. The returned object is * stored in the BundleTracker and is available from the * {@link BundleTracker#getObject(Bundle) getObject} method. * * @param bundle The Bundle being added to the * BundleTracker. * @param event The bundle event which caused this customizer method to be * called or null if there is no bundle event * associated with the call to this method. * @return The object to be tracked for the specified Bundle * object or null if the specified Bundle * object should not be tracked. */ public Object addingBundle(Bundle bundle, BundleEvent event) { if (bundle.getState() == Bundle.ACTIVE) { boolean isWebBundle = register(bundle); return isWebBundle ? bundle : null; } else if (bundle.getState() == Bundle.STOPPING) { unregister(bundle); } else { // we should not be called in that state as // we are registered only for ACTIVE and STOPPING } return null; } /** * A bundle tracked by the BundleTracker has been modified. * *

      * This method is called when a bundle being tracked by the * BundleTracker has had its state modified. * * @param bundle The Bundle whose state has been modified. * @param event The bundle event which caused this customizer method to be * called or null if there is no bundle event * associated with the call to this method. * @param object The tracked object for the specified bundle. */ public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) { // nothing the web-bundle was already track. something changed. // we only reload the webapps if the bundle is stopped and restarted. if (bundle.getState() == Bundle.STOPPING || bundle.getState() == Bundle.ACTIVE) { unregister(bundle); } if (bundle.getState() == Bundle.ACTIVE) { register(bundle); } } /** * A bundle tracked by the BundleTracker has been removed. * *

      * This method is called after a bundle is no longer being tracked by the * BundleTracker. * * @param bundle The Bundle that has been removed. * @param event The bundle event which caused this customizer method to be * called or null if there is no bundle event * associated with the call to this method. * @param object The tracked object for the specified bundle. */ public void removedBundle(Bundle bundle, BundleEvent event, Object object) { unregister(bundle); } /** * @param bundle * @return true if this bundle in indeed a web-bundle. */ private boolean register(Bundle bundle) { Dictionary dic = bundle.getHeaders(); String warFolderRelativePath = (String) dic.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH); if (warFolderRelativePath != null) { String contextPath = getWebContextPath(bundle, dic, false);// (String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH); if (contextPath == null || !contextPath.startsWith("/")) { LOG.warn("The manifest header '" + OSGiWebappConstants.JETTY_WAR_FOLDER_PATH + ": " + warFolderRelativePath + "' in the bundle " + bundle.getSymbolicName() + " is not valid: there is no Web-ContextPath defined in the manifest."); return false; } // create the corresponding service and publish it in the context of // the contributor bundle. try { JettyBootstrapActivator.registerWebapplication(bundle, warFolderRelativePath, contextPath); return true; } catch (Throwable e) { LOG.warn("Starting the web-bundle " + bundle.getSymbolicName() + " threw an exception.", e); return true;// maybe it did not work maybe it did. safer to track this bundle. } } else if (dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH) != null) { String contextFileRelativePath = (String) dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH); if (contextFileRelativePath == null) { // nothing to register here. return false; } // support for multiple webapps in the same bundle: String[] pathes = contextFileRelativePath.split(",;"); for (String path : pathes) { try { JettyBootstrapActivator.registerContext(bundle, path.trim()); } catch (Throwable e) { LOG.warn(e); } } return true; } else { // support for OSGi-RFC66; disclaimer, no access to the actual // (draft) of the spec: just a couple of posts on the // world-wide-web. URL rfc66Webxml = bundle.getEntry("/WEB-INF/web.xml"); if (rfc66Webxml == null && dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH) == null) { return false;// no webapp in here } // this is risky: should we make sure that there is no classes and // jars directly available // at the root of the of the bundle: otherwise they are accessible // through the browser. we should enforce that the whole classpath // is // pointing to files and folders inside WEB-INF. We should // filter-out // META-INF too String rfc66ContextPath = getWebContextPath(bundle, dic, rfc66Webxml == null); try { JettyBootstrapActivator.registerWebapplication(bundle, ".", rfc66ContextPath); return true; } catch (Throwable e) { LOG.warn(e); return true;// maybe it did not work maybe it did. safer to track this bundle. } } } private String getWebContextPath(Bundle bundle, Dictionary dic, boolean webinfWebxmlExists) { String rfc66ContextPath = (String) dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH); if (rfc66ContextPath == null) { if (!webinfWebxmlExists) { return null; } // extract from the last token of the bundle's location: // (really ? // could consider processing the symbolic name as an alternative // the location will often reflect the version. // maybe this is relevant when the file is a war) String location = bundle.getLocation(); String toks[] = location.replace('\\', '/').split("/"); rfc66ContextPath = toks[toks.length - 1]; // remove .jar, .war etc: int lastDot = rfc66ContextPath.lastIndexOf('.'); if (lastDot != -1) { rfc66ContextPath = rfc66ContextPath.substring(0, lastDot); } } if (!rfc66ContextPath.startsWith("/")) { rfc66ContextPath = "/" + rfc66ContextPath; } return rfc66ContextPath; } private void unregister(Bundle bundle) { // nothing to do: when the bundle is stopped, each one of its service // reference is also stopped and that is what we use to stop the // corresponding // webapps registered in that bundle. } } jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/000077500000000000000000000000001174773561500312015ustar00rootroot00000000000000BundleClassLoaderHelper.java000066400000000000000000000037451174773561500364640ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.utils; import org.eclipse.jetty.osgi.boot.utils.internal.DefaultBundleClassLoaderHelper; import org.osgi.framework.Bundle; /** * Is there a clean OSGi way to go from the Bundle object to the classloader of * the Bundle ? You can certainly take a class inside the bundle and get the * bundle's classloader that way. Getting the classloader directly from the * bundle would be nice. *

      * We could use fragments that are specific to each OSGi implementation. Using * introspection here to keep packaging simple and avoid the multiplication of * the jars. *

      *

      * The default implementation relies on introspection and supports equinox-3.5 * and felix-2.0.0 *

      */ public interface BundleClassLoaderHelper { /** The name of the custom implementation for this interface in a fragment. */ public static final String CLASS_NAME = "org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelperImpl"; /** The default instance supports felix and equinox */ public static BundleClassLoaderHelper DEFAULT = new DefaultBundleClassLoaderHelper(); /** * @return The classloader of a given bundle. Assuming the bundle is * started. */ public ClassLoader getBundleClassLoader(Bundle bundle); } BundleFileLocatorHelper.java000066400000000000000000000061641174773561500364710ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.utils; import java.io.File; import java.net.URL; import java.util.Enumeration; import org.eclipse.jetty.osgi.boot.utils.internal.DefaultFileLocatorHelper; import org.osgi.framework.Bundle; /** * From a bundle to its location on the filesystem. Assumes the bundle is not a * jar. * * @author hmalphettes */ public interface BundleFileLocatorHelper { /** The name of the custom implementation for this interface in a fragment. */ public static final String CLASS_NAME = "org.eclipse.jetty.osgi.boot.utils.FileLocatorHelperImpl"; /** The default instance supports felix and equinox */ public static BundleFileLocatorHelper DEFAULT = new DefaultFileLocatorHelper(); /** * Works with equinox, felix, nuxeo and probably more. Not exactly in the * spirit of OSGi but quite necessary to support self-contained webapps and * other situations. *

      * Currently only works with bundles that are not jar. *

      * * @param bundle * The bundle * @return Its installation location as a file. * @throws Exception */ public File getBundleInstallLocation(Bundle bundle) throws Exception; /** * Locate a file inside a bundle. * * @param bundle * @param path * @return file object * @throws Exception */ public File getFileInBundle(Bundle bundle, String path) throws Exception; /** * If the bundle is a jar, returns the jar. If the bundle is a folder, look * inside it and search for jars that it returns. *

      * Good enough for our purpose (TldLocationsCache when it scans for tld * files inside jars alone. In fact we only support the second situation for * development purpose where the bundle was imported in pde and the classes * kept in a jar. *

      * * @param bundle * @return The jar(s) file that is either the bundle itself, either the jars * embedded inside it. */ public File[] locateJarsInsideBundle(Bundle bundle) throws Exception; /** * Helper method equivalent to Bundle#getEntry(String entryPath) except that * it searches for entries in the fragments by using the findEntries method. * * @param bundle * @param entryPath * @return null or all the entries found for that path. */ public Enumeration findEntries(Bundle bundle, String entryPath); } WebappRegistrationCustomizer.java000066400000000000000000000047111174773561500376660ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.utils; import java.net.URL; import org.eclipse.jetty.osgi.boot.OSGiAppProvider; /** * Fix various shortcomings with the way jasper parses the tld files. */ public interface WebappRegistrationCustomizer { /** * we could do something a lot more pluggable with a custom header in the * manifest or some customer declarative services let's keep it simple for * now. hopefully the rest of the world won't need to customize this. */ public static final String CLASS_NAME = "org.eclipse.jetty.osgi.boot.jasper.WebappRegistrationCustomizerImpl"; /** * TODO: right now only the jetty-jsp bundle is scanned for common taglibs. * Should support a way to plug more bundles that contain taglibs. * * The jasper TldScanner expects a URLClassloader to parse a jar for the * /META-INF/*.tld it may contain. We place the bundles that we know contain * such tag-libraries. Please note that it will work if and only if the * bundle is a jar (!) Currently we just hardcode the bundle that contains * the jstl implemenation. * * A workaround when the tld cannot be parsed with this method is to copy * and paste it inside the WEB-INF of the webapplication where it is used. * * Support only 2 types of packaging for the bundle: - the bundle is a jar * (recommended for runtime.) - the bundle is a folder and contain jars in * the root and/or in the lib folder (nice for PDE developement situations) * Unsupported: the bundle is a jar that embeds more jars. * * @return array of URLs * @throws Exception */ URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper fileLocator) throws Exception; } jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/000077500000000000000000000000001174773561500330155ustar00rootroot00000000000000DefaultBundleClassLoaderHelper.java000066400000000000000000000167751174773561500416140ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.utils.internal; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; import java.net.URLConnection; import java.util.List; import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper; import org.osgi.framework.Bundle; /** * Default implementation of the BundleClassLoaderHelper. Uses introspection to * support equinox-3.5 and felix-2.0.0 */ public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper { private static boolean identifiedOsgiImpl = false; private static boolean isEquinox = false; private static boolean isFelix = false; private static void init(Bundle bundle) { identifiedOsgiImpl = true; try { isEquinox = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost") != null; } catch (Throwable t) { isEquinox = false; } if (!isEquinox) { try { isFelix = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl") != null; } catch (Throwable t2) { isFelix = false; } } // System.err.println("isEquinox=" + isEquinox); // System.err.println("isFelix=" + isFelix); } /** * Assuming the bundle is started. * * @param bundle * @return classloader object */ public ClassLoader getBundleClassLoader(Bundle bundle) { String bundleActivator = (String)bundle.getHeaders().get("Bundle-Activator"); if (bundleActivator == null) { bundleActivator = (String)bundle.getHeaders().get("Jetty-ClassInBundle"); } if (bundleActivator != null) { try { return bundle.loadClass(bundleActivator).getClassLoader(); } catch (ClassNotFoundException e) { // should not happen as we are called if the bundle is started // anyways. e.printStackTrace(); } } // resort to introspection if (!identifiedOsgiImpl) { init(bundle); } if (isEquinox) { return internalGetEquinoxBundleClassLoader(bundle); } else if (isFelix) { return internalGetFelixBundleClassLoader(bundle); } return null; } private static Method Equinox_BundleHost_getBundleLoader_method; private static Method Equinox_BundleLoader_createClassLoader_method; private static ClassLoader internalGetEquinoxBundleClassLoader(Bundle bundle) { // assume equinox: try { if (Equinox_BundleHost_getBundleLoader_method == null) { Equinox_BundleHost_getBundleLoader_method = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost") .getDeclaredMethod("getBundleLoader",new Class[] {}); Equinox_BundleHost_getBundleLoader_method.setAccessible(true); } Object bundleLoader = Equinox_BundleHost_getBundleLoader_method.invoke(bundle,new Object[] {}); if (Equinox_BundleLoader_createClassLoader_method == null && bundleLoader != null) { Equinox_BundleLoader_createClassLoader_method = bundleLoader.getClass().getClassLoader().loadClass( "org.eclipse.osgi.internal.loader.BundleLoader").getDeclaredMethod("createClassLoader",new Class[] {}); Equinox_BundleLoader_createClassLoader_method.setAccessible(true); } return (ClassLoader)Equinox_BundleLoader_createClassLoader_method.invoke(bundleLoader,new Object[] {}); } catch (Throwable t) { t.printStackTrace(); } return null; } private static Field Felix_BundleImpl_m_modules_field; private static Field Felix_ModuleImpl_m_classLoader_field; private static ClassLoader internalGetFelixBundleClassLoader(Bundle bundle) { // assume felix: try { // now get the current module from the bundle. // and return the private field m_classLoader of ModuleImpl if (Felix_BundleImpl_m_modules_field == null) { Felix_BundleImpl_m_modules_field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl").getDeclaredField( "m_modules"); Felix_BundleImpl_m_modules_field.setAccessible(true); } // Figure out which version of the modules is exported Object currentModuleImpl; try { Object[] moduleArray = (Object[])Felix_BundleImpl_m_modules_field.get(bundle); currentModuleImpl = moduleArray[moduleArray.length - 1]; } catch (Throwable t2) { @SuppressWarnings("unchecked") List moduleArray = (List)Felix_BundleImpl_m_modules_field.get(bundle); currentModuleImpl = moduleArray.get(moduleArray.size() - 1); } if (Felix_ModuleImpl_m_classLoader_field == null && currentModuleImpl != null) { Felix_ModuleImpl_m_classLoader_field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.ModuleImpl").getDeclaredField( "m_classLoader"); Felix_ModuleImpl_m_classLoader_field.setAccessible(true); } // first make sure that the classloader is ready: // the m_classLoader field must be initialized by the // ModuleImpl.getClassLoader() private method. ClassLoader cl = (ClassLoader)Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl); if (cl == null) { // looks like it was not ready: // the m_classLoader field must be initialized by the // ModuleImpl.getClassLoader() private method. // this call will do that. bundle.loadClass("java.lang.Object"); cl = (ClassLoader)Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl); // System.err.println("Got the bundle class loader of felix_: " // + cl); return cl; } else { // System.err.println("Got the bundle class loader of felix: " + // cl); return cl; } } catch (Throwable t) { t.printStackTrace(); } return null; } } DefaultFileLocatorHelper.java000066400000000000000000000347271174773561500404660ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.utils.internal; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Enumeration; import java.util.zip.ZipFile; import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.FileResource; import org.osgi.framework.Bundle; /** * From a bundle to its location on the filesystem. Assumes the bundle is not a * jar. * * @author hmalphettes */ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper { // hack to locate the file-system directly from the bundle. // support equinox, felix and nuxeo's osgi implementations. // not tested on nuxeo and felix just yet. // The url nuxeo and felix return is created directly from the File so it // should work. private static Field BUNDLE_ENTRY_FIELD = null; private static Field FILE_FIELD = null; private static Field BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY = null;// ZipBundleFile // inside // DirZipBundleEntry private static Field ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = null;// ZipFile /** * Works with equinox, felix, nuxeo and probably more. Not exactly in the * spirit of OSGi but quite necessary to support self-contained webapps and * other situations. * * @param bundle The bundle * @return Its installation location as a file. * @throws Exception */ public File getBundleInstallLocation(Bundle bundle) throws Exception { // String installedBundles = System.getProperty("osgi.bundles"); // grab the MANIFEST.MF's url // and then do what it takes. URL url = bundle.getEntry("/META-INF/MANIFEST.MF"); if (url.getProtocol().equals("file")) { // some osgi frameworks do use the file protocole directly in some // situations. Do use the FileResource to transform the URL into a // File: URL#toURI is broken return new FileResource(url).getFile().getParentFile().getParentFile(); } else if (url.getProtocol().equals("bundleentry")) { // say hello to equinox who has its own protocol. // we use introspection like there is no tomorrow to get access to // the File URLConnection con = url.openConnection(); con.setUseCaches(Resource.getDefaultUseCaches()); //work around problems where url connections cache references to jars if (BUNDLE_ENTRY_FIELD == null) { BUNDLE_ENTRY_FIELD = con.getClass().getDeclaredField("bundleEntry"); BUNDLE_ENTRY_FIELD.setAccessible(true); } Object bundleEntry = BUNDLE_ENTRY_FIELD.get(con); if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.FileBundleEntry")) { if (FILE_FIELD == null) { FILE_FIELD = bundleEntry.getClass().getDeclaredField("file"); FILE_FIELD.setAccessible(true); } File f = (File) FILE_FIELD.get(bundleEntry); return f.getParentFile().getParentFile(); } else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry")) { url = bundle.getEntry("/"); con = url.openConnection(); con.setDefaultUseCaches(Resource.getDefaultUseCaches()); if (BUNDLE_ENTRY_FIELD == null) {// this one will be a DirZipBundleEntry BUNDLE_ENTRY_FIELD = con.getClass().getDeclaredField("bundleEntry"); BUNDLE_ENTRY_FIELD.setAccessible(true); } bundleEntry = BUNDLE_ENTRY_FIELD.get(con); if (BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY == null) { BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY = bundleEntry.getClass().getDeclaredField("bundleFile"); BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY.setAccessible(true); } Object zipBundleFile = BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY.get(bundleEntry); if (ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE == null) { ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = zipBundleFile.getClass().getDeclaredField("zipFile"); ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.setAccessible(true); } ZipFile zipFile = (ZipFile) ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile); return new File(zipFile.getName()); } else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry")) { // that will not happen as we did ask for the manifest not a // directory. } } else if ("bundle".equals(url.getProtocol())) { // observed this on felix-2.0.0 String location = bundle.getLocation(); // System.err.println("location " + location); if (location.startsWith("file:/")) { URI uri = new URI(URIUtil.encodePath(location)); return new File(uri); } else if (location.startsWith("file:")) { // location defined in the BundleArchive m_bundleArchive // it is relative to relative to the BundleArchive's // m_archiveRootDir File res = new File(location.substring("file:".length())); if (!res.exists()) { return null; // Object bundleArchive = getFelixBundleArchive(bundle); // File archiveRoot = // getFelixBundleArchiveRootDir(bundleArchive); // String currentLocation = // getFelixBundleArchiveCurrentLocation(bundleArchive); // System.err.println("Got the archive root " + // archiveRoot.getAbsolutePath() // + " current location " + currentLocation + // " is directory ?"); // res = new File(archiveRoot, currentLocation != null // ? currentLocation : location.substring("file:".length())); } return res; } else if (location.startsWith("reference:file:")) { location = URLDecoder.decode(location.substring("reference:".length()), "UTF-8"); File file = new File(location.substring("file:".length())); return file; } } return null; } /** * Locate a file inside a bundle. * * @param bundle * @param path * @return file object * @throws Exception */ public File getFileInBundle(Bundle bundle, String path) throws Exception { if (path != null && path.length() > 0 && path.charAt(0) == '/') { path = path.substring(1); } File bundleInstall = getBundleInstallLocation(bundle); File webapp = path != null && path.length() != 0 ? new File(bundleInstall, path) : bundleInstall; if (!webapp.exists()) { throw new IllegalArgumentException("Unable to locate " + path + " inside " + bundle.getSymbolicName() + " (" + (bundleInstall != null ? bundleInstall.getAbsolutePath() : " no_bundle_location ") + ")"); } return webapp; } /** * Helper method equivalent to Bundle#getEntry(String entryPath) except that * it searches for entries in the fragments by using the Bundle#findEntries * method. * * @param bundle * @param entryPath * @return null or all the entries found for that path. */ public Enumeration findEntries(Bundle bundle, String entryPath) { int last = entryPath.lastIndexOf('/'); String path = last != -1 && last < entryPath.length() - 2 ? entryPath.substring(0, last) : "/"; if (!path.startsWith("/")) { path = "/" + path; } String pattern = last != -1 && last < entryPath.length() - 2 ? entryPath.substring(last + 1) : entryPath; Enumeration enUrls = bundle.findEntries(path, pattern, false); return enUrls; } /** * If the bundle is a jar, returns the jar. If the bundle is a folder, look * inside it and search for jars that it returns. *

      * Good enough for our purpose (TldLocationsCache when it scans for tld * files inside jars alone. In fact we only support the second situation for * development purpose where the bundle was imported in pde and the classes * kept in a jar. *

      * * @param bundle * @return The jar(s) file that is either the bundle itself, either the jars * embedded inside it. */ public File[] locateJarsInsideBundle(Bundle bundle) throws Exception { File jasperLocation = getBundleInstallLocation(bundle); if (jasperLocation.isDirectory()) { // try to find the jar files inside this folder ArrayList urls = new ArrayList(); for (File f : jasperLocation.listFiles()) { if (f.getName().endsWith(".jar") && f.isFile()) { urls.add(f); } else if (f.isDirectory() && f.getName().equals("lib")) { for (File f2 : jasperLocation.listFiles()) { if (f2.getName().endsWith(".jar") && f2.isFile()) { urls.add(f2); } } } } return urls.toArray(new File[urls.size()]); } else { return new File[] { jasperLocation }; } } // introspection on equinox to invoke the getLocalURL method on // BundleURLConnection // equivalent to using the FileLocator without depending on an equinox // class. private static Method BUNDLE_URL_CONNECTION_getLocalURL = null; private static Method BUNDLE_URL_CONNECTION_getFileURL = null; /** * Only useful for equinox: on felix we get the file:// or jar:// url * already. Other OSGi implementations have not been tested *

      * Get a URL to the bundle entry that uses a common protocol (i.e. file: * jar: or http: etc.). *

      * * @return a URL to the bundle entry that uses a common protocol */ public static URL getLocalURL(URL url) { if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol())) { try { URLConnection conn = url.openConnection(); conn.setDefaultUseCaches(Resource.getDefaultUseCaches()); if (BUNDLE_URL_CONNECTION_getLocalURL == null && conn.getClass().getName() .equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection")) { BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null); BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true); } if (BUNDLE_URL_CONNECTION_getLocalURL != null) { return (URL) BUNDLE_URL_CONNECTION_getLocalURL.invoke(conn, null); } } catch (Throwable t) { System.err.println("Unable to locate the OSGi url: '" + url + "'."); t.printStackTrace(); } } return url; } /** * Only useful for equinox: on felix we get the file:// url already. Other * OSGi implementations have not been tested *

      * Get a URL to the content of the bundle entry that uses the file: * protocol. The content of the bundle entry may be downloaded or extracted * to the local file system in order to create a file: URL. * * @return a URL to the content of the bundle entry that uses the file: * protocol *

      */ public static URL getFileURL(URL url) { if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol())) { try { URLConnection conn = url.openConnection(); conn.setDefaultUseCaches(Resource.getDefaultUseCaches()); if (BUNDLE_URL_CONNECTION_getFileURL == null && conn.getClass().getName() .equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection")) { BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null); BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true); } if (BUNDLE_URL_CONNECTION_getFileURL != null) { return (URL) BUNDLE_URL_CONNECTION_getFileURL.invoke(conn, null); } } catch (Throwable t) { t.printStackTrace(); } } return url; } } PackageAdminServiceTracker.java000066400000000000000000000274531174773561500407550ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal// ======================================================================== // Copyright (c) 2009 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.boot.utils.internal; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; import org.osgi.service.packageadmin.PackageAdmin; import org.osgi.service.startlevel.StartLevel; /** * When the PackageAdmin service is activated we can look for the fragments * attached to this bundle and "activate" them. */ public class PackageAdminServiceTracker implements ServiceListener { private BundleContext _context; private List _activatedFragments = new ArrayList(); private boolean _fragmentsWereActivated = false; //Use the deprecated StartLevel to stay compatible with older versions of OSGi. private StartLevel _startLevel; private int _maxStartLevel = 6; public static PackageAdminServiceTracker INSTANCE = null; public PackageAdminServiceTracker(BundleContext context) { INSTANCE = this; _context = context; if (!setup()) { try { _context.addServiceListener(this,"(objectclass=" + PackageAdmin.class.getName() + ")"); } catch (InvalidSyntaxException e) { e.printStackTrace(); // won't happen } } } /** * @return true if the fragments were activated by this method. */ private boolean setup() { ServiceReference sr = _context.getServiceReference(PackageAdmin.class.getName()); _fragmentsWereActivated = sr != null; if (sr != null) invokeFragmentActivators(sr); sr = _context.getServiceReference(StartLevel.class.getName()); if (sr != null) { _startLevel = (StartLevel)_context.getService(sr); try { _maxStartLevel = Integer.parseInt(System.getProperty("osgi.startLevel","6")); } catch (Exception e) { //nevermind default on the usual. _maxStartLevel = 6; } } return _fragmentsWereActivated; } /** * Invokes the optional BundleActivator in each fragment. By convention the * bundle activator for a fragment must be in the package that is defined by * the symbolic name of the fragment and the name of the class must be * 'FragmentActivator'. * * @param event * The ServiceEvent object. */ public void serviceChanged(ServiceEvent event) { if (event.getType() == ServiceEvent.REGISTERED) { invokeFragmentActivators(event.getServiceReference()); } } /** * Helper to access the PackageAdmin and return the fragments hosted by a bundle. * when we drop the support for the older versions of OSGi, we will stop using the PackageAdmin * service. * @param bundle * @return */ public Bundle[] getFragments(Bundle bundle) { ServiceReference sr = _context.getServiceReference(PackageAdmin.class.getName()); if (sr == null) {//we should never be here really. return null; } PackageAdmin admin = (PackageAdmin)_context.getService(sr); return admin.getFragments(bundle); } /** * Returns the fragments and the required-bundles of a bundle. * Recursively collect the required-bundles and fragment when the directive visibility:=reexport * is added to a required-bundle. * @param bundle * @param webFragOrAnnotationOrResources * @return */ public Bundle[] getFragmentsAndRequiredBundles(Bundle bundle) { ServiceReference sr = _context.getServiceReference(PackageAdmin.class.getName()); if (sr == null) {//we should never be here really. return null; } PackageAdmin admin = (PackageAdmin)_context.getService(sr); LinkedHashMap deps = new LinkedHashMap(); collectFragmentsAndRequiredBundles(bundle, admin, deps, false); return deps.values().toArray(new Bundle[deps.size()]); } /** * Returns the fragments and the required-bundles. Collects them transitively when the directive 'visibility:=reexport' * is added to a required-bundle. * @param bundle * @param webFragOrAnnotationOrResources * @return */ protected void collectFragmentsAndRequiredBundles(Bundle bundle, PackageAdmin admin, Map deps, boolean onlyReexport) { Bundle[] fragments = admin.getFragments(bundle); if (fragments != null) { //Also add the bundles required by the fragments. //this way we can inject onto an existing web-bundle a set of bundles that extend it for (Bundle f : fragments) { if (!deps.keySet().contains(f.getSymbolicName())) { deps.put(f.getSymbolicName(), f); collectRequiredBundles(f, admin, deps, onlyReexport); } } } collectRequiredBundles(bundle, admin, deps, onlyReexport); } /** * A simplistic but good enough parser for the Require-Bundle header. * Parses the version range attribute and the visibility directive. * * @param onlyReexport true to collect resources and web-fragments transitively if and only if the directive visibility is reexport. * @param bundle * @return The map of required bundles associated to the value of the jetty-web attribute. */ protected void collectRequiredBundles(Bundle bundle, PackageAdmin admin, Map deps, boolean onlyReexport) { String requiredBundleHeader = (String)bundle.getHeaders().get("Require-Bundle"); if (requiredBundleHeader == null) { return; } StringTokenizer tokenizer = new ManifestTokenizer(requiredBundleHeader); while (tokenizer.hasMoreTokens()) { String tok = tokenizer.nextToken().trim(); StringTokenizer tokenizer2 = new StringTokenizer(tok, ";"); String symbolicName = tokenizer2.nextToken().trim(); if (deps.keySet().contains(symbolicName)) { //was already added. 2 dependencies pointing at the same bundle. continue; } String versionRange = null; boolean reexport = false; while (tokenizer2.hasMoreTokens()) { String next = tokenizer2.nextToken().trim(); if (next.startsWith("bundle-version=")) { if (next.startsWith("bundle-version=\"") || next.startsWith("bundle-version='")) { versionRange = next.substring("bundle-version=\"".length(), next.length()-1); } else { versionRange = next.substring("bundle-version=".length()); } } else if (next.equals("visibility:=reexport")) { reexport = true; } } if (!reexport && onlyReexport) { return; } Bundle[] reqBundles = admin.getBundles(symbolicName, versionRange); if (reqBundles != null && reqBundles.length != 0) { Bundle reqBundle = null; for (Bundle b : reqBundles) { if (b.getState() == Bundle.ACTIVE || b.getState() == Bundle.STARTING) { reqBundle = b; break; } } if (reqBundle == null) { //strange? in OSGi with Require-Bundle, //the dependent bundle is supposed to be active already reqBundle = reqBundles[0]; } deps.put(reqBundle.getSymbolicName(),reqBundle); collectFragmentsAndRequiredBundles(reqBundle, admin, deps, true); } } } private void invokeFragmentActivators(ServiceReference sr) { PackageAdmin admin = (PackageAdmin)_context.getService(sr); Bundle[] fragments = admin.getFragments(_context.getBundle()); if (fragments == null) { return; } for (Bundle frag : fragments) { // find a convention to look for a class inside the fragment. try { String fragmentActivator = frag.getSymbolicName() + ".FragmentActivator"; Class c = Class.forName(fragmentActivator); if (c != null) { BundleActivator bActivator = (BundleActivator)c.newInstance(); bActivator.start(_context); _activatedFragments.add(bActivator); } } catch (NullPointerException e) { // e.printStackTrace(); } catch (InstantiationException e) { // e.printStackTrace(); } catch (IllegalAccessException e) { // e.printStackTrace(); } catch (ClassNotFoundException e) { // e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } public void stop() { INSTANCE = null; for (BundleActivator fragAct : _activatedFragments) { try { fragAct.stop(_context); } catch (Exception e) { e.printStackTrace(); } } } /** * @return true if the framework has completed all the start levels. */ public boolean frameworkHasCompletedAutostarts() { return _startLevel == null ? true : _startLevel.getStartLevel() >= _maxStartLevel; } private static class ManifestTokenizer extends StringTokenizer { public ManifestTokenizer(String header) { super(header, ","); } @Override public String nextToken() { String token = super.nextToken(); while (hasOpenQuote(token) && hasMoreTokens()) { token += "," + super.nextToken(); } return token; } private boolean hasOpenQuote(String token) { int i = -1; do { int quote = getQuote(token, i+1); if (quote < 0) { return false; } i = token.indexOf(quote, i+1); i = token.indexOf(quote, i+1); } while (i >= 0); return true; } private int getQuote(String token, int offset) { int i = token.indexOf('"', offset); int j = token.indexOf('\'', offset); if (i < 0) { if (j < 0) { return -1; } else { return '\''; } } if (j < 0) { return '"'; } if (i < j) { return '"'; } return '\''; } } } jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/nested/000077500000000000000000000000001174773561500303605ustar00rootroot00000000000000NestedConnectorListener.java000066400000000000000000000167601174773561500357610ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/nested// ======================================================================== // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.nested; import java.lang.reflect.Method; import javax.servlet.http.HttpServlet; import org.eclipse.jetty.nested.NestedConnector; import org.eclipse.jetty.util.component.AbstractLifeCycle.AbstractLifeCycleListener; import org.eclipse.jetty.util.component.LifeCycle; import org.osgi.framework.FrameworkUtil; /** * Listens to the start and stop of the NestedConnector to register and unregister the NestedConnector * with the BridgeServlet. *

      * All interactions with the BridgeServlet are done via introspection to avoid depending on it directly. * The BridgeServlet lives in the bootstrap-webapp; not inside equinox. *

      */ public class NestedConnectorListener extends AbstractLifeCycleListener { /** Name of the BridgeServlet class. By default org.eclipse.equinox.servletbridge.BridgeServlet */ private String bridgeServletClassName = "org.eclipse.equinox.servletbridge.BridgeServlet"; /** Name of the static method on the BridgeServlet class to register the * servlet delegate. By default 'registerServletDelegate' */ private String registerServletDelegateMethodName = "registerServletDelegate"; /** Name of the static method on the BridgeServlet class to register the * servlet delegate. By default 'unregisterServletDelegate' */ private String unregisterServletDelegateMethodName = "unregisterServletDelegate"; /** servlet that wraps this NestedConnector and uses the NestedConnector to service the requests. */ private NestedConnectorServletDelegate _servletDelegate; /** * The NestedConnector listened to. */ private NestedConnector nestedConnector; /** * @param bridgeServletClassName Name of the class that is the BridgeServlet. * By default org.eclipse.equinox.servletbridge.BridgeServlet */ public void setBridgeServletClassName(String bridgeServletClassName) { this.bridgeServletClassName = bridgeServletClassName; } public String getBridgeServletClassName() { return this.bridgeServletClassName; } public String getRegisterServletDelegateMethodName() { return this.registerServletDelegateMethodName; } public String getUnregisterServletDelegateMethodName() { return this.unregisterServletDelegateMethodName; } /** * @param registerServletDelegateMethodName Name of the static method on the BridgeServlet class * to register the servlet delegate. */ public void setRegisterServletDelegateMethodName(String registerServletDelegateMethodName) { this.registerServletDelegateMethodName = registerServletDelegateMethodName; } /** * @param unregisterServletDelegateMethodName Name of the static method on the BridgeServlet class * to unregister the servlet delegate. */ public void setUnregisterServletDelegateMethodName(String unregisterServletDelegateMethodName) { this.unregisterServletDelegateMethodName = unregisterServletDelegateMethodName; } /** * @param nestedConnector The NestedConnector that we are listening to here. */ public void setNestedConnector(NestedConnector nestedConnector) { this.nestedConnector = nestedConnector; } /** * @return The NestedConnector that we are listening to here. */ public NestedConnector getNestedConnector() { return this.nestedConnector; } @Override public void lifeCycleStarted(LifeCycle event) { try { registerWithBridgeServlet(); } catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException)e; } throw new RuntimeException("Unable to register the servlet delegate into the BridgeServlet.", e); } } @Override public void lifeCycleStopping(LifeCycle event) { try { unregisterWithBridgeServlet(); } catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException)e; } throw new RuntimeException("Unable to unregister the servlet delegate into the BridgeServlet.", e); } } /** * Hook into the BridgeServlet */ protected void registerWithBridgeServlet() throws Exception { _servletDelegate = new NestedConnectorServletDelegate(getNestedConnector()); try { invokeStaticMethod(getBridgeServletClassName(), getRegisterServletDelegateMethodName(), new Class[] {HttpServlet.class}, _servletDelegate); } catch (Throwable t) { _servletDelegate.destroy(); _servletDelegate = null; if (t instanceof Exception) { throw (Exception)t; } throw new RuntimeException("Unable to register the servlet delegate into the BridgeServlet.", t); } } /** * Unhook into the BridgeServlet */ protected void unregisterWithBridgeServlet() throws Exception { if (_servletDelegate != null) { try { invokeStaticMethod(getBridgeServletClassName(), getUnregisterServletDelegateMethodName(), new Class[] {HttpServlet.class}, _servletDelegate); } catch (Throwable t) { if (t instanceof Exception) { throw (Exception)t; } throw new RuntimeException("Unable to unregister the servlet delegate from the BridgeServlet.", t); } finally { _servletDelegate.destroy(); _servletDelegate = null; } } } /** * * @param clName * @param methName * @param argType * @throws Exception */ private static void invokeStaticMethod(String clName, String methName, Class[] argType, Object...args) throws Exception { Method m = getMethod(clName, methName, argType); m.invoke(null, args); } /** * * @param clName Class that belongs to the parent classloader of the OSGi framework. * @param methName Name of the method to find. * @param argType Argument types of the method to find. * @throws Exception */ private static Method getMethod(String clName, String methName, Class... argType) throws Exception { Class bridgeServletClass = FrameworkUtil.class.getClassLoader() .loadClass(clName); return getMethod(bridgeServletClass, methName, argType); } private static Method getMethod(Class cl, String methName, Class... argType) throws Exception { Method meth = null; try { meth = cl.getMethod(methName, argType); return meth; } catch (Exception e) { for (Method m : cl.getMethods()) { if (m.getName().equals(methName) && m.getParameterTypes().length == argType.length) { int i = 0; for (Class p : m.getParameterTypes()) { Class ap = argType[i]; if (p.getName().equals(ap.getName()) && !p.equals(ap)) { throw new IllegalStateException("The method \"" + m.toGenericString() + "\" was found. but the parameter class " + p.getName() + " is not the same " + " inside OSGi classloader (" + ap.getClassLoader() + ") and inside the " + cl.getName() + " classloader (" + p.getClassLoader() + ")." + " Are the ExtensionBundles correctly defined?"); } } } } throw e; } } } NestedConnectorServletDelegate.java000066400000000000000000000030651174773561500372450ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/nested// ======================================================================== // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.nested; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import org.eclipse.jetty.nested.NestedConnector; /** * Wraps a NestedConnector into a servlet that can be plugged into * BridgeServlet#registerServletDelegate */ public class NestedConnectorServletDelegate extends HttpServlet { private static final long serialVersionUID = 1L; private final NestedConnector _nestedConnector; public NestedConnectorServletDelegate(NestedConnector nestedConnector) { _nestedConnector = nestedConnector; } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { _nestedConnector.service(req, res); } } jetty8-8.1.3/jetty-osgi/jetty-osgi-equinoxtools/000077500000000000000000000000001174773561500217355ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-equinoxtools/META-INF/000077500000000000000000000000001174773561500230755ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-equinoxtools/META-INF/MANIFEST.MF000066400000000000000000000017511174773561500245330ustar00rootroot00000000000000Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Console Bundle-SymbolicName: org.eclipse.jetty.osgi.equinoxtools Bundle-Description: Example application: equinox console accesssible on the web Bundle-Version: 8.1.3.qualifier Bundle-Activator: org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator Import-Package: javax.servlet;version="2.5.0", javax.servlet.http;version="2.5.0", org.eclipse.jetty.continuation;version="8.1.3", org.eclipse.jetty.io;version="8.1.3", org.eclipse.jetty.util;version="8.1.3", org.eclipse.jetty.util.log;version="8.1.3", org.eclipse.jetty.websocket;version="8.1.3", org.eclipse.osgi.framework.console;version="1.1.0", org.osgi.framework;version="1.3.0", org.osgi.service.http;version="1.2.0", org.osgi.util.tracker;version="1.3.0" Export-Package: org.eclipse.jetty.osgi.equinoxtools;x-internal:=true;version="8.1.3", org.eclipse.jetty.osgi.equinoxtools.console;x-internal:=true;version="8.1.3" Bundle-RequiredExecutionEnvironment: J2SE-1.6 jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/000077500000000000000000000000001174773561500215245ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/META-INF/000077500000000000000000000000001174773561500226645ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/META-INF/MANIFEST.MF000066400000000000000000000013311174773561500243140ustar00rootroot00000000000000Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: OSGi HttpService provided by equinox HttpServiceServlet deployed on jetty Bundle-SymbolicName: org.eclipse.jetty.osgi.httpservice Bundle-Version: 8.1.3.qualifier Bundle-Vendor: Mort Bay Consulting Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Jetty-ContextFilePath: contexts/httpservice.xml Import-Package: javax.servlet;version="2.6.0", javax.servlet.http;version="2.6.0", org.eclipse.equinox.http.servlet, org.eclipse.jetty.server;version="8.1.3", org.eclipse.jetty.server.handler;version="8.1.3", org.eclipse.jetty.servlet;version="8.1.3", org.eclipse.jetty.util.component;version="8.1.3" Export-Package: org.eclipse.jetty.osgi.httpservice;version="8.1.3" jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/build.properties000066400000000000000000000001411174773561500247350ustar00rootroot00000000000000source.. = src/main/java/ output.. = target/classes/ bin.includes = META-INF/,\ . jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/contexts/000077500000000000000000000000001174773561500233735ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/contexts/httpservice.xml000066400000000000000000000025071174773561500264610ustar00rootroot00000000000000 org.eclipse.equinox.http.servlet.HttpServiceServlet /* 0 jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/pom.xml000066400000000000000000000056671174773561500230570ustar00rootroot00000000000000 org.eclipse.jetty.osgi jetty-osgi-project 8.1.3.v20120416 ../pom.xml 4.0.0 jetty-httpservice Jetty :: OSGi :: HttpService Jetty OSGi HttpService bundle ${project.groupId}.httpservice org.eclipse.jetty jetty-util org.eclipse.jetty jetty-servlet org.eclipse.equinox.http servlet org.eclipse.osgi org.eclipse.osgi org.eclipse.jetty.orbit javax.servlet maven-antrun-plugin process-resources run org.apache.maven.plugins maven-jar-plugin artifact-jar jar test-jar test-jar target/classes/META-INF/MANIFEST.MF org.codehaus.mojo findbugs-maven-plugin org.eclipse.jetty.osgi.httpservice.* jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/src/000077500000000000000000000000001174773561500223135ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/src/main/000077500000000000000000000000001174773561500232375ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/src/main/java/000077500000000000000000000000001174773561500241605ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/000077500000000000000000000000001174773561500247475ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/000077500000000000000000000000001174773561500263735ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500275325ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/000077500000000000000000000000001174773561500304735ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/000077500000000000000000000000001174773561500330335ustar00rootroot00000000000000HttpServiceErrorHandlerHelper.java000066400000000000000000000027441174773561500415360ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice// ======================================================================== // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.httpservice; import javax.servlet.http.HttpServlet; /** * For jetty agnostic handling of errors issued by the HttpService. * Pass a servlet to the method setHttpServiceErrorHandler. * In the servlet to read the status code of the error or the message or the exception, * use org.eclipse.jetty.server.Dispatch's constants: * int errorCode = httpServletRequest.getAttribute(Dispatcher.ERROR_STATUS_CODE) * for example. */ public class HttpServiceErrorHandlerHelper { private static HttpServlet _customErrorHandler; public static HttpServlet getCustomErrorHandler() { return _customErrorHandler; } public static void setHttpServiceErrorHandler(HttpServlet servlet) { _customErrorHandler = servlet; } } HttpServiceErrorPageErrorHandler.java000066400000000000000000000041301174773561500421740ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice// ======================================================================== // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.httpservice; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.servlet.ErrorPageErrorHandler; /** * Extended error page handler. * Makes it easy to plug a servlet to handle errors thrown by the HttpService or * to use Jetty's ErrorPageErrorHandler API to plug custom error pages. */ public class HttpServiceErrorPageErrorHandler extends ErrorPageErrorHandler { private static HttpServiceErrorPageErrorHandler INSTANCE; public static HttpServiceErrorPageErrorHandler getInstance() { return INSTANCE; } public HttpServiceErrorPageErrorHandler() { INSTANCE = this; } @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { if (HttpServiceErrorHandlerHelper.getCustomErrorHandler() != null) { try { HttpServiceErrorHandlerHelper.getCustomErrorHandler().service(request, response); } catch (ServletException e) { //well } } if (!response.isCommitted()) { super.handle(target, baseRequest, request, response); } } @Override protected void doStop() throws Exception { INSTANCE = null; super.doStop(); } } jetty8-8.1.3/jetty-osgi/jetty-osgi-servletbridge/000077500000000000000000000000001174773561500220255ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-servletbridge/src/000077500000000000000000000000001174773561500226145ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-servletbridge/src/main/000077500000000000000000000000001174773561500235405ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-servletbridge/src/main/java/000077500000000000000000000000001174773561500244615ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/000077500000000000000000000000001174773561500252505ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/000077500000000000000000000000001174773561500266745ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/000077500000000000000000000000001174773561500300335ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/000077500000000000000000000000001174773561500307745ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/000077500000000000000000000000001174773561500336355ustar00rootroot00000000000000BridgeServletExtended.java000066400000000000000000000035371174773561500406530ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge// ======================================================================== // Copyright (c) 2010-2011 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.osgi.servletbridge; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.equinox.servletbridge.BridgeServlet; /** * Override the BridgeServlet to report on whether equinox is actually started or not * in case it is started asynchroneously. * * @author hmalphettes */ public class BridgeServletExtended extends BridgeServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (FrameworkLauncherExtended.ASYNCH_START_IN_PROGRESS != null && req.getMethod().equals("GET")) { if (FrameworkLauncherExtended.ASYNCH_START_IN_PROGRESS) { resp.getWriter().append("Equinox is currently starting...\n"); return; } else if (FrameworkLauncherExtended.ASYNCH_START_FAILURE != null) { resp.getWriter().append("Equinox failed to start:\n"); FrameworkLauncherExtended.ASYNCH_START_FAILURE.printStackTrace(resp.getWriter()); return; } } super.service(req, resp); } } jetty8-8.1.3/jetty-osgi/pom.xml000066400000000000000000000147751174773561500164230ustar00rootroot00000000000000 4.0.0 org.eclipse.jetty jetty-project 8.1.3.v20120416 ../pom.xml org.eclipse.jetty.osgi jetty-osgi-project Jetty :: OSGi pom 3.6.0.v20100517 3.2.100.v20100503 1.0.0-v20070606 0.9.18 1.5.11 jetty-osgi-boot jetty-osgi-boot-jsp jetty-osgi-boot-warurl jetty-osgi-httpservice test-jetty-osgi META-INF/.. true **/.* **/*.jar .settings/**/* pom.xml jettyhome/**/* src/**/* target/**/* build.properties META-INF/**/* src/main/java **/*.java org.apache.maven.plugins maven-eclipse-plugin 2.8 prevent/overwriting/by/pointing/to/nonexisting/MANIFEST.MF true true **/.svn/** org.eclipse.jetty jetty-annotations ${project.version} org.eclipse.jetty jetty-continuation ${project.version} org.eclipse.jetty jetty-websocket ${project.version} org.eclipse.jetty jetty-util ${project.version} org.eclipse.jetty jetty-jmx ${project.version} org.eclipse.jetty jetty-webapp ${project.version} org.eclipse.jetty jetty-deploy ${project.version} org.eclipse.jetty jetty-nested ${project.version} org.eclipse.jetty jetty-servlet ${project.version} org.eclipse.jetty jetty-servlets ${project.version} org.eclipse.osgi org.eclipse.osgi.services ${osgi-services-version} org.eclipse.osgi org.eclipse.osgi ${osgi-version} org.eclipse.equinox.http servlet ${equinox-http-servlet-version} org.slf4j slf4j-api ${slf4j-version} org.slf4j jcl-over-slf4j ${slf4j-version} org.slf4j log4j-over-slf4j ${slf4j-version} ch.qos.logback logback-core ${logback-version} ch.qos.logback logback-classic ${logback-version} jetty8-8.1.3/jetty-osgi/test-jetty-osgi/000077500000000000000000000000001174773561500201435ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/pom.xml000066400000000000000000000206371174773561500214700ustar00rootroot00000000000000 org.eclipse.jetty.osgi jetty-osgi-project 8.1.3.v20120416 ../pom.xml 4.0.0 test-jetty-osgi Jetty :: OSGi :: Test Jetty OSGi Integration test ${project.groupId}.boot.test http://download.eclipse.org/jetty/orbit/ target/distribution 1.2.0 org.eclipse.jetty.orbit javax.servlet org.eclipse.jetty jetty-jsp ${project.version} org.eclipse.jetty.osgi jetty-osgi-boot ${project.version} provided org.eclipse.jetty.osgi jetty-osgi-boot-jsp ${project.version} provided org.eclipse.jetty.osgi jetty-httpservice ${project.version} provided org.eclipse.jetty jetty-webapp runtime org.eclipse.jetty jetty-deploy runtime org.eclipse.jetty jetty-server ${project.version} runtime org.eclipse.jetty jetty-servlet runtime org.eclipse.jetty jetty-servlets runtime org.eclipse.jetty jetty-xml ${project.version} runtime org.eclipse.jetty jetty-jmx runtime org.eclipse.jetty jetty-util runtime org.eclipse.jetty jetty-client ${project.version} runtime org.eclipse.jetty jetty-websocket runtime org.eclipse.jetty jetty-plus ${project.version} runtime org.eclipse.osgi org.eclipse.osgi runtime org.eclipse.osgi org.eclipse.osgi.services runtime org.eclipse.equinox.http servlet runtime org.eclipse.jetty test-jetty-webapp ${project.version} webbundle test org.ops4j.pax.exam pax-exam ${paxexam-version} test org.ops4j.pax.exam pax-exam-junit ${paxexam-version} test org.ops4j.pax.exam pax-exam-container-default ${paxexam-version} test junit junit test org.ops4j.pax.exam maven-paxexam-plugin ${paxexam-version} generate-config generate-depends-file generate-config ${project.build.directory}/paxexam org.apache.maven.plugins maven-dependency-plugin copy-orbit-servlet-api-deps generate-resources copy org.eclipse.jetty.orbit javax.servlet ${orbit-servlet-api-version} true ${assembly-directory}/lib servlet-api-2.5.jar copy-orbit-lib-jndi-deps generate-resources copy-dependencies org.eclipse.jetty.orbit javax.mail.glassfish,javax.activation jar ${assembly-directory}/lib/jndi copy-orbit-lib-jsp-deps generate-resources copy-dependencies org.eclipse.jetty.orbit com.sun.el,javax.el,javax.servlet.jsp,javax.servlet.jsp.jstl,org.apache.jasper.glassfish,org.apache.taglibs.standard.glassfish,org.eclipse.jdt.core jar ${assembly-directory}/lib/jsp org.apache.maven.plugins maven-eclipse-plugin 2.8 prevent/overwriting/by/pointing/to/nonexisting/MANIFEST.MF false true **/.svn/** jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/000077500000000000000000000000001174773561500207325ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/000077500000000000000000000000001174773561500217115ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/config/000077500000000000000000000000001174773561500231565ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/config/etc/000077500000000000000000000000001174773561500237315ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-testrealm.xml000066400000000000000000000020351174773561500276100ustar00rootroot00000000000000 Test Realm realm.properties 0 jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/config/etc/realm.properties000066400000000000000000000013711174773561500271510ustar00rootroot00000000000000# # This file defines users passwords and roles for a HashUserRealm # # The format is # : [, ...] # # Passwords may be clear text, obfuscated or checksummed. The class # org.eclipse.util.Password should be used to generate obfuscated # passwords or password checksums # # If DIGEST Authentication is used, the password must be in a recoverable # format, either plain text or OBF:. # jetty: MD5:164c88b302622e17050af52c89945d44,user admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin other: OBF:1xmk1w261u9r1w1c1xmq,user plain: plain,user user: password,user # This entry is for digest auth. The credential is a MD5 hash of username:realmname:password digest: MD5:6e120743ad67abfbc385bc2bb754e297,user jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/java/000077500000000000000000000000001174773561500226325ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/java/org/000077500000000000000000000000001174773561500234215ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/000077500000000000000000000000001174773561500250455ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/000077500000000000000000000000001174773561500262045ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/000077500000000000000000000000001174773561500271455ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/000077500000000000000000000000001174773561500301105ustar00rootroot00000000000000TestJettyOSGiBootCore.java000066400000000000000000000225011174773561500350120ustar00rootroot00000000000000jetty8-8.1.3/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot// ======================================================================== // Copyright (c) 2010 Intalio, Inc. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // Contributors: // Hugues Malphettes - initial API and implementation // ======================================================================== package org.eclipse.jetty.osgi.boot; import static org.ops4j.pax.exam.CoreOptions.*; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.Assert; import org.eclipse.jetty.client.ContentExchange; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Inject; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.container.def.PaxRunnerOptions; import org.ops4j.pax.exam.junit.Configuration; import org.ops4j.pax.exam.junit.JUnit4TestRunner; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.service.http.HttpService; /** * Pax-Exam to make sure the jetty-osgi-boot can be started along with the httpservice web-bundle. * Then make sure we can deploy an OSGi service on the top of this. */ @RunWith( JUnit4TestRunner.class ) public class TestJettyOSGiBootCore { /** * Jetty-osgi including webapp support and also jetty-client. * Sets the system property jetty.home.bunde=org.eclipse.jetty.osgi.boot * to use the jetty server configuration embedded in * * @return list of options */ public static List