jetty @ eclipse initial commit
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@8 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
bc1e0bd102
commit
da627b843f
|
@ -0,0 +1,202 @@
|
||||||
|
|
||||||
|
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.
|
|
@ -0,0 +1,119 @@
|
||||||
|
COMMON 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 Sectionsá2.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 Sectioná2.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 Sectionsá2.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 Sectioná2.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 Sectionsá2.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 Sectionsá6.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 48áC.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 48áC.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.
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,157 @@
|
||||||
|
Jetty 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
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
Jetty 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
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
||||||
|
______________________________________ ________________
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
-----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-----
|
|
@ -0,0 +1,141 @@
|
||||||
|
-----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-----
|
|
@ -0,0 +1,139 @@
|
||||||
|
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: 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-----
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
-----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-----
|
|
@ -0,0 +1,142 @@
|
||||||
|
-----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-----
|
|
@ -0,0 +1,143 @@
|
||||||
|
-----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-----
|
|
@ -0,0 +1,141 @@
|
||||||
|
-----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-----
|
|
@ -0,0 +1,141 @@
|
||||||
|
-----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-----
|
|
@ -0,0 +1,140 @@
|
||||||
|
-----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-----
|
|
@ -0,0 +1,131 @@
|
||||||
|
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:
|
||||||
|
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:
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
-----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-----
|
|
@ -0,0 +1,320 @@
|
||||||
|
<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"><head>
|
||||||
|
|
||||||
|
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||||
|
<meta name="ProgId" content="Word.Document">
|
||||||
|
<meta name="Generator" content="Microsoft Word 9">
|
||||||
|
<meta name="Originator" content="Microsoft Word 9">
|
||||||
|
<link rel="File-List" href="http://www.eclipse.org/legal/Eclipse%20EPL%202003_11_10%20Final_files/filelist.xml">
|
||||||
|
<title>Eclipse Public License - Version 1.0</title>
|
||||||
|
<!--[if gte mso 9]><xml>
|
||||||
|
<o:DocumentProperties>
|
||||||
|
<o:Revision>2</o:Revision>
|
||||||
|
<o:TotalTime>3</o:TotalTime>
|
||||||
|
<o:Created>2004-03-05T23:03:00Z</o:Created>
|
||||||
|
<o:LastSaved>2004-03-05T23:03:00Z</o:LastSaved>
|
||||||
|
<o:Pages>4</o:Pages>
|
||||||
|
<o:Words>1626</o:Words>
|
||||||
|
<o:Characters>9270</o:Characters>
|
||||||
|
<o:Lines>77</o:Lines>
|
||||||
|
<o:Paragraphs>18</o:Paragraphs>
|
||||||
|
<o:CharactersWithSpaces>11384</o:CharactersWithSpaces>
|
||||||
|
<o:Version>9.4402</o:Version>
|
||||||
|
</o:DocumentProperties>
|
||||||
|
</xml><![endif]--><!--[if gte mso 9]><xml>
|
||||||
|
<w:WordDocument>
|
||||||
|
<w:TrackRevisions/>
|
||||||
|
</w:WordDocument>
|
||||||
|
</xml><![endif]-->
|
||||||
|
<style>
|
||||||
|
<!--
|
||||||
|
/* Font Definitions */
|
||||||
|
@font-face
|
||||||
|
{font-family:Tahoma;
|
||||||
|
panose-1:2 11 6 4 3 5 4 4 2 4;
|
||||||
|
mso-font-charset:0;
|
||||||
|
mso-generic-font-family:swiss;
|
||||||
|
mso-font-pitch:variable;
|
||||||
|
mso-font-signature:553679495 -2147483648 8 0 66047 0;}
|
||||||
|
/* Style Definitions */
|
||||||
|
p.MsoNormal, li.MsoNormal, div.MsoNormal
|
||||||
|
{mso-style-parent:"";
|
||||||
|
margin:0in;
|
||||||
|
margin-bottom:.0001pt;
|
||||||
|
mso-pagination:widow-orphan;
|
||||||
|
font-size:12.0pt;
|
||||||
|
font-family:"Times New Roman";
|
||||||
|
mso-fareast-font-family:"Times New Roman";}
|
||||||
|
p
|
||||||
|
{margin-right:0in;
|
||||||
|
mso-margin-top-alt:auto;
|
||||||
|
mso-margin-bottom-alt:auto;
|
||||||
|
margin-left:0in;
|
||||||
|
mso-pagination:widow-orphan;
|
||||||
|
font-size:12.0pt;
|
||||||
|
font-family:"Times New Roman";
|
||||||
|
mso-fareast-font-family:"Times New Roman";}
|
||||||
|
p.BalloonText, li.BalloonText, div.BalloonText
|
||||||
|
{mso-style-name:"Balloon Text";
|
||||||
|
margin:0in;
|
||||||
|
margin-bottom:.0001pt;
|
||||||
|
mso-pagination:widow-orphan;
|
||||||
|
font-size:8.0pt;
|
||||||
|
font-family:Tahoma;
|
||||||
|
mso-fareast-font-family:"Times New Roman";}
|
||||||
|
@page Section1
|
||||||
|
{size:8.5in 11.0in;
|
||||||
|
margin:1.0in 1.25in 1.0in 1.25in;
|
||||||
|
mso-header-margin:.5in;
|
||||||
|
mso-footer-margin:.5in;
|
||||||
|
mso-paper-source:0;}
|
||||||
|
div.Section1
|
||||||
|
{page:Section1;}
|
||||||
|
-->
|
||||||
|
</style>
|
||||||
|
</head><body style="" lang="EN-US">
|
||||||
|
|
||||||
|
<div class="Section1">
|
||||||
|
|
||||||
|
<p style="text-align: center;" align="center"><b>Eclipse Public License - v 1.0</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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.</span> </p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">1. DEFINITIONS</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">"Contribution" means:</span> </p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">a)
|
||||||
|
in the case of the initial Contributor, the initial code and documentation
|
||||||
|
distributed under this Agreement, and<br clear="left">
|
||||||
|
b) in the case of each subsequent Contributor:</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">i)
|
||||||
|
changes to the Program, and</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">ii)
|
||||||
|
additions to the Program;</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">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. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">"Contributor" means any person or
|
||||||
|
entity that distributes the Program.</span> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">"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. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">"Program" means the Contributions
|
||||||
|
distributed in accordance with this Agreement.</span> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">"Recipient" means anyone who
|
||||||
|
receives the Program under this Agreement, including all Contributors.</span> </p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">2. GRANT OF RIGHTS</span></b> </p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">a)
|
||||||
|
Subject to the terms of this Agreement, each Contributor hereby grants Recipient
|
||||||
|
a non-exclusive, worldwide, royalty-free copyright license to<span style="color: red;"> </span>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.</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">b)
|
||||||
|
Subject to the terms of this Agreement, each Contributor hereby grants
|
||||||
|
Recipient a non-exclusive, worldwide,<span style="color: green;"> </span>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. </span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">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.</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">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. </span></p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">3. REQUIREMENTS</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">A Contributor may choose to distribute the
|
||||||
|
Program in object code form under its own license agreement, provided that:</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">a)
|
||||||
|
it complies with the terms and conditions of this Agreement; and</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">b)
|
||||||
|
its license agreement:</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">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; </span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">ii)
|
||||||
|
effectively excludes on behalf of all Contributors all liability for damages,
|
||||||
|
including direct, indirect, special, incidental and consequential damages, such
|
||||||
|
as lost profits; </span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">iii)
|
||||||
|
states that any provisions which differ from this Agreement are offered by that
|
||||||
|
Contributor alone and not by any other party; and</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">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.<span style="color: blue;"> </span></span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">When the Program is made available in source
|
||||||
|
code form:</span> </p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">a)
|
||||||
|
it must be made available under this Agreement; and </span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">b) a
|
||||||
|
copy of this Agreement must be included with each copy of the Program. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">Contributors may not remove or alter any
|
||||||
|
copyright notices contained within the Program. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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. </span></p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">4. COMMERCIAL DISTRIBUTION</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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.</span> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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.</span> </p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">5. NO WARRANTY</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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. </span></p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">6. DISCLAIMER OF LIABILITY</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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.</span> </p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">7. GENERAL</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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.</span> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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.</span> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">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.</span> </p>
|
||||||
|
|
||||||
|
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--><o:p></o:p></p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body></html>
|
|
@ -0,0 +1,21 @@
|
||||||
|
==============================================================
|
||||||
|
Jetty Web Container
|
||||||
|
Copyright 1995-2009 Mort Bay Consulting Pty Ltd
|
||||||
|
==============================================================
|
||||||
|
|
||||||
|
The Jetty Web Container is Copyright Mort Bay Consulting Pty Ltd
|
||||||
|
unless otherwise noted. It is dual licensed under the apache 2.0
|
||||||
|
license and eclipse 1.0 license. 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.
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
This is the Jetty 7 HTTP server and servlet container.
|
||||||
|
|
||||||
|
For more information about Jetty, please see the Jetty wiki:
|
||||||
|
|
||||||
|
http://docs.codehaus.org/display/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
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,76 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-project</artifactId>
|
||||||
|
<version>7.0.0.incubation0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>jetty-ajp</artifactId>
|
||||||
|
<name>Jetty :: AJP</name>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<version>1.4.2</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>manifest</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-SymbolicName>org.eclipse.jetty.ajp</Bundle-SymbolicName>
|
||||||
|
<Bundle-RequiredExecutionEnvironment>J2SE-1.5</Bundle-RequiredExecutionEnvironment>
|
||||||
|
<Bundle-DocURL>http://jetty.eclipse.org</Bundle-DocURL>
|
||||||
|
<Export-Package>org.eclipse.jetty.ajp;version=${project.version}</Export-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<!--
|
||||||
|
Required for OSGI
|
||||||
|
-->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>config.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.eclipse.org/configure.dtd">
|
||||||
|
|
||||||
|
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||||
|
|
||||||
|
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||||
|
<!-- Add a AJP listener on port 8009 -->
|
||||||
|
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||||
|
<Call name="addConnector">
|
||||||
|
<Arg>
|
||||||
|
<New class="org.eclipse.jetty.ajp.Ajp13SocketConnector">
|
||||||
|
<Set name="port">8009</Set>
|
||||||
|
</New>
|
||||||
|
</Arg>
|
||||||
|
</Call>
|
||||||
|
|
||||||
|
</Configure>
|
||||||
|
|
|
@ -0,0 +1,252 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.io.Buffer;
|
||||||
|
import org.eclipse.jetty.io.EndPoint;
|
||||||
|
import org.eclipse.jetty.io.HttpException;
|
||||||
|
import org.eclipse.jetty.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.HttpConnection;
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connection implementation of the Ajp13 protocol. <p/> XXX Refactor to remove
|
||||||
|
* duplication of HttpConnection
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Ajp13Connection extends HttpConnection
|
||||||
|
{
|
||||||
|
public Ajp13Connection(Connector connector, EndPoint endPoint, Server server)
|
||||||
|
{
|
||||||
|
super(connector, endPoint, server,
|
||||||
|
new Ajp13Parser(connector, endPoint),
|
||||||
|
new Ajp13Generator(connector, endPoint, connector.getHeaderBufferSize(), connector.getResponseBufferSize()),
|
||||||
|
new Ajp13Request()
|
||||||
|
);
|
||||||
|
|
||||||
|
((Ajp13Parser)_parser).setEventHandler(new RequestHandler());
|
||||||
|
((Ajp13Parser)_parser).setGenerator((Ajp13Generator)_generator);
|
||||||
|
((Ajp13Request)_request).setConnection(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConfidential(Request request)
|
||||||
|
{
|
||||||
|
return ((Ajp13Request) request).isSslSecure();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIntegral(Request request)
|
||||||
|
{
|
||||||
|
return ((Ajp13Request) request).isSslSecure();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServletInputStream getInputStream()
|
||||||
|
{
|
||||||
|
if (_in == null)
|
||||||
|
_in = new Ajp13Parser.Input((Ajp13Parser) _parser, _connector.getMaxIdleTime());
|
||||||
|
return _in;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RequestHandler implements Ajp13Parser.EventHandler
|
||||||
|
{
|
||||||
|
boolean _delayedHandling = false;
|
||||||
|
|
||||||
|
public void startForwardRequest() throws IOException
|
||||||
|
{
|
||||||
|
_delayedHandling = false;
|
||||||
|
_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<? extends java.security.cert.Certificate> 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)
|
||||||
|
{
|
||||||
|
org.eclipse.jetty.util.log.Log.warn(e.toString());
|
||||||
|
org.eclipse.jetty.util.log.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
|
||||||
|
{
|
||||||
|
_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
|
||||||
|
{
|
||||||
|
if (((Ajp13Parser) _parser).getContentLength() <= 0)
|
||||||
|
{
|
||||||
|
handleRequest();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_delayedHandling = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void messageComplete(long contextLength) throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void content(Buffer ref) throws IOException
|
||||||
|
{
|
||||||
|
if (_delayedHandling)
|
||||||
|
{
|
||||||
|
_delayedHandling = false;
|
||||||
|
handleRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,803 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.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.TypeUtil;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Ajp13Generator extends AbstractGenerator
|
||||||
|
{
|
||||||
|
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(6.0.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, int headerBufferSize, int contentBufferSize)
|
||||||
|
{
|
||||||
|
super(buffers, io, headerBufferSize, contentBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void reset(boolean returnBuffers)
|
||||||
|
{
|
||||||
|
super.reset(returnBuffers);
|
||||||
|
|
||||||
|
_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;
|
||||||
|
_close = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_header = null; // Buffer for HTTP header (and maybe small _content)
|
||||||
|
_buffer = null; // Buffer for copy of passed _content
|
||||||
|
_content = null; // Buffer passed to addContent
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Add content.
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @param last
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* if <code>content</code> 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
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
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 (_version == HttpVersions.HTTP_1_0_ORDINAL)
|
||||||
|
_close = true;
|
||||||
|
|
||||||
|
// get a header buffer
|
||||||
|
if (_header == null)
|
||||||
|
_header = _buffers.getBuffer(_headerBufferSize);
|
||||||
|
|
||||||
|
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(TypeUtil.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
|
||||||
|
*/
|
||||||
|
public void complete() throws IOException
|
||||||
|
{
|
||||||
|
if (_state == STATE_END)
|
||||||
|
return;
|
||||||
|
|
||||||
|
super.complete();
|
||||||
|
|
||||||
|
if (_state < STATE_FLUSHING)
|
||||||
|
{
|
||||||
|
_state = STATE_FLUSHING;
|
||||||
|
_needEOC = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public long 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.getBuffer(_headerBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public boolean isComplete()
|
||||||
|
{
|
||||||
|
return !_expectMore && _state == STATE_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
private void initContent() throws IOException
|
||||||
|
{
|
||||||
|
if (_buffer == null)
|
||||||
|
{
|
||||||
|
_buffer = _buffers.getBuffer(_contentBufferSize);
|
||||||
|
_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)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
_needMore = true;
|
||||||
|
_expectMore = true;
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void gotBody()
|
||||||
|
{
|
||||||
|
_needMore = false;
|
||||||
|
_expectMore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void sendCPong() throws IOException
|
||||||
|
{
|
||||||
|
|
||||||
|
Buffer buff = _buffers.getBuffer(AJP13_CPONG_RESPONSE.length);
|
||||||
|
buff.put(AJP13_CPONG_RESPONSE);
|
||||||
|
|
||||||
|
// flushing cpong response
|
||||||
|
do
|
||||||
|
{
|
||||||
|
_endp.flush(buff);
|
||||||
|
|
||||||
|
}
|
||||||
|
while(buff.length() >0);
|
||||||
|
_buffers.returnBuffer(buff);
|
||||||
|
|
||||||
|
reset(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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);
|
||||||
|
}
|
|
@ -0,0 +1,876 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Ajp13Parser implements Parser
|
||||||
|
{
|
||||||
|
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(false);
|
||||||
|
if (_state != STATE_START)
|
||||||
|
throw new IllegalStateException("!START");
|
||||||
|
|
||||||
|
// continue parsing
|
||||||
|
while (!isComplete())
|
||||||
|
{
|
||||||
|
parseNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
public long parseAvailable() throws IOException
|
||||||
|
{
|
||||||
|
long len = parseNext();
|
||||||
|
long total = len > 0 ? len : 0;
|
||||||
|
|
||||||
|
// continue parsing
|
||||||
|
while (!isComplete() && _buffer != null && _buffer.length() > 0)
|
||||||
|
{
|
||||||
|
len = parseNext();
|
||||||
|
if (len > 0)
|
||||||
|
total += len;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
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(true);
|
||||||
|
throw (e instanceof EofException) ? e : new EofException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filled < 0)
|
||||||
|
{
|
||||||
|
if (_state > STATE_END)
|
||||||
|
{
|
||||||
|
_state = STATE_END;
|
||||||
|
_handler.messageComplete(_contentPosition);
|
||||||
|
return filled;
|
||||||
|
}
|
||||||
|
reset(true);
|
||||||
|
throw new EofException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return filled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
public long parseNext() throws IOException
|
||||||
|
{
|
||||||
|
long total_filled = -1;
|
||||||
|
|
||||||
|
if (_buffer == null)
|
||||||
|
{
|
||||||
|
if (_header == null)
|
||||||
|
{
|
||||||
|
_header = _buffers.getBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
_header.clear();
|
||||||
|
}
|
||||||
|
_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 total_filled;
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
((Ajp13Generator) _generator).sendCPong();
|
||||||
|
|
||||||
|
if(_header != null)
|
||||||
|
{
|
||||||
|
_buffers.returnBuffer(_header);
|
||||||
|
_header = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_body != null)
|
||||||
|
{
|
||||||
|
_buffers.returnBuffer(_body);
|
||||||
|
_body = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_buffer= null;
|
||||||
|
|
||||||
|
reset(true);
|
||||||
|
|
||||||
|
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:
|
||||||
|
// XXX Using old Jetty 5 key,
|
||||||
|
// should change!
|
||||||
|
// Note used in
|
||||||
|
// org.eclipse.jetty.servlet.HashSessionIdManager
|
||||||
|
_handler.parsedRequestAttribute("org.eclipse.http.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(Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
_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(Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
_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;
|
||||||
|
|
||||||
|
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()<remaining)
|
||||||
|
{
|
||||||
|
remaining=_buffer.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk=Ajp13RequestPacket.get(_buffer,(int)remaining);
|
||||||
|
_contentPosition+=chunk.length();
|
||||||
|
_chunkPosition+=chunk.length();
|
||||||
|
_contentView.update(chunk);
|
||||||
|
|
||||||
|
remaining=_chunkLength-_chunkPosition;
|
||||||
|
|
||||||
|
if (remaining==0)
|
||||||
|
{
|
||||||
|
_state=STATE_AJP13CHUNK_START;
|
||||||
|
if (_contentPosition<_contentLength || _contentLength == HttpTokens.UNKNOWN_CONTENT)
|
||||||
|
{
|
||||||
|
_generator.getBodyChunk();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_generator.gotBody();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_handler.content(chunk);
|
||||||
|
|
||||||
|
return total_filled;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("Invalid Content State");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_filled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
public void reset(boolean returnBuffers)
|
||||||
|
{
|
||||||
|
_state = STATE_START;
|
||||||
|
_contentLength = HttpTokens.UNKNOWN_CONTENT;
|
||||||
|
_contentPosition = 0;
|
||||||
|
_length = 0;
|
||||||
|
_packetLength = 0;
|
||||||
|
|
||||||
|
if (_body != null)
|
||||||
|
{
|
||||||
|
if (_body.hasContent())
|
||||||
|
{
|
||||||
|
_header.setMarkIndex(-1);
|
||||||
|
_header.compact();
|
||||||
|
// TODO if pipelined requests received after big
|
||||||
|
// input - maybe this is not good?.
|
||||||
|
_body.skip(_header.put(_body));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_body.length() == 0)
|
||||||
|
{
|
||||||
|
if (_buffers != null && returnBuffers)
|
||||||
|
_buffers.returnBuffer(_body);
|
||||||
|
_body = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_body.setMarkIndex(-1);
|
||||||
|
_body.compact();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_header != null)
|
||||||
|
{
|
||||||
|
_header.setMarkIndex(-1);
|
||||||
|
if (!_header.hasContent() && _buffers != null && returnBuffers)
|
||||||
|
{
|
||||||
|
_buffers.returnBuffer(_header);
|
||||||
|
_header = null;
|
||||||
|
_buffer = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_header.compact();
|
||||||
|
_tok0.update(_header);
|
||||||
|
_tok0.update(0, 0);
|
||||||
|
_tok1.update(_header);
|
||||||
|
_tok1.update(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_buffer = _header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public int read() throws IOException
|
||||||
|
{
|
||||||
|
int c = -1;
|
||||||
|
if (blockForContent())
|
||||||
|
c = 0xff & _content.get();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/*
|
||||||
|
* @see java.io.InputStream#read(byte[], int, int)
|
||||||
|
*/
|
||||||
|
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))
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.HttpConnection;
|
||||||
|
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(HttpConnection connection)
|
||||||
|
{
|
||||||
|
super(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Ajp13Request()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
void setConnection(Ajp13Connection connection)
|
||||||
|
{
|
||||||
|
super.setConnection(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setRemoteUser(String remoteUser)
|
||||||
|
{
|
||||||
|
_remoteUser = remoteUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String getRemoteUser()
|
||||||
|
{
|
||||||
|
if(_remoteUser != null)
|
||||||
|
return _remoteUser;
|
||||||
|
return super.getRemoteUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String getRemoteAddr()
|
||||||
|
{
|
||||||
|
if (_remoteAddr != null)
|
||||||
|
return _remoteAddr;
|
||||||
|
if (_remoteHost != null)
|
||||||
|
return _remoteHost;
|
||||||
|
return super.getRemoteAddr();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setRemoteAddr(String remoteAddr)
|
||||||
|
{
|
||||||
|
_remoteAddr = remoteAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String getRemoteHost()
|
||||||
|
{
|
||||||
|
if (_remoteHost != null)
|
||||||
|
return _remoteHost;
|
||||||
|
if (_remoteAddr != null)
|
||||||
|
return _remoteAddr;
|
||||||
|
return super.getRemoteHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setRemoteHost(String remoteHost)
|
||||||
|
{
|
||||||
|
_remoteHost = remoteHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public boolean isSslSecure()
|
||||||
|
{
|
||||||
|
return _sslSecure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setSslSecure(boolean sslSecure)
|
||||||
|
{
|
||||||
|
_sslSecure = sslSecure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
protected void recycle()
|
||||||
|
{
|
||||||
|
super.recycle();
|
||||||
|
_remoteAddr = null;
|
||||||
|
_remoteHost = null;
|
||||||
|
_remoteUser = null;
|
||||||
|
_sslSecure = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.EndPoint;
|
||||||
|
import org.eclipse.jetty.server.HttpConnection;
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jetty.server.bio.SocketConnector;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Ajp13SocketConnector extends SocketConnector
|
||||||
|
{
|
||||||
|
static String __secretWord = null;
|
||||||
|
static boolean __allowShutdown = false;
|
||||||
|
public Ajp13SocketConnector()
|
||||||
|
{
|
||||||
|
super.setHeaderBufferSize(Ajp13Packet.MAX_DATA_SIZE);
|
||||||
|
super.setRequestBufferSize(Ajp13Packet.MAX_DATA_SIZE);
|
||||||
|
super.setResponseBufferSize(Ajp13Packet.MAX_DATA_SIZE);
|
||||||
|
// IN AJP protocol the socket stay open, so
|
||||||
|
// by default the time out is set to 900 seconds
|
||||||
|
super.setMaxIdleTime(900000);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
*/
|
||||||
|
public void customize(EndPoint endpoint, Request request) throws IOException
|
||||||
|
{
|
||||||
|
super.customize(endpoint,request);
|
||||||
|
if (request.isSecure())
|
||||||
|
request.setScheme(HttpSchemes.HTTPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
protected HttpConnection newHttpConnection(EndPoint endpoint)
|
||||||
|
{
|
||||||
|
return new Ajp13Connection(this,endpoint,getServer());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
// Secured on a packet by packet bases not by connection
|
||||||
|
public boolean isConfidential(Request request)
|
||||||
|
{
|
||||||
|
return ((Ajp13Request) request).isSslSecure();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
// Secured on a packet by packet bases not by connection
|
||||||
|
public boolean isIntegral(Request request)
|
||||||
|
{
|
||||||
|
return ((Ajp13Request) request).isSslSecure();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setHeaderBufferSize(int headerBufferSize)
|
||||||
|
{
|
||||||
|
Log.debug(Log.IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setRequestBufferSize(int requestBufferSize)
|
||||||
|
{
|
||||||
|
Log.debug(Log.IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,313 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.HttpConnection;
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||||
|
import org.eclipse.jetty.util.TypeUtil;
|
||||||
|
|
||||||
|
public class Ajp13ConnectionTest extends TestCase
|
||||||
|
{
|
||||||
|
private Server _server;
|
||||||
|
private Ajp13SocketConnector _connector;
|
||||||
|
private Socket _client;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
_server=new Server();
|
||||||
|
_connector=new Ajp13SocketConnector();
|
||||||
|
|
||||||
|
_connector.setPort(0);
|
||||||
|
_connector.setMaxIdleTime(100);
|
||||||
|
_server.setConnectors(new Connector[] { _connector });
|
||||||
|
_server.setHandler(new Handler());
|
||||||
|
_server.start();
|
||||||
|
|
||||||
|
_client=new Socket("localhost",_connector.getLocalPort());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
_client.close();
|
||||||
|
_connector.close();
|
||||||
|
_server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPacket1() throws Exception
|
||||||
|
{
|
||||||
|
OutputStream os=_client.getOutputStream();
|
||||||
|
|
||||||
|
String packet="123401070202000f77696474683d20485454502f312e300000122f636f6e74726f6c2f70726f647563742f2200000e3230382e32372e3230332e31323800ffff000c7777772e756c74612e636f6d000050000005a006000a6b6565702d616c69766500a00b000c7777772e756c74612e636f6d00a00e002b4d6f7a696c6c612f342e302028636f6d70617469626c653b20426f726465724d616e6167657220332e302900a0010043696d6167652f6769662c20696d6167652f782d786269746d61702c20696d6167652f6a7065672c20696d6167652f706a7065672c20696d6167652f706d672c202a2f2a00a008000130000600067570726f64310008000a4145533235362d53484100ff";
|
||||||
|
os.write(TypeUtil.fromHexString(packet));
|
||||||
|
os.flush();
|
||||||
|
|
||||||
|
readResponse(_client);
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPacket2() throws Exception
|
||||||
|
{
|
||||||
|
OutputStream os=_client.getOutputStream();
|
||||||
|
|
||||||
|
String packet="1234020102020008485454502f312e3100000f2f6363632d7777777777772f61616100000c38382e3838382e38382e383830ffff00116363632e6363636363636363632e636f6d0001bb010009a00b00116363632e6363636363636363632e636f6d00a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004039324643303544413043444141443232303137413743443141453939353132413330443938363838423843433041454643364231363035323543433232353341000b0100ff";
|
||||||
|
os.write(TypeUtil.fromHexString(packet));
|
||||||
|
os.flush();
|
||||||
|
|
||||||
|
readResponse(_client);
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPacket3() throws Exception
|
||||||
|
{
|
||||||
|
OutputStream os=_client.getOutputStream();
|
||||||
|
|
||||||
|
String packet="1234028f02020008485454502f312e3100000d2f666f726d746573742e6a737000000d3139322e3136382e342e31383000ffff00107777772e777265636b6167652e6f726700005000000aa0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a00200075554462d382c2a00a003000c677a69702c6465666c61746500a004000e656e2d67622c656e3b713d302e3500a006000a6b6565702d616c69766500a00900f95048505345535349443d37626361383232616638333466316465373663633630336366636435313938633b20667041757468436f6f6b69653d433035383430394537393344364245434633324230353234344242303039343230383344443645443533304230454637464137414544413745453231313538333745363033454435364332364446353531383635333335423433374531423637414641343533364345304546323342333642323133374243423932333943363631433131443330393842333938414546334546334146454344423746353842443b204a53455353494f4e49443d7365366331623864663432762e6a657474793300a00b00107777772e777265636b6167652e6f726700000a6b6565702d616c69766500000333303000a00e00654d6f7a696c6c612f352e3020285831313b20553b204c696e7578207838365f36343b20656e2d55533b2072763a312e382e302e3929204765636b6f2f3230303631323035202844656269616e2d312e382e302e392d3129204570697068616e792f322e313400a008000130000600066a657474793300ff";
|
||||||
|
os.write(TypeUtil.fromHexString(packet));
|
||||||
|
os.flush();
|
||||||
|
readResponse(_client);
|
||||||
|
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSSLPacketWithIntegerKeySize() throws Exception
|
||||||
|
{
|
||||||
|
OutputStream os=_client.getOutputStream();
|
||||||
|
|
||||||
|
String packet="1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b0100ff";
|
||||||
|
os.write(TypeUtil.fromHexString(packet));
|
||||||
|
os.flush();
|
||||||
|
readResponse(_client);
|
||||||
|
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSSLPacketWithStringKeySize() throws Exception
|
||||||
|
{
|
||||||
|
OutputStream os=_client.getOutputStream();
|
||||||
|
|
||||||
|
String packet="1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b000332353600ff";
|
||||||
|
os.write(TypeUtil.fromHexString(packet));
|
||||||
|
os.flush();
|
||||||
|
readResponse(_client);
|
||||||
|
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
BufferedReader br=null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
br=new BufferedReader(new InputStreamReader(_client.getInputStream()));
|
||||||
|
|
||||||
|
StringBuffer sb=new StringBuffer();
|
||||||
|
String line;
|
||||||
|
while ((line=br.readLine()) != null)
|
||||||
|
{
|
||||||
|
sb.append(line);
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (br != null)
|
||||||
|
{
|
||||||
|
br.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Handler extends AbstractHandler
|
||||||
|
{
|
||||||
|
public void handle(String target, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
Request base_request=(request instanceof Request) ? (Request) request : HttpConnection.getCurrentConnection().getRequest();
|
||||||
|
base_request.setHandled(true);
|
||||||
|
response.setStatus(HttpServletResponse.SC_OK);
|
||||||
|
response.setContentType("text/plain");
|
||||||
|
response.getWriter().println("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,620 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 java.io.IOException;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class TestAjpParser extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
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(new Buffer[]{buffer});
|
||||||
|
|
||||||
|
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,0,0));
|
||||||
|
|
||||||
|
parser.parseAvailable();
|
||||||
|
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(new Buffer[]
|
||||||
|
{ buffer });
|
||||||
|
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,0,0));
|
||||||
|
parser.parse();
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(new Buffer[]
|
||||||
|
{ buffer });
|
||||||
|
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,0,0));
|
||||||
|
parser.parse();
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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(new Buffer[]{buffer});
|
||||||
|
|
||||||
|
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,0,0));
|
||||||
|
|
||||||
|
parser.parseAvailable();
|
||||||
|
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(new Buffer[]{buffer});
|
||||||
|
|
||||||
|
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,0,0));
|
||||||
|
|
||||||
|
parser.parseAvailable();
|
||||||
|
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSSLPacketFragment() throws Exception
|
||||||
|
{
|
||||||
|
String packet = "1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b0100ff";
|
||||||
|
byte[] src = TypeUtil.fromHexString(packet);
|
||||||
|
|
||||||
|
for (int f=1;f<src.length;f++)
|
||||||
|
{
|
||||||
|
byte[] frag0=new byte[src.length-f];
|
||||||
|
byte[] frag1=new byte[f];
|
||||||
|
|
||||||
|
System.arraycopy(src,0,frag0,0,src.length-f);
|
||||||
|
System.arraycopy(src,src.length-f,frag1,0,f);
|
||||||
|
|
||||||
|
ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
SimpleBuffers buffers=new SimpleBuffers(new Buffer[]{buffer});
|
||||||
|
|
||||||
|
ByteArrayEndPoint endp = new ByteArrayEndPoint(frag0,Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
endp.setNonBlocking(true);
|
||||||
|
|
||||||
|
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
||||||
|
parser.setEventHandler(new EH());
|
||||||
|
parser.setGenerator(new Ajp13Generator(buffers,endp,0,0));
|
||||||
|
parser.parseNext();
|
||||||
|
|
||||||
|
endp.setIn(new ByteArrayBuffer(frag1));
|
||||||
|
parser.parseAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void testPacketWithBody() throws Exception
|
||||||
|
{
|
||||||
|
String packet=getTestHeader();
|
||||||
|
byte[] src=TypeUtil.fromHexString(packet);
|
||||||
|
ByteArrayBuffer buffer=new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
SimpleBuffers buffers=new SimpleBuffers(new Buffer[]
|
||||||
|
{ buffer });
|
||||||
|
ByteArrayEndPoint endp=new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
endp.setNonBlocking(true);
|
||||||
|
|
||||||
|
final int count[]={0};
|
||||||
|
Ajp13Generator gen = new Ajp13Generator(buffers,endp,0,0)
|
||||||
|
{
|
||||||
|
public void getBodyChunk() throws IOException
|
||||||
|
{
|
||||||
|
count[0]++;
|
||||||
|
super.getBodyChunk();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
||||||
|
parser.setEventHandler(new EH());
|
||||||
|
parser.setGenerator(gen);
|
||||||
|
|
||||||
|
parser.parseNext();
|
||||||
|
assertEquals(1,parser.getState());
|
||||||
|
assertEquals(0,count[0]);
|
||||||
|
|
||||||
|
endp.setIn(new ByteArrayBuffer(TypeUtil.fromHexString(getTestShortBody())));
|
||||||
|
|
||||||
|
parser.parseNext();
|
||||||
|
assertEquals(1,parser.getState());
|
||||||
|
assertEquals(1,count[0]);
|
||||||
|
|
||||||
|
endp.setIn(new ByteArrayBuffer(TypeUtil.fromHexString(getTestTinyBody())));
|
||||||
|
|
||||||
|
parser.parseNext();
|
||||||
|
parser.parseNext();
|
||||||
|
assertEquals(0,parser.getState());
|
||||||
|
assertEquals(1,count[0]);
|
||||||
|
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void testPacketWithChunkedBody() throws Exception
|
||||||
|
{
|
||||||
|
String packet="123400ff02040008485454502f312e3100000f2f746573742f64756d702f696e666f0000093132372e302e302e3100ffff00096c6f63616c686f7374000050000007a00e000d4a6176612f312e352e305f313100a00b00096c6f63616c686f737400a0010034746578742f68746d6c2c20696d6167652f6769662c20696d6167652f6a7065672c202a3b20713d2e322c202a2f2a3b20713d2e3200a006000a6b6565702d616c69766500a00700216170706c69636174696f6e2f782d7777772d666f726d2d75726c656e636f6465640000115472616e736665722d456e636f64696e670000076368756e6b656400000c4d61782d466f727761726473000002313000ff";
|
||||||
|
byte[] src=TypeUtil.fromHexString(packet);
|
||||||
|
ByteArrayBuffer buffer=new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
SimpleBuffers buffers=new SimpleBuffers(new Buffer[]
|
||||||
|
{ buffer });
|
||||||
|
ByteArrayEndPoint endp=new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
endp.setNonBlocking(true);
|
||||||
|
|
||||||
|
final int count[]={0};
|
||||||
|
Ajp13Generator gen = new Ajp13Generator(buffers,endp,0,0)
|
||||||
|
{
|
||||||
|
public void getBodyChunk() throws IOException
|
||||||
|
{
|
||||||
|
count[0]++;
|
||||||
|
super.getBodyChunk();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
||||||
|
parser.setEventHandler(new EH());
|
||||||
|
parser.setGenerator(gen);
|
||||||
|
|
||||||
|
parser.parseNext();
|
||||||
|
assertEquals(1,parser.getState());
|
||||||
|
assertEquals(1,count[0]);
|
||||||
|
|
||||||
|
endp.setIn(new ByteArrayBuffer(TypeUtil.fromHexString("1234007e007c7468656e616d653d746865253230717569636b25323062726f776e253230666f782532306a756d70732532306f766572253230746f2532307468652532306c617a79253230646f67253230544845253230515549434b25323042524f574e253230464f582532304a554d50532532304f564552253230544f25323054")));
|
||||||
|
|
||||||
|
while (parser.parseNext()>0);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void testPacketFragment() throws Exception
|
||||||
|
{
|
||||||
|
String packet = "123401070202000f77696474683d20485454502f312e300000122f636f6e74726f6c2f70726f647563742f2200000e3230382e32372e3230332e31323800ffff000c7777772e756c74612e636f6d000050000005a006000a6b6565702d616c69766500a00b000c7777772e756c74612e636f6d00a00e002b4d6f7a696c6c612f342e302028636f6d70617469626c653b20426f726465724d616e6167657220332e302900a0010043696d6167652f6769662c20696d6167652f782d786269746d61702c20696d6167652f6a7065672c20696d6167652f706a7065672c20696d6167652f706d672c202a2f2a00a008000130000600067570726f64310008000a4145533235362d53484100ff";
|
||||||
|
byte[] src = TypeUtil.fromHexString(packet);
|
||||||
|
|
||||||
|
for (int f=1;f<src.length;f++)
|
||||||
|
{
|
||||||
|
byte[] frag0=new byte[src.length-f];
|
||||||
|
byte[] frag1=new byte[f];
|
||||||
|
|
||||||
|
System.arraycopy(src,0,frag0,0,src.length-f);
|
||||||
|
System.arraycopy(src,src.length-f,frag1,0,f);
|
||||||
|
|
||||||
|
ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
SimpleBuffers buffers=new SimpleBuffers(new Buffer[]{buffer});
|
||||||
|
|
||||||
|
ByteArrayEndPoint endp = new ByteArrayEndPoint(frag0,Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
endp.setNonBlocking(true);
|
||||||
|
|
||||||
|
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
||||||
|
parser.setEventHandler(new EH());
|
||||||
|
parser.setGenerator(new Ajp13Generator(buffers,endp,0,0));
|
||||||
|
parser.parseNext();
|
||||||
|
|
||||||
|
endp.setIn(new ByteArrayBuffer(frag1));
|
||||||
|
parser.parseAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void testPacketFragmentWithBody() throws Exception
|
||||||
|
{
|
||||||
|
String packet = getTestHeader()+getTestBody();
|
||||||
|
byte[] src = TypeUtil.fromHexString(packet);
|
||||||
|
|
||||||
|
for (int f=1;f<src.length;f++)
|
||||||
|
{
|
||||||
|
byte[] frag0=new byte[src.length-f];
|
||||||
|
byte[] frag1=new byte[f];
|
||||||
|
|
||||||
|
System.arraycopy(src,0,frag0,0,src.length-f);
|
||||||
|
System.arraycopy(src,src.length-f,frag1,0,f);
|
||||||
|
|
||||||
|
ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
SimpleBuffers buffers=new SimpleBuffers(new Buffer[]{buffer});
|
||||||
|
|
||||||
|
ByteArrayEndPoint endp = new ByteArrayEndPoint(frag0,Ajp13Packet.MAX_PACKET_SIZE);
|
||||||
|
endp.setNonBlocking(true);
|
||||||
|
|
||||||
|
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
||||||
|
parser.setEventHandler(new EH());
|
||||||
|
parser.setGenerator(new Ajp13Generator(buffers,endp,0,0));
|
||||||
|
parser.parseNext();
|
||||||
|
|
||||||
|
endp.setIn(new ByteArrayBuffer(frag1));
|
||||||
|
parser.parseAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 getTestBody()
|
||||||
|
{
|
||||||
|
StringBuffer body = new StringBuffer("");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
body.append("123402f902f72d2d2d2d2d2d2d2d");
|
||||||
|
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("33383332353432363038372d2d0d0a");
|
||||||
|
|
||||||
|
|
||||||
|
return body.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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class EH implements Ajp13Parser.EventHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
public void content(Buffer ref) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void headerComplete() throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println("--");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void messageComplete(long contextLength) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println("==");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedHeader(Buffer name, Buffer value) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println(name+": "+value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedMethod(Buffer method) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedProtocol(Buffer protocol) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println(protocol);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedQueryString(Buffer value) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println("?"+value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedRemoteAddr(Buffer addr) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println("addr="+addr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedRemoteHost(Buffer host) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println("host="+host);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedRequestAttribute(String key, Buffer value) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println(key+":: "+value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedServerName(Buffer name) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println("Server:: "+name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedServerPort(int port) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println("Port:: "+port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedSslSecure(boolean secure) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println("Secure:: "+secure);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedUri(Buffer uri) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startForwardRequest() throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println("..");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedAuthorizationType(Buffer authType) throws IOException
|
||||||
|
{
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedRemoteUser(Buffer remoteUser) throws IOException
|
||||||
|
{
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedServletPath(Buffer servletPath) throws IOException
|
||||||
|
{
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedContextPath(Buffer context) throws IOException
|
||||||
|
{
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedSslCert(Buffer sslCert) throws IOException
|
||||||
|
{
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedSslCipher(Buffer sslCipher) throws IOException
|
||||||
|
{
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedSslSession(Buffer sslSession) throws IOException
|
||||||
|
{
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedSslKeySize(int keySize) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println(key+":: "+value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsedRequestAttribute(String key, int value) throws IOException
|
||||||
|
{
|
||||||
|
// System.err.println(key+":: "+value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-project</artifactId>
|
||||||
|
<version>7.0.0.incubation0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>jetty-annotations</artifactId>
|
||||||
|
<name>Jetty :: Servlet Annotations</name>
|
||||||
|
<description>Annotation support for deploying servlets in jetty.</description>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<version>1.4.2</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>manifest</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-RequiredExecutionEnvironment>J2SE-1.5</Bundle-RequiredExecutionEnvironment>
|
||||||
|
<Bundle-DocURL>http://jetty.eclipse.org</Bundle-DocURL>
|
||||||
|
<Import-Package>!org.eclipse.jetty.annotations.*,*</Import-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<!--
|
||||||
|
Required for OSGI
|
||||||
|
-->
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mortbay.jetty</groupId>
|
||||||
|
<artifactId>servlet-annotation-spec</artifactId>
|
||||||
|
<version>3.0.pre0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jndi</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-plus</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-webapp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.geronimo.specs</groupId>
|
||||||
|
<artifactId>geronimo-annotation_1.0_spec</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>asm</groupId>
|
||||||
|
<artifactId>asm-commons</artifactId>
|
||||||
|
<version>3.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,729 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 java.io.InputStream;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.Loader;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
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.Type;
|
||||||
|
import org.objectweb.asm.commons.EmptyVisitor;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnnotationFinder
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Scans class sources using asm to find annotations.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AnnotationFinder
|
||||||
|
{
|
||||||
|
private Map<String,ParsedClass> parsedClasses = new HashMap<String, ParsedClass>();
|
||||||
|
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
name = name.replace('$', '.');
|
||||||
|
|
||||||
|
return name.replace('/', '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class convertType (org.objectweb.asm.Type t)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
if (t == null)
|
||||||
|
return (Class)null;
|
||||||
|
|
||||||
|
switch (t.getSort())
|
||||||
|
{
|
||||||
|
case Type.BOOLEAN:
|
||||||
|
{
|
||||||
|
return Boolean.TYPE;
|
||||||
|
}
|
||||||
|
case Type.ARRAY:
|
||||||
|
{
|
||||||
|
Class clazz = convertType(t.getElementType());
|
||||||
|
return Array.newInstance(clazz, 0).getClass();
|
||||||
|
}
|
||||||
|
case Type.BYTE:
|
||||||
|
{
|
||||||
|
return Byte.TYPE;
|
||||||
|
}
|
||||||
|
case Type.CHAR:
|
||||||
|
{
|
||||||
|
return Character.TYPE;
|
||||||
|
}
|
||||||
|
case Type.DOUBLE:
|
||||||
|
{
|
||||||
|
return Double.TYPE;
|
||||||
|
}
|
||||||
|
case Type.FLOAT:
|
||||||
|
{
|
||||||
|
return Float.TYPE;
|
||||||
|
}
|
||||||
|
case Type.INT:
|
||||||
|
{
|
||||||
|
return Integer.TYPE;
|
||||||
|
}
|
||||||
|
case Type.LONG:
|
||||||
|
{
|
||||||
|
return Long.TYPE;
|
||||||
|
}
|
||||||
|
case Type.OBJECT:
|
||||||
|
{
|
||||||
|
return (Loader.loadClass(null, t.getClassName()));
|
||||||
|
}
|
||||||
|
case Type.SHORT:
|
||||||
|
{
|
||||||
|
return Short.TYPE;
|
||||||
|
}
|
||||||
|
case Type.VOID:
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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<types.length; i++)
|
||||||
|
{
|
||||||
|
classArray[i] = convertType(types[i]);
|
||||||
|
}
|
||||||
|
return classArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnnotatedStructure
|
||||||
|
*
|
||||||
|
* Annotations on an object such as a class, field or method.
|
||||||
|
*/
|
||||||
|
public static class AnnotatedStructure extends EmptyVisitor
|
||||||
|
{
|
||||||
|
Map<String, Map<String, Object>> annotations = new HashMap<String, Map<String,Object>>();
|
||||||
|
|
||||||
|
|
||||||
|
public AnnotationVisitor addAnnotation (final String name)
|
||||||
|
{
|
||||||
|
final HashMap<String,Object> annotationValues = new HashMap<String,Object>();
|
||||||
|
this.annotations.put(normalize(name), annotationValues);
|
||||||
|
return new AnnotationVisitor()
|
||||||
|
{
|
||||||
|
public void visit(String name, Object value)
|
||||||
|
{
|
||||||
|
annotationValues.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnnotationVisitor visitAnnotation(String name, String desc)
|
||||||
|
{
|
||||||
|
return null; //ignore nested annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnnotationVisitor visitArray(String arg0)
|
||||||
|
{
|
||||||
|
return null;//ignore array valued annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitEnd()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitEnum(String name, String desc, String value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Map<String, Object>> getAnnotations ()
|
||||||
|
{
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuffer strbuff = new StringBuffer();
|
||||||
|
|
||||||
|
for (Map.Entry<String, Map<String,Object>> e: annotations.entrySet())
|
||||||
|
{
|
||||||
|
strbuff.append(e.getKey()+"\n");
|
||||||
|
for (Map.Entry<String,Object> v: e.getValue().entrySet())
|
||||||
|
{
|
||||||
|
strbuff.append("\t"+v.getKey()+"="+v.getValue()+", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strbuff.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ParsedClass
|
||||||
|
*
|
||||||
|
* A class that contains annotations.
|
||||||
|
*/
|
||||||
|
public static class ParsedClass extends AnnotatedStructure
|
||||||
|
{
|
||||||
|
String className;
|
||||||
|
String superClassName;
|
||||||
|
Class clazz;
|
||||||
|
List<ParsedMethod> methods = new ArrayList<ParsedMethod>();
|
||||||
|
List<ParsedField> fields = new ArrayList<ParsedField>();
|
||||||
|
|
||||||
|
|
||||||
|
public ParsedClass (String className, String superClassName)
|
||||||
|
{
|
||||||
|
this.className = normalize(className);
|
||||||
|
this.superClassName = normalize(superClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClassName()
|
||||||
|
{
|
||||||
|
return this.className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSuperClassName ()
|
||||||
|
{
|
||||||
|
return this.superClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class toClass ()
|
||||||
|
throws ClassNotFoundException
|
||||||
|
{
|
||||||
|
if (clazz==null)
|
||||||
|
clazz = Loader.loadClass(null, className);
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ParsedMethod> getMethods ()
|
||||||
|
{
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParsedMethod getMethod(String name, String paramString)
|
||||||
|
{
|
||||||
|
Iterator<ParsedMethod> itor = methods.iterator();
|
||||||
|
ParsedMethod method = null;
|
||||||
|
while (itor.hasNext() && method==null)
|
||||||
|
{
|
||||||
|
ParsedMethod m = itor.next();
|
||||||
|
if (m.matches(name, paramString))
|
||||||
|
method = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMethod (ParsedMethod m)
|
||||||
|
{
|
||||||
|
if (getMethod(m.methodName, m.paramString)!= null)
|
||||||
|
return;
|
||||||
|
methods.add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ParsedField> getFields()
|
||||||
|
{
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParsedField getField(String name)
|
||||||
|
{
|
||||||
|
Iterator<ParsedField> itor = fields.iterator();
|
||||||
|
ParsedField field = null;
|
||||||
|
while (itor.hasNext() && field==null)
|
||||||
|
{
|
||||||
|
ParsedField f = itor.next();
|
||||||
|
if (f.matches(name))
|
||||||
|
field=f;
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addField (ParsedField f)
|
||||||
|
{
|
||||||
|
if (getField(f.fieldName) != null)
|
||||||
|
return;
|
||||||
|
fields.add(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
StringBuffer strbuff = new StringBuffer();
|
||||||
|
strbuff.append(this.className+"\n");
|
||||||
|
strbuff.append("Class annotations\n"+super.toString());
|
||||||
|
strbuff.append("\n");
|
||||||
|
strbuff.append("Method annotations\n");
|
||||||
|
for (ParsedMethod p:methods)
|
||||||
|
strbuff.append(p+"\n");
|
||||||
|
strbuff.append("\n");
|
||||||
|
strbuff.append("Field annotations\n");
|
||||||
|
for (ParsedField f:fields)
|
||||||
|
strbuff.append(f+"\n");
|
||||||
|
strbuff.append("\n");
|
||||||
|
return strbuff.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ParsedMethod
|
||||||
|
*
|
||||||
|
* A class method that can contain annotations.
|
||||||
|
*/
|
||||||
|
public static class ParsedMethod extends AnnotatedStructure
|
||||||
|
{
|
||||||
|
ParsedClass pclass;
|
||||||
|
String methodName;
|
||||||
|
String paramString;
|
||||||
|
Method method;
|
||||||
|
|
||||||
|
|
||||||
|
public ParsedMethod(ParsedClass pclass, String name, String paramString)
|
||||||
|
{
|
||||||
|
this.pclass=pclass;
|
||||||
|
this.methodName=name;
|
||||||
|
this.paramString=paramString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
|
||||||
|
{
|
||||||
|
this.pclass.addMethod(this);
|
||||||
|
return addAnnotation(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method toMethod ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
if (method == null)
|
||||||
|
{
|
||||||
|
Type[] types = null;
|
||||||
|
if (paramString!=null)
|
||||||
|
types = Type.getArgumentTypes(paramString);
|
||||||
|
|
||||||
|
Class[] args = convertTypes(types);
|
||||||
|
method = pclass.toClass().getDeclaredMethod(methodName, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches (String name, String paramString)
|
||||||
|
{
|
||||||
|
if (!methodName.equals(name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (this.paramString!=null && this.paramString.equals(paramString))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return (this.paramString == paramString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return pclass.getClassName()+"."+methodName+"\n\t"+super.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ParsedField
|
||||||
|
*
|
||||||
|
* A class field that can contain annotations. Also implements the
|
||||||
|
* asm visitor for Annotations.
|
||||||
|
*/
|
||||||
|
public static class ParsedField extends AnnotatedStructure
|
||||||
|
{
|
||||||
|
ParsedClass pclass;
|
||||||
|
String fieldName;
|
||||||
|
Field field;
|
||||||
|
|
||||||
|
public ParsedField (ParsedClass pclass, String name)
|
||||||
|
{
|
||||||
|
this.pclass=pclass;
|
||||||
|
this.fieldName=name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
|
||||||
|
{
|
||||||
|
this.pclass.addField(this);
|
||||||
|
return addAnnotation(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field toField ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
if (field==null)
|
||||||
|
{
|
||||||
|
field=this.pclass.toClass().getDeclaredField(fieldName);
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean matches (String name)
|
||||||
|
{
|
||||||
|
if (fieldName.equals(name))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return pclass.getClassName()+"."+fieldName+"\n\t"+super.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MyClassVisitor
|
||||||
|
*
|
||||||
|
* ASM visitor for a class.
|
||||||
|
*/
|
||||||
|
public class MyClassVisitor extends EmptyVisitor
|
||||||
|
{
|
||||||
|
ParsedClass pclass;
|
||||||
|
|
||||||
|
|
||||||
|
public void visit (int version,
|
||||||
|
int access,
|
||||||
|
String name,
|
||||||
|
String signature,
|
||||||
|
String superName,
|
||||||
|
String[] interfaces)
|
||||||
|
{
|
||||||
|
pclass = new ParsedClass(name, superName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnnotationVisitor visitAnnotation (String desc, boolean visible)
|
||||||
|
{
|
||||||
|
if (!parsedClasses.containsKey(pclass.getClassName()))
|
||||||
|
parsedClasses.put(pclass.getClassName(), pclass);
|
||||||
|
|
||||||
|
return pclass.addAnnotation(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodVisitor visitMethod (int access,
|
||||||
|
String name,
|
||||||
|
String desc,
|
||||||
|
String signature,
|
||||||
|
String[] exceptions)
|
||||||
|
{
|
||||||
|
if (!parsedClasses.values().contains(pclass))
|
||||||
|
parsedClasses.put(pclass.getClassName(),pclass);
|
||||||
|
|
||||||
|
ParsedMethod method = pclass.getMethod(name, desc);
|
||||||
|
if (method==null)
|
||||||
|
method = new ParsedMethod(pclass, name, desc);
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FieldVisitor visitField (int access,
|
||||||
|
String name,
|
||||||
|
String desc,
|
||||||
|
String signature,
|
||||||
|
Object value)
|
||||||
|
{
|
||||||
|
if (!parsedClasses.values().contains(pclass))
|
||||||
|
parsedClasses.put(pclass.getClassName(),pclass);
|
||||||
|
|
||||||
|
ParsedField field = pclass.getField(name);
|
||||||
|
if (field==null)
|
||||||
|
field = new ParsedField(pclass, name);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void find (String className, ClassNameResolver resolver)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
if (className == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!resolver.isExcluded(className))
|
||||||
|
{
|
||||||
|
if ((parsedClasses.get(className) == null) || (resolver.shouldOverride(className)))
|
||||||
|
{
|
||||||
|
parsedClasses.remove(className);
|
||||||
|
className = className.replace('.', '/')+".class";
|
||||||
|
URL resource = Loader.getResource(this.getClass(), className, false);
|
||||||
|
if (resource!= null)
|
||||||
|
scanClass(resource.openStream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void find (String[] classNames, ClassNameResolver resolver)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
if (classNames == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
find(Arrays.asList(classNames), resolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void find (List<String> classNames, ClassNameResolver resolver)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
for (String s:classNames)
|
||||||
|
{
|
||||||
|
if (!resolver.isExcluded(s))
|
||||||
|
{
|
||||||
|
if ((parsedClasses.get(s) == null) || (resolver.shouldOverride(s)))
|
||||||
|
{
|
||||||
|
parsedClasses.remove(s);
|
||||||
|
s = s.replace('.', '/')+".class";
|
||||||
|
URL resource = Loader.getResource(this.getClass(), s, false);
|
||||||
|
if (resource!= null)
|
||||||
|
scanClass(resource.openStream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void find (Resource dir, ClassNameResolver resolver)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
if (!dir.isDirectory() || !dir.exists())
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
String[] files=dir.list();
|
||||||
|
for (int f=0;files!=null && f<files.length;f++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Resource res = dir.addPath(files[f]);
|
||||||
|
if (res.isDirectory())
|
||||||
|
find(res, resolver);
|
||||||
|
String name = res.getName();
|
||||||
|
if (name.endsWith(".class"))
|
||||||
|
{
|
||||||
|
if (!resolver.isExcluded(name))
|
||||||
|
{
|
||||||
|
if ((parsedClasses.get(name) == null) || (resolver.shouldOverride(name)))
|
||||||
|
{
|
||||||
|
parsedClasses.remove(name);
|
||||||
|
scanClass(res.getURL().openStream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.warn(Log.EXCEPTION,ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void find (ClassLoader loader, boolean visitParents, String jarNamePattern, boolean nullInclusive, final ClassNameResolver resolver)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
if (loader==null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(loader instanceof URLClassLoader))
|
||||||
|
return; //can't extract classes?
|
||||||
|
|
||||||
|
JarScanner scanner = new JarScanner()
|
||||||
|
{
|
||||||
|
public void processEntry(URL jarUrl, JarEntry entry)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String name = entry.getName();
|
||||||
|
if (name.toLowerCase().endsWith(".class"))
|
||||||
|
{
|
||||||
|
String shortName = name.replace('/', '.').substring(0,name.length()-6);
|
||||||
|
if (!resolver.isExcluded(shortName))
|
||||||
|
{
|
||||||
|
if ((parsedClasses.get(shortName) == null) || (resolver.shouldOverride(shortName)))
|
||||||
|
{
|
||||||
|
parsedClasses.remove(shortName);
|
||||||
|
Resource clazz = Resource.newResource("jar:"+jarUrl+"!/"+name);
|
||||||
|
scanClass(clazz.getInputStream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.warn("Problem processing jar entry "+entry, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
Pattern pattern = null;
|
||||||
|
if (jarNamePattern!=null)
|
||||||
|
pattern = Pattern.compile(jarNamePattern);
|
||||||
|
|
||||||
|
scanner.scan(pattern, loader, nullInclusive, visitParents);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Exclude class by name
|
||||||
|
* Instances of {@link AnnotationFinder} can implement this method to exclude
|
||||||
|
* classes by name.
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected boolean excludeClass (String name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public List<Class<?>> getClassesForAnnotation(Class<?> annotationClass)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
List<Class<?>> classes = new ArrayList<Class<?>>();
|
||||||
|
for (Map.Entry<String, ParsedClass> e: parsedClasses.entrySet())
|
||||||
|
{
|
||||||
|
ParsedClass pc = e.getValue();
|
||||||
|
Map<String, Map<String,Object>> annotations = pc.getAnnotations();
|
||||||
|
for (String key:annotations.keySet())
|
||||||
|
{
|
||||||
|
if (key.equals(annotationClass.getName()))
|
||||||
|
{
|
||||||
|
classes.add(pc.toClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return classes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public List<Method> getMethodsForAnnotation (Class<?> annotationClass)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
List<Method> methods = new ArrayList<Method>();
|
||||||
|
|
||||||
|
for (Map.Entry<String, ParsedClass> e: parsedClasses.entrySet())
|
||||||
|
{
|
||||||
|
ParsedClass pc = e.getValue();
|
||||||
|
|
||||||
|
List<ParsedMethod> pmethods = pc.getMethods();
|
||||||
|
for (ParsedMethod p:pmethods)
|
||||||
|
{
|
||||||
|
for (String key:p.getAnnotations().keySet())
|
||||||
|
{
|
||||||
|
if (key.equals(annotationClass.getName()))
|
||||||
|
{
|
||||||
|
methods.add(p.toMethod());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return methods;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<Field> getFieldsForAnnotation (Class<?> annotation)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
List<Field> fields = new ArrayList<Field>();
|
||||||
|
for (Map.Entry<String, ParsedClass> e: parsedClasses.entrySet())
|
||||||
|
{
|
||||||
|
ParsedClass pc = e.getValue();
|
||||||
|
|
||||||
|
List<ParsedField> pfields = pc.getFields();
|
||||||
|
for (ParsedField f:pfields)
|
||||||
|
{
|
||||||
|
for (String key:f.getAnnotations().keySet())
|
||||||
|
{
|
||||||
|
if (key.equals(annotation.getName()))
|
||||||
|
{
|
||||||
|
fields.add(f.toField());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
StringBuffer strbuff = new StringBuffer();
|
||||||
|
for (Map.Entry<String, ParsedClass> e:parsedClasses.entrySet())
|
||||||
|
{
|
||||||
|
strbuff.append(e.getValue());
|
||||||
|
strbuff.append("\n");
|
||||||
|
}
|
||||||
|
return strbuff.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void scanClass (InputStream is)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
ClassReader reader = new ClassReader(is);
|
||||||
|
reader.accept(new MyClassVisitor(), ClassReader.SKIP_CODE|ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,782 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.annotation.Resources;
|
||||||
|
import javax.annotation.security.RunAs;
|
||||||
|
import javax.naming.InitialContext;
|
||||||
|
import javax.naming.NameNotFoundException;
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.servlet.DispatcherType;
|
||||||
|
import javax.servlet.http.annotation.InitParam;
|
||||||
|
import javax.servlet.http.annotation.jaxrs.DELETE;
|
||||||
|
import javax.servlet.http.annotation.jaxrs.GET;
|
||||||
|
import javax.servlet.http.annotation.jaxrs.HEAD;
|
||||||
|
import javax.servlet.http.annotation.jaxrs.POST;
|
||||||
|
import javax.servlet.http.annotation.jaxrs.PUT;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.plus.annotation.Injection;
|
||||||
|
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||||
|
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||||
|
import org.eclipse.jetty.plus.annotation.PojoContextListener;
|
||||||
|
import org.eclipse.jetty.plus.annotation.PojoFilter;
|
||||||
|
import org.eclipse.jetty.plus.annotation.PojoServlet;
|
||||||
|
import org.eclipse.jetty.plus.annotation.PostConstructCallback;
|
||||||
|
import org.eclipse.jetty.plus.annotation.PreDestroyCallback;
|
||||||
|
import org.eclipse.jetty.plus.annotation.RunAsCollection;
|
||||||
|
import org.eclipse.jetty.servlet.FilterHolder;
|
||||||
|
import org.eclipse.jetty.servlet.FilterMapping;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jetty.servlet.ServletMapping;
|
||||||
|
import org.eclipse.jetty.util.IntrospectionUtil;
|
||||||
|
import org.eclipse.jetty.util.LazyList;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnnotationProcessor
|
||||||
|
*
|
||||||
|
* Act on the annotations discovered in the webapp.
|
||||||
|
*/
|
||||||
|
public class AnnotationProcessor
|
||||||
|
{
|
||||||
|
AnnotationFinder _finder;
|
||||||
|
ClassLoader _loader;
|
||||||
|
RunAsCollection _runAs;
|
||||||
|
InjectionCollection _injections;
|
||||||
|
LifeCycleCallbackCollection _callbacks;
|
||||||
|
List _servlets;
|
||||||
|
List _filters;
|
||||||
|
List _listeners;
|
||||||
|
List _servletMappings;
|
||||||
|
List _filterMappings;
|
||||||
|
Map _pojoInstances = new HashMap();
|
||||||
|
WebAppContext _webApp;
|
||||||
|
|
||||||
|
private static Class[] __envEntryTypes =
|
||||||
|
new Class[] {String.class, Character.class, Integer.class, Boolean.class, Double.class, Byte.class, Short.class, Long.class, Float.class};
|
||||||
|
|
||||||
|
public AnnotationProcessor(WebAppContext webApp, AnnotationFinder finder, RunAsCollection runAs, InjectionCollection injections, LifeCycleCallbackCollection callbacks,
|
||||||
|
List servlets, List filters, List listeners, List servletMappings, List filterMappings)
|
||||||
|
{
|
||||||
|
_webApp=webApp;
|
||||||
|
_finder=finder;
|
||||||
|
_runAs=runAs;
|
||||||
|
_injections=injections;
|
||||||
|
_callbacks=callbacks;
|
||||||
|
_servlets=servlets;
|
||||||
|
_filters=filters;
|
||||||
|
_listeners=listeners;
|
||||||
|
_servletMappings=servletMappings;
|
||||||
|
_filterMappings=filterMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void process ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
processServlets();
|
||||||
|
processFilters();
|
||||||
|
processListeners();
|
||||||
|
processRunAsAnnotations();
|
||||||
|
processLifeCycleCallbackAnnotations();
|
||||||
|
processResourcesAnnotations();
|
||||||
|
processResourceAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processServlets ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
//@Servlet(urlMappings=String[], description=String, icon=String, loadOnStartup=int, name=String, initParams=InitParams[])
|
||||||
|
for (Class clazz:_finder.getClassesForAnnotation(javax.servlet.http.annotation.Servlet.class))
|
||||||
|
{
|
||||||
|
javax.servlet.http.annotation.Servlet annotation = (javax.servlet.http.annotation.Servlet)clazz.getAnnotation(javax.servlet.http.annotation.Servlet.class);
|
||||||
|
PojoServlet servlet = new PojoServlet(getPojoInstanceFor(clazz));
|
||||||
|
|
||||||
|
List<Method> methods = _finder.getMethodsForAnnotation(GET.class);
|
||||||
|
if (methods.size() > 1)
|
||||||
|
throw new IllegalStateException ("More than one GET annotation on "+clazz.getName());
|
||||||
|
else if (methods.size() == 1)
|
||||||
|
servlet.setGetMethodName(methods.get(0).getName());
|
||||||
|
|
||||||
|
methods = _finder.getMethodsForAnnotation(POST.class);
|
||||||
|
if (methods.size() > 1)
|
||||||
|
throw new IllegalStateException ("More than one POST annotation on "+clazz.getName());
|
||||||
|
else if (methods.size() == 1)
|
||||||
|
servlet.setPostMethodName(methods.get(0).getName());
|
||||||
|
|
||||||
|
methods = _finder.getMethodsForAnnotation(PUT.class);
|
||||||
|
if (methods.size() > 1)
|
||||||
|
throw new IllegalStateException ("More than one PUT annotation on "+clazz.getName());
|
||||||
|
else if (methods.size() == 1)
|
||||||
|
servlet.setPutMethodName(methods.get(0).getName());
|
||||||
|
|
||||||
|
methods = _finder.getMethodsForAnnotation(DELETE.class);
|
||||||
|
if (methods.size() > 1)
|
||||||
|
throw new IllegalStateException ("More than one DELETE annotation on "+clazz.getName());
|
||||||
|
else if (methods.size() == 1)
|
||||||
|
servlet.setDeleteMethodName(methods.get(0).getName());
|
||||||
|
|
||||||
|
methods = _finder.getMethodsForAnnotation(HEAD.class);
|
||||||
|
if (methods.size() > 1)
|
||||||
|
throw new IllegalStateException ("More than one HEAD annotation on "+clazz.getName());
|
||||||
|
else if (methods.size() == 1)
|
||||||
|
servlet.setHeadMethodName(methods.get(0).getName());
|
||||||
|
|
||||||
|
ServletHolder holder = new ServletHolder(servlet);
|
||||||
|
holder.setName((annotation.name().equals("")?clazz.getName():annotation.name()));
|
||||||
|
holder.setInitOrder(annotation.loadOnStartup());
|
||||||
|
LazyList.add(_servlets, holder);
|
||||||
|
|
||||||
|
for (InitParam ip:annotation.initParams())
|
||||||
|
{
|
||||||
|
holder.setInitParameter(ip.name(), ip.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (annotation.urlMappings().length > 0)
|
||||||
|
{
|
||||||
|
ArrayList paths = new ArrayList();
|
||||||
|
ServletMapping mapping = new ServletMapping();
|
||||||
|
mapping.setServletName(holder.getName());
|
||||||
|
for (String s:annotation.urlMappings())
|
||||||
|
{
|
||||||
|
paths.add(normalizePattern(s));
|
||||||
|
}
|
||||||
|
mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
|
||||||
|
LazyList.add(_servletMappings,mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processFilters ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
//@ServletFilter(description=String, filterName=String, displayName=String, icon=String,initParams=InitParam[], filterMapping=FilterMapping)
|
||||||
|
for (Class clazz:_finder.getClassesForAnnotation(javax.servlet.http.annotation.ServletFilter.class))
|
||||||
|
{
|
||||||
|
javax.servlet.http.annotation.ServletFilter annotation = (javax.servlet.http.annotation.ServletFilter)clazz.getAnnotation(javax.servlet.http.annotation.ServletFilter.class);
|
||||||
|
PojoFilter filter = new PojoFilter(getPojoInstanceFor(clazz));
|
||||||
|
|
||||||
|
FilterHolder holder = new FilterHolder(filter);
|
||||||
|
holder.setName((annotation.filterName().equals("")?clazz.getName():annotation.filterName()));
|
||||||
|
holder.setDisplayName(annotation.displayName());
|
||||||
|
LazyList.add(_filters, holder);
|
||||||
|
|
||||||
|
for (InitParam ip:annotation.initParams())
|
||||||
|
{
|
||||||
|
holder.setInitParameter(ip.name(), ip.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (annotation.filterMapping() != null)
|
||||||
|
{
|
||||||
|
FilterMapping mapping = new FilterMapping();
|
||||||
|
mapping.setFilterName(holder.getName());
|
||||||
|
ArrayList paths = new ArrayList();
|
||||||
|
for (String s:annotation.filterMapping().urlPattern())
|
||||||
|
{
|
||||||
|
paths.add(normalizePattern(s));
|
||||||
|
}
|
||||||
|
mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
|
||||||
|
ArrayList names = new ArrayList();
|
||||||
|
for (String s:annotation.filterMapping().servletNames())
|
||||||
|
{
|
||||||
|
names.add(s);
|
||||||
|
}
|
||||||
|
mapping.setServletNames((String[])names.toArray(new String[names.size()]));
|
||||||
|
|
||||||
|
int dispatcher=FilterMapping.DEFAULT;
|
||||||
|
for (DispatcherType d:annotation.filterMapping().dispatcherTypes())
|
||||||
|
{
|
||||||
|
dispatcher = dispatcher|FilterMapping.dispatch(d);
|
||||||
|
}
|
||||||
|
mapping.setDispatches(dispatcher);
|
||||||
|
LazyList.add(_filterMappings,mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void processListeners ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
//@ServletContextListener(description=String)
|
||||||
|
for (Class clazz:_finder.getClassesForAnnotation(javax.servlet.http.annotation.ServletContextListener.class))
|
||||||
|
{
|
||||||
|
PojoContextListener listener = new PojoContextListener(getPojoInstanceFor(clazz));
|
||||||
|
LazyList.add(_listeners, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List getServlets ()
|
||||||
|
{
|
||||||
|
return _servlets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getServletMappings ()
|
||||||
|
{
|
||||||
|
return _servletMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getFilters ()
|
||||||
|
{
|
||||||
|
return _filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getFilterMappings ()
|
||||||
|
{
|
||||||
|
return _filterMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getListeners()
|
||||||
|
{
|
||||||
|
return _listeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void processRunAsAnnotations ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
for (Class clazz:_finder.getClassesForAnnotation(RunAs.class))
|
||||||
|
{
|
||||||
|
if (!javax.servlet.Servlet.class.isAssignableFrom(clazz) && !(_pojoInstances.containsKey(clazz)))
|
||||||
|
{
|
||||||
|
Log.debug("Ignoring runAs notation on on-servlet class "+clazz.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RunAs runAs = (RunAs)clazz.getAnnotation(RunAs.class);
|
||||||
|
if (runAs != null)
|
||||||
|
{
|
||||||
|
String role = runAs.value();
|
||||||
|
if (role != null)
|
||||||
|
{
|
||||||
|
org.eclipse.jetty.plus.annotation.RunAs ra = new org.eclipse.jetty.plus.annotation.RunAs();
|
||||||
|
ra.setTargetClass(clazz);
|
||||||
|
ra.setRoleName(role);
|
||||||
|
_runAs.add(ra);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void processLifeCycleCallbackAnnotations()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
processPostConstructAnnotations();
|
||||||
|
processPreDestroyAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processPostConstructAnnotations ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
// TODO: check that the same class does not have more than one
|
||||||
|
for (Method m:_finder.getMethodsForAnnotation(PostConstruct.class))
|
||||||
|
{
|
||||||
|
if (!isServletType(m.getDeclaringClass()))
|
||||||
|
{
|
||||||
|
Log.debug("Ignoring "+m.getName()+" as non-servlet type");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m.getParameterTypes().length != 0)
|
||||||
|
throw new IllegalStateException(m+" has parameters");
|
||||||
|
if (m.getReturnType() != Void.TYPE)
|
||||||
|
throw new IllegalStateException(m+" is not void");
|
||||||
|
if (m.getExceptionTypes().length != 0)
|
||||||
|
throw new IllegalStateException(m+" throws checked exceptions");
|
||||||
|
if (Modifier.isStatic(m.getModifiers()))
|
||||||
|
throw new IllegalStateException(m+" is static");
|
||||||
|
|
||||||
|
PostConstructCallback callback = new PostConstructCallback();
|
||||||
|
callback.setTargetClass(m.getDeclaringClass());
|
||||||
|
callback.setTarget(m);
|
||||||
|
_callbacks.add(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processPreDestroyAnnotations ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
//TODO: check that the same class does not have more than one
|
||||||
|
|
||||||
|
for (Method m: _finder.getMethodsForAnnotation(PreDestroy.class))
|
||||||
|
{
|
||||||
|
if (!isServletType(m.getDeclaringClass()))
|
||||||
|
{
|
||||||
|
Log.debug("Ignoring "+m.getName()+" as non-servlet type");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m.getParameterTypes().length != 0)
|
||||||
|
throw new IllegalStateException(m+" has parameters");
|
||||||
|
if (m.getReturnType() != Void.TYPE)
|
||||||
|
throw new IllegalStateException(m+" is not void");
|
||||||
|
if (m.getExceptionTypes().length != 0)
|
||||||
|
throw new IllegalStateException(m+" throws checked exceptions");
|
||||||
|
if (Modifier.isStatic(m.getModifiers()))
|
||||||
|
throw new IllegalStateException(m+" is static");
|
||||||
|
|
||||||
|
PreDestroyCallback callback = new PreDestroyCallback();
|
||||||
|
callback.setTargetClass(m.getDeclaringClass());
|
||||||
|
callback.setTarget(m);
|
||||||
|
_callbacks.add(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process @Resources annotation on classes
|
||||||
|
*/
|
||||||
|
public void processResourcesAnnotations ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
List<Class<?>> classes = _finder.getClassesForAnnotation(Resources.class);
|
||||||
|
for (Class<?> clazz:classes)
|
||||||
|
{
|
||||||
|
if (!isServletType(clazz))
|
||||||
|
{
|
||||||
|
Log.debug("Ignoring @Resources annotation on on-servlet type class "+clazz.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//Handle Resources annotation - add namespace entries
|
||||||
|
Resources resources = (Resources)clazz.getAnnotation(Resources.class);
|
||||||
|
if (resources == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Resource[] resArray = resources.value();
|
||||||
|
if (resArray==null||resArray.length==0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int j=0;j<resArray.length;j++)
|
||||||
|
{
|
||||||
|
String name = resArray[j].name();
|
||||||
|
String mappedName = resArray[j].mappedName();
|
||||||
|
Resource.AuthenticationType auth = resArray[j].authenticationType();
|
||||||
|
Class type = resArray[j].type();
|
||||||
|
boolean shareable = resArray[j].shareable();
|
||||||
|
|
||||||
|
if (name==null || name.trim().equals(""))
|
||||||
|
throw new IllegalStateException ("Class level Resource annotations must contain a name (Common Annotations Spec Section 2.3)");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//TODO don't ignore the shareable, auth etc etc
|
||||||
|
|
||||||
|
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp, name, mappedName))
|
||||||
|
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp.getServer(), name, mappedName))
|
||||||
|
throw new IllegalStateException("No resource bound at "+(mappedName==null?name:mappedName));
|
||||||
|
}
|
||||||
|
catch (NamingException e)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void processResourceAnnotations ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
processClassResourceAnnotations();
|
||||||
|
processMethodResourceAnnotations();
|
||||||
|
processFieldResourceAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class level Resource annotations declare a name in the
|
||||||
|
* environment that will be looked up at runtime. They do
|
||||||
|
* not specify an injection.
|
||||||
|
*/
|
||||||
|
public void processClassResourceAnnotations ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
List<Class<?>> classes = _finder.getClassesForAnnotation(Resource.class);
|
||||||
|
for (Class<?> clazz:classes)
|
||||||
|
{
|
||||||
|
if (!isServletType(clazz))
|
||||||
|
{
|
||||||
|
Log.debug("Ignoring @Resource annotation on on-servlet type class "+clazz.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//Handle Resource annotation - add namespace entries
|
||||||
|
Resource resource = (Resource)clazz.getAnnotation(Resource.class);
|
||||||
|
if (resource != null)
|
||||||
|
{
|
||||||
|
String name = resource.name();
|
||||||
|
String mappedName = resource.mappedName();
|
||||||
|
Resource.AuthenticationType auth = resource.authenticationType();
|
||||||
|
Class type = resource.type();
|
||||||
|
boolean shareable = resource.shareable();
|
||||||
|
|
||||||
|
if (name==null || name.trim().equals(""))
|
||||||
|
throw new IllegalStateException ("Class level Resource annotations must contain a name (Common Annotations Spec Section 2.3)");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//TODO don't ignore the shareable, auth etc etc
|
||||||
|
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp, name,mappedName))
|
||||||
|
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp.getServer(), name,mappedName))
|
||||||
|
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||||
|
}
|
||||||
|
catch (NamingException e)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a Resource annotation on the Methods.
|
||||||
|
*
|
||||||
|
* This will generate a JNDI entry, and an Injection to be
|
||||||
|
* processed when an instance of the class is created.
|
||||||
|
* @param injections
|
||||||
|
*/
|
||||||
|
public void processMethodResourceAnnotations ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
//Get all methods that have a Resource annotation
|
||||||
|
List<Method> methods = _finder.getMethodsForAnnotation(javax.annotation.Resource.class);
|
||||||
|
|
||||||
|
for (Method m: methods)
|
||||||
|
{
|
||||||
|
if (!isServletType(m.getDeclaringClass()))
|
||||||
|
{
|
||||||
|
Log.debug("Ignoring @Resource annotation on on-servlet type method "+m.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Commons Annotations Spec 2.3
|
||||||
|
* " The Resource annotation is used to declare a reference to a resource.
|
||||||
|
* It can be specified on a class, methods or on fields. When the
|
||||||
|
* annotation is applied on a field or method, the container will
|
||||||
|
* inject an instance of the requested resource into the application
|
||||||
|
* when the application is initialized... Even though this annotation
|
||||||
|
* is not marked Inherited, if used all superclasses MUST be examined
|
||||||
|
* to discover all uses of this annotation. All such annotation instances
|
||||||
|
* specify resources that are needed by the application. Note that this
|
||||||
|
* annotation may appear on private fields and methods of the superclasses.
|
||||||
|
* Injection of the declared resources needs to happen in these cases as
|
||||||
|
* well, even if a method with such an annotation is overridden by a subclass."
|
||||||
|
*
|
||||||
|
* Which IMHO, put more succinctly means "If you find a @Resource on any method
|
||||||
|
* or field, inject it!".
|
||||||
|
*/
|
||||||
|
Resource resource = (Resource)m.getAnnotation(Resource.class);
|
||||||
|
if (resource == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//JavaEE Spec 5.2.3: Method cannot be static
|
||||||
|
if (Modifier.isStatic(m.getModifiers()))
|
||||||
|
throw new IllegalStateException(m+" cannot be static");
|
||||||
|
|
||||||
|
|
||||||
|
// Check it is a valid javabean
|
||||||
|
if (!IntrospectionUtil.isJavaBeanCompliantSetter(m))
|
||||||
|
throw new IllegalStateException(m+" is not a java bean compliant setter method");
|
||||||
|
|
||||||
|
//default name is the javabean property name
|
||||||
|
String name = m.getName().substring(3);
|
||||||
|
name = name.substring(0,1).toLowerCase()+name.substring(1);
|
||||||
|
name = m.getDeclaringClass().getCanonicalName()+"/"+name;
|
||||||
|
//allow default name to be overridden
|
||||||
|
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);
|
||||||
|
//get the mappedName if there is one
|
||||||
|
String mappedName = (resource.mappedName()!=null && !resource.mappedName().trim().equals("")?resource.mappedName():null);
|
||||||
|
|
||||||
|
Class type = m.getParameterTypes()[0];
|
||||||
|
|
||||||
|
//get other parts that can be specified in @Resource
|
||||||
|
Resource.AuthenticationType auth = resource.authenticationType();
|
||||||
|
boolean shareable = resource.shareable();
|
||||||
|
|
||||||
|
//if @Resource specifies a type, check it is compatible with setter param
|
||||||
|
if ((resource.type() != null)
|
||||||
|
&&
|
||||||
|
!resource.type().equals(Object.class)
|
||||||
|
&&
|
||||||
|
(!IntrospectionUtil.isTypeCompatible(type, resource.type(), false)))
|
||||||
|
throw new IllegalStateException("@Resource incompatible type="+resource.type()+ " with method param="+type+ " for "+m);
|
||||||
|
|
||||||
|
//check if an injection has already been setup for this target by web.xml
|
||||||
|
Injection webXmlInjection = _injections.getInjection(m.getDeclaringClass(), m);
|
||||||
|
if (webXmlInjection == null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//try binding name to environment
|
||||||
|
//try the webapp's environment first
|
||||||
|
boolean bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp, name, mappedName);
|
||||||
|
|
||||||
|
//try the server's environment
|
||||||
|
if (!bound)
|
||||||
|
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp.getServer(), name, mappedName);
|
||||||
|
|
||||||
|
//try the jvm's environment
|
||||||
|
if (!bound)
|
||||||
|
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(null, name, mappedName);
|
||||||
|
|
||||||
|
//TODO if it is an env-entry from web.xml it can be injected, in which case there will be no
|
||||||
|
//NamingEntry, just a value bound in java:comp/env
|
||||||
|
if (!bound)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InitialContext ic = new InitialContext();
|
||||||
|
String nameInEnvironment = (mappedName!=null?mappedName:name);
|
||||||
|
ic.lookup("java:comp/env/"+nameInEnvironment);
|
||||||
|
bound = true;
|
||||||
|
}
|
||||||
|
catch (NameNotFoundException e)
|
||||||
|
{
|
||||||
|
bound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bound)
|
||||||
|
{
|
||||||
|
Log.debug("Bound "+(mappedName==null?name:mappedName) + " as "+ name);
|
||||||
|
// Make the Injection for it
|
||||||
|
Injection injection = new Injection();
|
||||||
|
injection.setTargetClass(m.getDeclaringClass());
|
||||||
|
injection.setJndiName(name);
|
||||||
|
injection.setMappingName(mappedName);
|
||||||
|
injection.setTarget(m);
|
||||||
|
_injections.add(injection);
|
||||||
|
}
|
||||||
|
else if (!isEnvEntryType(type))
|
||||||
|
{
|
||||||
|
|
||||||
|
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||||
|
//an error, it just means that perhaps the code will use a default value instead
|
||||||
|
// JavaEE Spec. sec 5.4.1.3
|
||||||
|
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NamingException e)
|
||||||
|
{
|
||||||
|
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||||
|
//an error, it just means that perhaps the code will use a default value instead
|
||||||
|
// JavaEE Spec. sec 5.4.1.3
|
||||||
|
if (!isEnvEntryType(type))
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if an injection is already set up for this name, then the types must be compatible
|
||||||
|
//JavaEE spec sec 5.2.4
|
||||||
|
|
||||||
|
Object value = webXmlInjection.lookupInjectedValue();
|
||||||
|
if (!IntrospectionUtil.isTypeCompatible(type, value.getClass(), false))
|
||||||
|
throw new IllegalStateException("Type of field="+type+" is not compatible with Resource type="+value.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process @Resource annotation for a Field. These will both set up a
|
||||||
|
* JNDI entry and generate an Injection. Or they can be the equivalent
|
||||||
|
* of env-entries with default values
|
||||||
|
*
|
||||||
|
* @param injections
|
||||||
|
*/
|
||||||
|
public void processFieldResourceAnnotations ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
//Get all fields that have a Resource annotation
|
||||||
|
List<Field> fields = _finder.getFieldsForAnnotation(Resource.class);
|
||||||
|
for (Field f: fields)
|
||||||
|
{
|
||||||
|
if (!isServletType(f.getDeclaringClass()))
|
||||||
|
{
|
||||||
|
Log.debug("Ignoring @Resource annotation on on-servlet type field "+f.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Resource resource = (Resource)f.getAnnotation(Resource.class);
|
||||||
|
if (resource == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//JavaEE Spec 5.2.3: Field cannot be static
|
||||||
|
if (Modifier.isStatic(f.getModifiers()))
|
||||||
|
throw new IllegalStateException(f+" cannot be static");
|
||||||
|
|
||||||
|
//JavaEE Spec 5.2.3: Field cannot be final
|
||||||
|
if (Modifier.isFinal(f.getModifiers()))
|
||||||
|
throw new IllegalStateException(f+" cannot be final");
|
||||||
|
|
||||||
|
//work out default name
|
||||||
|
String name = f.getDeclaringClass().getCanonicalName()+"/"+f.getName();
|
||||||
|
//allow @Resource name= to override the field name
|
||||||
|
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);
|
||||||
|
|
||||||
|
//get the type of the Field
|
||||||
|
Class type = f.getType();
|
||||||
|
//if @Resource specifies a type, check it is compatible with field type
|
||||||
|
if ((resource.type() != null)
|
||||||
|
&&
|
||||||
|
!resource.type().equals(Object.class)
|
||||||
|
&&
|
||||||
|
(!IntrospectionUtil.isTypeCompatible(type, resource.type(), false)))
|
||||||
|
throw new IllegalStateException("@Resource incompatible type="+resource.type()+ " with field type ="+f.getType());
|
||||||
|
|
||||||
|
//get the mappedName if there is one
|
||||||
|
String mappedName = (resource.mappedName()!=null && !resource.mappedName().trim().equals("")?resource.mappedName():null);
|
||||||
|
//get other parts that can be specified in @Resource
|
||||||
|
Resource.AuthenticationType auth = resource.authenticationType();
|
||||||
|
boolean shareable = resource.shareable();
|
||||||
|
//check if an injection has already been setup for this target by web.xml
|
||||||
|
Injection webXmlInjection = _injections.getInjection(f.getDeclaringClass(), f);
|
||||||
|
if (webXmlInjection == null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boolean bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp, name, mappedName);
|
||||||
|
if (!bound)
|
||||||
|
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp.getServer(), name, mappedName);
|
||||||
|
if (!bound)
|
||||||
|
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(null, name, mappedName);
|
||||||
|
if (!bound)
|
||||||
|
{
|
||||||
|
//see if there is an env-entry value been bound from web.xml
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InitialContext ic = new InitialContext();
|
||||||
|
String nameInEnvironment = (mappedName!=null?mappedName:name);
|
||||||
|
ic.lookup("java:comp/env/"+nameInEnvironment);
|
||||||
|
bound = true;
|
||||||
|
}
|
||||||
|
catch (NameNotFoundException e)
|
||||||
|
{
|
||||||
|
bound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Check there is a JNDI entry for this annotation
|
||||||
|
if (bound)
|
||||||
|
{
|
||||||
|
Log.debug("Bound "+(mappedName==null?name:mappedName) + " as "+ name);
|
||||||
|
// Make the Injection for it if the binding succeeded
|
||||||
|
Injection injection = new Injection();
|
||||||
|
injection.setTargetClass(f.getDeclaringClass());
|
||||||
|
injection.setJndiName(name);
|
||||||
|
injection.setMappingName(mappedName);
|
||||||
|
injection.setTarget(f);
|
||||||
|
_injections.add(injection);
|
||||||
|
}
|
||||||
|
else if (!isEnvEntryType(type))
|
||||||
|
{
|
||||||
|
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||||
|
//an error, it just means that perhaps the code will use a default value instead
|
||||||
|
// JavaEE Spec. sec 5.4.1.3
|
||||||
|
|
||||||
|
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NamingException e)
|
||||||
|
{
|
||||||
|
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||||
|
//an error, it just means that perhaps the code will use a default value instead
|
||||||
|
// JavaEE Spec. sec 5.4.1.3
|
||||||
|
if (!isEnvEntryType(type))
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if an injection is already set up for this name, then the types must be compatible
|
||||||
|
//JavaEE spec sec 5.2.4
|
||||||
|
Object value = webXmlInjection.lookupInjectedValue();
|
||||||
|
if (!IntrospectionUtil.isTypeCompatible(type, value.getClass(), false))
|
||||||
|
throw new IllegalStateException("Type of field="+type+" is not compatible with Resource type="+value.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the presented method belongs to a class that is one
|
||||||
|
* of the classes with which a servlet container should be concerned.
|
||||||
|
* @param m
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private 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) ||
|
||||||
|
(_pojoInstances.get(c) != null))
|
||||||
|
|
||||||
|
isServlet=true;
|
||||||
|
|
||||||
|
return isServlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an already-created instance of a pojo, or create one
|
||||||
|
* otherwise.
|
||||||
|
* @param clazz
|
||||||
|
* @return
|
||||||
|
* @throws InstantiationException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
private Object getPojoInstanceFor (Class clazz)
|
||||||
|
throws InstantiationException, IllegalAccessException
|
||||||
|
{
|
||||||
|
Object instance = _pojoInstances.get(clazz);
|
||||||
|
if (instance == null)
|
||||||
|
{
|
||||||
|
instance = clazz.newInstance();
|
||||||
|
_pojoInstances.put(clazz, instance);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isEnvEntryType (Class type)
|
||||||
|
{
|
||||||
|
boolean result = false;
|
||||||
|
for (int i=0;i<__envEntryTypes.length && !result;i++)
|
||||||
|
{
|
||||||
|
result = (type.equals(__envEntryTypes[i]));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String normalizePattern(String p)
|
||||||
|
{
|
||||||
|
if (p!=null && p.length()>0 && !p.startsWith("/") && !p.startsWith("*"))
|
||||||
|
return "/"+p;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.annotations;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public interface ClassNameResolver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Based on the execution context, should the class represented
|
||||||
|
* by "name" be excluded from consideration?
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isExcluded (String name);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on the execution context, if a duplicate class
|
||||||
|
* represented by "name" is detected, should the existing
|
||||||
|
* one be overridden or not?
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean shouldOverride (String name);
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 org.eclipse.jetty.servlet.FilterHolder;
|
||||||
|
import org.eclipse.jetty.servlet.FilterMapping;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Configuration extends org.eclipse.jetty.plus.webapp.Configuration
|
||||||
|
{
|
||||||
|
public static final String __web_inf_pattern = "org.eclipse.jetty.server.webapp.WebInfIncludeAnnotationJarPattern";
|
||||||
|
public static final String __container_pattern = "org.eclipse.jetty.server.webapp.ContainerIncludeAnnotationJarPattern";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Configuration () throws ClassNotFoundException
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#parseAnnotations()
|
||||||
|
*/
|
||||||
|
public void parseAnnotations() throws Exception
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* TODO Need to also take account of hidden classes on system classpath that should never
|
||||||
|
* contribute annotations to a webapp (system and server classes):
|
||||||
|
*
|
||||||
|
* --- when scanning system classpath:
|
||||||
|
* + system classes : should always be scanned (subject to pattern)
|
||||||
|
* + server classes : always ignored
|
||||||
|
*
|
||||||
|
* --- when scanning webapp classpath:
|
||||||
|
* + system classes : always ignored
|
||||||
|
* + server classes : always scanned
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* If same class is found in both container and in context then need to use
|
||||||
|
* webappcontext parentloaderpriority to work out which one contributes the
|
||||||
|
* annotation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
AnnotationFinder finder = new AnnotationFinder();
|
||||||
|
|
||||||
|
//if no pattern for the container path is defined, then by default scan NOTHING
|
||||||
|
Log.debug("Scanning system jars");
|
||||||
|
finder.find(getWebAppContext().getClassLoader().getParent(), true, getWebAppContext().getInitParameter(__container_pattern), false,
|
||||||
|
new ClassNameResolver ()
|
||||||
|
{
|
||||||
|
public boolean isExcluded (String name)
|
||||||
|
{
|
||||||
|
if (getWebAppContext().isSystemClass(name)) return false;
|
||||||
|
if (getWebAppContext().isServerClass(name)) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldOverride (String name)
|
||||||
|
{
|
||||||
|
//looking at system classpath
|
||||||
|
if (getWebAppContext().isParentLoaderPriority())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Log.debug("Scanning WEB-INF/lib jars");
|
||||||
|
//if no pattern for web-inf/lib is defined, then by default scan everything in it
|
||||||
|
finder.find (getWebAppContext().getClassLoader(), false, getWebAppContext().getInitParameter(__web_inf_pattern), true,
|
||||||
|
new ClassNameResolver()
|
||||||
|
{
|
||||||
|
public boolean isExcluded (String name)
|
||||||
|
{
|
||||||
|
if (getWebAppContext().isSystemClass(name)) return true;
|
||||||
|
if (getWebAppContext().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 (getWebAppContext().isParentLoaderPriority())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Log.debug("Scanning classes in WEB-INF/classes");
|
||||||
|
finder.find(_context.getWebInf().addPath("classes/"),
|
||||||
|
new ClassNameResolver()
|
||||||
|
{
|
||||||
|
public boolean isExcluded (String name)
|
||||||
|
{
|
||||||
|
if (getWebAppContext().isSystemClass(name)) return true;
|
||||||
|
if (getWebAppContext().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 (getWebAppContext().isParentLoaderPriority())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AnnotationProcessor processor = new AnnotationProcessor(getWebAppContext(), finder, _runAsCollection, _injections, _callbacks,
|
||||||
|
LazyList.getList(_servlets), LazyList.getList(_filters), LazyList.getList(_listeners),
|
||||||
|
LazyList.getList(_servletMappings), LazyList.getList(_filterMappings));
|
||||||
|
processor.process();
|
||||||
|
_servlets = processor.getServlets();
|
||||||
|
_filters = processor.getFilters();
|
||||||
|
_servletMappings = processor.getServletMappings();
|
||||||
|
_filterMappings = processor.getFilterMappings();
|
||||||
|
_listeners = processor.getListeners();
|
||||||
|
_servletHandler.setFilters((FilterHolder[])LazyList.toArray(_filters,FilterHolder.class));
|
||||||
|
_servletHandler.setFilterMappings((FilterMapping[])LazyList.toArray(_filterMappings,FilterMapping.class));
|
||||||
|
_servletHandler.setServlets((ServletHolder[])LazyList.toArray(_servlets,ServletHolder.class));
|
||||||
|
_servletHandler.setServletMappings((ServletMapping[])LazyList.toArray(_servletMappings,ServletMapping.class));
|
||||||
|
getWebAppContext().setEventListeners((EventListener[])LazyList.toArray(_listeners,EventListener.class));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Util
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Util
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all annotations directly and inherited on a class.
|
||||||
|
*
|
||||||
|
* @param clazz
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public List findMethodAnnotations (Class clazz)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List findFieldAnnotations (Class clazz)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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)
|
||||||
|
public class ClassB extends ClassA
|
||||||
|
{
|
||||||
|
|
||||||
|
//test override of public scope method
|
||||||
|
@Sample(value=51)
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import javax.servlet.http.annotation.FilterMapping;
|
||||||
|
import javax.servlet.http.annotation.InitParam;
|
||||||
|
import javax.servlet.http.annotation.Servlet;
|
||||||
|
import javax.servlet.http.annotation.ServletFilter;
|
||||||
|
import javax.servlet.http.annotation.jaxrs.GET;
|
||||||
|
import javax.servlet.http.annotation.jaxrs.POST;
|
||||||
|
|
||||||
|
|
||||||
|
@Servlet(urlMappings = { "/foo/*", "/bah/*" }, name="CServlet", initParams={@InitParam(name="x", value="y")})
|
||||||
|
@ServletFilter(filterName="CFilter", filterMapping=@FilterMapping(dispatcherTypes={DispatcherType.REQUEST}, urlPattern = {"/*"}), initParams={@InitParam(name="a", value="99")})
|
||||||
|
@RunAs("admin")
|
||||||
|
public class ClassC
|
||||||
|
{
|
||||||
|
@Resource (mappedName="foo")
|
||||||
|
private Double foo;
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void pre ()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void post()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET()
|
||||||
|
@POST()
|
||||||
|
public void anything (HttpServletRequest request, HttpServletResponse response)
|
||||||
|
throws ServletException, IOException
|
||||||
|
{
|
||||||
|
response.setContentType("text/html");
|
||||||
|
response.getWriter().println("<h1>Pojo Servlet</h1>");
|
||||||
|
response.getWriter().println("Acting like a Servlet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void doFilter (HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||||
|
throws java.io.IOException, javax.servlet.ServletException
|
||||||
|
{
|
||||||
|
HttpSession session = request.getSession(true);
|
||||||
|
String val = request.getParameter("action");
|
||||||
|
if (val!=null)
|
||||||
|
session.setAttribute("action", val);
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.naming.Context;
|
||||||
|
import javax.naming.InitialContext;
|
||||||
|
import javax.naming.NameNotFoundException;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.plus.annotation.Injection;
|
||||||
|
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||||
|
import org.eclipse.jetty.plus.annotation.LifeCycleCallback;
|
||||||
|
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||||
|
import org.eclipse.jetty.plus.annotation.PojoFilter;
|
||||||
|
import org.eclipse.jetty.plus.annotation.PojoServlet;
|
||||||
|
import org.eclipse.jetty.plus.annotation.RunAs;
|
||||||
|
import org.eclipse.jetty.plus.annotation.RunAsCollection;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.servlet.FilterHolder;
|
||||||
|
import org.eclipse.jetty.servlet.FilterMapping;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jetty.servlet.ServletMapping;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
|
||||||
|
public class ServletAnnotationTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public void tearDown()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
InitialContext ic = new InitialContext();
|
||||||
|
Context comp = (Context)ic.lookup("java:comp");
|
||||||
|
comp.destroySubcontext("env");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAnnotations() throws Exception
|
||||||
|
{
|
||||||
|
Server server = new Server();
|
||||||
|
WebAppContext wac = new WebAppContext();
|
||||||
|
wac.setServer(server);
|
||||||
|
|
||||||
|
InitialContext ic = new InitialContext();
|
||||||
|
Context comp = (Context)ic.lookup("java:comp");
|
||||||
|
Context env = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
env = (Context)comp.lookup("env");
|
||||||
|
}
|
||||||
|
catch (NameNotFoundException e)
|
||||||
|
{
|
||||||
|
env = comp.createSubcontext("env");
|
||||||
|
}
|
||||||
|
|
||||||
|
org.eclipse.jetty.plus.jndi.EnvEntry foo = new org.eclipse.jetty.plus.jndi.EnvEntry("foo", new Double(1000.00), false);
|
||||||
|
List servlets = new ArrayList();
|
||||||
|
List filters = new ArrayList();
|
||||||
|
List listeners = new ArrayList();
|
||||||
|
List servletMappings = new ArrayList();
|
||||||
|
List filterMappings = new ArrayList();
|
||||||
|
|
||||||
|
List classes = new ArrayList();
|
||||||
|
classes.add("org.eclipse.jetty.annotations.ClassC");
|
||||||
|
|
||||||
|
AnnotationFinder finder = new AnnotationFinder();
|
||||||
|
finder.find (classes,
|
||||||
|
new ClassNameResolver()
|
||||||
|
{
|
||||||
|
|
||||||
|
public boolean isExcluded(String name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldOverride(String name)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
RunAsCollection runAs = new RunAsCollection();
|
||||||
|
InjectionCollection injections = new InjectionCollection();
|
||||||
|
LifeCycleCallbackCollection callbacks = new LifeCycleCallbackCollection();
|
||||||
|
|
||||||
|
AnnotationProcessor processor = new AnnotationProcessor (wac, finder, runAs, injections, callbacks,
|
||||||
|
servlets, filters, listeners, servletMappings, filterMappings);
|
||||||
|
processor.process();
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals(1, servlets.size());
|
||||||
|
ServletHolder sholder = (ServletHolder)servlets.get(0);
|
||||||
|
assertEquals("CServlet", sholder.getName());
|
||||||
|
assertTrue(sholder.getServlet() instanceof PojoServlet);
|
||||||
|
PojoServlet ps = (PojoServlet)sholder.getServlet();
|
||||||
|
assertEquals("anything", ps.getGetMethodName());
|
||||||
|
assertEquals("anything", ps.getPostMethodName());
|
||||||
|
Map sinitparams = sholder.getInitParameters();
|
||||||
|
assertEquals(1, sinitparams.size());
|
||||||
|
assertTrue(sinitparams.containsKey("x"));
|
||||||
|
assertTrue(sinitparams.containsValue("y"));
|
||||||
|
assertEquals(1, filters.size());
|
||||||
|
FilterHolder fholder = (FilterHolder)filters.get(0);
|
||||||
|
assertTrue(fholder.getFilter() instanceof PojoFilter);
|
||||||
|
|
||||||
|
Map finitparams = fholder.getInitParameters();
|
||||||
|
assertEquals(1, finitparams.size());
|
||||||
|
assertTrue(finitparams.containsKey("a"));
|
||||||
|
assertTrue(finitparams.containsValue("99"));
|
||||||
|
assertEquals(1, servletMappings.size());
|
||||||
|
ServletMapping smap = (ServletMapping)servletMappings.get(0);
|
||||||
|
assertEquals("CServlet", smap.getServletName());
|
||||||
|
assertEquals(2, smap.getPathSpecs().length);
|
||||||
|
assertEquals(1, filterMappings.size());
|
||||||
|
FilterMapping fmap = (FilterMapping)filterMappings.get(0);
|
||||||
|
assertEquals("CFilter", fmap.getFilterName());
|
||||||
|
assertEquals(1, fmap.getPathSpecs().length);
|
||||||
|
|
||||||
|
List<Injection> fieldInjections = injections.getFieldInjections(ClassC.class);
|
||||||
|
assertNotNull(fieldInjections);
|
||||||
|
assertEquals(1, fieldInjections.size());
|
||||||
|
|
||||||
|
RunAs ra = runAs.getRunAs(sholder);
|
||||||
|
assertNotNull(ra);
|
||||||
|
assertEquals("admin", ra.getRoleName());
|
||||||
|
|
||||||
|
List predestroys = callbacks.getPreDestroyCallbacks(sholder.getServlet());
|
||||||
|
assertNotNull(predestroys);
|
||||||
|
assertEquals(1, predestroys.size());
|
||||||
|
LifeCycleCallback cb = (LifeCycleCallback)predestroys.get(0);
|
||||||
|
assertTrue(cb.getTarget().equals(ClassC.class.getDeclaredMethod("pre", new Class[]{})));
|
||||||
|
|
||||||
|
List postconstructs = callbacks.getPostConstructCallbacks(sholder.getServlet());
|
||||||
|
assertNotNull(postconstructs);
|
||||||
|
assertEquals(1, postconstructs.size());
|
||||||
|
cb = (LifeCycleCallback)postconstructs.get(0);
|
||||||
|
assertTrue(cb.getTarget().equals(ClassC.class.getDeclaredMethod("post", new Class[]{})));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
public class TestAnnotationFinder extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public void testNormalize()
|
||||||
|
{
|
||||||
|
assertEquals("org.eclipse.test.Foo", AnnotationFinder.normalize("Lorg/eclipse/test/Foo;"));
|
||||||
|
assertEquals("org.eclipse.test.Foo.Bar", AnnotationFinder.normalize("org/eclipse/test/Foo$Bar.class"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertType ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testSampleAnnotation ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
String[] classNames = new String[]{"org.eclipse.jetty.annotations.ClassA"};
|
||||||
|
AnnotationFinder finder = new AnnotationFinder();
|
||||||
|
|
||||||
|
finder.find(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)));
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
List<Class<?>> classes = finder.getClassesForAnnotation(Sample.class);
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.err.println("Time to find classes matching annotation: "+((end-start)));
|
||||||
|
|
||||||
|
assertNotNull(classes);
|
||||||
|
assertEquals(1, classes.size());
|
||||||
|
assertTrue(classes.contains(org.eclipse.jetty.annotations.ClassA.class));
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
List<Method> methods = finder.getMethodsForAnnotation(Sample.class);
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.err.println("Time to find methods matching annotation : "+((end-start)));
|
||||||
|
|
||||||
|
assertNotNull(methods);
|
||||||
|
assertEquals (5, methods.size());
|
||||||
|
|
||||||
|
Method a = ClassA.class.getDeclaredMethod("a", new Class[]{Array.newInstance(Integer.class, 0).getClass()});
|
||||||
|
Method b = ClassA.class.getDeclaredMethod("b", new Class[]{Array.newInstance(ClassA.Foo.class, 0).getClass()});
|
||||||
|
Method c = ClassA.class.getDeclaredMethod("c", new Class[]{Array.newInstance(Integer.TYPE, 0).getClass()});
|
||||||
|
Method d = ClassA.class.getDeclaredMethod("d", new Class[]{Integer.TYPE, String.class});
|
||||||
|
Method l = ClassA.class.getDeclaredMethod("l", new Class[]{});
|
||||||
|
|
||||||
|
assertTrue(methods.contains(a));
|
||||||
|
assertTrue(methods.contains(b));
|
||||||
|
assertTrue(methods.contains(c));
|
||||||
|
assertTrue(methods.contains(d));
|
||||||
|
assertTrue(methods.contains(l));
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
List<Field> fields = finder.getFieldsForAnnotation(Sample.class);
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.err.println("Time to find fields matching annotation : "+((end-start)));
|
||||||
|
|
||||||
|
assertNotNull(fields);
|
||||||
|
assertEquals(1, fields.size());
|
||||||
|
|
||||||
|
Field m = ClassA.class.getDeclaredField("m");
|
||||||
|
assertTrue(fields.contains(m));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,249 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.annotation.Resources;
|
||||||
|
import javax.naming.Context;
|
||||||
|
import javax.naming.InitialContext;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.annotations.resources.ResourceA;
|
||||||
|
import org.eclipse.jetty.annotations.resources.ResourceB;
|
||||||
|
import org.eclipse.jetty.plus.annotation.Injection;
|
||||||
|
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||||
|
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||||
|
import org.eclipse.jetty.plus.annotation.RunAsCollection;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TestAnnotationInheritance
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TestAnnotationInheritance extends TestCase
|
||||||
|
{
|
||||||
|
List<String> classNames = new ArrayList<String>();
|
||||||
|
|
||||||
|
|
||||||
|
public void tearDown () throws Exception
|
||||||
|
{
|
||||||
|
classNames.clear();
|
||||||
|
InitialContext ic = new InitialContext();
|
||||||
|
Context comp = (Context)ic.lookup("java:comp");
|
||||||
|
comp.destroySubcontext("env");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInheritance ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
classNames.add(ClassA.class.getName());
|
||||||
|
classNames.add(ClassB.class.getName());
|
||||||
|
|
||||||
|
AnnotationFinder finder = new AnnotationFinder();
|
||||||
|
finder.find(classNames, new ClassNameResolver ()
|
||||||
|
{
|
||||||
|
public boolean isExcluded(String name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldOverride(String name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
List<Class<?>> classes = finder.getClassesForAnnotation(Sample.class);
|
||||||
|
assertEquals(2, classes.size());
|
||||||
|
|
||||||
|
//check methods
|
||||||
|
//List methods = collection.getMethods();
|
||||||
|
List<Method> methods = finder.getMethodsForAnnotation(Sample.class);
|
||||||
|
|
||||||
|
assertTrue(methods!=null);
|
||||||
|
assertFalse(methods.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testExclusions()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
AnnotationFinder finder = new AnnotationFinder();
|
||||||
|
finder.find(ClassA.class.getName(), new ClassNameResolver()
|
||||||
|
{
|
||||||
|
public boolean isExcluded(String name)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldOverride(String name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertTrue(finder.getClassesForAnnotation(Sample.class).isEmpty());
|
||||||
|
|
||||||
|
finder.find (ClassA.class.getName(), new ClassNameResolver()
|
||||||
|
{
|
||||||
|
public boolean isExcluded(String name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldOverride(String name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertEquals(1, finder.getClassesForAnnotation(Sample.class).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testResourceAnnotations ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
Server server = new Server();
|
||||||
|
WebAppContext wac = new WebAppContext();
|
||||||
|
wac.setServer(server);
|
||||||
|
|
||||||
|
InitialContext ic = new InitialContext();
|
||||||
|
Context comp = (Context)ic.lookup("java:comp");
|
||||||
|
Context env = comp.createSubcontext("env");
|
||||||
|
|
||||||
|
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", new Integer(1000), false);
|
||||||
|
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", new Integer(2000), false);
|
||||||
|
|
||||||
|
|
||||||
|
classNames.add(ResourceA.class.getName());
|
||||||
|
classNames.add(ResourceB.class.getName());
|
||||||
|
AnnotationFinder finder = new AnnotationFinder();
|
||||||
|
finder.find(classNames, new ClassNameResolver()
|
||||||
|
{
|
||||||
|
public boolean isExcluded(String name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldOverride(String name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
List<Class<?>> resourcesClasses = finder.getClassesForAnnotation(Resources.class);
|
||||||
|
assertNotNull(resourcesClasses);
|
||||||
|
assertEquals(1, resourcesClasses.size());
|
||||||
|
|
||||||
|
List<Class<?>> annotatedClasses = finder.getClassesForAnnotation(Resource.class);
|
||||||
|
List<Method> annotatedMethods = finder.getMethodsForAnnotation(Resource.class);
|
||||||
|
List<Field> annotatedFields = finder.getFieldsForAnnotation(Resource.class);
|
||||||
|
assertNotNull(annotatedClasses);
|
||||||
|
assertEquals(0, annotatedClasses.size());
|
||||||
|
assertEquals(3, annotatedMethods.size());
|
||||||
|
assertEquals(6, annotatedFields.size());
|
||||||
|
|
||||||
|
InjectionCollection injections = new InjectionCollection();
|
||||||
|
LifeCycleCallbackCollection callbacks = new LifeCycleCallbackCollection();
|
||||||
|
RunAsCollection runAses = new RunAsCollection();
|
||||||
|
AnnotationProcessor processor = new AnnotationProcessor(wac, finder, runAses, injections, callbacks,
|
||||||
|
Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST);
|
||||||
|
//process with all the specific annotations turned into injections, callbacks etc
|
||||||
|
processor.process();
|
||||||
|
|
||||||
|
//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(resourceB.getObjectToBind(), env.lookup("myf"));
|
||||||
|
assertEquals(resourceA.getObjectToBind(), env.lookup("mye"));
|
||||||
|
assertEquals(resourceA.getObjectToBind(), env.lookup("resA"));
|
||||||
|
assertEquals(resourceA.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/g"));
|
||||||
|
assertEquals(resourceA.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/h"));
|
||||||
|
assertEquals(resourceB.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceB/f"));
|
||||||
|
assertEquals(resourceB.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/n"));
|
||||||
|
|
||||||
|
//we should have Injections
|
||||||
|
assertNotNull(injections);
|
||||||
|
|
||||||
|
List<Injection> fieldInjections = injections.getFieldInjections(ResourceB.class);
|
||||||
|
assertNotNull(fieldInjections);
|
||||||
|
|
||||||
|
Iterator itor = fieldInjections.iterator();
|
||||||
|
System.err.println("Field injections:");
|
||||||
|
while (itor.hasNext())
|
||||||
|
{
|
||||||
|
System.err.println(itor.next());
|
||||||
|
}
|
||||||
|
//only 1 field injection because the other has no Resource mapping
|
||||||
|
assertEquals(1, fieldInjections.size());
|
||||||
|
|
||||||
|
fieldInjections = injections.getFieldInjections(ResourceA.class);
|
||||||
|
assertNotNull(fieldInjections);
|
||||||
|
assertEquals(4, fieldInjections.size());
|
||||||
|
|
||||||
|
|
||||||
|
List<Injection> methodInjections = injections.getMethodInjections(ResourceB.class);
|
||||||
|
itor = methodInjections.iterator();
|
||||||
|
System.err.println("Method injections:");
|
||||||
|
while (itor.hasNext())
|
||||||
|
System.err.println(itor.next());
|
||||||
|
|
||||||
|
assertNotNull(methodInjections);
|
||||||
|
assertEquals(0, methodInjections.size());
|
||||||
|
|
||||||
|
methodInjections = injections.getMethodInjections(ResourceA.class);
|
||||||
|
assertNotNull(methodInjections);
|
||||||
|
assertEquals(3, methodInjections.size());
|
||||||
|
|
||||||
|
//test injection
|
||||||
|
ResourceB binst = new ResourceB();
|
||||||
|
injections.inject(binst);
|
||||||
|
|
||||||
|
//check injected values
|
||||||
|
Field f = ResourceB.class.getDeclaredField ("f");
|
||||||
|
f.setAccessible(true);
|
||||||
|
assertEquals(resourceB.getObjectToBind() , 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(resourceA.getObjectToBind(), 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(resourceA.getObjectToBind(), f.get(binst));
|
||||||
|
|
||||||
|
//@Resource(mappedName="resB") //test using the default name on an inherited field
|
||||||
|
f = ResourceA.class.getDeclaredField("n");
|
||||||
|
f.setAccessible(true);
|
||||||
|
assertEquals(resourceB.getObjectToBind(), f.get(binst));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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="fluff", mappedName="resA"),
|
||||||
|
@Resource(name="stuff", 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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-project</artifactId>
|
||||||
|
<version>7.0.0.incubation0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>jetty-assembly-descriptor</artifactId>
|
||||||
|
<name>Jetty :: Assembly Descriptor</name>
|
||||||
|
</project>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<assembly>
|
||||||
|
<id>config</id>
|
||||||
|
<includeBaseDirectory>false</includeBaseDirectory>
|
||||||
|
<formats>
|
||||||
|
<format>jar</format>
|
||||||
|
</formats>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>src/main/config</directory>
|
||||||
|
<outputDirectory></outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>**</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</assembly>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<assembly>
|
||||||
|
<id>site-component</id>
|
||||||
|
<formats>
|
||||||
|
<format>jar</format>
|
||||||
|
</formats>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${basedir}</directory>
|
||||||
|
<includes>
|
||||||
|
<include>src/main/resources/org/eclipse/**</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</assembly>
|
|
@ -0,0 +1,503 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-project</artifactId>
|
||||||
|
<version>7.0.0.incubation0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>jetty-assembly</artifactId>
|
||||||
|
<name>Jetty :: Distribution Assemblies</name>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<properties>
|
||||||
|
<assembly.directory>target/assembly-prep</assembly.directory>
|
||||||
|
<slf4j-version>1.5.6</slf4j-version>
|
||||||
|
<jsp-2-1-version>9.1.02.B04.p0</jsp-2-1-version>
|
||||||
|
</properties>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>2.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>unpack</id>
|
||||||
|
<phase>generate-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>unpack</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-rewrite</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>config</classifier>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-ajp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>config</classifier>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-test-webapp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>config</classifier>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jmx</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>config</classifier>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-util</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>config</classifier>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-webapp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>config</classifier>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-plus</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>config</classifier>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>config</classifier>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<!--artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-setuid-java</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>config</classifier>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-win32-service</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>config</classifier>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem-->
|
||||||
|
</artifactItems>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<execution>
|
||||||
|
<id>copy</id>
|
||||||
|
<phase>generate-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<artifactItems>
|
||||||
|
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-util</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-io</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-http</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-security</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlet</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlets</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-xml</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-webapp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-deploy</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jmx</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-rewrite</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-ajp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-annotations</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-client</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jndi</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.mortbay.jetty</groupId>
|
||||||
|
<artifactId>jsp-api-2.1-glassfish</artifactId>
|
||||||
|
<version>${jsp-2-1-version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib/jsp-2.1</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.mortbay.jetty</groupId>
|
||||||
|
<artifactId>jsp-2.1-glassfish</artifactId>
|
||||||
|
<version>${jsp-2-1-version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib/jsp-2.1</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-plus</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.mortbay.jetty</groupId>
|
||||||
|
<artifactId>servlet-api</artifactId>
|
||||||
|
<version>${servlet-api-version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-test-webapp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>war</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/webapps</outputDirectory>
|
||||||
|
<destFileName>test.war</destFileName>
|
||||||
|
</artifactItem>
|
||||||
|
<!--artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-setuid-java</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-win32-service</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
</artifactItem-->
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-start</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}</outputDirectory>
|
||||||
|
<destFileName>start.jar</destFileName>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>${slf4j-version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib/slf4j</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>jcl104-over-slf4j</artifactId>
|
||||||
|
<version>${slf4j-version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib/slf4j</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>${slf4j-version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<includes>**</includes>
|
||||||
|
<outputDirectory>${assembly.directory}/lib/slf4j</outputDirectory>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<phase>generate-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>ant</groupId>
|
||||||
|
<artifactId>ant</artifactId>
|
||||||
|
<version>${ant-version}</version>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.eclipse.jdt</groupId>
|
||||||
|
<artifactId>core</artifactId>
|
||||||
|
<version>${eclipse-compiler-version}</version>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.mortbay.jetty</groupId>
|
||||||
|
<artifactId>jsp-api-2.1-glassfish</artifactId>
|
||||||
|
<version>${jsp-2-1-version}</version>
|
||||||
|
</artifactItem>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>org.mortbay.jetty</groupId>
|
||||||
|
<artifactId>jsp-2.1-glassfish</artifactId>
|
||||||
|
<version>${jsp-2-1-version}</version>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
<outputDirectory>${assembly.directory}/lib/jsp-2.1</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>src/main/assembly/jetty.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-deploy</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-rewrite</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-ajp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-annotations</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-test-webapp</artifactId>
|
||||||
|
<type>war</type>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jmx</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jndi</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-plus</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-client</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-start</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<assembly>
|
||||||
|
<id>src</id>
|
||||||
|
<formats>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
<format>tar.bz2</format>
|
||||||
|
<format>zip</format>
|
||||||
|
</formats>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${basedir}/target/dist-src</directory>
|
||||||
|
<outputDirectory></outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>**</include>
|
||||||
|
</includes>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/target/**</exclude>
|
||||||
|
<exclude>**/.svn/**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</assembly>
|
|
@ -0,0 +1,19 @@
|
||||||
|
<assembly>
|
||||||
|
<formats>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
<format>tar.bz2</format>
|
||||||
|
<format>zip</format>
|
||||||
|
</formats>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${assembly.directory}</directory>
|
||||||
|
<outputDirectory></outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>**</include>
|
||||||
|
</includes>
|
||||||
|
<excludes>
|
||||||
|
<exclude>*-config.jar</exclude>
|
||||||
|
</excludes>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</assembly>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<assembly>
|
||||||
|
<id>site-component</id>
|
||||||
|
<formats>
|
||||||
|
<format>jar</format>
|
||||||
|
</formats>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${basedir}/target/dist-src</directory>
|
||||||
|
<outputDirectory>jetty-distribution-${version}-site-component</outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>target/site/**</include>
|
||||||
|
<include>README**</include>
|
||||||
|
<include>VERSION**</include>
|
||||||
|
<include>LICENSES/**</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</assembly>
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
[ $# -eq 1 ] || { echo "Usage - $0 jetty-dir" >&2 ; exit 1 ; }
|
||||||
|
|
||||||
|
cd $1
|
||||||
|
D=$(pwd)
|
||||||
|
N=$(basename $D)
|
||||||
|
D=$(dirname $D)
|
||||||
|
cd $D
|
||||||
|
|
||||||
|
find $N -type f |\
|
||||||
|
egrep -v /\\.svn |\
|
||||||
|
egrep -v /target |\
|
||||||
|
egrep -v /\\. |\
|
||||||
|
egrep -v $N/start.jar |\
|
||||||
|
egrep -v $N/lib |\
|
||||||
|
egrep -v $N/logs |\
|
||||||
|
egrep -v $N/webapp |\
|
||||||
|
egrep -v $N/javadoc |\
|
||||||
|
xargs zip $D/$N-src.zip $N/logs
|
||||||
|
|
||||||
|
find $N -type f |\
|
||||||
|
egrep -v /\\.svn |\
|
||||||
|
egrep -v /target |\
|
||||||
|
egrep -v /\\. |\
|
||||||
|
egrep -v $N/logs |\
|
||||||
|
xargs zip $D/$N.zip $N/logs
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/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
|
||||||
|
|
|
@ -0,0 +1,656 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Startup script for jetty under *nix systems (it works under NT/cygwin too).
|
||||||
|
#
|
||||||
|
# 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.:
|
||||||
|
#
|
||||||
|
# <Arg><SystemProperty name="jetty.home" default="."/>/webapps/jetty.war</Arg>
|
||||||
|
#
|
||||||
|
# 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:
|
||||||
|
#
|
||||||
|
# <Set name="Port"><SystemProperty name="jetty.port" default="8080"/></Set>
|
||||||
|
#
|
||||||
|
# Note: that the config file could ignore this property simply by saying:
|
||||||
|
#
|
||||||
|
# <Set name="Port">8080</Set>
|
||||||
|
#
|
||||||
|
# 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/jetty6 ] ; then
|
||||||
|
. /etc/default/jetty6
|
||||||
|
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-6 \
|
||||||
|
jetty6 \
|
||||||
|
jetty-6.* \
|
||||||
|
jetty \
|
||||||
|
Jetty-6 \
|
||||||
|
Jetty6 \
|
||||||
|
Jetty-6.* \
|
||||||
|
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
|
||||||
|
|
||||||
|
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/jetty6";
|
||||||
|
exit 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if 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 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
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
This directory contains example contexts that may be deployed by
|
||||||
|
moving/copying/linking them to the ../contexts directory.
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
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.
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.eclipse.org/configure.dtd">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Configure a custom context for the javadoc.
|
||||||
|
|
||||||
|
This context contains only a ServletHandler with a default servlet
|
||||||
|
to serve static html files and images.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
|
||||||
|
<Call class="org.eclipse.jetty.util.log.Log" name="debug"><Arg>Configure javadoc.xml</Arg></Call>
|
||||||
|
<Set name="contextPath">/javadoc</Set>
|
||||||
|
<Set name="resourceBase"><SystemProperty name="jetty.home" default="."/>/javadoc/</Set>
|
||||||
|
<Set name="handler">
|
||||||
|
<New class="org.eclipse.jetty.server.handler.ResourceHandler">
|
||||||
|
<Set name="welcomeFiles">
|
||||||
|
<Array type="String">
|
||||||
|
<Item>index.html</Item>
|
||||||
|
<Item>contents.html</Item> <!-- the index if javadoc not generated -->
|
||||||
|
</Array>
|
||||||
|
</Set>
|
||||||
|
<Set name="cacheControl">max-age=3600,public</Set>
|
||||||
|
</New>
|
||||||
|
</Set>
|
||||||
|
|
||||||
|
</Configure>
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<h1>Jetty Javadoc - NOT BUILT!</h1>
|
||||||
|
|
||||||
|
Please run build the project-website module
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-project</artifactId>
|
||||||
|
<version>7.0.0.incubation0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>jetty-client</artifactId>
|
||||||
|
<name>Jetty :: Asynchronous HTTP Client</name>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<version>1.4.2</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>manifest</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-RequiredExecutionEnvironment>J2SE-1.4</Bundle-RequiredExecutionEnvironment>
|
||||||
|
<Export-Package>org.eclipse.jetty.client;version=${project.version}</Export-Package>
|
||||||
|
<Bundle-DocURL>http://jetty.eclipse.org</Bundle-DocURL>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<!--
|
||||||
|
Required for OSGI
|
||||||
|
-->
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-http</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-security</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlet</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!--
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlet</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
-->
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,86 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.net.InetSocketAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version $Revision: 4135 $ $Date: 2008-12-02 11:57:07 +0100 (Tue, 02 Dec 2008) $
|
||||||
|
*/
|
||||||
|
public class Address
|
||||||
|
{
|
||||||
|
private final String host;
|
||||||
|
private final int port;
|
||||||
|
|
||||||
|
public static Address from(String hostAndPort)
|
||||||
|
{
|
||||||
|
String host;
|
||||||
|
int port;
|
||||||
|
int colon = hostAndPort.indexOf(':');
|
||||||
|
if (colon >= 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)
|
||||||
|
{
|
||||||
|
this.host = host.trim();
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 caches response status and fields for later use.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CachedExchange extends HttpExchange
|
||||||
|
{
|
||||||
|
int _responseStatus;
|
||||||
|
HttpFields _responseFields;
|
||||||
|
|
||||||
|
public CachedExchange(boolean cacheFields)
|
||||||
|
{
|
||||||
|
if (cacheFields)
|
||||||
|
_responseFields = new HttpFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public int getResponseStatus()
|
||||||
|
{
|
||||||
|
if (_status < HttpExchange.STATUS_PARSING_HEADERS)
|
||||||
|
throw new IllegalStateException("Response not received");
|
||||||
|
return _responseStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public HttpFields getResponseFields()
|
||||||
|
{
|
||||||
|
if (_status < HttpExchange.STATUS_PARSING_CONTENT)
|
||||||
|
throw new IllegalStateException("Headers not complete");
|
||||||
|
return _responseFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
|
||||||
|
{
|
||||||
|
_responseStatus = status;
|
||||||
|
super.onResponseStatus(version,status,reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
|
||||||
|
{
|
||||||
|
if (_responseFields != null)
|
||||||
|
_responseFields.add(name,value);
|
||||||
|
super.onResponseHeader(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 CachedExchange that retains all content for later use.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ContentExchange extends CachedExchange
|
||||||
|
{
|
||||||
|
int _contentLength = 1024;
|
||||||
|
String _encoding = "utf-8";
|
||||||
|
ByteArrayOutputStream _responseContent;
|
||||||
|
|
||||||
|
File _fileForUpload;
|
||||||
|
|
||||||
|
public ContentExchange()
|
||||||
|
{
|
||||||
|
super(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public ContentExchange(boolean cacheFields)
|
||||||
|
{
|
||||||
|
super(cacheFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String getResponseContent() throws UnsupportedEncodingException
|
||||||
|
{
|
||||||
|
if (_responseContent != null)
|
||||||
|
{
|
||||||
|
return _responseContent.toString(_encoding);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
|
||||||
|
{
|
||||||
|
super.onResponseHeader(name,value);
|
||||||
|
int header = HttpHeaders.CACHE.getOrdinal(value);
|
||||||
|
switch (header)
|
||||||
|
{
|
||||||
|
case HttpHeaders.CONTENT_LENGTH_ORDINAL:
|
||||||
|
_contentLength = BufferUtil.toInt(value);
|
||||||
|
break;
|
||||||
|
case HttpHeaders.CONTENT_TYPE_ORDINAL:
|
||||||
|
|
||||||
|
String mime = StringUtil.asciiToLowerCase(value.toString());
|
||||||
|
int i = mime.indexOf("charset=");
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
mime = mime.substring(i + 8);
|
||||||
|
i = mime.indexOf(';');
|
||||||
|
if (i > 0)
|
||||||
|
mime = mime.substring(0,i);
|
||||||
|
}
|
||||||
|
if (mime != null && mime.length() > 0)
|
||||||
|
_encoding = mime;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseContent(Buffer content) throws IOException
|
||||||
|
{
|
||||||
|
super.onResponseContent( content );
|
||||||
|
if (_responseContent == null)
|
||||||
|
_responseContent = new ByteArrayOutputStream(_contentLength);
|
||||||
|
content.writeTo(_responseContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onRetry() throws IOException
|
||||||
|
{
|
||||||
|
if ( _fileForUpload != null )
|
||||||
|
{
|
||||||
|
_requestContent = null;
|
||||||
|
_requestContentSource = getInputStream();
|
||||||
|
}
|
||||||
|
else if ( _requestContentSource != null )
|
||||||
|
{
|
||||||
|
throw new IOException("Unsupported Retry attempt, no registered file for upload.");
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onRetry();
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream getInputStream() throws IOException
|
||||||
|
{
|
||||||
|
return new FileInputStream( _fileForUpload );
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getFileForUpload()
|
||||||
|
{
|
||||||
|
return _fileForUpload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileForUpload(File fileForUpload) throws IOException
|
||||||
|
{
|
||||||
|
this._fileForUpload = fileForUpload;
|
||||||
|
_requestContentSource = getInputStream();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,699 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.security.KeyStore;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
import javax.net.ssl.KeyManager;
|
||||||
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.security.Authorization;
|
||||||
|
import org.eclipse.jetty.client.security.RealmResolver;
|
||||||
|
import org.eclipse.jetty.http.HttpSchemes;
|
||||||
|
import org.eclipse.jetty.io.AbstractBuffers;
|
||||||
|
import org.eclipse.jetty.io.Buffer;
|
||||||
|
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||||
|
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
|
||||||
|
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
|
||||||
|
import org.eclipse.jetty.util.Attributes;
|
||||||
|
import org.eclipse.jetty.util.AttributesMap;
|
||||||
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||||
|
import org.eclipse.jetty.util.thread.ThreadPool;
|
||||||
|
import org.eclipse.jetty.util.thread.Timeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http Client.
|
||||||
|
* <p/>
|
||||||
|
* 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)}).
|
||||||
|
* <p/>
|
||||||
|
* 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 HttpConnection},
|
||||||
|
* queued in the {@link HttpConnection} waiting to be transmitted or pipelined on the actual
|
||||||
|
* TCP/IP connection waiting for a response.
|
||||||
|
* <p/>
|
||||||
|
* The {@link HttpDestination} class is an aggregation of {@link HttpConnection}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 {@link HttpExchange}
|
||||||
|
* @see {@link HttpDestination}
|
||||||
|
*/
|
||||||
|
public class HttpClient extends AbstractBuffers implements Attributes
|
||||||
|
{
|
||||||
|
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 int _maxConnectionsPerAddress = 32;
|
||||||
|
private Map<Address, HttpDestination> _destinations = new HashMap<Address, HttpDestination>();
|
||||||
|
ThreadPool _threadPool;
|
||||||
|
Connector _connector;
|
||||||
|
private long _idleTimeout = 20000;
|
||||||
|
private long _timeout = 320000;
|
||||||
|
int _soTimeout = 10000;
|
||||||
|
private Timeout _timeoutQ = new Timeout();
|
||||||
|
private Address _proxy;
|
||||||
|
private Authorization _proxyAuthentication;
|
||||||
|
private Set<String> _noProxy;
|
||||||
|
private int _maxRetries = 3;
|
||||||
|
private LinkedList<String> _registeredListeners;
|
||||||
|
|
||||||
|
// TODO clean up and add getters/setters to some of this maybe
|
||||||
|
private String _keyStoreLocation;
|
||||||
|
private String _keyStoreType = "JKS";
|
||||||
|
private String _keyStorePassword;
|
||||||
|
private String _keyManagerAlgorithm = "SunX509";
|
||||||
|
private String _keyManagerPassword;
|
||||||
|
private String _trustStoreLocation;
|
||||||
|
private String _trustStoreType = "JKS";
|
||||||
|
private String _trustStorePassword;
|
||||||
|
private String _trustManagerAlgorithm = "SunX509";
|
||||||
|
|
||||||
|
private SSLContext _sslContext;
|
||||||
|
|
||||||
|
private String _protocol = "TLS";
|
||||||
|
private String _provider;
|
||||||
|
private String _secureRandomAlgorithm;
|
||||||
|
|
||||||
|
private RealmResolver _realmResolver;
|
||||||
|
|
||||||
|
private AttributesMap _attributes=new AttributesMap();
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
public void dump() throws IOException
|
||||||
|
{
|
||||||
|
for (Map.Entry<Address, HttpDestination> entry : _destinations.entrySet())
|
||||||
|
{
|
||||||
|
System.err.println("\n" + entry.getKey() + ":");
|
||||||
|
entry.getValue().dump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param threadPool the threadPool to set
|
||||||
|
*/
|
||||||
|
public void setThreadPool(ThreadPool threadPool)
|
||||||
|
{
|
||||||
|
_threadPool = 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void clearAttributes()
|
||||||
|
{
|
||||||
|
_attributes.clearAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
public HttpDestination getDestination(Address remote, boolean ssl) throws UnknownHostException, IOException
|
||||||
|
{
|
||||||
|
if (remote == null)
|
||||||
|
throw new UnknownHostException("Remote socket address cannot be null.");
|
||||||
|
|
||||||
|
synchronized (_destinations)
|
||||||
|
{
|
||||||
|
HttpDestination destination = _destinations.get(remote);
|
||||||
|
if (destination == null)
|
||||||
|
{
|
||||||
|
destination = new HttpDestination(this, remote, ssl, _maxConnectionsPerAddress);
|
||||||
|
if (_proxy != null && (_noProxy == null || !_noProxy.contains(remote.getHost())))
|
||||||
|
{
|
||||||
|
destination.setProxy(_proxy);
|
||||||
|
if (_proxyAuthentication != null)
|
||||||
|
destination.setProxyAuthentication(_proxyAuthentication);
|
||||||
|
}
|
||||||
|
_destinations.put(remote, destination);
|
||||||
|
}
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void schedule(Timeout.Task task)
|
||||||
|
{
|
||||||
|
_timeoutQ.schedule(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void cancel(Timeout.Task task)
|
||||||
|
{
|
||||||
|
task.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Get whether the connector can use direct NIO buffers.
|
||||||
|
*/
|
||||||
|
public boolean getUseDirectBuffers()
|
||||||
|
{
|
||||||
|
return _useDirectBuffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setRealmResolver(RealmResolver resolver)
|
||||||
|
{
|
||||||
|
_realmResolver = resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* returns the SecurityRealmResolver registered with the HttpClient or null
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
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 preceeding
|
||||||
|
* listener in a delegation model.
|
||||||
|
* <p/>
|
||||||
|
* 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<String>();
|
||||||
|
}
|
||||||
|
_registeredListeners.add(listenerClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedList<String> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Get the type of connector (socket, blocking or select) in use.
|
||||||
|
*/
|
||||||
|
public int getConnectorType()
|
||||||
|
{
|
||||||
|
return _connectorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setConnectorType(int connectorType)
|
||||||
|
{
|
||||||
|
this._connectorType = connectorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Create a new NIO buffer. If using direct buffers, it will create a direct
|
||||||
|
* NIO buffer, other than an indirect buffer.
|
||||||
|
*/
|
||||||
|
public Buffer newBuffer(int size)
|
||||||
|
{
|
||||||
|
if (_connectorType != CONNECTOR_SOCKET)
|
||||||
|
{
|
||||||
|
Buffer buf = null;
|
||||||
|
if (size==getHeaderBufferSize())
|
||||||
|
buf=new IndirectNIOBuffer(size);
|
||||||
|
else if (_useDirectBuffers)
|
||||||
|
buf=new DirectNIOBuffer(size);
|
||||||
|
else
|
||||||
|
buf=new IndirectNIOBuffer(size);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new ByteArrayBuffer(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public int getMaxConnectionsPerAddress()
|
||||||
|
{
|
||||||
|
return _maxConnectionsPerAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setMaxConnectionsPerAddress(int maxConnectionsPerAddress)
|
||||||
|
{
|
||||||
|
_maxConnectionsPerAddress = maxConnectionsPerAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
protected void doStart() throws Exception
|
||||||
|
{
|
||||||
|
super.doStart();
|
||||||
|
|
||||||
|
_timeoutQ.setNow();
|
||||||
|
_timeoutQ.setDuration(_timeout);
|
||||||
|
|
||||||
|
if (_threadPool == null)
|
||||||
|
{
|
||||||
|
QueuedThreadPool pool = new QueuedThreadPool();
|
||||||
|
pool.setMaxThreads(16);
|
||||||
|
pool.setDaemon(true);
|
||||||
|
pool.setName("HttpClient");
|
||||||
|
_threadPool = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_threadPool instanceof LifeCycle)
|
||||||
|
{
|
||||||
|
((LifeCycle)_threadPool).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (_connectorType == CONNECTOR_SELECT_CHANNEL)
|
||||||
|
{
|
||||||
|
|
||||||
|
_connector = new SelectConnector(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_connector = new SocketConnector(this);
|
||||||
|
}
|
||||||
|
_connector.start();
|
||||||
|
|
||||||
|
_threadPool.dispatch(new Runnable()
|
||||||
|
{
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
while (isRunning())
|
||||||
|
{
|
||||||
|
_timeoutQ.setNow();
|
||||||
|
_timeoutQ.tick();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(1000);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
protected void doStop() throws Exception
|
||||||
|
{
|
||||||
|
_connector.stop();
|
||||||
|
_connector = null;
|
||||||
|
if (_threadPool instanceof LifeCycle)
|
||||||
|
{
|
||||||
|
((LifeCycle)_threadPool).stop();
|
||||||
|
}
|
||||||
|
for (HttpDestination destination : _destinations.values())
|
||||||
|
{
|
||||||
|
destination.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeoutQ.cancelAll();
|
||||||
|
super.doStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
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
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
protected SSLContext getSSLContext() throws IOException
|
||||||
|
{
|
||||||
|
if (_sslContext == null)
|
||||||
|
{
|
||||||
|
if (_keyStoreLocation == null)
|
||||||
|
{
|
||||||
|
_sslContext = getLooseSSLContext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_sslContext = getStrictSSLContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _sslContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SSLContext getStrictSSLContext() throws IOException
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_trustStoreLocation == null)
|
||||||
|
{
|
||||||
|
_trustStoreLocation = _keyStoreLocation;
|
||||||
|
_trustStoreType = _keyStoreType;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyManager[] keyManagers = null;
|
||||||
|
InputStream keystoreInputStream = null;
|
||||||
|
|
||||||
|
keystoreInputStream = Resource.newResource(_keyStoreLocation).getInputStream();
|
||||||
|
KeyStore keyStore = KeyStore.getInstance(_keyStoreType);
|
||||||
|
keyStore.load(keystoreInputStream, _keyStorePassword == null ? null : _keyStorePassword.toString().toCharArray());
|
||||||
|
|
||||||
|
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_keyManagerAlgorithm);
|
||||||
|
keyManagerFactory.init(keyStore, _keyManagerPassword == null ? null : _keyManagerPassword.toString().toCharArray());
|
||||||
|
keyManagers = keyManagerFactory.getKeyManagers();
|
||||||
|
|
||||||
|
TrustManager[] trustManagers = null;
|
||||||
|
InputStream truststoreInputStream = null;
|
||||||
|
|
||||||
|
truststoreInputStream = Resource.newResource(_trustStoreLocation).getInputStream();
|
||||||
|
KeyStore trustStore = KeyStore.getInstance(_trustStoreType);
|
||||||
|
trustStore.load(truststoreInputStream, _trustStorePassword == null ? null : _trustStorePassword.toString().toCharArray());
|
||||||
|
|
||||||
|
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerAlgorithm);
|
||||||
|
trustManagerFactory.init(trustStore);
|
||||||
|
trustManagers = trustManagerFactory.getTrustManagers();
|
||||||
|
|
||||||
|
SecureRandom secureRandom = _secureRandomAlgorithm == null ? null : SecureRandom.getInstance(_secureRandomAlgorithm);
|
||||||
|
SSLContext context = _provider == null ? SSLContext.getInstance(_protocol) : SSLContext.getInstance(_protocol, _provider);
|
||||||
|
context.init(keyManagers, trustManagers, secureRandom);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new IOException("error generating ssl context for " + _keyStoreLocation + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SSLContext getLooseSSLContext() throws IOException
|
||||||
|
{
|
||||||
|
|
||||||
|
// Create a trust manager that does not validate certificate
|
||||||
|
// chains
|
||||||
|
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager()
|
||||||
|
{
|
||||||
|
public java.security.cert.X509Certificate[] getAcceptedIssuers()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
HostnameVerifier hostnameVerifier = new HostnameVerifier()
|
||||||
|
{
|
||||||
|
public boolean verify(String urlHostName, SSLSession session)
|
||||||
|
{
|
||||||
|
Log.warn("Warning: URL Host: " + urlHostName + " vs." + session.getPeerHost());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Install the all-trusting trust manager
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO real trust manager
|
||||||
|
SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||||
|
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
|
||||||
|
return sslContext;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new IOException("issue ignoring certs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
|
||||||
|
*/
|
||||||
|
public long getIdleTimeout()
|
||||||
|
{
|
||||||
|
return _idleTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param ms the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
|
||||||
|
*/
|
||||||
|
public void setIdleTimeout(long ms)
|
||||||
|
{
|
||||||
|
_idleTimeout = ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public int getSoTimeout()
|
||||||
|
{
|
||||||
|
return _soTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setSoTimeout(int so)
|
||||||
|
{
|
||||||
|
_soTimeout = so;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return the period in ms that an exchange will wait for a response from the server.
|
||||||
|
*/
|
||||||
|
public long getTimeout()
|
||||||
|
{
|
||||||
|
return _timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param ms the period in ms that an exchange will wait for a response from the server.
|
||||||
|
*/
|
||||||
|
public void setTimeout(long ms)
|
||||||
|
{
|
||||||
|
_timeout = ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Address getProxy()
|
||||||
|
{
|
||||||
|
return _proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setProxy(Address proxy)
|
||||||
|
{
|
||||||
|
this._proxy = proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Authorization getProxyAuthentication()
|
||||||
|
{
|
||||||
|
return _proxyAuthentication;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setProxyAuthentication(Authorization authentication)
|
||||||
|
{
|
||||||
|
_proxyAuthentication = authentication;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public boolean isProxied()
|
||||||
|
{
|
||||||
|
return this._proxy != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Set<String> getNoProxy()
|
||||||
|
{
|
||||||
|
return _noProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setNoProxy(Set<String> noProxyAddresses)
|
||||||
|
{
|
||||||
|
_noProxy = noProxyAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public int maxRetries()
|
||||||
|
{
|
||||||
|
return _maxRetries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setMaxRetries(int retries)
|
||||||
|
{
|
||||||
|
_maxRetries = retries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTrustStoreLocation()
|
||||||
|
{
|
||||||
|
return _trustStoreLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTrustStoreLocation(String trustStoreLocation)
|
||||||
|
{
|
||||||
|
this._trustStoreLocation = trustStoreLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeyStoreLocation()
|
||||||
|
{
|
||||||
|
return _keyStoreLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyStoreLocation(String keyStoreLocation)
|
||||||
|
{
|
||||||
|
this._keyStoreLocation = keyStoreLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyStorePassword(String _keyStorePassword)
|
||||||
|
{
|
||||||
|
this._keyStorePassword = _keyStorePassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyManagerPassword(String _keyManagerPassword)
|
||||||
|
{
|
||||||
|
this._keyManagerPassword = _keyManagerPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTrustStorePassword(String _trustStorePassword)
|
||||||
|
{
|
||||||
|
this._trustStorePassword = _trustStorePassword;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,574 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.io.InterruptedIOException;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.security.Authorization;
|
||||||
|
import org.eclipse.jetty.http.HttpGenerator;
|
||||||
|
import org.eclipse.jetty.http.HttpHeaderValues;
|
||||||
|
import org.eclipse.jetty.http.HttpHeaders;
|
||||||
|
import org.eclipse.jetty.http.HttpParser;
|
||||||
|
import org.eclipse.jetty.http.HttpSchemes;
|
||||||
|
import org.eclipse.jetty.http.HttpVersions;
|
||||||
|
import org.eclipse.jetty.http.ssl.SslSelectChannelEndPoint;
|
||||||
|
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.nio.SelectChannelEndPoint;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.thread.Timeout;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class HttpConnection implements Connection
|
||||||
|
{
|
||||||
|
HttpDestination _destination;
|
||||||
|
EndPoint _endp;
|
||||||
|
HttpGenerator _generator;
|
||||||
|
HttpParser _parser;
|
||||||
|
boolean _http11 = true;
|
||||||
|
Buffer _connectionHeader;
|
||||||
|
Buffer _requestContentChunk;
|
||||||
|
long _last;
|
||||||
|
boolean _requestComplete;
|
||||||
|
public String _message;
|
||||||
|
public Throwable _throwable;
|
||||||
|
public boolean _reserved;
|
||||||
|
|
||||||
|
/* The current exchange waiting for a response */
|
||||||
|
volatile HttpExchange _exchange;
|
||||||
|
HttpExchange _pipeline;
|
||||||
|
|
||||||
|
public void dump() throws IOException
|
||||||
|
{
|
||||||
|
System.err.println("endp=" + _endp + " " + _endp.isBufferingInput() + " " + _endp.isBufferingOutput());
|
||||||
|
System.err.println("generator=" + _generator);
|
||||||
|
System.err.println("parser=" + _parser.getState() + " " + _parser.isMoreInBuffer());
|
||||||
|
System.err.println("exchange=" + _exchange);
|
||||||
|
if (_endp instanceof SslSelectChannelEndPoint)
|
||||||
|
((SslSelectChannelEndPoint)_endp).dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
Timeout.Task _timeout = new Timeout.Task()
|
||||||
|
{
|
||||||
|
public void expired()
|
||||||
|
{
|
||||||
|
HttpExchange ex = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
synchronized (HttpConnection.this)
|
||||||
|
{
|
||||||
|
ex = _exchange;
|
||||||
|
_exchange = null;
|
||||||
|
if (ex != null)
|
||||||
|
_destination.returnConnection(HttpConnection.this,true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.debug(e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_endp.close();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
Log.ignore(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ex!=null && ex.getStatus() < HttpExchange.STATUS_COMPLETED)
|
||||||
|
{
|
||||||
|
ex.setStatus(HttpExchange.STATUS_EXPIRED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
HttpConnection(Buffers buffers, EndPoint endp, int hbs, int cbs)
|
||||||
|
{
|
||||||
|
_endp = endp;
|
||||||
|
_generator = new HttpGenerator(buffers,endp,hbs,cbs);
|
||||||
|
_parser = new HttpParser(buffers,endp,new Handler(),hbs,cbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
// _message =
|
||||||
|
// Thread.currentThread().getName()+": Generator instance="+_generator
|
||||||
|
// .hashCode()+" state= "+_generator.getState()+" _exchange="+_exchange;
|
||||||
|
_throwable = new Throwable();
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
if (_exchange != null)
|
||||||
|
{
|
||||||
|
if (_pipeline != null)
|
||||||
|
throw new IllegalStateException(this + " PIPELINED!!! _exchange=" + _exchange);
|
||||||
|
_pipeline = ex;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_endp.isOpen())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ex.setStatus(HttpExchange.STATUS_WAITING_FOR_COMMIT);
|
||||||
|
_exchange = ex;
|
||||||
|
|
||||||
|
if (_endp.isBlocking())
|
||||||
|
this.notify();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectChannelEndPoint scep = (SelectChannelEndPoint)_endp;
|
||||||
|
scep.scheduleWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_endp.isBlocking())
|
||||||
|
_destination.getHttpClient().schedule(_timeout);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void handle() throws IOException
|
||||||
|
{
|
||||||
|
int no_progress = 0;
|
||||||
|
long flushed = 0;
|
||||||
|
|
||||||
|
boolean failed = false;
|
||||||
|
while (_endp.isBufferingInput() || _endp.isOpen())
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
while (_exchange == null)
|
||||||
|
{
|
||||||
|
if (_endp.isBlocking())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
throw new InterruptedIOException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Hopefully just space?
|
||||||
|
_parser.fill();
|
||||||
|
_parser.skipCRLF();
|
||||||
|
if (_parser.isMoreInBuffer())
|
||||||
|
{
|
||||||
|
Log.warn("unexpected data");
|
||||||
|
_endp.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT)
|
||||||
|
{
|
||||||
|
no_progress = 0;
|
||||||
|
commitRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
long io = 0;
|
||||||
|
_endp.flush();
|
||||||
|
|
||||||
|
if (_generator.isComplete())
|
||||||
|
{
|
||||||
|
if (!_requestComplete)
|
||||||
|
{
|
||||||
|
_requestComplete = true;
|
||||||
|
_exchange.getEventListener().onRequestComplete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Write as much of the request as possible
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
if (_exchange == null)
|
||||||
|
continue;
|
||||||
|
flushed = _generator.flushBuffer();
|
||||||
|
io += flushed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_generator.isComplete())
|
||||||
|
{
|
||||||
|
InputStream in = _exchange.getRequestContentSource();
|
||||||
|
if (in != null)
|
||||||
|
{
|
||||||
|
if (_requestContentChunk == null || _requestContentChunk.length() == 0)
|
||||||
|
{
|
||||||
|
_requestContentChunk = _exchange.getRequestContentChunk();
|
||||||
|
if (_requestContentChunk != null)
|
||||||
|
_generator.addContent(_requestContentChunk,false);
|
||||||
|
else
|
||||||
|
_generator.complete();
|
||||||
|
io += _generator.flushBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_generator.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If we are not ended then parse available
|
||||||
|
if (!_parser.isComplete() && _generator.isCommitted())
|
||||||
|
{
|
||||||
|
long filled = _parser.parseAvailable();
|
||||||
|
io += filled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (io > 0)
|
||||||
|
no_progress = 0;
|
||||||
|
else if (no_progress++ >= 2 && !_endp.isBlocking())
|
||||||
|
{
|
||||||
|
// SSL may need an extra flush as it may have made "no progress" while actually doing a handshake.
|
||||||
|
if (_endp instanceof SslSelectChannelEndPoint && !_generator.isComplete() && !_generator.isEmpty())
|
||||||
|
{
|
||||||
|
if (_generator.flushBuffer()>0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
if (_exchange != null)
|
||||||
|
{
|
||||||
|
_exchange.getEventListener().onException(e);
|
||||||
|
_exchange.setStatus(HttpExchange.STATUS_EXCEPTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
failed = true;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
boolean complete = false;
|
||||||
|
boolean close = failed; // always close the connection on error
|
||||||
|
if (!failed)
|
||||||
|
{
|
||||||
|
// are we complete?
|
||||||
|
if (_generator.isComplete())
|
||||||
|
{
|
||||||
|
if (!_requestComplete)
|
||||||
|
{
|
||||||
|
_requestComplete = true;
|
||||||
|
_exchange.getEventListener().onRequestComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to return the HttpConnection to a state that
|
||||||
|
// it can be reused or closed out
|
||||||
|
if (_parser.isComplete())
|
||||||
|
{
|
||||||
|
_destination.getHttpClient().cancel(_timeout);
|
||||||
|
complete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (complete || failed)
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
if (!close)
|
||||||
|
close = shouldClose();
|
||||||
|
|
||||||
|
reset(true);
|
||||||
|
no_progress = 0;
|
||||||
|
flushed = -1;
|
||||||
|
if (_exchange != null)
|
||||||
|
{
|
||||||
|
_exchange = null;
|
||||||
|
|
||||||
|
if (_pipeline == null)
|
||||||
|
{
|
||||||
|
if (!isReserved())
|
||||||
|
_destination.returnConnection(this,close);
|
||||||
|
if (close)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (close)
|
||||||
|
{
|
||||||
|
if (!isReserved())
|
||||||
|
_destination.returnConnection(this,close);
|
||||||
|
_destination.send(_pipeline);
|
||||||
|
_pipeline = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpExchange ex = _pipeline;
|
||||||
|
_pipeline = null;
|
||||||
|
|
||||||
|
send(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public boolean isIdle()
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
return _exchange == null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public EndPoint getEndPoint()
|
||||||
|
{
|
||||||
|
return _endp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
private void commitRequest() throws IOException
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
if (_exchange.getStatus() != HttpExchange.STATUS_WAITING_FOR_COMMIT)
|
||||||
|
throw new IllegalStateException();
|
||||||
|
|
||||||
|
_exchange.setStatus(HttpExchange.STATUS_SENDING_REQUEST);
|
||||||
|
_generator.setVersion(_exchange._version);
|
||||||
|
|
||||||
|
String uri = _exchange._uri;
|
||||||
|
if (_destination.isProxied() && uri.startsWith("/"))
|
||||||
|
{
|
||||||
|
// TODO suppress port 80 or 443
|
||||||
|
uri = (_destination.isSecure()?HttpSchemes.HTTPS:HttpSchemes.HTTP) + "://" + _destination.getAddress().getHost() + ":"
|
||||||
|
+ _destination.getAddress().getPort() + uri;
|
||||||
|
Authorization auth = _destination.getProxyAuthentication();
|
||||||
|
if (auth != null)
|
||||||
|
auth.setCredentials(_exchange);
|
||||||
|
}
|
||||||
|
|
||||||
|
_generator.setRequest(_exchange._method,uri);
|
||||||
|
|
||||||
|
if (_exchange._version >= HttpVersions.HTTP_1_1_ORDINAL)
|
||||||
|
{
|
||||||
|
if (!_exchange._requestFields.containsKey(HttpHeaders.HOST_BUFFER))
|
||||||
|
_exchange._requestFields.add(HttpHeaders.HOST_BUFFER,_destination.getHostHeader());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_exchange._requestContent != null)
|
||||||
|
{
|
||||||
|
_exchange._requestFields.putLongField(HttpHeaders.CONTENT_LENGTH,_exchange._requestContent.length());
|
||||||
|
_generator.completeHeader(_exchange._requestFields,false);
|
||||||
|
_generator.addContent(_exchange._requestContent,true);
|
||||||
|
}
|
||||||
|
else if (_exchange._requestContentSource != null)
|
||||||
|
{
|
||||||
|
_generator.completeHeader(_exchange._requestFields,false);
|
||||||
|
int available = _exchange._requestContentSource.available();
|
||||||
|
if (available > 0)
|
||||||
|
{
|
||||||
|
// TODO deal with any known content length
|
||||||
|
|
||||||
|
// TODO reuse this buffer!
|
||||||
|
byte[] buf = new byte[available];
|
||||||
|
int length = _exchange._requestContentSource.read(buf);
|
||||||
|
_generator.addContent(new ByteArrayBuffer(buf,0,length),false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_exchange._requestFields.remove(HttpHeaders.CONTENT_LENGTH); // TODO
|
||||||
|
// :
|
||||||
|
// should
|
||||||
|
// not
|
||||||
|
// be
|
||||||
|
// needed
|
||||||
|
_generator.completeHeader(_exchange._requestFields,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
protected void reset(boolean returnBuffers) throws IOException
|
||||||
|
{
|
||||||
|
_requestComplete = false;
|
||||||
|
_connectionHeader = null;
|
||||||
|
_parser.reset(returnBuffers);
|
||||||
|
_generator.reset(returnBuffers);
|
||||||
|
_http11 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
private boolean shouldClose()
|
||||||
|
{
|
||||||
|
if (_connectionHeader!=null)
|
||||||
|
{
|
||||||
|
if (HttpHeaderValues.CLOSE_BUFFER.equals(_connectionHeader))
|
||||||
|
return true;
|
||||||
|
if (HttpHeaderValues.KEEP_ALIVE_BUFFER.equals(_connectionHeader))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !_http11;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
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 <!DOCTYPE goop was coming
|
||||||
|
// out here
|
||||||
|
// throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startResponse(Buffer version, int status, Buffer reason) throws IOException
|
||||||
|
{
|
||||||
|
HttpExchange exchange = _exchange;
|
||||||
|
if (exchange!=null)
|
||||||
|
{
|
||||||
|
_http11 = HttpVersions.HTTP_1_1_BUFFER.equals(version);
|
||||||
|
exchange.getEventListener().onResponseStatus(version,status,reason);
|
||||||
|
exchange.setStatus(HttpExchange.STATUS_PARSING_HEADERS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parsedHeader(Buffer name, Buffer value) throws IOException
|
||||||
|
{
|
||||||
|
HttpExchange exchange = _exchange;
|
||||||
|
if (exchange!=null)
|
||||||
|
{
|
||||||
|
if (HttpHeaders.CACHE.getOrdinal(name) == HttpHeaders.CONNECTION_ORDINAL)
|
||||||
|
{
|
||||||
|
_connectionHeader = HttpHeaderValues.CACHE.lookup(value);
|
||||||
|
}
|
||||||
|
exchange.getEventListener().onResponseHeader(name,value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void headerComplete() throws IOException
|
||||||
|
{
|
||||||
|
HttpExchange exchange = _exchange;
|
||||||
|
if (exchange!=null)
|
||||||
|
exchange.setStatus(HttpExchange.STATUS_PARSING_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void content(Buffer ref) throws IOException
|
||||||
|
{
|
||||||
|
HttpExchange exchange = _exchange;
|
||||||
|
if (exchange!=null)
|
||||||
|
exchange.getEventListener().onResponseContent(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void messageComplete(long contextLength) throws IOException
|
||||||
|
{
|
||||||
|
HttpExchange exchange = _exchange;
|
||||||
|
if (exchange!=null)
|
||||||
|
exchange.setStatus(HttpExchange.STATUS_COMPLETED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "HttpConnection@" + hashCode() + "//" + _destination.getAddress().getHost() + ":" + _destination.getAddress().getPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String toDetailString()
|
||||||
|
{
|
||||||
|
return toString() + " ex=" + _exchange + " " + _timeout.getAge();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return the last
|
||||||
|
*/
|
||||||
|
public long getLast()
|
||||||
|
{
|
||||||
|
return _last;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param last
|
||||||
|
* the last to set
|
||||||
|
*/
|
||||||
|
public void setLast(long last)
|
||||||
|
{
|
||||||
|
_last = last;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void close() throws IOException
|
||||||
|
{
|
||||||
|
_endp.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,546 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.security.Authorization;
|
||||||
|
import org.eclipse.jetty.client.security.SecurityListener;
|
||||||
|
import org.eclipse.jetty.http.HttpCookie;
|
||||||
|
import org.eclipse.jetty.http.HttpHeaders;
|
||||||
|
import org.eclipse.jetty.http.PathMap;
|
||||||
|
import org.eclipse.jetty.io.Buffer;
|
||||||
|
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class HttpDestination
|
||||||
|
{
|
||||||
|
private ByteArrayBuffer _hostHeader;
|
||||||
|
private final Address _address;
|
||||||
|
private final LinkedList<HttpConnection> _connections = new LinkedList<HttpConnection>();
|
||||||
|
private final ArrayList<HttpConnection> _idle = new ArrayList<HttpConnection>();
|
||||||
|
private final HttpClient _client;
|
||||||
|
private final boolean _ssl;
|
||||||
|
private int _maxConnections;
|
||||||
|
private int _pendingConnections = 0;
|
||||||
|
private ArrayBlockingQueue<Object> _newQueue = new ArrayBlockingQueue<Object>(10, true);
|
||||||
|
private int _newConnection = 0;
|
||||||
|
private Address _proxy;
|
||||||
|
private Authorization _proxyAuthentication;
|
||||||
|
private PathMap _authorizations;
|
||||||
|
private List<HttpCookie> _cookies;
|
||||||
|
|
||||||
|
public void dump() throws IOException
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
System.err.println(this);
|
||||||
|
System.err.println("connections=" + _connections.size());
|
||||||
|
System.err.println("idle=" + _idle.size());
|
||||||
|
System.err.println("pending=" + _pendingConnections);
|
||||||
|
for (HttpConnection c : _connections)
|
||||||
|
{
|
||||||
|
if (!c.isIdle())
|
||||||
|
c.dump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The queue of exchanged for this destination if connections are limited */
|
||||||
|
private LinkedList<HttpExchange> _queue = new LinkedList<HttpExchange>();
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
HttpDestination(HttpClient pool, Address address, boolean ssl, int maxConnections)
|
||||||
|
{
|
||||||
|
_client = pool;
|
||||||
|
_address = address;
|
||||||
|
_ssl = ssl;
|
||||||
|
_maxConnections = maxConnections;
|
||||||
|
String addressString = address.getHost();
|
||||||
|
if (address.getPort() != (_ssl ? 443 : 80)) addressString += ":" + address.getPort();
|
||||||
|
_hostHeader = new ByteArrayBuffer(addressString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Address getAddress()
|
||||||
|
{
|
||||||
|
return _address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Buffer getHostHeader()
|
||||||
|
{
|
||||||
|
return _hostHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public HttpClient getHttpClient()
|
||||||
|
{
|
||||||
|
return _client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public boolean isSecure()
|
||||||
|
{
|
||||||
|
return _ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void addAuthorization(String pathSpec, Authorization 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<HttpCookie>();
|
||||||
|
_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
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private HttpConnection getConnection(long timeout) throws IOException
|
||||||
|
{
|
||||||
|
HttpConnection connection = null;
|
||||||
|
|
||||||
|
while ((connection == null) && (connection = getIdleConnection()) == null && timeout>0)
|
||||||
|
{
|
||||||
|
int totalConnections = 0;
|
||||||
|
boolean starting = false;
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
totalConnections = _connections.size() + _pendingConnections;
|
||||||
|
if (totalConnections < _maxConnections)
|
||||||
|
{
|
||||||
|
_newConnection++;
|
||||||
|
startNewConnection();
|
||||||
|
starting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!starting)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.currentThread().sleep(200);
|
||||||
|
timeout-=200;
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
Log.ignore(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Object o = _newQueue.take();
|
||||||
|
if (o instanceof HttpConnection)
|
||||||
|
{
|
||||||
|
connection = (HttpConnection)o;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw (IOException)o;
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
Log.ignore(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
public HttpConnection reserveConnection(long timeout) throws IOException
|
||||||
|
{
|
||||||
|
HttpConnection connection = getConnection(timeout);
|
||||||
|
if (connection != null)
|
||||||
|
connection.setReserved(true);
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
public HttpConnection getIdleConnection() throws IOException
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long idleTimeout = _client.getIdleTimeout();
|
||||||
|
|
||||||
|
// Find an idle connection
|
||||||
|
while (_idle.size() > 0)
|
||||||
|
{
|
||||||
|
HttpConnection connection = _idle.remove(_idle.size() - 1);
|
||||||
|
long last = connection.getLast();
|
||||||
|
if (connection.getEndPoint().isOpen() && (last == 0 || ((now - last) < idleTimeout)))
|
||||||
|
return connection;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_connections.remove(connection);
|
||||||
|
connection.getEndPoint().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
protected void startNewConnection()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
_pendingConnections++;
|
||||||
|
}
|
||||||
|
_client._connector.startConnection(this);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
onConnectionFailed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
public void onConnectionFailed(Throwable throwable)
|
||||||
|
{
|
||||||
|
Throwable connect_failure = null;
|
||||||
|
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
_pendingConnections--;
|
||||||
|
if (_newConnection > 0)
|
||||||
|
{
|
||||||
|
connect_failure = throwable;
|
||||||
|
_newConnection--;
|
||||||
|
}
|
||||||
|
else if (_queue.size() > 0)
|
||||||
|
{
|
||||||
|
HttpExchange ex = _queue.removeFirst();
|
||||||
|
ex.getEventListener().onConnectionFailed(throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.removeFirst();
|
||||||
|
ex.getEventListener().onException(throwable);
|
||||||
|
ex.setStatus(HttpExchange.STATUS_EXCEPTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
public void onNewConnection(HttpConnection connection) throws IOException
|
||||||
|
{
|
||||||
|
HttpConnection q_connection = null;
|
||||||
|
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
_pendingConnections--;
|
||||||
|
_connections.add(connection);
|
||||||
|
|
||||||
|
if (_newConnection > 0)
|
||||||
|
{
|
||||||
|
q_connection = connection;
|
||||||
|
_newConnection--;
|
||||||
|
}
|
||||||
|
else if (_queue.size() == 0)
|
||||||
|
{
|
||||||
|
_idle.add(connection);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HttpExchange ex = _queue.removeFirst();
|
||||||
|
connection.send(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (q_connection != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_newQueue.put(q_connection);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
Log.ignore(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- */
|
||||||
|
public void returnConnection(HttpConnection 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.setLast(System.currentTimeMillis());
|
||||||
|
_idle.add(connection);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HttpExchange ex = _queue.removeFirst();
|
||||||
|
connection.send(ex);
|
||||||
|
}
|
||||||
|
this.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
_connections.remove(connection);
|
||||||
|
if (!_queue.isEmpty())
|
||||||
|
startNewConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void send(HttpExchange ex) throws IOException
|
||||||
|
{
|
||||||
|
LinkedList<String> 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 (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new IOException("Unable to instantiate registered listener for destination: " + listenerClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
Authorization auth = (Authorization)_authorizations.match(ex.getURI());
|
||||||
|
if (auth != null)
|
||||||
|
((Authorization)auth).setCredentials(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
//System.out.println( "Sending: " + ex.toString() );
|
||||||
|
|
||||||
|
HttpConnection connection = null;
|
||||||
|
if (_queue.size() > 0 || (connection = getIdleConnection()) == null || !connection.send(ex))
|
||||||
|
{
|
||||||
|
_queue.add(ex);
|
||||||
|
if (_connections.size() + _pendingConnections < _maxConnections)
|
||||||
|
{
|
||||||
|
startNewConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public synchronized String toString()
|
||||||
|
{
|
||||||
|
return "HttpDestination@" + hashCode() + "//" + _address.getHost() + ":" + _address.getPort() + "(" + _connections.size() + "," + _idle.size() + "," + _queue.size() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public synchronized String toDetailString()
|
||||||
|
{
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append(toString());
|
||||||
|
b.append('\n');
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
for (HttpConnection connection : _connections)
|
||||||
|
{
|
||||||
|
if (connection._exchange != null)
|
||||||
|
{
|
||||||
|
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 Authorization getProxyAuthentication()
|
||||||
|
{
|
||||||
|
return _proxyAuthentication;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setProxyAuthentication(Authorization authentication)
|
||||||
|
{
|
||||||
|
_proxyAuthentication = authentication;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public boolean isProxied()
|
||||||
|
{
|
||||||
|
return _proxy != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void close() throws IOException
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
for (HttpConnection connection : _connections)
|
||||||
|
{
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
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 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)
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRetry()
|
||||||
|
{
|
||||||
|
if (_delegatingRequests)
|
||||||
|
_listener.onRetry();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,645 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.InetSocketAddress;
|
||||||
|
|
||||||
|
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.ByteArrayBuffer;
|
||||||
|
import org.eclipse.jetty.io.BufferCache.CachedBuffer;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An HTTP client API that encapsulates Exchange with a HTTP server.
|
||||||
|
*
|
||||||
|
* This object encapsulates:<ul>
|
||||||
|
* <li>The HTTP server. (see {@link #setAddress(InetSocketAddress)} or {@link #setURL(String)})
|
||||||
|
* <li>The HTTP request method, URI and HTTP version (see {@link #setMethod(String)}, {@link #setURI(String)}, and {@link #setVersion(int)}
|
||||||
|
* <li>The Request headers (see {@link #addRequestHeader(String, String)} or {@link #setRequestHeader(String, String)})
|
||||||
|
* <li>The Request content (see {@link #setRequestContent(Buffer)} or {@link #setRequestContentSource(InputStream)})
|
||||||
|
* <li>The status of the exchange (see {@link #getStatus()})
|
||||||
|
* <li>Callbacks to handle state changes (see the onXxx methods such as {@link #onRequestComplete()} or {@link #onResponseComplete()})
|
||||||
|
* <li>The ability to intercept callbacks (see {@link #setEventListener(HttpEventListener)}
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* 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 implements some or all of the onXxx callbacks. There are also some predefined HttpExchange subtypes
|
||||||
|
* that can be used as a basis (see {@link ContentExchange} and {@link CachedExchange}.
|
||||||
|
*
|
||||||
|
* <p>Typically the HttpExchange is passed to a the {@link HttpClient#send(HttpExchange)} method, which in
|
||||||
|
* turn selects a {@link HttpDestination} and calls it's {@link HttpDestination#send(HttpExchange), which
|
||||||
|
* then creates or selects a {@link HttpConnection} and calls its {@link HttpConnection#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).
|
||||||
|
*
|
||||||
|
* <p>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
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
Address _address;
|
||||||
|
String _method = HttpMethods.GET;
|
||||||
|
Buffer _scheme = HttpSchemes.HTTP_BUFFER;
|
||||||
|
int _version = HttpVersions.HTTP_1_1_ORDINAL;
|
||||||
|
String _uri;
|
||||||
|
int _status = STATUS_START;
|
||||||
|
HttpFields _requestFields = new HttpFields();
|
||||||
|
Buffer _requestContent;
|
||||||
|
InputStream _requestContentSource;
|
||||||
|
Buffer _requestContentChunk;
|
||||||
|
boolean _retryStatus = false;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* boolean controlling if the exchange will have listeners autoconfigured by
|
||||||
|
* the destination
|
||||||
|
*/
|
||||||
|
boolean _configureListeners = true;
|
||||||
|
|
||||||
|
|
||||||
|
private HttpEventListener _listener = new Listener();
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
// methods to build request
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public int getStatus()
|
||||||
|
{
|
||||||
|
return _status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public void waitForStatus(int status) throws InterruptedException
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
while (_status < status)
|
||||||
|
{
|
||||||
|
this.wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int waitForDone () throws InterruptedException
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
while (!isDone(_status))
|
||||||
|
this.wait();
|
||||||
|
}
|
||||||
|
return _status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void reset()
|
||||||
|
{
|
||||||
|
setStatus(STATUS_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
void setStatus(int status)
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
_status = status;
|
||||||
|
this.notifyAll();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case STATUS_WAITING_FOR_CONNECTION:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATUS_WAITING_FOR_COMMIT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATUS_SENDING_REQUEST:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HttpExchange.STATUS_WAITING_FOR_RESPONSE:
|
||||||
|
getEventListener().onRequestCommitted();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATUS_PARSING_HEADERS:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATUS_PARSING_CONTENT:
|
||||||
|
getEventListener().onResponseHeaderComplete();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATUS_COMPLETED:
|
||||||
|
getEventListener().onResponseComplete();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATUS_EXPIRED:
|
||||||
|
getEventListener().onExpire();
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
Log.warn(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public boolean isDone (int status)
|
||||||
|
{
|
||||||
|
return ((status == STATUS_COMPLETED) || (status == STATUS_EXPIRED) || (status == STATUS_EXCEPTED));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public HttpEventListener getEventListener()
|
||||||
|
{
|
||||||
|
return _listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setEventListener(HttpEventListener listener)
|
||||||
|
{
|
||||||
|
_listener=listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param url Including protocol, host and port
|
||||||
|
*/
|
||||||
|
public void setURL(String url)
|
||||||
|
{
|
||||||
|
HttpURI uri = new HttpURI(url);
|
||||||
|
String scheme = uri.getScheme();
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
int port = uri.getPort();
|
||||||
|
if (port <= 0)
|
||||||
|
port = "https".equalsIgnoreCase(scheme)?443:80;
|
||||||
|
|
||||||
|
setAddress(new Address(uri.getHost(),port));
|
||||||
|
|
||||||
|
String completePath = uri.getCompletePath();
|
||||||
|
if (completePath == null)
|
||||||
|
completePath = "/";
|
||||||
|
|
||||||
|
setURI(completePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param address
|
||||||
|
*/
|
||||||
|
public void setAddress(Address address)
|
||||||
|
{
|
||||||
|
_address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Address getAddress()
|
||||||
|
{
|
||||||
|
return _address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param scheme
|
||||||
|
*/
|
||||||
|
public void setScheme(Buffer scheme)
|
||||||
|
{
|
||||||
|
_scheme = scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Buffer getScheme()
|
||||||
|
{
|
||||||
|
return _scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param version as integer, 9, 10 or 11 for 0.9, 1.0 or 1.1
|
||||||
|
*/
|
||||||
|
public void setVersion(int version)
|
||||||
|
{
|
||||||
|
_version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setVersion(String version)
|
||||||
|
{
|
||||||
|
CachedBuffer v = HttpVersions.CACHE.get(version);
|
||||||
|
if (v == null)
|
||||||
|
_version = 10;
|
||||||
|
else
|
||||||
|
_version = v.getOrdinal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getVersion()
|
||||||
|
{
|
||||||
|
return _version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param method
|
||||||
|
*/
|
||||||
|
public void setMethod(String method)
|
||||||
|
{
|
||||||
|
_method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getMethod()
|
||||||
|
{
|
||||||
|
return _method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getURI()
|
||||||
|
{
|
||||||
|
return _uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param uri
|
||||||
|
*/
|
||||||
|
public void setURI(String uri)
|
||||||
|
{
|
||||||
|
_uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public void addRequestHeader(String name, String value)
|
||||||
|
{
|
||||||
|
getRequestFields().add(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public void addRequestHeader(Buffer name, Buffer value)
|
||||||
|
{
|
||||||
|
getRequestFields().add(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public void setRequestHeader(String name, String value)
|
||||||
|
{
|
||||||
|
getRequestFields().put(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public void setRequestHeader(Buffer name, Buffer value)
|
||||||
|
{
|
||||||
|
getRequestFields().put(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public void setRequestContentType(String value)
|
||||||
|
{
|
||||||
|
getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public HttpFields getRequestFields()
|
||||||
|
{
|
||||||
|
return _requestFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
// methods to commit and/or send the request
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param requestContent
|
||||||
|
*/
|
||||||
|
public void setRequestContent(Buffer requestContent)
|
||||||
|
{
|
||||||
|
_requestContent = requestContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param in
|
||||||
|
*/
|
||||||
|
public void setRequestContentSource(InputStream in)
|
||||||
|
{
|
||||||
|
_requestContentSource = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public InputStream getRequestContentSource()
|
||||||
|
{
|
||||||
|
return _requestContentSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Buffer getRequestContentChunk() throws IOException
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
if (_requestContentChunk == null)
|
||||||
|
_requestContentChunk = new ByteArrayBuffer(4096); // TODO configure
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_requestContentChunk.hasContent())
|
||||||
|
throw new IllegalStateException();
|
||||||
|
_requestContentChunk.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int read = _requestContentChunk.capacity();
|
||||||
|
int length = _requestContentSource.read(_requestContentChunk.array(),0,read);
|
||||||
|
if (length >= 0)
|
||||||
|
{
|
||||||
|
_requestContentChunk.setPutIndex(length);
|
||||||
|
return _requestContentChunk;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Buffer getRequestContent()
|
||||||
|
{
|
||||||
|
return _requestContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getRetryStatus()
|
||||||
|
{
|
||||||
|
return _retryStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRetryStatus( boolean retryStatus )
|
||||||
|
{
|
||||||
|
_retryStatus = retryStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/** Cancel this exchange
|
||||||
|
* Currently this implementation does nothing.
|
||||||
|
*/
|
||||||
|
public void cancel()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "HttpExchange@" + hashCode() + "=" + _method + "//" + _address.getHost() + ":" + _address.getPort() + _uri + "#" + _status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
// methods to handle response
|
||||||
|
protected void onRequestCommitted() throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onRequestComplete() throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseHeaderComplete() throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseContent(Buffer content) throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseComplete() throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onConnectionFailed(Throwable ex)
|
||||||
|
{
|
||||||
|
Log.warn("CONNECTION FAILED on " + this,ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onException(Throwable ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
Log.warn("EXCEPTION on " + this,ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onExpire()
|
||||||
|
{
|
||||||
|
Log.debug("EXPIRED " + this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onRetry() throws IOException
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* true of the exchange should have listeners configured for it by the destination
|
||||||
|
*
|
||||||
|
* false if this is being managed elsewhere
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean configureListeners()
|
||||||
|
{
|
||||||
|
return _configureListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigureListeners(boolean autoConfigure )
|
||||||
|
{
|
||||||
|
this._configureListeners = autoConfigure;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Listener implements HttpEventListener
|
||||||
|
{
|
||||||
|
public void onConnectionFailed(Throwable ex)
|
||||||
|
{
|
||||||
|
HttpExchange.this.onConnectionFailed(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onException(Throwable ex)
|
||||||
|
{
|
||||||
|
HttpExchange.this.onException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onExpire()
|
||||||
|
{
|
||||||
|
HttpExchange.this.onExpire();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRequestCommitted() throws IOException
|
||||||
|
{
|
||||||
|
HttpExchange.this.onRequestCommitted();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRequestComplete() throws IOException
|
||||||
|
{
|
||||||
|
HttpExchange.this.onRequestComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResponseComplete() throws IOException
|
||||||
|
{
|
||||||
|
HttpExchange.this.onResponseComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link org.eclipse.jetty.client.CachedExchange}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static class CachedExchange extends org.eclipse.jetty.client.CachedExchange
|
||||||
|
{
|
||||||
|
public CachedExchange(boolean cacheFields)
|
||||||
|
{
|
||||||
|
super(cacheFields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link org.eclipse.jetty.client.ContentExchange}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static class ContentExchange extends org.eclipse.jetty.client.ContentExchange
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.nio.channels.SelectionKey;
|
||||||
|
import java.nio.channels.SocketChannel;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLEngine;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.HttpMethods;
|
||||||
|
import org.eclipse.jetty.http.HttpVersions;
|
||||||
|
import org.eclipse.jetty.http.ssl.SslSelectChannelEndPoint;
|
||||||
|
import org.eclipse.jetty.io.AbstractBuffers;
|
||||||
|
import org.eclipse.jetty.io.Buffer;
|
||||||
|
import org.eclipse.jetty.io.Buffers;
|
||||||
|
import org.eclipse.jetty.io.Connection;
|
||||||
|
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
|
||||||
|
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
|
||||||
|
import org.eclipse.jetty.io.nio.SelectorManager;
|
||||||
|
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
|
||||||
|
class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector, Runnable
|
||||||
|
{
|
||||||
|
private final HttpClient _httpClient;
|
||||||
|
private SSLContext _sslContext;
|
||||||
|
private Buffers _sslBuffers;
|
||||||
|
|
||||||
|
SelectorManager _selectorManager=new Manager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param httpClient
|
||||||
|
*/
|
||||||
|
SelectConnector(HttpClient httpClient)
|
||||||
|
{
|
||||||
|
_httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doStart() throws Exception
|
||||||
|
{
|
||||||
|
_selectorManager.start();
|
||||||
|
_httpClient._threadPool.dispatch(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doStop() throws Exception
|
||||||
|
{
|
||||||
|
_selectorManager.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startConnection( HttpDestination destination )
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
SocketChannel channel = SocketChannel.open();
|
||||||
|
Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
|
||||||
|
channel.connect(address.toSocketAddress());
|
||||||
|
channel.configureBlocking( false );
|
||||||
|
channel.socket().setSoTimeout( _httpClient._soTimeout );
|
||||||
|
_selectorManager.register( channel, destination );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
while (_httpClient.isRunning())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_selectorManager.doSelect(0);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Manager extends SelectorManager
|
||||||
|
{
|
||||||
|
protected SocketChannel acceptChannel(SelectionKey key) throws IOException
|
||||||
|
{
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean dispatch(Runnable task)
|
||||||
|
{
|
||||||
|
return SelectConnector.this._httpClient._threadPool.dispatch(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void endPointOpened(SelectChannelEndPoint endpoint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void endPointClosed(SelectChannelEndPoint endpoint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Connection newConnection(SocketChannel channel, SelectChannelEndPoint endpoint)
|
||||||
|
{
|
||||||
|
return new HttpConnection(_httpClient,endpoint,SelectConnector.this._httpClient.getHeaderBufferSize(),SelectConnector.this._httpClient.getRequestBufferSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
|
||||||
|
{
|
||||||
|
// key should have destination at this point (will be replaced by endpoint after this call)
|
||||||
|
HttpDestination dest=(HttpDestination)key.attachment();
|
||||||
|
|
||||||
|
|
||||||
|
SelectChannelEndPoint ep=null;
|
||||||
|
|
||||||
|
if (dest.isSecure())
|
||||||
|
{
|
||||||
|
if (dest.isProxied())
|
||||||
|
{
|
||||||
|
String connect = HttpMethods.CONNECT+" "+dest.getAddress()+HttpVersions.HTTP_1_0+"\r\n\r\n";
|
||||||
|
// TODO need to send this over channel unencrypted and setup endpoint to ignore the 200 OK response.
|
||||||
|
|
||||||
|
throw new IllegalStateException("Not Implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLEngine engine=newSslEngine();
|
||||||
|
ep = new SslSelectChannelEndPoint(_sslBuffers,channel,selectSet,key,engine);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ep=new SelectChannelEndPoint(channel,selectSet,key);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpConnection connection=(HttpConnection)ep.getConnection();
|
||||||
|
connection.setDestination(dest);
|
||||||
|
dest.onNewConnection(connection);
|
||||||
|
return ep;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized SSLEngine newSslEngine() throws IOException
|
||||||
|
{
|
||||||
|
if (_sslContext==null)
|
||||||
|
{
|
||||||
|
_sslContext = SelectConnector.this._httpClient.getSSLContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLEngine sslEngine = _sslContext.createSSLEngine();
|
||||||
|
sslEngine.setUseClientMode(true);
|
||||||
|
sslEngine.beginHandshake();
|
||||||
|
|
||||||
|
if (_sslBuffers==null)
|
||||||
|
{
|
||||||
|
AbstractBuffers buffers = new AbstractBuffers()
|
||||||
|
{
|
||||||
|
public Buffer newBuffer( int size )
|
||||||
|
{
|
||||||
|
return new IndirectNIOBuffer( size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
buffers.setRequestBufferSize( sslEngine.getSession().getPacketBufferSize());
|
||||||
|
buffers.setResponseBufferSize(sslEngine.getSession().getApplicationBufferSize());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
buffers.start();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
_sslBuffers=buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sslEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.io.nio.SelectorManager#connectionFailed(java.nio.channels.SocketChannel, java.lang.Throwable, java.lang.Object)
|
||||||
|
*/
|
||||||
|
protected void connectionFailed(SocketChannel channel, Throwable ex, Object attachment)
|
||||||
|
{
|
||||||
|
if (attachment instanceof HttpDestination)
|
||||||
|
((HttpDestination)attachment).onConnectionFailed(ex);
|
||||||
|
else
|
||||||
|
Log.warn(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private final HttpClient _httpClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param httpClient
|
||||||
|
*/
|
||||||
|
SocketConnector(HttpClient httpClient)
|
||||||
|
{
|
||||||
|
_httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startConnection(final HttpDestination destination) throws IOException
|
||||||
|
{
|
||||||
|
Socket socket=null;
|
||||||
|
|
||||||
|
if ( destination.isSecure() )
|
||||||
|
{
|
||||||
|
SSLContext sslContext = _httpClient.getSSLContext();
|
||||||
|
socket = sslContext.getSocketFactory().createSocket();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.debug("Using Regular Socket");
|
||||||
|
socket = SocketFactory.getDefault().createSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
|
||||||
|
socket.connect(address.toSocketAddress());
|
||||||
|
|
||||||
|
EndPoint endpoint=new SocketEndPoint(socket);
|
||||||
|
|
||||||
|
final HttpConnection connection=new HttpConnection(_httpClient,endpoint,_httpClient.getHeaderBufferSize(),_httpClient.getRequestBufferSize());
|
||||||
|
connection.setDestination(destination);
|
||||||
|
destination.onNewConnection(connection);
|
||||||
|
_httpClient.getThreadPool().dispatch(new Runnable()
|
||||||
|
{
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection.handle();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
if (e instanceof InterruptedIOException)
|
||||||
|
Log.ignore(e);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.warn(e);
|
||||||
|
destination.onException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 Authorization
|
||||||
|
{
|
||||||
|
public void setCredentials( HttpExchange exchange) throws IOException;
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.http.security.B64Code;
|
||||||
|
import org.eclipse.jetty.io.Buffer;
|
||||||
|
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||||
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets authentication headers for BASIC authentication challenges
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class BasicAuthorization implements Authorization
|
||||||
|
{
|
||||||
|
private Buffer _authorization;
|
||||||
|
|
||||||
|
public BasicAuthorization(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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 DigestAuthorization implements Authorization
|
||||||
|
{
|
||||||
|
private static final String NC = "00000001";
|
||||||
|
Realm securityRealm;
|
||||||
|
Map details;
|
||||||
|
|
||||||
|
public DigestAuthorization(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)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String encode(byte[] data)
|
||||||
|
{
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
for (int i=0; i<data.length; i++)
|
||||||
|
{
|
||||||
|
buffer.append(Integer.toHexString((data[i] & 0xf0) >>> 4));
|
||||||
|
buffer.append(Integer.toHexString(data[i] & 0x0f));
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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<String, Realm>_realmMap;
|
||||||
|
|
||||||
|
public void addSecurityRealm( Realm realm )
|
||||||
|
{
|
||||||
|
if (_realmMap == null)
|
||||||
|
{
|
||||||
|
_realmMap = new HashMap<String, Realm>();
|
||||||
|
}
|
||||||
|
_realmMap.put( realm.getId(), realm );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Realm getRealm( String realmName, HttpDestination destination, String path ) throws IOException
|
||||||
|
{
|
||||||
|
return _realmMap.get( realmName );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.http.security.B64Code;
|
||||||
|
import org.eclipse.jetty.io.Buffer;
|
||||||
|
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||||
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets proxy authentication headers for BASIC authentication challenges
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ProxyAuthorization implements Authorization
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
}
|
|
@ -0,0 +1,260 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SecurityListener
|
||||||
|
*
|
||||||
|
* Allow for insertion of security dialog when performing an
|
||||||
|
* HttpExchange.
|
||||||
|
*/
|
||||||
|
public class SecurityListener extends HttpEventListenerWrapper
|
||||||
|
{
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
protected Map<String, String> scrapeAuthenticationDetails( String authString )
|
||||||
|
{
|
||||||
|
Map<String, String> authenticationDetails = new HashMap<String, String>();
|
||||||
|
authString = authString.substring( authString.indexOf( " " ) + 1, authString.length() );
|
||||||
|
StringTokenizer strtok = new StringTokenizer( authString, ",");
|
||||||
|
|
||||||
|
while ( strtok.hasMoreTokens() )
|
||||||
|
{
|
||||||
|
String[] pair = strtok.nextToken().split( "=" );
|
||||||
|
if ( pair.length == 2 )
|
||||||
|
{
|
||||||
|
String itemName = pair[0].trim();
|
||||||
|
String itemValue = pair[1].trim();
|
||||||
|
|
||||||
|
itemValue = StringUtil.unquote( itemValue );
|
||||||
|
|
||||||
|
authenticationDetails.put( itemName, itemValue );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException( "unable to process authentication details" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return authenticationDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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<String,String> 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 DigestAuthorization(realm,details));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if ("basic".equalsIgnoreCase(type))
|
||||||
|
{
|
||||||
|
_destination.addAuthorization(pathSpec,new BasicAuthorization(realm));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onResponseHeader(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRetry()
|
||||||
|
{
|
||||||
|
_attempts++;
|
||||||
|
setDelegatingRequests(true);
|
||||||
|
setDelegatingResponses(true);
|
||||||
|
_requestComplete=false;
|
||||||
|
_responseComplete=false;
|
||||||
|
_needIntercept=false;
|
||||||
|
super.onRetry();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.
|
||||||
|
* <p> 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
|
||||||
|
public class MkcolExchange extends CachedExchange
|
||||||
|
{
|
||||||
|
boolean exists = false;
|
||||||
|
|
||||||
|
public MkcolExchange()
|
||||||
|
{
|
||||||
|
super(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
|
||||||
|
public class PropfindExchange extends HttpExchange
|
||||||
|
{
|
||||||
|
boolean _propertyExists = false;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,312 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WebdavListener
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class WebdavListener extends HttpEventListenerWrapper
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @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 ( !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
|
||||||
|
{
|
||||||
|
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.setURI( 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.setURI( 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.setURI( _exchange.getURI() );
|
||||||
|
|
||||||
|
_destination.send( supportedExchange );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
supportedExchange.waitTilCompletion();
|
||||||
|
return supportedExchange.isWebdavSupported();
|
||||||
|
}
|
||||||
|
catch (InterruptedException ie )
|
||||||
|
{
|
||||||
|
Log.ignore( ie );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
|
||||||
|
public class WebdavSupportedExchange extends HttpExchange
|
||||||
|
{
|
||||||
|
private boolean _webdavSupported = false;
|
||||||
|
private boolean _isComplete = false;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseComplete() throws IOException
|
||||||
|
{
|
||||||
|
_isComplete = true;
|
||||||
|
|
||||||
|
super.onResponseComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWebdavSupported()
|
||||||
|
{
|
||||||
|
return _webdavSupported;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest
|
||||||
|
{
|
||||||
|
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
_scheme="https://";
|
||||||
|
startServer();
|
||||||
|
_httpClient=new HttpClient();
|
||||||
|
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
|
||||||
|
_httpClient.setMaxConnectionsPerAddress(2);
|
||||||
|
_httpClient.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPerf() throws Exception
|
||||||
|
{
|
||||||
|
super.testPerf();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
public class AsyncSslSecurityListenerTest extends SslSecurityListenerTest
|
||||||
|
{
|
||||||
|
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
_type = HttpClient.CONNECTOR_SELECT_CHANNEL;
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
package 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 java.io.IOException;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Test expiring connections
|
||||||
|
*
|
||||||
|
* Test contributed by: Michiel Thuys for JETTY-806
|
||||||
|
*/
|
||||||
|
public class ExpireTest extends TestCase
|
||||||
|
{
|
||||||
|
HttpClient client;
|
||||||
|
|
||||||
|
Server server;
|
||||||
|
|
||||||
|
AtomicInteger expireCount = new AtomicInteger();
|
||||||
|
|
||||||
|
final String host = "localhost";
|
||||||
|
|
||||||
|
int _port;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
client = new HttpClient();
|
||||||
|
client.setConnectorType( HttpClient.CONNECTOR_SELECT_CHANNEL );
|
||||||
|
client.setTimeout( 200 );
|
||||||
|
client.setMaxRetries( 0 );
|
||||||
|
client.setMaxConnectionsPerAddress(100);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.start();
|
||||||
|
}
|
||||||
|
catch ( Exception e )
|
||||||
|
{
|
||||||
|
throw new Error( "Cannot start HTTP client: " + e );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create server
|
||||||
|
server = new Server();
|
||||||
|
SelectChannelConnector connector = new SelectChannelConnector();
|
||||||
|
connector.setHost( host );
|
||||||
|
connector.setPort( 0 );
|
||||||
|
server.setConnectors( new Connector[] { connector } );
|
||||||
|
server.setHandler( new AbstractHandler()
|
||||||
|
{
|
||||||
|
public void handle( String target, HttpServletRequest servletRequest, HttpServletResponse response ) throws IOException,
|
||||||
|
ServletException
|
||||||
|
{
|
||||||
|
Request request = (Request) servletRequest;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep( 2000 );
|
||||||
|
}
|
||||||
|
catch ( InterruptedException e )
|
||||||
|
{
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
request.setHandled( true );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
try
|
||||||
|
{
|
||||||
|
server.start();
|
||||||
|
_port = connector.getLocalPort();
|
||||||
|
}
|
||||||
|
catch ( Exception e )
|
||||||
|
{
|
||||||
|
Log.warn( "Cannot create server: " + e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
client.stop();
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExpire() throws IOException
|
||||||
|
{
|
||||||
|
String baseUrl = "http://" + host + ":" + _port + "/";
|
||||||
|
|
||||||
|
int count = 200;
|
||||||
|
expireCount.set( 0 );
|
||||||
|
Log.info( "Starting test on " + baseUrl );
|
||||||
|
|
||||||
|
for (int i=0;i<count;i++)
|
||||||
|
{
|
||||||
|
if (i%10==0)
|
||||||
|
System.err.print('.');
|
||||||
|
expireCount.incrementAndGet();
|
||||||
|
final ContentExchange ex = new ContentExchange()
|
||||||
|
{
|
||||||
|
protected void onExpire()
|
||||||
|
{
|
||||||
|
expireCount.decrementAndGet();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ex.setMethod( "GET" );
|
||||||
|
ex.setURL( baseUrl );
|
||||||
|
|
||||||
|
client.send( ex );
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep( 50 );
|
||||||
|
}
|
||||||
|
catch ( InterruptedException e )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Log.info("Test done");
|
||||||
|
// Wait to be sure that all exchanges have expired
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep( 2000 );
|
||||||
|
int loops = 0;
|
||||||
|
while ( expireCount.get()>0 && loops < 10 ) // max out at 30 seconds
|
||||||
|
{
|
||||||
|
Log.info( "waiting for test to complete: "+expireCount.get()+" of "+count );
|
||||||
|
++loops;
|
||||||
|
Thread.sleep( 2000 );
|
||||||
|
}
|
||||||
|
Thread.sleep( 2000 );
|
||||||
|
}
|
||||||
|
catch ( InterruptedException e )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
System.err.println('!');
|
||||||
|
|
||||||
|
assertEquals( 0, expireCount.get() );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 java.io.File;
|
||||||
|
|
||||||
|
public class ExternalKeyStoreAsyncSslHttpExchangeTest extends SslHttpExchangeTest
|
||||||
|
{
|
||||||
|
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
_scheme="https://";
|
||||||
|
startServer();
|
||||||
|
_httpClient=new HttpClient();
|
||||||
|
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
|
||||||
|
_httpClient.setMaxConnectionsPerAddress(2);
|
||||||
|
|
||||||
|
String keystore = System.getProperty("user.dir") + File.separator + "src" + File.separator + "test" + File.separator + "resources" + File.separator
|
||||||
|
+ "keystore";
|
||||||
|
|
||||||
|
_httpClient.setKeyStoreLocation( keystore );
|
||||||
|
_httpClient.setKeyStorePassword( "storepwd");
|
||||||
|
_httpClient.setKeyManagerPassword( "keypwd" );
|
||||||
|
_httpClient.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,391 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.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 junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.security.ProxyAuthorization;
|
||||||
|
import org.eclipse.jetty.http.HttpHeaders;
|
||||||
|
import org.eclipse.jetty.http.HttpMethods;
|
||||||
|
import org.eclipse.jetty.io.Buffer;
|
||||||
|
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||||
|
import org.eclipse.jetty.io.EofException;
|
||||||
|
import org.eclipse.jetty.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.HttpConnection;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functional testing for HttpExchange.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class HttpExchangeTest extends TestCase
|
||||||
|
{
|
||||||
|
private boolean _stress=Boolean.getBoolean("STRESS");
|
||||||
|
protected int _maxConnectionsPerAddress = 2;
|
||||||
|
protected String _scheme = "http://";
|
||||||
|
protected Server _server;
|
||||||
|
protected int _port;
|
||||||
|
protected HttpClient _httpClient;
|
||||||
|
protected Connector _connector;
|
||||||
|
protected AtomicInteger _count = new AtomicInteger();
|
||||||
|
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
startServer();
|
||||||
|
_httpClient=new HttpClient();
|
||||||
|
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
|
||||||
|
_httpClient.setMaxConnectionsPerAddress(_maxConnectionsPerAddress);
|
||||||
|
_httpClient.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
_httpClient.stop();
|
||||||
|
Thread.sleep(500);
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPerf() throws Exception
|
||||||
|
{
|
||||||
|
sender(1,false);
|
||||||
|
sender(1,true);
|
||||||
|
sender(10,false);
|
||||||
|
sender(10,true);
|
||||||
|
sender(100,false);
|
||||||
|
sender(100,true);
|
||||||
|
if (_stress)
|
||||||
|
{
|
||||||
|
sender(1000,false);
|
||||||
|
sender(1000,true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test sending data through the exchange.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void sender(final int nb,final boolean close) throws Exception
|
||||||
|
{
|
||||||
|
_count.set(0);
|
||||||
|
final CountDownLatch complete=new CountDownLatch(nb);
|
||||||
|
final CountDownLatch latch=new CountDownLatch(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;
|
||||||
|
protected void onRequestCommitted()
|
||||||
|
{
|
||||||
|
result="committed";
|
||||||
|
// System.err.println(n+" Request committed: "+close);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onRequestComplete() throws IOException
|
||||||
|
{
|
||||||
|
result="sent";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseStatus(Buffer version, int status, Buffer reason)
|
||||||
|
{
|
||||||
|
result="status";
|
||||||
|
// System.err.println(n+" Response Status: " + version+" "+status+" "+reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseHeader(Buffer name, Buffer value)
|
||||||
|
{
|
||||||
|
// System.err.println(n+" Response header: " + name + " = " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseHeaderComplete() throws IOException
|
||||||
|
{
|
||||||
|
result="content";
|
||||||
|
super.onResponseHeaderComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseContent(Buffer content)
|
||||||
|
{
|
||||||
|
len+=content.length();
|
||||||
|
// System.err.println(n+" Response content:" + content.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseComplete()
|
||||||
|
{
|
||||||
|
result="complete";
|
||||||
|
// System.err.println(n+" Response completed "+len);
|
||||||
|
if (len==2009)
|
||||||
|
latch.countDown();
|
||||||
|
else
|
||||||
|
System.err.println(n+" ONLY "+len);
|
||||||
|
complete.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onConnectionFailed(Throwable ex)
|
||||||
|
{
|
||||||
|
complete.countDown();
|
||||||
|
result="failed";
|
||||||
|
System.err.println(n+" FAILED "+ex);
|
||||||
|
super.onConnectionFailed(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onException(Throwable ex)
|
||||||
|
{
|
||||||
|
complete.countDown();
|
||||||
|
result="excepted";
|
||||||
|
System.err.println(n+" EXCEPTED "+ex);
|
||||||
|
super.onException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onExpire()
|
||||||
|
{
|
||||||
|
complete.countDown();
|
||||||
|
result="expired";
|
||||||
|
System.err.println(n+" EXPIRED "+len);
|
||||||
|
super.onExpire();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return n+" "+result+" "+len;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
httpExchange[n].setURL(_scheme+"localhost:"+_port+"/"+n);
|
||||||
|
httpExchange[n].addRequestHeader("arbitrary","value");
|
||||||
|
if (close)
|
||||||
|
httpExchange[n].setRequestHeader("Connection","close");
|
||||||
|
|
||||||
|
_httpClient.send(httpExchange[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(complete.await(45,TimeUnit.SECONDS));
|
||||||
|
|
||||||
|
long elapsed=System.currentTimeMillis()-start;
|
||||||
|
// make windows-friendly ... System.currentTimeMillis() on windows is dope!
|
||||||
|
if(elapsed>0)
|
||||||
|
System.err.println(nb+"/"+_count+" c="+close+" rate="+(nb*1000/elapsed));
|
||||||
|
|
||||||
|
assertEquals("nb="+nb+" close="+close,0,latch.getCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPostWithContentExchange() throws Exception
|
||||||
|
{
|
||||||
|
for (int i=0;i<200;i++)
|
||||||
|
{
|
||||||
|
ContentExchange httpExchange=new ContentExchange();
|
||||||
|
//httpExchange.setURL(_scheme+"localhost:"+_port+"/");
|
||||||
|
httpExchange.setURL(_scheme+"localhost:"+_port);
|
||||||
|
httpExchange.setMethod(HttpMethods.POST);
|
||||||
|
httpExchange.setRequestContent(new ByteArrayBuffer("<hello />"));
|
||||||
|
_httpClient.send(httpExchange);
|
||||||
|
int status = httpExchange.waitForDone();
|
||||||
|
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
|
||||||
|
String result=httpExchange.getResponseContent();
|
||||||
|
assertEquals(HttpExchange.STATUS_COMPLETED, status);
|
||||||
|
assertEquals("i="+i,"<hello />",result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetWithContentExchange() throws Exception
|
||||||
|
{
|
||||||
|
for (int i=0;i<200;i++)
|
||||||
|
{
|
||||||
|
ContentExchange httpExchange=new ContentExchange();
|
||||||
|
httpExchange.setURL(_scheme+"localhost:"+_port+"/?i="+i);
|
||||||
|
httpExchange.setMethod(HttpMethods.GET);
|
||||||
|
_httpClient.send(httpExchange);
|
||||||
|
int status = httpExchange.waitForDone();
|
||||||
|
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
|
||||||
|
String result=httpExchange.getResponseContent();
|
||||||
|
assertEquals("i="+i,0,result.indexOf("<hello>"));
|
||||||
|
assertEquals("i="+i,result.length()-10,result.indexOf("</hello>"));
|
||||||
|
assertEquals(HttpExchange.STATUS_COMPLETED, status);
|
||||||
|
Thread.sleep(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.setURI("/jetty-6");
|
||||||
|
_httpClient.send(httpExchange);
|
||||||
|
int status = httpExchange.waitForDone();
|
||||||
|
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
|
||||||
|
String result=httpExchange.getResponseContent();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testReserveConnections () throws Exception
|
||||||
|
{
|
||||||
|
final HttpDestination destination = _httpClient.getDestination (new Address("localhost", _port), _scheme.equalsIgnoreCase("https://"));
|
||||||
|
final org.eclipse.jetty.client.HttpConnection[] connections = new org.eclipse.jetty.client.HttpConnection[_maxConnectionsPerAddress];
|
||||||
|
for (int i=0; i < _maxConnectionsPerAddress; i++)
|
||||||
|
{
|
||||||
|
connections[i] = destination.reserveConnection(200);
|
||||||
|
assertNotNull(connections[i]);
|
||||||
|
HttpExchange ex = new ContentExchange();
|
||||||
|
ex.setURL(_scheme+"localhost:"+_port+"/?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
|
||||||
|
org.eclipse.jetty.client.HttpConnection 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);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
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 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, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
int i=0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Request base_request=(request instanceof Request)?(Request)request:HttpConnection.getCurrentConnection().getRequest();
|
||||||
|
base_request.setHandled(true);
|
||||||
|
response.setStatus(200);
|
||||||
|
_count.incrementAndGet();
|
||||||
|
|
||||||
|
if (request.getServerName().equals("jetty.eclipse.org"))
|
||||||
|
{
|
||||||
|
// System.err.println("HANDLING Proxy");
|
||||||
|
response.getOutputStream().println("Proxy request: "+request.getRequestURL());
|
||||||
|
response.getOutputStream().println(request.getHeader(HttpHeaders.PROXY_AUTHORIZATION));
|
||||||
|
}
|
||||||
|
else if (request.getMethod().equalsIgnoreCase("GET"))
|
||||||
|
{
|
||||||
|
// System.err.println("HANDLING Hello "+request.getRequestURI());
|
||||||
|
response.getOutputStream().println("<hello>");
|
||||||
|
for (; i<100; i++)
|
||||||
|
{
|
||||||
|
response.getOutputStream().println(" <world>"+i+"</world");
|
||||||
|
if (i%20==0)
|
||||||
|
response.getOutputStream().flush();
|
||||||
|
}
|
||||||
|
response.getOutputStream().println("</hello>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// System.err.println("HANDLING "+request.getMethod());
|
||||||
|
copyStream(request.getInputStream(),response.getOutputStream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
catch(Throwable e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new ServletException(e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// System.err.println("HANDLED "+i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_server.start();
|
||||||
|
_port=_connector.getLocalPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopServer() throws Exception
|
||||||
|
{
|
||||||
|
_server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,330 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.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 junit.framework.TestCase;
|
||||||
|
|
||||||
|
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.security.Constraint;
|
||||||
|
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.HttpConnection;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functional testing for HttpExchange.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SecurityListenerTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
private Server _server;
|
||||||
|
private int _port;
|
||||||
|
private HttpClient _httpClient;
|
||||||
|
|
||||||
|
private Realm _jettyRealm;
|
||||||
|
private static final String APP_CONTEXT = "localhost /";
|
||||||
|
|
||||||
|
protected 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) );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
stopServer();
|
||||||
|
_httpClient.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
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; i<nb; i++)
|
||||||
|
{
|
||||||
|
final int n=i;
|
||||||
|
if (n%1000==0)
|
||||||
|
{
|
||||||
|
Thread.sleep(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpExchange httpExchange=new HttpExchange()
|
||||||
|
{
|
||||||
|
protected void onRequestCommitted()
|
||||||
|
{
|
||||||
|
// System.err.println("Request committed");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseStatus(Buffer version, int status, Buffer reason)
|
||||||
|
{
|
||||||
|
// System.err.println("Response Status: " + version+" "+status+" "+reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseHeader(Buffer name, Buffer value)
|
||||||
|
{
|
||||||
|
// System.err.println("Response header: " + name + " = " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseContent(Buffer content)
|
||||||
|
{
|
||||||
|
// System.err.println("Response content:" + content);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onResponseComplete()
|
||||||
|
{
|
||||||
|
// System.err.println("Response completed "+n);
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
httpExchange.setURL("http://localhost:"+_port+"/");
|
||||||
|
httpExchange.addRequestHeader("arbitrary","value");
|
||||||
|
|
||||||
|
_httpClient.send(httpExchange);
|
||||||
|
}
|
||||||
|
|
||||||
|
long last=latch.getCount();
|
||||||
|
while(last>0)
|
||||||
|
{
|
||||||
|
// 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){}
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
public void testDestinationSecurityCaching() throws Exception
|
||||||
|
{
|
||||||
|
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=1");
|
||||||
|
httpExchange.setMethod(HttpMethods.GET);
|
||||||
|
|
||||||
|
_httpClient.send(httpExchange);
|
||||||
|
|
||||||
|
try{barrier.await();}catch(Exception e){}
|
||||||
|
|
||||||
|
|
||||||
|
barrier.reset();
|
||||||
|
ContentExchange httpExchange2 = new ContentExchange()
|
||||||
|
{
|
||||||
|
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("/*");
|
||||||
|
|
||||||
|
LoginService loginService = new HashLoginService("MyRealm","src/test/resources/realm.properties");
|
||||||
|
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, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
// System.out.println("passed authentication!");
|
||||||
|
Request base_request=(request instanceof Request)?(Request)request:HttpConnection.getCurrentConnection().getRequest();
|
||||||
|
base_request.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("<hello>");
|
||||||
|
for (int i=0; i<100; i++)
|
||||||
|
{
|
||||||
|
response.getOutputStream().println(" <world>"+i+"</world>");
|
||||||
|
if (i%20==0)
|
||||||
|
response.getOutputStream().flush();
|
||||||
|
}
|
||||||
|
response.getOutputStream().println("</hello>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
copyStream(request.getInputStream(),response.getOutputStream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sh.setHandler(testHandler);
|
||||||
|
|
||||||
|
_server.start();
|
||||||
|
_port = connector.getLocalPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void stopServer() throws Exception
|
||||||
|
{
|
||||||
|
_server.stop();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.ssl.SslSocketConnector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functional testing for HttpExchange.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SslHttpExchangeTest extends HttpExchangeTest
|
||||||
|
{
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
_scheme="https://";
|
||||||
|
startServer();
|
||||||
|
_httpClient=new HttpClient();
|
||||||
|
// _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
|
||||||
|
_httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
|
||||||
|
_httpClient.setMaxConnectionsPerAddress(2);
|
||||||
|
_httpClient.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void newServer()
|
||||||
|
{
|
||||||
|
_server = new Server();
|
||||||
|
//SslSelectChannelConnector connector = new SslSelectChannelConnector();
|
||||||
|
SslSocketConnector connector = new SslSocketConnector();
|
||||||
|
|
||||||
|
String keystore = System.getProperty("user.dir") + File.separator + "src" + File.separator + "test" + File.separator + "resources" + File.separator
|
||||||
|
+ "keystore";
|
||||||
|
|
||||||
|
connector.setPort(0);
|
||||||
|
connector.setKeystore(keystore);
|
||||||
|
connector.setPassword("storepwd");
|
||||||
|
connector.setKeyPassword("keypwd");
|
||||||
|
|
||||||
|
_server.setConnectors(new Connector[]
|
||||||
|
{ connector });
|
||||||
|
_connector=connector;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
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 junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.security.HashRealmResolver;
|
||||||
|
import org.eclipse.jetty.client.security.Realm;
|
||||||
|
import org.eclipse.jetty.http.HttpMethods;
|
||||||
|
import org.eclipse.jetty.http.security.Constraint;
|
||||||
|
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.authentication.BasicAuthenticator;
|
||||||
|
import org.eclipse.jetty.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
import org.eclipse.jetty.server.HttpConnection;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functional testing.
|
||||||
|
*/
|
||||||
|
public class SslSecurityListenerTest extends TestCase
|
||||||
|
{
|
||||||
|
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 /";
|
||||||
|
|
||||||
|
protected 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
Thread.sleep(1000);
|
||||||
|
_httpClient.stop();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSslGet() throws Exception
|
||||||
|
{
|
||||||
|
final CyclicBarrier barrier = new CyclicBarrier(2);
|
||||||
|
|
||||||
|
ContentExchange httpExchange = new ContentExchange(true)
|
||||||
|
{
|
||||||
|
protected void onResponseComplete() throws IOException
|
||||||
|
{
|
||||||
|
super.onResponseComplete();
|
||||||
|
try{barrier.await();}catch(Exception e){}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// httpExchange.setURL("https://dav.codehaus.org/user/jesse/index.html");
|
||||||
|
httpExchange.setURL("https://localhost:" + _port + "/");
|
||||||
|
httpExchange.setMethod(HttpMethods.GET);
|
||||||
|
// httpExchange.setRequestHeader("Connection","close");
|
||||||
|
|
||||||
|
_httpClient.send(httpExchange);
|
||||||
|
|
||||||
|
barrier.await(10000,TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
assertEquals(HttpServletResponse.SC_OK,httpExchange.getResponseStatus());
|
||||||
|
|
||||||
|
// System.err.println(httpExchange.getResponseContent());
|
||||||
|
assertTrue(httpExchange.getResponseContent().length()>400);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startServer() throws Exception
|
||||||
|
{
|
||||||
|
_server = new Server();
|
||||||
|
//SslSelectChannelConnector connector = new SslSelectChannelConnector();
|
||||||
|
SslSocketConnector connector = new SslSocketConnector();
|
||||||
|
|
||||||
|
String keystore = System.getProperty("user.dir") + File.separator + "src" + File.separator + "test" + File.separator + "resources" + File.separator
|
||||||
|
+ "keystore";
|
||||||
|
|
||||||
|
connector.setPort(0);
|
||||||
|
connector.setKeystore(keystore);
|
||||||
|
connector.setPassword("storepwd");
|
||||||
|
connector.setKeyPassword("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("/*");
|
||||||
|
|
||||||
|
HashLoginService loginService = new HashLoginService("MyRealm","src/test/resources/realm.properties");
|
||||||
|
_server.addBean(loginService);
|
||||||
|
|
||||||
|
BasicAuthenticator authenticator = new BasicAuthenticator();
|
||||||
|
|
||||||
|
ConstraintSecurityHandler sh = new ConstraintSecurityHandler();
|
||||||
|
sh.setAuthenticator(authenticator);
|
||||||
|
|
||||||
|
Set<String> roles = new HashSet<String>(Arrays.asList(new String[]{"user", "admin"}));
|
||||||
|
sh.setConstraintMappings(new ConstraintMapping[] { cm }, roles);
|
||||||
|
_server.setHandler(sh);
|
||||||
|
|
||||||
|
Handler testHandler = new AbstractHandler()
|
||||||
|
{
|
||||||
|
|
||||||
|
public void handle(String target, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
// System.err.println("passed authentication!\n"+((Request)request).getConnection().getRequestFields());
|
||||||
|
|
||||||
|
Request base_request = (request instanceof Request)?(Request)request:HttpConnection.getCurrentConnection().getRequest();
|
||||||
|
base_request.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("<hello>");
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
response.getOutputStream().println(" <world>" + i + "</world>");
|
||||||
|
if (i % 20 == 0)
|
||||||
|
response.getOutputStream().flush();
|
||||||
|
}
|
||||||
|
response.getOutputStream().println("</hello>");
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.security.Realm;
|
||||||
|
import org.eclipse.jetty.client.security.SimpleRealmResolver;
|
||||||
|
import org.eclipse.jetty.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functional testing for HttpExchange.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class WebdavListenerTest extends TestCase//extends HttpExchangeTest
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void tearDown () throws Exception
|
||||||
|
{
|
||||||
|
_httpClient.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testPUTandDELETEwithSSL() throws Exception
|
||||||
|
{
|
||||||
|
File file = new File("src/test/resources/foo.txt");
|
||||||
|
assertTrue(file.exists());
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UNCOMMENT TO TEST WITH REAL DAV SERVER
|
||||||
|
* Remember to set _username and _password to a real user's account.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
//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();
|
||||||
|
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();
|
||||||
|
assertEquals(201, singleFileExchange.getResponseStatus());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//DELETE the single file
|
||||||
|
HttpExchange del = new HttpExchange();
|
||||||
|
del.setURL(_singleFileURL);
|
||||||
|
del.setMethod(HttpMethods.DELETE);
|
||||||
|
_httpClient.send(del);
|
||||||
|
del.waitForCompletion();
|
||||||
|
|
||||||
|
//DELETE the whole dir
|
||||||
|
del.setURL(_dirURL);
|
||||||
|
del.setMethod(HttpMethods.DELETE);
|
||||||
|
del.setRequestHeader("Depth", "infinity");
|
||||||
|
_httpClient.send(del);
|
||||||
|
del.waitForCompletion();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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 junit.framework.TestCase;
|
||||||
|
|
||||||
|
public class SecurityResolverTest extends TestCase
|
||||||
|
{
|
||||||
|
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<String,String> testMap = resolver.scrapeAuthenticationDetails( value.toString() );
|
||||||
|
assertEquals( 3, testMap.size() );
|
||||||
|
assertEquals( "boo", testMap.get("a") );
|
||||||
|
assertEquals( "doo", testMap.get("c") );
|
||||||
|
assertEquals( "foo", testMap.get("egg") );
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<html/>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue