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:
Greg Wilkins 2009-03-24 21:07:27 +00:00
parent bc1e0bd102
commit da627b843f
660 changed files with 149998 additions and 0 deletions

202
LICENSE-APACHE-2.0.txt Normal file
View File

@ -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.

View File

@ -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.

View File

@ -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
______________________________________ ________________
______________________________________ ________________

View File

@ -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
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________
______________________________________ ________________

View File

@ -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-----

View File

@ -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-----

View File

@ -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-----

View File

@ -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-----

View File

@ -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-----

View File

@ -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-----

View File

@ -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-----

View File

@ -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-----

View File

@ -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-----

View File

@ -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:

View File

@ -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-----

320
LICENSE-ECLIPSE-1.0.html Normal file
View File

@ -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]-->&nbsp;<!--[endif]--><o:p></o:p></p>
</div>
</body></html>

21
NOTICE.txt Normal file
View File

@ -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.

17
README.txt Normal file
View File

@ -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

3968
VERSION.txt Normal file

File diff suppressed because it is too large Load Diff

76
jetty-ajp/pom.xml Normal file
View File

@ -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>

View File

@ -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>

View File

@ -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();
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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");
}
}
}

View File

@ -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);
}
}
}

85
jetty-annotations/pom.xml Normal file
View File

@ -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>

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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));
}
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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[]{})));
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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
}
}

View File

@ -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");
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

503
jetty-assembly/pom.xml Normal file
View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,3 @@
This directory contains example contexts that may be deployed by
moving/copying/linking them to the ../contexts directory.

View File

@ -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.

View File

@ -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>

View File

@ -0,0 +1,7 @@
<h1>Jetty Javadoc - NOT BUILT!</h1>
Please run build the project-website module

View File

@ -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

85
jetty-client/pom.xml Normal file
View File

@ -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>

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}
}
}

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -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
{
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}
});
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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 );
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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() );
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
*/
}
}

View File

@ -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") );
}
*/
}

View File

@ -0,0 +1 @@
<html/>

Some files were not shown because too many files have changed in this diff Show More