Initial import. Needs to:
* rename packages * update license information
This commit is contained in:
commit
aef2ab453a
177
LICENSE.commons-logging.txt
Normal file
177
LICENSE.commons-logging.txt
Normal file
@ -0,0 +1,177 @@
|
||||
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
|
||||
|
504
LICENSE.jboss-logging.txt
Normal file
504
LICENSE.jboss-logging.txt
Normal file
@ -0,0 +1,504 @@
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
177
LICENSE.log4j.txt
Normal file
177
LICENSE.log4j.txt
Normal file
@ -0,0 +1,177 @@
|
||||
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
|
||||
|
23
LICENSE.slf4j.txt
Normal file
23
LICENSE.slf4j.txt
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 QOS.ch
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
504
LICENSE.txt
Normal file
504
LICENSE.txt
Normal file
@ -0,0 +1,504 @@
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
56
NOTICE.txt
Normal file
56
NOTICE.txt
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
Netty
|
||||
|
||||
Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
This product includes software developed by:
|
||||
|
||||
* Trustin Heuiseung Lee (http://gleamynode.net/)
|
||||
|
||||
Please visit Netty web site for more information:
|
||||
|
||||
* http://www.jboss.org/netty/
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
This product is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This product is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Please refer to each LICENSE.<component>.txt file for the
|
||||
license terms of the components that Netty depends on.
|
||||
|
||||
This product optionally depends on 'SLF4J', a simple logging facade for Java,
|
||||
which can be obtained at:
|
||||
|
||||
* http://www.slf4j.org/
|
||||
|
||||
This product optionally depends on 'Apache Commons Logging', a logging
|
||||
framework, which can be obtained at:
|
||||
|
||||
* http://commons.apache.org/logging/
|
||||
|
||||
This product optionally depends on 'Apache Log4J', a logging framework,
|
||||
which can be obtained at:
|
||||
|
||||
* http://logging.apache.org/log4j/
|
||||
|
||||
This product optionally depends on 'JBoss Logging', a logging framework,
|
||||
which can be obtained at:
|
||||
|
||||
* http://anonsvn.jboss.org/repos/common/common-logging-spi/
|
||||
|
378
pom.xml
Normal file
378
pom.xml
Normal file
@ -0,0 +1,378 @@
|
||||
<!--
|
||||
Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
-->
|
||||
|
||||
<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>
|
||||
<groupId>org.jboss.netty</groupId>
|
||||
<artifactId>netty</artifactId>
|
||||
<version>3.0.0.M8-SNAPSHOT</version>
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<name>The Netty Project</name>
|
||||
<description>
|
||||
The Netty project is an effort to provide an asynchronous / event-driven network application framework for rapid development of high-performance / high-scalability protocol servers and clients, including its related out-of-the-box protocol extensions and tool suite.
|
||||
</description>
|
||||
|
||||
<url>http://www.jboss.org/netty/</url>
|
||||
<organization>
|
||||
<name>JBoss.org</name>
|
||||
<url>http://www.jboss.org/</url>
|
||||
</organization>
|
||||
|
||||
<inceptionYear>2008</inceptionYear>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU Lesser General Public License</name>
|
||||
<url>http://www.gnu.org/licenses/lgpl.html</url>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://anonsvn.jboss.org/repos/netty/trunk</connection>
|
||||
<developerConnection>scm:svn:https://svn.jboss.org/repos/netty/trunk</developerConnection>
|
||||
</scm>
|
||||
|
||||
<repositories>
|
||||
<!-- APIviz repository -->
|
||||
<repository>
|
||||
<id>apiviz.release</id>
|
||||
<name>APIviz releases</name>
|
||||
<url>http://apiviz.googlecode.com/svn/site/repo/mvn/release</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<!-- JBoss repository -->
|
||||
<repository>
|
||||
<id>jboss.release</id>
|
||||
<name>JBoss releases</name>
|
||||
<url>http://repository.jboss.org/maven2</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>repository.jboss.org</id>
|
||||
<name>JBoss.org Release Distribution Repository</name>
|
||||
<url>http://repository.jboss.org/maven2</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>snapshots.jboss.org</id>
|
||||
<name>JBoss.org Development Snapshot Repository</name>
|
||||
<url>http://snapshots.jboss.org/maven2</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
<dependencies>
|
||||
<!-- Logging frameworks (all optional) -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.5.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging-spi</artifactId>
|
||||
<version>2.0.5.GA</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.15</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>javax.jms</groupId>
|
||||
<artifactId>jms</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jdmk</groupId>
|
||||
<artifactId>jmxtools</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jmx</groupId>
|
||||
<artifactId>jmxri</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
<debug>true</debug>
|
||||
<optimize>true</optimize>
|
||||
<showDeprecations>true</showDeprecations>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>run-pmd</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
<goal>cpd-check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<sourceEncoding>UTF-8</sourceEncoding>
|
||||
<targetJdk>1.5</targetJdk>
|
||||
<failOnViolation>false</failOnViolation>
|
||||
<linkXRef>false</linkXRef>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/Abstract*</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>run-coverage-test</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>cobertura</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-SymbolicName>${project.groupId}</Bundle-SymbolicName>
|
||||
<Export-Package>${project.groupId}.buffer.*,${project.groupId}.channel.*,${project.groupId}.bootstrap.*,${project.groupId}.handler.*</Export-Package>
|
||||
<Private-Package>${project.groupId}.util.*</Private-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-source</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadoc</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<doclet>net.gleamynode.apiviz.APIviz</doclet>
|
||||
<docletArtifact>
|
||||
<groupId>net.gleamynode.apiviz</groupId>
|
||||
<artifactId>apiviz</artifactId>
|
||||
<version>1.1.3</version>
|
||||
</docletArtifact>
|
||||
<aggregate>true</aggregate>
|
||||
<additionalparam>
|
||||
-charset UTF-8
|
||||
-docencoding UTF-8
|
||||
-version
|
||||
-author
|
||||
-breakiterator
|
||||
-linksource
|
||||
-sourcetab 4
|
||||
-windowtitle "${project.name} ${project.version} API Reference"
|
||||
-doctitle "${project.name} ${project.version} API Reference"
|
||||
-bottom "Copyright © ${project.inceptionYear}-Present ${project.organization.name}. All Rights Reserved."
|
||||
-link http://java.sun.com/javase/6/docs/api/
|
||||
-group "Low-level data representation" ${project.groupId}.buffer*
|
||||
-group "Central interface for all I/O operations" ${project.groupId}.channel*
|
||||
-group "Client & Server bootstrapping utilities" ${project.groupId}.bootstrap*
|
||||
-group "Reusable I/O event interceptors" ${project.groupId}.handler*
|
||||
-group "Miscellaneous" ${project.groupId}.logging*
|
||||
</additionalparam>
|
||||
<encoding>UTF-8</encoding>
|
||||
<locale>en_US</locale>
|
||||
<excludePackageNames>${project.groupId}.example*:${project.groupId}.util*</excludePackageNames>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jxr-plugin</artifactId>
|
||||
<configuration>
|
||||
<inputEncoding>UTF-8</inputEncoding>
|
||||
<outputEncoding>UTF-8</outputEncoding>
|
||||
<linkJavadoc>false</linkJavadoc>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-license</id>
|
||||
<phase>package</phase>
|
||||
<configuration>
|
||||
<tasks>
|
||||
<taskdef resource="net/sf/antcontrib/antlib.xml" />
|
||||
<if>
|
||||
<or>
|
||||
<equals arg1="${project.packaging}" arg2="jar" />
|
||||
<equals arg1="${project.packaging}" arg2="bundle" />
|
||||
</or>
|
||||
<then>
|
||||
<move file="${project.build.directory}/${project.build.finalName}.jar" tofile="${project.build.directory}/${project.build.finalName}.orig.jar" />
|
||||
<zip destfile="${project.build.directory}/${project.build.finalName}.jar">
|
||||
<zipfileset dir="${basedir}" prefix="META-INF/">
|
||||
<include name="LICENSE.*" />
|
||||
<include name="NOTICE.*" />
|
||||
</zipfileset>
|
||||
<zipfileset src="${project.build.directory}/${project.build.finalName}.orig.jar" filemode="644" dirmode="755">
|
||||
<exclude name="*/*/*/example/**" />
|
||||
</zipfileset>
|
||||
</zip>
|
||||
<delete file="${project.build.directory}/${project.build.finalName}.orig.jar" />
|
||||
<move file="${project.build.directory}/${project.build.finalName}-sources.jar" tofile="${project.build.directory}/${project.build.finalName}-sources.orig.jar" />
|
||||
<zip destfile="${project.build.directory}/${project.build.finalName}-sources.jar">
|
||||
<zipfileset dir="${basedir}" prefix="META-INF/">
|
||||
<include name="LICENSE.*" />
|
||||
<include name="NOTICE.*" />
|
||||
</zipfileset>
|
||||
<zipfileset src="${project.build.directory}/${project.build.finalName}-sources.orig.jar" filemode="644" dirmode="755">
|
||||
<exclude name="*/*/*/example/**" />
|
||||
</zipfileset>
|
||||
</zip>
|
||||
<delete file="${project.build.directory}/${project.build.finalName}-sources.orig.jar" />
|
||||
<move file="${project.build.directory}/${project.build.finalName}-javadoc.jar" tofile="${project.build.directory}/${project.build.finalName}-javadoc.orig.jar" />
|
||||
<zip destfile="${project.build.directory}/${project.build.finalName}-javadoc.jar">
|
||||
<zipfileset dir="${basedir}" prefix="META-INF/">
|
||||
<include name="LICENSE.*" />
|
||||
<include name="NOTICE.*" />
|
||||
</zipfileset>
|
||||
<zipfileset src="${project.build.directory}/${project.build.finalName}-javadoc.orig.jar" filemode="644" dirmode="755" />
|
||||
</zip>
|
||||
<delete file="${project.build.directory}/${project.build.finalName}-javadoc.orig.jar" />
|
||||
</then>
|
||||
</if>
|
||||
</tasks>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ant-contrib</groupId>
|
||||
<artifactId>ant-contrib</artifactId>
|
||||
<version>1.0b2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-distribution</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>attached</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>${basedir}/src/assembly/default.xml</descriptor>
|
||||
</descriptors>
|
||||
<appendAssemblyId>true</appendAssemblyId>
|
||||
<tarLongFileMode>gnu</tarLongFileMode>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<configuration>
|
||||
<tagBase>
|
||||
https://svn.jboss.org/repos/netty/tags
|
||||
</tagBase>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<reporting>
|
||||
<plugins>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</project>
|
36
src/assembly/default.xml
Normal file
36
src/assembly/default.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<assembly>
|
||||
<id>dist</id>
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<includeSiteDirectory>false</includeSiteDirectory>
|
||||
<fileSets>
|
||||
<!-- Source Code -->
|
||||
<fileSet>
|
||||
<includes>
|
||||
<include>**/README*</include>
|
||||
<include>**/LICENSE*</include>
|
||||
<include>**/NOTICE*</include>
|
||||
<include>**/*.txt</include>
|
||||
<include>**/*.xml</include>
|
||||
<include>**/src/**</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/target/**</exclude>
|
||||
<exclude>**/.*/**</exclude>
|
||||
</excludes>
|
||||
</fileSet>
|
||||
|
||||
<!-- JAR -->
|
||||
<fileSet>
|
||||
<directory>target</directory>
|
||||
<outputDirectory>jar</outputDirectory>
|
||||
<includes>
|
||||
<include>${project.build.finalName}*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
|
255
src/main/java/net/gleamynode/netty/bootstrap/Bootstrap.java
Normal file
255
src/main/java/net/gleamynode/netty/bootstrap/Bootstrap.java
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.bootstrap;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelHandler;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelPipelineFactory;
|
||||
import net.gleamynode.netty.channel.SimpleChannelHandler;
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.uses net.gleamynode.netty.channel.ChannelFactory
|
||||
*/
|
||||
public class Bootstrap {
|
||||
|
||||
private static Logger logger = Logger.getLogger(Bootstrap.class);
|
||||
|
||||
private volatile ChannelFactory factory;
|
||||
private volatile ChannelPipeline pipeline = pipeline();
|
||||
private volatile ChannelPipelineFactory pipelineFactory = pipelineFactory(pipeline);
|
||||
private volatile Map<String, Object> options = new HashMap<String, Object>();
|
||||
|
||||
public Bootstrap() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Bootstrap(ChannelFactory channelFactory) {
|
||||
setFactory(channelFactory);
|
||||
}
|
||||
|
||||
public ChannelFactory getFactory() {
|
||||
ChannelFactory factory = this.factory;
|
||||
if (factory == null) {
|
||||
throw new IllegalStateException(
|
||||
"factory is not set yet.");
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
|
||||
public void setFactory(ChannelFactory factory) {
|
||||
if (this.factory != null) {
|
||||
throw new IllegalStateException(
|
||||
"factory can't change once set.");
|
||||
}
|
||||
if (factory == null) {
|
||||
throw new NullPointerException("factory");
|
||||
}
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
public void setPipeline(ChannelPipeline pipeline) {
|
||||
if (pipeline == null) {
|
||||
throw new NullPointerException("pipeline");
|
||||
}
|
||||
pipeline = this.pipeline;
|
||||
pipelineFactory = pipelineFactory(pipeline);
|
||||
}
|
||||
|
||||
public Map<String, ChannelHandler> getPipelineAsMap() {
|
||||
ChannelPipeline pipeline = this.pipeline;
|
||||
if (pipeline == null) {
|
||||
throw new IllegalStateException("pipelineFactory in use");
|
||||
}
|
||||
return pipeline.toMap();
|
||||
}
|
||||
|
||||
public void setPipelineAsMap(Map<String, ChannelHandler> pipelineMap) {
|
||||
if (pipelineMap == null) {
|
||||
throw new NullPointerException("pipelineMap");
|
||||
}
|
||||
|
||||
if (!isOrderedMap(pipelineMap)) {
|
||||
throw new IllegalArgumentException(
|
||||
"pipelineMap is not an ordered map. " +
|
||||
"Please use " +
|
||||
LinkedHashMap.class.getName() + ".");
|
||||
}
|
||||
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
for(Map.Entry<String, ChannelHandler> e: pipelineMap.entrySet()) {
|
||||
pipeline.addLast(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
setPipeline(pipeline);
|
||||
}
|
||||
|
||||
public ChannelPipelineFactory getPipelineFactory() {
|
||||
return pipelineFactory;
|
||||
}
|
||||
|
||||
public void setPipelineFactory(ChannelPipelineFactory pipelineFactory) {
|
||||
if (pipelineFactory == null) {
|
||||
throw new NullPointerException("pipelineFactory");
|
||||
}
|
||||
pipeline = null;
|
||||
this.pipelineFactory = pipelineFactory;
|
||||
}
|
||||
|
||||
public Map<String, Object> getOptions() {
|
||||
return new TreeMap<String, Object>(options);
|
||||
}
|
||||
|
||||
public void setOptions(Map<String, Object> options) {
|
||||
if (options == null) {
|
||||
throw new NullPointerException("options");
|
||||
}
|
||||
this.options = new HashMap<String, Object>(options);
|
||||
}
|
||||
|
||||
public Object getOption(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
return options.get(key);
|
||||
}
|
||||
|
||||
public void setOption(String key, Object value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
options.remove(key);
|
||||
} else {
|
||||
options.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isOrderedMap(Map<String, ChannelHandler> map) {
|
||||
Class<Map<String, ChannelHandler>> mapType = getMapClass(map);
|
||||
if (LinkedHashMap.class.isAssignableFrom(mapType)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(mapType.getSimpleName() + " is an ordered map.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
mapType.getName() + " is not a " +
|
||||
LinkedHashMap.class.getSimpleName());
|
||||
}
|
||||
|
||||
// Detect Apache Commons Collections OrderedMap implementations.
|
||||
Class<?> type = mapType;
|
||||
while (type != null) {
|
||||
for (Class<?> i: type.getInterfaces()) {
|
||||
if (i.getName().endsWith("OrderedMap")) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
mapType.getSimpleName() +
|
||||
" is an ordered map (guessed from that it " +
|
||||
" implements OrderedMap interface.)");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
mapType.getName() +
|
||||
" doesn't implement OrderedMap interface.");
|
||||
}
|
||||
|
||||
// Last resort: try to create a new instance and test if it maintains
|
||||
// the insertion order.
|
||||
logger.debug(
|
||||
"Last resort; trying to create a new map instance with a " +
|
||||
"default constructor and test if insertion order is " +
|
||||
"maintained.");
|
||||
|
||||
Map<String, ChannelHandler> newMap;
|
||||
try {
|
||||
newMap = mapType.newInstance();
|
||||
} catch (Exception e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"Failed to create a new map instance of '" +
|
||||
mapType.getName() +"'.", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Random rand = new Random();
|
||||
List<String> expectedNames = new ArrayList<String>();
|
||||
ChannelHandler dummyHandler = new SimpleChannelHandler();
|
||||
for (int i = 0; i < 65536; i ++) {
|
||||
String filterName;
|
||||
do {
|
||||
filterName = String.valueOf(rand.nextInt());
|
||||
} while (newMap.containsKey(filterName));
|
||||
|
||||
newMap.put(filterName, dummyHandler);
|
||||
expectedNames.add(filterName);
|
||||
|
||||
Iterator<String> it = expectedNames.iterator();
|
||||
for (Object key: newMap.keySet()) {
|
||||
if (!it.next().equals(key)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"The specified map didn't pass the insertion " +
|
||||
"order test after " + (i + 1) + " tries.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("The specified map passed the insertion order test.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Class<Map<String, ChannelHandler>> getMapClass(
|
||||
Map<String, ChannelHandler> map) {
|
||||
return (Class<Map<String, ChannelHandler>>) map.getClass();
|
||||
}
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.bootstrap;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelHandlerContext;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelPipelineCoverage;
|
||||
import net.gleamynode.netty.channel.ChannelPipelineException;
|
||||
import net.gleamynode.netty.channel.ChannelStateEvent;
|
||||
import net.gleamynode.netty.channel.ExceptionEvent;
|
||||
import net.gleamynode.netty.channel.SimpleChannelHandler;
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
*/
|
||||
public class ClientBootstrap extends Bootstrap {
|
||||
|
||||
public ClientBootstrap() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ClientBootstrap(ChannelFactory channelFactory) {
|
||||
super(channelFactory);
|
||||
}
|
||||
|
||||
public ChannelFuture connect() {
|
||||
SocketAddress remoteAddress = (SocketAddress) getOption("remoteAddress");
|
||||
if (remoteAddress == null) {
|
||||
throw new IllegalStateException("remoteAddress option is not set.");
|
||||
}
|
||||
SocketAddress localAddress = (SocketAddress) getOption("localAddress");
|
||||
return connect(remoteAddress, localAddress);
|
||||
}
|
||||
|
||||
public ChannelFuture connect(SocketAddress remoteAddress) {
|
||||
if (remoteAddress == null) {
|
||||
throw new NullPointerException("remotedAddress");
|
||||
}
|
||||
return connect(remoteAddress, null);
|
||||
}
|
||||
|
||||
public ChannelFuture connect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
|
||||
|
||||
final BlockingQueue<ChannelFuture> futureQueue =
|
||||
new LinkedBlockingQueue<ChannelFuture>();
|
||||
|
||||
ChannelPipeline pipeline;
|
||||
try {
|
||||
pipeline = getPipelineFactory().getPipeline();
|
||||
} catch (Exception e) {
|
||||
throw new ChannelPipelineException("Failed to initialize a pipeline.", e);
|
||||
}
|
||||
|
||||
pipeline.addFirst("connector", new Connector(remoteAddress, localAddress, futureQueue));
|
||||
|
||||
getFactory().newChannel(pipeline);
|
||||
|
||||
// Wait until the future is available.
|
||||
ChannelFuture future = null;
|
||||
do {
|
||||
try {
|
||||
future = futureQueue.poll(Integer.MAX_VALUE, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore
|
||||
}
|
||||
} while (future == null);
|
||||
|
||||
pipeline.remove(pipeline.get("connector"));
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
@ChannelPipelineCoverage("one")
|
||||
private final class Connector extends SimpleChannelHandler {
|
||||
private final SocketAddress localAddress;
|
||||
private final BlockingQueue<ChannelFuture> futureQueue;
|
||||
private final SocketAddress remoteAddress;
|
||||
private volatile boolean finished = false;
|
||||
|
||||
Connector(SocketAddress remoteAddress,
|
||||
SocketAddress localAddress,
|
||||
BlockingQueue<ChannelFuture> futureQueue) {
|
||||
this.localAddress = localAddress;
|
||||
this.futureQueue = futureQueue;
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelOpen(
|
||||
ChannelHandlerContext context,
|
||||
ChannelStateEvent event) {
|
||||
context.sendUpstream(event);
|
||||
|
||||
// Apply options.
|
||||
event.getChannel().getConfig().setOptions(getOptions());
|
||||
|
||||
// Bind or connect.
|
||||
if (localAddress != null) {
|
||||
event.getChannel().bind(localAddress);
|
||||
} else {
|
||||
futureQueue.offer(event.getChannel().connect(remoteAddress));
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelBound(
|
||||
ChannelHandlerContext context,
|
||||
ChannelStateEvent event) {
|
||||
context.sendUpstream(event);
|
||||
|
||||
// Connect if not connected yet.
|
||||
if (localAddress != null) {
|
||||
futureQueue.offer(event.getChannel().connect(remoteAddress));
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
if (!finished) {
|
||||
e.getChannel().close();
|
||||
futureQueue.offer(failedFuture(e.getChannel(), e.getCause()));
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.bootstrap;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
import net.gleamynode.netty.channel.ChannelException;
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelHandler;
|
||||
import net.gleamynode.netty.channel.ChannelHandlerContext;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelPipelineCoverage;
|
||||
import net.gleamynode.netty.channel.ChannelStateEvent;
|
||||
import net.gleamynode.netty.channel.ChildChannelStateEvent;
|
||||
import net.gleamynode.netty.channel.ExceptionEvent;
|
||||
import net.gleamynode.netty.channel.SimpleChannelHandler;
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
*/
|
||||
public class ServerBootstrap extends Bootstrap {
|
||||
|
||||
private volatile ChannelHandler parentHandler;
|
||||
|
||||
public ServerBootstrap() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ServerBootstrap(ChannelFactory channelFactory) {
|
||||
super(channelFactory);
|
||||
}
|
||||
|
||||
public ChannelHandler getParentHandler() {
|
||||
return parentHandler;
|
||||
}
|
||||
|
||||
public void setParentHandler(ChannelHandler parentHandler) {
|
||||
this.parentHandler = parentHandler;
|
||||
}
|
||||
|
||||
public Channel bind() {
|
||||
SocketAddress localAddress = (SocketAddress) getOption("localAddress");
|
||||
if (localAddress == null) {
|
||||
throw new IllegalStateException("localAddress option is not set.");
|
||||
}
|
||||
return bind(localAddress);
|
||||
}
|
||||
|
||||
public Channel bind(final SocketAddress localAddress) {
|
||||
final BlockingQueue<ChannelFuture> futureQueue =
|
||||
new LinkedBlockingQueue<ChannelFuture>();
|
||||
|
||||
ChannelPipeline bossPipeline = pipeline();
|
||||
bossPipeline.addLast("binder", new Binder(localAddress, futureQueue));
|
||||
|
||||
ChannelHandler parentHandler = getParentHandler();
|
||||
if (parentHandler != null) {
|
||||
bossPipeline.addLast("userHandler", parentHandler);
|
||||
}
|
||||
|
||||
Channel channel = getFactory().newChannel(bossPipeline);
|
||||
|
||||
// Wait until the future is available.
|
||||
ChannelFuture future = null;
|
||||
do {
|
||||
try {
|
||||
future = futureQueue.poll(Integer.MAX_VALUE, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore
|
||||
}
|
||||
} while (future == null);
|
||||
|
||||
// Wait for the future.
|
||||
future.awaitUninterruptibly();
|
||||
if (!future.isSuccess()) {
|
||||
future.getChannel().close().awaitUninterruptibly();
|
||||
throw new ChannelException("Failed to bind to: " + localAddress, future.getCause());
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
@ChannelPipelineCoverage("one")
|
||||
private final class Binder extends SimpleChannelHandler {
|
||||
|
||||
private final SocketAddress localAddress;
|
||||
private final BlockingQueue<ChannelFuture> futureQueue;
|
||||
private final Map<String, Object> childOptions =
|
||||
new HashMap<String, Object>();
|
||||
|
||||
Binder(SocketAddress localAddress, BlockingQueue<ChannelFuture> futureQueue) {
|
||||
this.localAddress = localAddress;
|
||||
this.futureQueue = futureQueue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelOpen(
|
||||
ChannelHandlerContext ctx,
|
||||
ChannelStateEvent evt) {
|
||||
evt.getChannel().getConfig().setPipelineFactory(getPipelineFactory());
|
||||
|
||||
// Split options into two categories: parent and child.
|
||||
Map<String, Object> allOptions = getOptions();
|
||||
Map<String, Object> parentOptions = new HashMap<String, Object>();
|
||||
for (Entry<String, Object> e: allOptions.entrySet()) {
|
||||
if (e.getKey().startsWith("child.")) {
|
||||
childOptions.put(
|
||||
e.getKey().substring(6),
|
||||
e.getValue());
|
||||
} else if (!e.getKey().equals("pipelineFactory")) {
|
||||
parentOptions.put(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// Apply parent options.
|
||||
evt.getChannel().getConfig().setOptions(parentOptions);
|
||||
|
||||
futureQueue.offer(evt.getChannel().bind(localAddress));
|
||||
ctx.sendUpstream(evt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childChannelOpen(
|
||||
ChannelHandlerContext ctx,
|
||||
ChildChannelStateEvent e) throws Exception {
|
||||
// Apply child options.
|
||||
e.getChildChannel().getConfig().setOptions(childOptions);
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper classes which enable an easy implementation of typical client and
|
||||
* server socket initialization.
|
||||
*
|
||||
* @apiviz.landmark
|
||||
*/
|
||||
package net.gleamynode.netty.bootstrap;
|
@ -0,0 +1,418 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public abstract class AbstractChannelBuffer implements ChannelBuffer {
|
||||
|
||||
private int hashCode;
|
||||
private int readerIndex;
|
||||
private int writerIndex;
|
||||
private int markedReaderIndex;
|
||||
private int markedWriterIndex;
|
||||
|
||||
public int readerIndex() {
|
||||
return readerIndex;
|
||||
}
|
||||
|
||||
public void readerIndex(int readerIndex) {
|
||||
if (readerIndex < 0 || readerIndex > writerIndex) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
this.readerIndex = readerIndex;
|
||||
}
|
||||
|
||||
public int writerIndex() {
|
||||
return writerIndex;
|
||||
}
|
||||
|
||||
public void writerIndex(int writerIndex) {
|
||||
if (writerIndex < readerIndex || writerIndex > capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
this.writerIndex = writerIndex;
|
||||
}
|
||||
|
||||
public void setIndex(int readerIndex, int writerIndex) {
|
||||
if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
this.readerIndex = readerIndex;
|
||||
this.writerIndex = writerIndex;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
readerIndex = writerIndex = 0;
|
||||
}
|
||||
|
||||
public boolean readable() {
|
||||
return readableBytes() > 0;
|
||||
}
|
||||
|
||||
public boolean writable() {
|
||||
return writableBytes() > 0;
|
||||
}
|
||||
|
||||
public int readableBytes() {
|
||||
return writerIndex - readerIndex;
|
||||
}
|
||||
|
||||
public int writableBytes() {
|
||||
return capacity() - writerIndex;
|
||||
}
|
||||
|
||||
public void markReaderIndex() {
|
||||
markedReaderIndex = readerIndex;
|
||||
}
|
||||
|
||||
public void resetReaderIndex() {
|
||||
readerIndex(markedReaderIndex);
|
||||
}
|
||||
|
||||
public void markWriterIndex() {
|
||||
markedWriterIndex = writerIndex;
|
||||
}
|
||||
|
||||
public void resetWriterIndex() {
|
||||
writerIndex = markedWriterIndex;
|
||||
}
|
||||
|
||||
public void discardReadBytes() {
|
||||
if (readerIndex == 0) {
|
||||
return;
|
||||
}
|
||||
setBytes(0, this, readerIndex, writerIndex - readerIndex);
|
||||
writerIndex -= readerIndex;
|
||||
markedReaderIndex = Math.max(markedReaderIndex - readerIndex, 0);
|
||||
markedWriterIndex = Math.max(markedWriterIndex - readerIndex, 0);
|
||||
readerIndex = 0;
|
||||
}
|
||||
|
||||
public void getBytes(int index, byte[] dst) {
|
||||
getBytes(index, dst, 0, dst.length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ChannelBuffer dst) {
|
||||
getBytes(index, dst, dst.readerIndex(), dst.readableBytes());
|
||||
}
|
||||
|
||||
public void setBytes(int index, byte[] src) {
|
||||
setBytes(index, src, 0, src.length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ChannelBuffer src) {
|
||||
setBytes(index, src, src.readerIndex(), src.readableBytes());
|
||||
}
|
||||
|
||||
public byte readByte() {
|
||||
if (readerIndex == writerIndex) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return getByte(readerIndex ++);
|
||||
}
|
||||
|
||||
public short readShort() {
|
||||
checkReadableBytes(2);
|
||||
short v = getShort(readerIndex);
|
||||
readerIndex += 2;
|
||||
return v;
|
||||
}
|
||||
|
||||
public int readMedium() {
|
||||
checkReadableBytes(3);
|
||||
int v = getMedium(readerIndex);
|
||||
readerIndex += 3;
|
||||
return v;
|
||||
}
|
||||
|
||||
public int readInt() {
|
||||
checkReadableBytes(4);
|
||||
int v = getInt(readerIndex);
|
||||
readerIndex += 4;
|
||||
return v;
|
||||
}
|
||||
|
||||
public long readLong() {
|
||||
checkReadableBytes(8);
|
||||
long v = getLong(readerIndex);
|
||||
readerIndex += 8;
|
||||
return v;
|
||||
}
|
||||
|
||||
public ChannelBuffer readBytes() {
|
||||
return readBytes(readableBytes());
|
||||
}
|
||||
|
||||
public ChannelBuffer readBytes(int length) {
|
||||
checkReadableBytes(length);
|
||||
if (length == 0) {
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
ChannelBuffer buf = ChannelBuffers.buffer(length);
|
||||
buf.writeBytes(this, readerIndex, length);
|
||||
readerIndex += length;
|
||||
return buf;
|
||||
}
|
||||
|
||||
public ChannelBuffer readBytes(ChannelBufferIndexFinder endIndexFinder) {
|
||||
int endIndex = indexOf(readerIndex, writerIndex, endIndexFinder);
|
||||
if (endIndex < 0) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return readBytes(endIndex);
|
||||
}
|
||||
|
||||
public void readBytes(byte[] dst, int dstIndex, int length) {
|
||||
checkReadableBytes(length);
|
||||
getBytes(readerIndex, dst, dstIndex, length);
|
||||
readerIndex += length;
|
||||
}
|
||||
|
||||
public void readBytes(byte[] dst) {
|
||||
readBytes(dst, 0, dst.length);
|
||||
}
|
||||
|
||||
public void readBytes(ChannelBuffer dst) {
|
||||
readBytes(dst, dst.writableBytes());
|
||||
}
|
||||
|
||||
public void readBytes(ChannelBuffer dst, int length) {
|
||||
readBytes(dst, dst.writerIndex(), length);
|
||||
dst.writerIndex(dst.writerIndex() + length);
|
||||
}
|
||||
|
||||
public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
|
||||
checkReadableBytes(length);
|
||||
getBytes(readerIndex, dst, dstIndex, length);
|
||||
readerIndex += length;
|
||||
}
|
||||
|
||||
public void readBytes(ByteBuffer dst) {
|
||||
int length = dst.remaining();
|
||||
checkReadableBytes(length);
|
||||
getBytes(readerIndex, dst);
|
||||
readerIndex += length;
|
||||
}
|
||||
|
||||
public int readBytes(GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
checkReadableBytes(length);
|
||||
int readBytes = getBytes(readerIndex, out, length);
|
||||
readerIndex += readBytes;
|
||||
return readBytes;
|
||||
}
|
||||
|
||||
public void readBytes(OutputStream out, int length) throws IOException {
|
||||
checkReadableBytes(length);
|
||||
getBytes(readerIndex, out, length);
|
||||
readerIndex += length;
|
||||
}
|
||||
|
||||
public void skipBytes(int length) {
|
||||
int newReaderIndex = readerIndex + length;
|
||||
if (newReaderIndex > writerIndex) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
readerIndex = newReaderIndex;
|
||||
}
|
||||
|
||||
public int skipBytes(ChannelBufferIndexFinder firstIndexFinder) {
|
||||
int oldReaderIndex = readerIndex;
|
||||
int newReaderIndex = indexOf(oldReaderIndex, writerIndex, firstIndexFinder);
|
||||
if (newReaderIndex < 0) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
readerIndex(newReaderIndex);
|
||||
return newReaderIndex - oldReaderIndex;
|
||||
}
|
||||
|
||||
public void writeByte(byte value) {
|
||||
setByte(writerIndex ++, value);
|
||||
}
|
||||
|
||||
public void writeShort(short value) {
|
||||
setShort(writerIndex, value);
|
||||
writerIndex += 2;
|
||||
}
|
||||
|
||||
public void writeMedium(int value) {
|
||||
setMedium(writerIndex, value);
|
||||
writerIndex += 3;
|
||||
}
|
||||
|
||||
public void writeInt(int value) {
|
||||
setInt(writerIndex, value);
|
||||
writerIndex += 4;
|
||||
}
|
||||
|
||||
public void writeLong(long value) {
|
||||
setLong(writerIndex, value);
|
||||
writerIndex += 8;
|
||||
}
|
||||
|
||||
public void writeBytes(byte[] src, int srcIndex, int length) {
|
||||
setBytes(writerIndex, src, srcIndex, length);
|
||||
writerIndex += length;
|
||||
}
|
||||
|
||||
public void writeBytes(byte[] src) {
|
||||
writeBytes(src, 0, src.length);
|
||||
}
|
||||
|
||||
public void writeBytes(ChannelBuffer src) {
|
||||
writeBytes(src, src.readableBytes());
|
||||
}
|
||||
|
||||
public void writeBytes(ChannelBuffer src, int length) {
|
||||
writeBytes(src, src.readerIndex(), length);
|
||||
src.readerIndex(src.readerIndex() + length);
|
||||
}
|
||||
|
||||
public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
|
||||
setBytes(writerIndex, src, srcIndex, length);
|
||||
writerIndex += length;
|
||||
}
|
||||
|
||||
public void writeBytes(ByteBuffer src) {
|
||||
int length = src.remaining();
|
||||
setBytes(writerIndex, src);
|
||||
writerIndex += length;
|
||||
}
|
||||
|
||||
public void writeBytes(InputStream in, int length)
|
||||
throws IOException {
|
||||
setBytes(writerIndex, in, length);
|
||||
writerIndex += length;
|
||||
}
|
||||
|
||||
public int writeBytes(ScatteringByteChannel in, int length)
|
||||
throws IOException {
|
||||
int writtenBytes = setBytes(writerIndex, in, length);
|
||||
writerIndex += writtenBytes;
|
||||
return writtenBytes;
|
||||
}
|
||||
|
||||
public void writePlaceholder(int length) {
|
||||
if (length == 0) {
|
||||
return;
|
||||
}
|
||||
if (length < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"length must be 0 or greater than 0.");
|
||||
}
|
||||
int nLong = length >>> 3;
|
||||
int nBytes = length & 7;
|
||||
for (int i = nLong; i > 0; i --) {
|
||||
writeLong(0);
|
||||
}
|
||||
if (nBytes == 4) {
|
||||
writeInt(0);
|
||||
} else if (nBytes < 4) {
|
||||
for (int i = nBytes; i > 0; i --) {
|
||||
writeByte((byte) 0);
|
||||
}
|
||||
} else {
|
||||
writeInt(0);
|
||||
for (int i = nBytes - 4; i > 0; i --) {
|
||||
writeByte((byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelBuffer copy() {
|
||||
return copy(readerIndex, readableBytes());
|
||||
}
|
||||
|
||||
public ChannelBuffer slice() {
|
||||
return slice(readerIndex, readableBytes());
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBuffer() {
|
||||
return toByteBuffer(readerIndex, readableBytes());
|
||||
}
|
||||
|
||||
public ByteBuffer[] toByteBuffers() {
|
||||
return toByteBuffers(readerIndex, readableBytes());
|
||||
}
|
||||
|
||||
public ByteBuffer[] toByteBuffers(int index, int length) {
|
||||
return new ByteBuffer[] { toByteBuffer(index, length) };
|
||||
}
|
||||
|
||||
public int indexOf(int fromIndex, int toIndex, byte value) {
|
||||
return ChannelBuffers.indexOf(this, fromIndex, toIndex, value);
|
||||
}
|
||||
|
||||
public int indexOf(int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
|
||||
return ChannelBuffers.indexOf(this, fromIndex, toIndex, indexFinder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (hashCode != 0) {
|
||||
return hashCode;
|
||||
}
|
||||
return hashCode = ChannelBuffers.hashCode(this);
|
||||
}
|
||||
|
||||
protected void clearHashCode() {
|
||||
hashCode = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof ChannelBuffer)) {
|
||||
return false;
|
||||
}
|
||||
return ChannelBuffers.equals(this, (ChannelBuffer) o);
|
||||
}
|
||||
|
||||
public int compareTo(ChannelBuffer that) {
|
||||
return ChannelBuffers.compare(this, that);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + '(' +
|
||||
"ridx=" + readerIndex + ", " +
|
||||
"widx=" + writerIndex + ", " +
|
||||
"cap=" + capacity() +
|
||||
')';
|
||||
}
|
||||
|
||||
protected void checkReadableBytes(int minimumReadableBytes) {
|
||||
if (readableBytes() < minimumReadableBytes) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public class BigEndianHeapChannelBuffer extends HeapChannelBuffer {
|
||||
|
||||
public BigEndianHeapChannelBuffer(int length) {
|
||||
super(length);
|
||||
}
|
||||
|
||||
public BigEndianHeapChannelBuffer(byte[] array) {
|
||||
super(array);
|
||||
}
|
||||
|
||||
private BigEndianHeapChannelBuffer(byte[] array, int readerIndex, int writerIndex) {
|
||||
super(array, readerIndex, writerIndex);
|
||||
}
|
||||
|
||||
public ByteOrder order() {
|
||||
return ByteOrder.BIG_ENDIAN;
|
||||
}
|
||||
|
||||
public short getShort(int index) {
|
||||
return (short) (array[index] << 8 | array[index+1] & 0xFF);
|
||||
}
|
||||
|
||||
public int getMedium(int index) {
|
||||
return (array[index] & 0xff) << 16 |
|
||||
(array[index+1] & 0xff) << 8 |
|
||||
(array[index+2] & 0xff) << 0;
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
return (array[index] & 0xff) << 24 |
|
||||
(array[index+1] & 0xff) << 16 |
|
||||
(array[index+2] & 0xff) << 8 |
|
||||
(array[index+3] & 0xff) << 0;
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
return ((long) array[index] & 0xff) << 56 |
|
||||
((long) array[index+1] & 0xff) << 48 |
|
||||
((long) array[index+2] & 0xff) << 40 |
|
||||
((long) array[index+3] & 0xff) << 32 |
|
||||
((long) array[index+4] & 0xff) << 24 |
|
||||
((long) array[index+5] & 0xff) << 16 |
|
||||
((long) array[index+6] & 0xff) << 8 |
|
||||
((long) array[index+7] & 0xff) << 0;
|
||||
}
|
||||
|
||||
public void setShort(int index, short value) {
|
||||
array[index ] = (byte) (value >>> 8);
|
||||
array[index+1] = (byte) (value >>> 0);
|
||||
}
|
||||
|
||||
public void setMedium(int index, int value) {
|
||||
array[index ] = (byte) (value >>> 16);
|
||||
array[index+1] = (byte) (value >>> 8);
|
||||
array[index+2] = (byte) (value >>> 0);
|
||||
}
|
||||
|
||||
public void setInt(int index, int value) {
|
||||
array[index ] = (byte) (value >>> 24);
|
||||
array[index+1] = (byte) (value >>> 16);
|
||||
array[index+2] = (byte) (value >>> 8);
|
||||
array[index+3] = (byte) (value >>> 0);
|
||||
}
|
||||
|
||||
public void setLong(int index, long value) {
|
||||
array[index ] = (byte) (value >>> 56);
|
||||
array[index+1] = (byte) (value >>> 48);
|
||||
array[index+2] = (byte) (value >>> 40);
|
||||
array[index+3] = (byte) (value >>> 32);
|
||||
array[index+4] = (byte) (value >>> 24);
|
||||
array[index+5] = (byte) (value >>> 16);
|
||||
array[index+6] = (byte) (value >>> 8);
|
||||
array[index+7] = (byte) (value >>> 0);
|
||||
}
|
||||
|
||||
public ChannelBuffer duplicate() {
|
||||
return new BigEndianHeapChannelBuffer(array, readerIndex(), writerIndex());
|
||||
}
|
||||
|
||||
public ChannelBuffer copy(int index, int length) {
|
||||
if (index < 0 || length < 0 || index + length > array.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
byte[] copiedArray = new byte[length];
|
||||
System.arraycopy(array, index, copiedArray, 0, length);
|
||||
return new BigEndianHeapChannelBuffer(copiedArray);
|
||||
}
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
|
||||
public class ByteBufferBackedChannelBuffer extends AbstractChannelBuffer {
|
||||
|
||||
private final ByteBuffer buffer;
|
||||
private final int capacity;
|
||||
|
||||
public ByteBufferBackedChannelBuffer(ByteBuffer buffer) {
|
||||
if (buffer == null) {
|
||||
throw new NullPointerException("buffer");
|
||||
}
|
||||
|
||||
this.buffer = buffer.slice();
|
||||
capacity = buffer.remaining();
|
||||
writerIndex(capacity);
|
||||
}
|
||||
|
||||
private ByteBufferBackedChannelBuffer(ByteBufferBackedChannelBuffer buffer) {
|
||||
this.buffer = buffer.buffer;
|
||||
capacity = buffer.capacity;
|
||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||
}
|
||||
|
||||
public ByteOrder order() {
|
||||
return buffer.order();
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public byte getByte(int index) {
|
||||
return buffer.get(index);
|
||||
}
|
||||
|
||||
public short getShort(int index) {
|
||||
return buffer.getShort(index);
|
||||
}
|
||||
|
||||
public int getMedium(int index) {
|
||||
return (getByte(index) & 0xff) << 16 |
|
||||
(getByte(index+1) & 0xff) << 8 |
|
||||
(getByte(index+2) & 0xff) << 0;
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
return buffer.getInt(index);
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
return buffer.getLong(index);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
|
||||
if (dst instanceof ByteBufferBackedChannelBuffer) {
|
||||
ByteBufferBackedChannelBuffer bbdst = (ByteBufferBackedChannelBuffer) dst;
|
||||
ByteBuffer data = bbdst.buffer.duplicate();
|
||||
|
||||
data.limit(dstIndex + length).position(dstIndex);
|
||||
getBytes(index, data);
|
||||
} else if (buffer.hasArray()) {
|
||||
dst.setBytes(dstIndex, buffer.array(), index + buffer.arrayOffset(), length);
|
||||
} else {
|
||||
dst.setBytes(dstIndex, this, index, length);
|
||||
}
|
||||
}
|
||||
|
||||
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
ByteBuffer data = buffer.duplicate();
|
||||
try {
|
||||
data.limit(index + length).position(index);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
data.get(dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ByteBuffer dst) {
|
||||
ByteBuffer data = buffer.duplicate();
|
||||
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
|
||||
try {
|
||||
data.limit(index + bytesToCopy).position(index);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
dst.put(data);
|
||||
}
|
||||
|
||||
public void setByte(int index, byte value) {
|
||||
buffer.put(index, value);
|
||||
}
|
||||
|
||||
public void setShort(int index, short value) {
|
||||
buffer.putShort(index, value);
|
||||
}
|
||||
|
||||
public void setMedium(int index, int value) {
|
||||
setByte(index, (byte) (value >>> 16));
|
||||
setByte(index+1, (byte) (value >>> 8));
|
||||
setByte(index+2, (byte) (value >>> 0));
|
||||
}
|
||||
|
||||
public void setInt(int index, int value) {
|
||||
buffer.putInt(index, value);
|
||||
}
|
||||
|
||||
public void setLong(int index, long value) {
|
||||
buffer.putLong(index, value);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
|
||||
if (src instanceof ByteBufferBackedChannelBuffer) {
|
||||
ByteBufferBackedChannelBuffer bbsrc = (ByteBufferBackedChannelBuffer) src;
|
||||
ByteBuffer data = bbsrc.buffer.duplicate();
|
||||
|
||||
data.limit(srcIndex + length).position(srcIndex);
|
||||
setBytes(index, data);
|
||||
} else if (buffer.hasArray()) {
|
||||
src.getBytes(srcIndex, buffer.array(), index + buffer.arrayOffset(), length);
|
||||
} else {
|
||||
src.getBytes(srcIndex, this, index, length);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
ByteBuffer data = buffer.duplicate();
|
||||
data.limit(index + length).position(index);
|
||||
data.put(src, srcIndex, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ByteBuffer src) {
|
||||
ByteBuffer data = buffer.duplicate();
|
||||
data.limit(index + src.remaining()).position(index);
|
||||
data.put(src);
|
||||
}
|
||||
|
||||
public void getBytes(int index, OutputStream out, int length) throws IOException {
|
||||
if (length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!buffer.isReadOnly() && buffer.hasArray()) {
|
||||
out.write(
|
||||
buffer.array(),
|
||||
index + buffer.arrayOffset(),
|
||||
length);
|
||||
} else {
|
||||
byte[] tmp = new byte[length];
|
||||
((ByteBuffer) buffer.duplicate().position(index)).get(tmp);
|
||||
out.write(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
||||
if (length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return out.write((ByteBuffer) buffer.duplicate().position(index).limit(index + length));
|
||||
}
|
||||
|
||||
public void setBytes(int index, InputStream in, int length)
|
||||
throws IOException {
|
||||
if (length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!buffer.isReadOnly() && buffer.hasArray()) {
|
||||
index += buffer.arrayOffset();
|
||||
do {
|
||||
int readBytes = in.read(
|
||||
buffer.array(), index, length);
|
||||
if (readBytes < 0) {
|
||||
throw new EOFException();
|
||||
}
|
||||
index += readBytes;
|
||||
length -= readBytes;
|
||||
} while (length > 0);
|
||||
} else {
|
||||
byte[] tmp = new byte[length];
|
||||
for (int i = 0; i < tmp.length;) {
|
||||
int readBytes = in.read(tmp, i, tmp.length - i);
|
||||
if (readBytes < 0) {
|
||||
throw new EOFException();
|
||||
}
|
||||
i += readBytes;
|
||||
}
|
||||
((ByteBuffer) buffer.duplicate().position(index)).get(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length)
|
||||
throws IOException {
|
||||
return in.read((ByteBuffer) buffer.duplicate().limit(index + length).position(index));
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBuffer(int index, int length) {
|
||||
if (index == 0 && length == capacity()) {
|
||||
return buffer.duplicate();
|
||||
} else {
|
||||
return ((ByteBuffer) buffer.duplicate().position(index).limit(index + length)).slice();
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
if (index == 0 && length == capacity()) {
|
||||
return duplicate();
|
||||
} else {
|
||||
return new ByteBufferBackedChannelBuffer(
|
||||
((ByteBuffer) buffer.duplicate().position(index).limit(index + length)));
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelBuffer duplicate() {
|
||||
return new ByteBufferBackedChannelBuffer(this);
|
||||
}
|
||||
|
||||
public ChannelBuffer copy(int index, int length) {
|
||||
ByteBuffer src = (ByteBuffer) buffer.duplicate().position(index).limit(index + length);
|
||||
ByteBuffer dst = buffer.isDirect() ? ByteBuffer.allocateDirect(length) : ByteBuffer.allocate(length);
|
||||
dst.put(src);
|
||||
dst.clear();
|
||||
return new ByteBufferBackedChannelBuffer(dst);
|
||||
}
|
||||
}
|
516
src/main/java/net/gleamynode/netty/buffer/ChannelBuffer.java
Normal file
516
src/main/java/net/gleamynode/netty/buffer/ChannelBuffer.java
Normal file
@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
/**
|
||||
* A random and sequential accessible sequence of zero or more bytes (octets).
|
||||
* This interface provides an abstract view for one or more primitive byte
|
||||
* arrays ({@code byte[]}) and {@linkplain ByteBuffer NIO buffers}.
|
||||
*
|
||||
* <h3>Creation of a buffer</h3>
|
||||
*
|
||||
* It is common for a user to create a new buffer using {@link ChannelBuffers}
|
||||
* utility class rather than calling an individual implementation's constructor.
|
||||
*
|
||||
* <h3>Random Access Indexing</h3>
|
||||
*
|
||||
* Just like an ordinary primitive byte array, {@link ChannelBuffer} uses
|
||||
* <a href="http://en.wikipedia.org/wiki/Index_(information_technology)#Array_element_identifier">zero-based indexing</a>.
|
||||
* It means the index of the first byte is always {@code 0} and the index of
|
||||
* the last byte is always {@link #capacity() capacity - 1}. For example, to
|
||||
* iterate all bytes of a buffer, you can do the following, regardless of
|
||||
* its internal implementation:
|
||||
*
|
||||
* <pre>
|
||||
* ChannelBuffer buffer = ...;
|
||||
* for (int i = 0; i < buffer.capacity(); i ++</strong>) {
|
||||
* byte b = array.getByte(i);
|
||||
* System.out.println((char) b);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <h3>Sequential Access Indexing</h3>
|
||||
*
|
||||
* {@link ChannelBuffer} provides two pointer variables to support sequential
|
||||
* read and write operations - {@link #readerIndex() readerIndex} for a read
|
||||
* operation and {@link #writerIndex() writerIndex} for a write operation
|
||||
* respectively. The following diagram shows how a buffer is segmented into
|
||||
* three areas by the two pointers:
|
||||
*
|
||||
* <pre>
|
||||
* +-------------------+------------------+------------------+
|
||||
* | discardable bytes | readable bytes | writable space |
|
||||
* | | (CONTENT) | |
|
||||
* +-------------------+------------------+------------------+
|
||||
* | | | |
|
||||
* 0 <= readerIndex <= writerIndex <= capacity
|
||||
* </pre>
|
||||
*
|
||||
* <h4>Readable bytes (the actual 'content' of the buffer)</h4>
|
||||
*
|
||||
* This segment, so called 'the <strong>content</strong> of a buffer', is where
|
||||
* the actual data is stored. Any operation whose name starts with
|
||||
* {@code read} or {@code skip} will get or skip the data at the current
|
||||
* {@link #readerIndex() readerIndex} and increase it by the number of read
|
||||
* bytes. If the argument of the read operation is also a {@link ChannelBuffer}
|
||||
* and no start index is specified, the specified buffer's
|
||||
* {@link #readerIndex() readerIndex} is increased together.
|
||||
* <p>
|
||||
* If there's not enough content left, {@link IndexOutOfBoundsException} is
|
||||
* raised. The default value of newly allocated, wrapped or copied buffer's
|
||||
* {@link #readerIndex() readerIndex} is {@code 0}.
|
||||
*
|
||||
* <pre>
|
||||
* // Iterates the readable bytes of a buffer.
|
||||
* ChannelBuffer buffer = ...;
|
||||
* while (buffer.readable()) {
|
||||
* System.out.println(buffer.readByte());
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <h4>Writable space</h4>
|
||||
*
|
||||
* This segment is a undefined space which needs to be filled. Any operation
|
||||
* whose name ends with {@code write} will write the data at the current
|
||||
* {@link #writerIndex() writerIndex} and increase it by the number of written
|
||||
* bytes. If the argument of the write operation is also a {@link ChannelBuffer},
|
||||
* and no start index is specified, the specified buffer's
|
||||
* {@link #readerIndex() readerIndex} is increased together.
|
||||
* <p>
|
||||
* If there's not enough writable space left, {@link IndexOutOfBoundsException}
|
||||
* is raised. The default value of newly allocated buffer's
|
||||
* {@link #writerIndex() writerIndex} is {@code 0}. The default value of
|
||||
* wrapped or copied buffer's {@link #writerIndex() writerIndex} is the
|
||||
* {@link #capacity() capacity} of the buffer.
|
||||
*
|
||||
* <pre>
|
||||
* // Fills the writable space of a buffer with random integers.
|
||||
* ChannelBuffer buffer = ...;
|
||||
* while (buffer.writableBytes() >= 4) {
|
||||
* buffer.writeInt(random.nextInt());
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <h4>Discardable bytes</h4>
|
||||
*
|
||||
* This segment contains the bytes which were read already by a read operation.
|
||||
* Initially, the size of this segment is {@code 0}, but its size increases up
|
||||
* to the {@link #writerIndex() writerIndex} as read operations are executed.
|
||||
* The read bytes can be discarded by calling {@link #discardReadBytes()} to
|
||||
* reclaim unused area as depicted by the following diagram:
|
||||
*
|
||||
* <pre>
|
||||
* BEFORE discardReadBytes()
|
||||
*
|
||||
* +-------------------+------------------+------------------+
|
||||
* | discardable bytes | readable bytes | writable space |
|
||||
* | | (CONTENT) | |
|
||||
* +-------------------+------------------+------------------+
|
||||
* | | | |
|
||||
* 0 <= readerIndex <= writerIndex <= capacity
|
||||
*
|
||||
*
|
||||
* AFTER discardReadBytes()
|
||||
*
|
||||
* +------------------+--------------------------------------+
|
||||
* | readable bytes | writable space (got more space) |
|
||||
* | (CONTENT) | |
|
||||
* +------------------+--------------------------------------+
|
||||
* | | |
|
||||
* readerIndex (0) <= writerIndex (decreased) <= capacity
|
||||
* </pre>
|
||||
*
|
||||
* <h4>Clearing the buffer indexes</h4>
|
||||
*
|
||||
* You can set both {@link #readerIndex() readerIndex} and
|
||||
* {@link #writerIndex() writerIndex} to {@code 0} by calling {@link #clear()}.
|
||||
* It doesn't clear the buffer content (e.g. filling with {@code 0}) but just
|
||||
* clears the two pointers. Please also note that the semantic of this
|
||||
* operation is different from {@link ByteBuffer#clear()}.
|
||||
*
|
||||
* <pre>
|
||||
* BEFORE clear()
|
||||
*
|
||||
* +-------------------+------------------+------------------+
|
||||
* | discardable bytes | readable bytes | writable space |
|
||||
* | | (CONTENT) | |
|
||||
* +-------------------+------------------+------------------+
|
||||
* | | | |
|
||||
* 0 <= readerIndex <= writerIndex <= capacity
|
||||
*
|
||||
*
|
||||
* AFTER clear()
|
||||
*
|
||||
* +---------------------------------------------------------+
|
||||
* | writable space (got more space) |
|
||||
* +---------------------------------------------------------+
|
||||
* | |
|
||||
* 0 = readerIndex = writerIndex <= capacity
|
||||
* </pre>
|
||||
*
|
||||
* <h3>Search operations</h3>
|
||||
*
|
||||
* Various {@code indexOf()} methods help you locate an index of a value which
|
||||
* meets a certain criteria. Complicated dynamic sequential search can be done
|
||||
* with {@link ChannelBufferIndexFinder} as well as simple static single byte
|
||||
* search.
|
||||
*
|
||||
* <h3>Mark and reset</h3>
|
||||
*
|
||||
* There are two marker indexes in every buffer. One is for storing
|
||||
* {@link #readerIndex() readerIndex} and the other is for storing
|
||||
* {@link #writerIndex() writerIndex}. You can always reposition one of the
|
||||
* two indexes by calling a reset method. It works in a similar fashion to
|
||||
* the mark and reset methods in {@link InputStream} except that there's no
|
||||
* {@code readlimit}.
|
||||
*
|
||||
* <h3>Derived buffers</h3>
|
||||
*
|
||||
* You can create a view of an existing buffer by calling either
|
||||
* {@link #duplicate()}, {@link #slice()} or {@link #slice(int, int)}.
|
||||
* A derived buffer will have an independent {@link #readerIndex() readerIndex},
|
||||
* {@link #writerIndex() writerIndex} and marker indexes, while it shares
|
||||
* other internal data representation, just like a NIO {@link ByteBuffer} does.
|
||||
* <p>
|
||||
* In case a completely fresh copy of an existing buffer is required, please
|
||||
* call {@link #copy()} method instead.
|
||||
*
|
||||
* <h3>Conversion to existing JDK types</h3>
|
||||
*
|
||||
* Various {@link #toByteBuffer()} and {@link #toByteBuffers()} methods convert
|
||||
* a {@link ChannelBuffer} into one or more NIO buffers. These methods avoid
|
||||
* buffer allocation and memory copy whenever possible, but there's no
|
||||
* guarantee that memory copy will not be involved or that an explicit memory
|
||||
* copy will be involved.
|
||||
* <p>
|
||||
* In case you need to convert a {@link ChannelBuffer} into
|
||||
* an {@link InputStream} or an {@link OutputStream}, please refer to
|
||||
* {@link ChannelBufferInputStream} and {@link ChannelBufferOutputStream}.
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
*/
|
||||
public interface ChannelBuffer extends Comparable<ChannelBuffer> {
|
||||
|
||||
/**
|
||||
* A buffer whose capacity is {@code 0}.
|
||||
*/
|
||||
static ChannelBuffer EMPTY_BUFFER = new BigEndianHeapChannelBuffer(0);
|
||||
|
||||
/**
|
||||
* Returns the number of bytes (octets) this buffer can contain.
|
||||
*/
|
||||
int capacity();
|
||||
|
||||
/**
|
||||
* Returns the <a href="http://en.wikipedia.org/wiki/Endianness">endianness</a>
|
||||
* of this buffer.
|
||||
*/
|
||||
ByteOrder order();
|
||||
|
||||
/**
|
||||
* Returns the {@code readerIndex} of this buffer.
|
||||
*/
|
||||
int readerIndex();
|
||||
|
||||
/**
|
||||
* Sets the {@code readerIndex} of this buffer.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if the specified {@code readerIndex} is less than 0 or
|
||||
* greater than {@code writerIndex}
|
||||
*/
|
||||
void readerIndex(int readerIndex);
|
||||
|
||||
/**
|
||||
* Returns the {@code writerIndex} of this buffer.
|
||||
*/
|
||||
int writerIndex();
|
||||
|
||||
/**
|
||||
* Sets the {@code writerIndex} of this buffer.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if the specified {@code writerIndex} is less than
|
||||
* {@code readerIndex} or greater than {@code capacity}
|
||||
*/
|
||||
void writerIndex(int writerIndex);
|
||||
|
||||
/**
|
||||
* Sets the {@code readerIndex} and {@code writerIndex} of this buffer
|
||||
* in one shot. This method is useful because you don't need to worry
|
||||
* about the invocation order of {@link #readerIndex(int)} and {@link #writerIndex(int)}
|
||||
* methods. For example, the following code will fail:
|
||||
*
|
||||
* <pre>
|
||||
* // Create a buffer whose readerIndex, writerIndex and capacity are
|
||||
* // 0, 0 and 8 respectively.
|
||||
* ChannelBuffer buf = ChannelBuffers.buffer(8);
|
||||
*
|
||||
* // IndexOutOfBoundsException is thrown because the specified
|
||||
* // readerIndex (2) cannot be greater than the current writerIndex (0).
|
||||
* buf.readerIndex(2);
|
||||
* buf.writerIndex(4);
|
||||
* </pre>
|
||||
*
|
||||
* The following code will also fail:
|
||||
*
|
||||
* <pre>
|
||||
* // Create a buffer whose readerIndex, writerIndex and capacity are
|
||||
* // 0, 8 and 8 respectively.
|
||||
* ChannelBuffer buf = ChannelBuffers.wrappedBuffer(new byte[8]);
|
||||
*
|
||||
* // readerIndex becomes 8.
|
||||
* buf.readLong();
|
||||
*
|
||||
* // IndexOutOfBoundsException is thrown because the specified
|
||||
* // writerIndex (4) cannot be less than the current readerIndex (8).
|
||||
* buf.writerIndex(4);
|
||||
* buf.readerIndex(2);
|
||||
* </pre>
|
||||
*
|
||||
* By contrast, {@link #setIndex(int, int)} guarantees that it never
|
||||
* throws an {@link IndexOutOfBoundsException} as long as the specified
|
||||
* indexes meets all constraints, regardless what the current index values
|
||||
* of the buffer are:
|
||||
*
|
||||
* <pre>
|
||||
* // No matter what the current state of the buffer is, the following
|
||||
* // call always succeeds as long as the capacity of the buffer is not
|
||||
* // less than 4.
|
||||
* buf.setIndex(2, 4);
|
||||
* </pre>
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if the specified {@code readerIndex} is less than 0,
|
||||
* if the specified {@code writerIndex} is less than the specified
|
||||
* {@code readerIndex} or if the specified {@code writerIndex} is
|
||||
* greater than {@code capacity}
|
||||
*/
|
||||
void setIndex(int readerIndex, int writerIndex);
|
||||
|
||||
/**
|
||||
* Returns the number of readable bytes which equals to
|
||||
* {@code (writerIndex - readerIndex)}.
|
||||
*/
|
||||
int readableBytes();
|
||||
|
||||
/**
|
||||
* Returns the number of writable bytes which equals to
|
||||
* {@code (capacity - writerIndex)}.
|
||||
*/
|
||||
int writableBytes();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if {@link #readableBytes() readableBytes}
|
||||
* if greater than {@code 0}.
|
||||
*/
|
||||
boolean readable();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if {@link #writableBytes() writableBytes}
|
||||
* if greater than {@code 0}.
|
||||
*/
|
||||
boolean writable();
|
||||
|
||||
/**
|
||||
* Sets the {@code readerIndex} and {@code writerIndex} of this buffer to
|
||||
* {@code 0}.
|
||||
* This method is identical to {@link #setIndex(int, int) setIndex(0, 0)}.
|
||||
* <p>
|
||||
* Please note that the behavior of this method is different
|
||||
* from that of NIO {@link ByteBuffer}, which sets the {@code limit} to
|
||||
* the {@code capacity}.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Marks the current {@code readerIndex} in this buffer. You can restore
|
||||
* the marked {@code readerIndex} by calling {@link #resetReaderIndex()}.
|
||||
* The initial value of the marked {@code readerIndex} is always {@code 0}.
|
||||
*/
|
||||
void markReaderIndex();
|
||||
|
||||
/**
|
||||
* Repositions the current {@code readerIndex} to the marked {@code readerIndex}
|
||||
* in this buffer.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if the current {@code writerIndex} is less than the marked
|
||||
* {@code readerIndex}
|
||||
*/
|
||||
void resetReaderIndex();
|
||||
|
||||
/**
|
||||
* Marks the current {@code writerIndex} in this buffer. You can restore
|
||||
* the marked {@code writerIndex} by calling {@link #resetWriterIndex()}.
|
||||
* The initial value of the marked {@code writerIndex} is always {@code 0}.
|
||||
*/
|
||||
void markWriterIndex();
|
||||
|
||||
/**
|
||||
* Repositions the current {@code writerIndex} to the marked {@code writerIndex}
|
||||
* in this buffer.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if the current {@code readerIndex} is greater than the marked
|
||||
* {@code writerIndex}
|
||||
*/
|
||||
void resetWriterIndex();
|
||||
|
||||
/**
|
||||
* Discards the bytes between the 0th index and {@code readerIndex}.
|
||||
* It moves the bytes between {@code readerIndex} and {@code writerIndex}
|
||||
* to the 0th index, and sets {@code readerIndex} and {@code writerIndex}
|
||||
* to {@code 0} and {@code oldWriterIndex - oldReaderIndex} respectively.
|
||||
* <p>
|
||||
* Please refer to the class documentation for more detailed explanation
|
||||
* with a diagram.
|
||||
*/
|
||||
void discardReadBytes();
|
||||
|
||||
byte getByte(int index);
|
||||
short getShort(int index);
|
||||
int getMedium(int index);
|
||||
int getInt(int index);
|
||||
long getLong(int index);
|
||||
|
||||
void getBytes(int index, ChannelBuffer dst);
|
||||
void getBytes(int index, ChannelBuffer dst, int dstIndex, int length);
|
||||
void getBytes(int index, byte[] dst);
|
||||
void getBytes(int index, byte[] dst, int dstIndex, int length);
|
||||
void getBytes(int index, ByteBuffer dst);
|
||||
void getBytes(int index, OutputStream out, int length) throws IOException;
|
||||
int getBytes(int index, GatheringByteChannel out, int length) throws IOException;
|
||||
|
||||
void setByte(int index, byte value);
|
||||
void setShort(int index, short value);
|
||||
void setMedium(int index, int value);
|
||||
void setInt(int index, int value);
|
||||
void setLong(int index, long value);
|
||||
|
||||
void setBytes(int index, ChannelBuffer src);
|
||||
void setBytes(int index, ChannelBuffer src, int srcIndex, int length);
|
||||
void setBytes(int index, byte[] src);
|
||||
void setBytes(int index, byte[] src, int srcIndex, int length);
|
||||
void setBytes(int index, ByteBuffer src);
|
||||
void setBytes(int index, InputStream in, int length) throws IOException;
|
||||
int setBytes(int index, ScatteringByteChannel in, int length) throws IOException;
|
||||
|
||||
byte readByte();
|
||||
short readShort();
|
||||
int readMedium();
|
||||
int readInt();
|
||||
long readLong();
|
||||
|
||||
ChannelBuffer readBytes();
|
||||
ChannelBuffer readBytes(int length);
|
||||
ChannelBuffer readBytes(ChannelBufferIndexFinder endIndexFinder);
|
||||
void readBytes(ChannelBuffer dst);
|
||||
void readBytes(ChannelBuffer dst, int length);
|
||||
void readBytes(ChannelBuffer dst, int dstIndex, int length);
|
||||
void readBytes(byte[] dst);
|
||||
void readBytes(byte[] dst, int dstIndex, int length);
|
||||
void readBytes(ByteBuffer dst);
|
||||
void readBytes(OutputStream out, int length) throws IOException;
|
||||
int readBytes(GatheringByteChannel out, int length) throws IOException;
|
||||
|
||||
void skipBytes(int length);
|
||||
int skipBytes(ChannelBufferIndexFinder firstIndexFinder);
|
||||
|
||||
void writeByte(byte value);
|
||||
void writeShort(short value);
|
||||
void writeMedium(int value);
|
||||
void writeInt(int value);
|
||||
void writeLong(long value);
|
||||
|
||||
void writeBytes(ChannelBuffer src);
|
||||
void writeBytes(ChannelBuffer src, int length);
|
||||
void writeBytes(ChannelBuffer src, int srcIndex, int length);
|
||||
void writeBytes(byte[] src);
|
||||
void writeBytes(byte[] src, int srcIndex, int length);
|
||||
void writeBytes(ByteBuffer src);
|
||||
void writeBytes(InputStream in, int length) throws IOException;
|
||||
int writeBytes(ScatteringByteChannel in, int length) throws IOException;
|
||||
|
||||
void writePlaceholder(int length);
|
||||
|
||||
int indexOf(int fromIndex, int toIndex, byte value);
|
||||
int indexOf(int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder);
|
||||
|
||||
ChannelBuffer copy();
|
||||
ChannelBuffer copy(int index, int length);
|
||||
ChannelBuffer slice();
|
||||
ChannelBuffer slice(int index, int length);
|
||||
ChannelBuffer duplicate();
|
||||
|
||||
ByteBuffer toByteBuffer();
|
||||
ByteBuffer toByteBuffer(int index, int length);
|
||||
ByteBuffer[] toByteBuffers();
|
||||
ByteBuffer[] toByteBuffers(int index, int length);
|
||||
|
||||
/**
|
||||
* Returns a hash code which was calculated from the content of this
|
||||
* buffer. If there's a byte array which is
|
||||
* {@linkplain #equals(Object) equal to} this array, both arrays should
|
||||
* return the same value.
|
||||
*/
|
||||
int hashCode();
|
||||
|
||||
/**
|
||||
* Determines if the content of the specified buffer is identical to the
|
||||
* content of this array. 'Identical' here means:
|
||||
* <ul>
|
||||
* <li>the size of the contents of the two buffers are same and</li>
|
||||
* <li>every single byte of the content of the two buffers are same.</li>
|
||||
* </ul>
|
||||
* Please note that it doesn't compare {@link #readerIndex()} nor
|
||||
* {@link #writerIndex()}. This method also returns {@code false} for
|
||||
* {@code null} and an object which is not an instance of
|
||||
* {@link ChannelBuffer} type.
|
||||
*/
|
||||
boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* Compares the content of the specified buffer to the content of this
|
||||
* buffer. Comparison is performed in the same manner with the string
|
||||
* comparison functions of various languages such as {@code strcmp},
|
||||
* {@code memcmp} and {@link String#compareTo(String)}.
|
||||
*/
|
||||
int compareTo(ChannelBuffer buffer);
|
||||
|
||||
/**
|
||||
* Returns the string representation of this buffer. This method doesn't
|
||||
* necessarily return the whole content of the buffer but returns
|
||||
* the values of the key properties such as {@link #readerIndex()},
|
||||
* {@link #writerIndex()} and {@link #capacity()}..
|
||||
*/
|
||||
String toString();
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.uses net.gleamynode.netty.buffer.ChannelBuffer
|
||||
*/
|
||||
public interface ChannelBufferIndexFinder {
|
||||
|
||||
boolean find(ChannelBuffer buffer, int guessedIndex);
|
||||
|
||||
static ChannelBufferIndexFinder NUL = new ChannelBufferIndexFinder() {
|
||||
public boolean find(ChannelBuffer buffer, int guessedIndex) {
|
||||
return buffer.getByte(guessedIndex) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
static ChannelBufferIndexFinder NOT_NUL = new ChannelBufferIndexFinder() {
|
||||
public boolean find(ChannelBuffer buffer, int guessedIndex) {
|
||||
return buffer.getByte(guessedIndex) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
static ChannelBufferIndexFinder CR = new ChannelBufferIndexFinder() {
|
||||
public boolean find(ChannelBuffer buffer, int guessedIndex) {
|
||||
return buffer.getByte(guessedIndex) == '\r';
|
||||
}
|
||||
};
|
||||
|
||||
static ChannelBufferIndexFinder NOT_CR = new ChannelBufferIndexFinder() {
|
||||
public boolean find(ChannelBuffer buffer, int guessedIndex) {
|
||||
return buffer.getByte(guessedIndex) != '\r';
|
||||
}
|
||||
};
|
||||
|
||||
static ChannelBufferIndexFinder LF = new ChannelBufferIndexFinder() {
|
||||
public boolean find(ChannelBuffer buffer, int guessedIndex) {
|
||||
return buffer.getByte(guessedIndex) == '\n';
|
||||
}
|
||||
};
|
||||
|
||||
static ChannelBufferIndexFinder NOT_LF = new ChannelBufferIndexFinder() {
|
||||
public boolean find(ChannelBuffer buffer, int guessedIndex) {
|
||||
return buffer.getByte(guessedIndex) != '\n';
|
||||
}
|
||||
};
|
||||
|
||||
static ChannelBufferIndexFinder CRLF = new ChannelBufferIndexFinder() {
|
||||
public boolean find(ChannelBuffer buffer, int guessedIndex) {
|
||||
byte b = buffer.getByte(guessedIndex);
|
||||
return b == '\r' || b == '\n';
|
||||
}
|
||||
};
|
||||
|
||||
static ChannelBufferIndexFinder NOT_CRLF = new ChannelBufferIndexFinder() {
|
||||
public boolean find(ChannelBuffer buffer, int guessedIndex) {
|
||||
byte b = buffer.getByte(guessedIndex);
|
||||
return b != '\r' && b != '\n';
|
||||
}
|
||||
};
|
||||
|
||||
static ChannelBufferIndexFinder LINEAR_WHITESPACE = new ChannelBufferIndexFinder() {
|
||||
public boolean find(ChannelBuffer buffer, int guessedIndex) {
|
||||
byte b = buffer.getByte(guessedIndex);
|
||||
return b == ' ' || b == '\t';
|
||||
}
|
||||
};
|
||||
|
||||
static ChannelBufferIndexFinder NOT_LINEAR_WHITESPACE = new ChannelBufferIndexFinder() {
|
||||
public boolean find(ChannelBuffer buffer, int guessedIndex) {
|
||||
byte b = buffer.getByte(guessedIndex);
|
||||
return b != ' ' && b != '\t';
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @see ChannelBufferOutputStream
|
||||
* @apiviz.uses net.gleamynode.netty.buffer.ChannelBuffer
|
||||
*/
|
||||
public class ChannelBufferInputStream extends InputStream implements DataInput {
|
||||
|
||||
private final ChannelBuffer buffer;
|
||||
private final int startIndex;
|
||||
private final int endIndex;
|
||||
|
||||
public ChannelBufferInputStream(ChannelBuffer buffer) {
|
||||
this(buffer, buffer.readableBytes());
|
||||
}
|
||||
|
||||
public ChannelBufferInputStream(ChannelBuffer buffer, int length) {
|
||||
if (buffer == null) {
|
||||
throw new NullPointerException("buffer");
|
||||
}
|
||||
if (length > buffer.readableBytes()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
this.buffer = buffer;
|
||||
startIndex = buffer.readerIndex();
|
||||
endIndex = startIndex + length;
|
||||
buffer.markReaderIndex();
|
||||
}
|
||||
|
||||
public int readBytes() {
|
||||
return buffer.readerIndex() - startIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return endIndex - buffer.readerIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(int readlimit) {
|
||||
buffer.markReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (!buffer.readable()) {
|
||||
return -1;
|
||||
}
|
||||
return buffer.readByte() & 0xff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
int available = available();
|
||||
if (available == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = Math.min(available, len);
|
||||
buffer.readBytes(b, off, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
buffer.resetReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
if (n > Integer.MAX_VALUE) {
|
||||
return skipBytes(Integer.MAX_VALUE);
|
||||
} else {
|
||||
return skipBytes((int) n);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean readBoolean() throws IOException {
|
||||
int b = read();
|
||||
if (b < 0) {
|
||||
throw new EOFException();
|
||||
}
|
||||
return b != 0;
|
||||
}
|
||||
|
||||
public byte readByte() throws IOException {
|
||||
if (!buffer.readable()) {
|
||||
throw new EOFException();
|
||||
}
|
||||
return buffer.readByte();
|
||||
}
|
||||
|
||||
public char readChar() throws IOException {
|
||||
return (char) readShort();
|
||||
}
|
||||
|
||||
public double readDouble() throws IOException {
|
||||
return Double.longBitsToDouble(readLong());
|
||||
}
|
||||
|
||||
public float readFloat() throws IOException {
|
||||
return Float.intBitsToFloat(readInt());
|
||||
}
|
||||
|
||||
public void readFully(byte[] b) throws IOException {
|
||||
readFully(b, 0, b.length);
|
||||
}
|
||||
|
||||
public void readFully(byte[] b, int off, int len) throws IOException {
|
||||
checkAvailable(len);
|
||||
buffer.readBytes(b, off, len);
|
||||
}
|
||||
|
||||
public int readInt() throws IOException {
|
||||
checkAvailable(4);
|
||||
return buffer.readInt();
|
||||
}
|
||||
|
||||
private final StringBuilder lineBuf = new StringBuilder();
|
||||
|
||||
public String readLine() throws IOException {
|
||||
lineBuf.setLength(0);
|
||||
for (;;) {
|
||||
int b = read();
|
||||
if (b < 0 || b == '\n') {
|
||||
break;
|
||||
}
|
||||
|
||||
lineBuf.append((char) b);
|
||||
}
|
||||
|
||||
while (lineBuf.charAt(lineBuf.length() - 1) == '\r') {
|
||||
lineBuf.setLength(lineBuf.length() - 1);
|
||||
}
|
||||
|
||||
return lineBuf.toString();
|
||||
}
|
||||
|
||||
public long readLong() throws IOException {
|
||||
checkAvailable(8);
|
||||
return buffer.readLong();
|
||||
}
|
||||
|
||||
public short readShort() throws IOException {
|
||||
checkAvailable(2);
|
||||
return buffer.readShort();
|
||||
}
|
||||
|
||||
public String readUTF() throws IOException {
|
||||
return DataInputStream.readUTF(this);
|
||||
}
|
||||
|
||||
public int readUnsignedByte() throws IOException {
|
||||
return readByte() & 0xff;
|
||||
}
|
||||
|
||||
public int readUnsignedShort() throws IOException {
|
||||
return readShort() & 0xffff;
|
||||
}
|
||||
|
||||
public int skipBytes(int n) throws IOException {
|
||||
int nBytes = Math.min(available(), n);
|
||||
buffer.skipBytes(n);
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
private void checkAvailable(int fieldSize) throws IOException {
|
||||
if (fieldSize < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
if (fieldSize > available()) {
|
||||
throw new EOFException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @see ChannelBufferInputStream
|
||||
* @apiviz.uses net.gleamynode.netty.buffer.ChannelBuffer
|
||||
*/
|
||||
public class ChannelBufferOutputStream extends OutputStream implements DataOutput {
|
||||
|
||||
private final ChannelBuffer buffer;
|
||||
private final DataOutputStream utf8out = new DataOutputStream(this);
|
||||
|
||||
public ChannelBufferOutputStream(ChannelBuffer buffer) {
|
||||
if (buffer == null) {
|
||||
throw new NullPointerException("buffer");
|
||||
}
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.writeBytes(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
buffer.writeBytes(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
buffer.writeByte((byte) b);
|
||||
}
|
||||
|
||||
public void writeBoolean(boolean v) throws IOException {
|
||||
write(v? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
public void writeByte(int v) throws IOException {
|
||||
write(v);
|
||||
}
|
||||
|
||||
public void writeBytes(String s) throws IOException {
|
||||
int len = s.length();
|
||||
for (int i = 0; i < len; i ++) {
|
||||
write((byte) s.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void writeChar(int v) throws IOException {
|
||||
writeShort((short) v);
|
||||
}
|
||||
|
||||
public void writeChars(String s) throws IOException {
|
||||
int len = s.length();
|
||||
for (int i = 0 ; i < len ; i ++) {
|
||||
writeChar(s.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void writeDouble(double v) throws IOException {
|
||||
writeLong(Double.doubleToLongBits(v));
|
||||
}
|
||||
|
||||
public void writeFloat(float v) throws IOException {
|
||||
writeInt(Float.floatToIntBits(v));
|
||||
}
|
||||
|
||||
public void writeInt(int v) throws IOException {
|
||||
buffer.writeInt(v);
|
||||
}
|
||||
|
||||
public void writeLong(long v) throws IOException {
|
||||
buffer.writeLong(v);
|
||||
}
|
||||
|
||||
public void writeShort(int v) throws IOException {
|
||||
buffer.writeShort((short) v);
|
||||
}
|
||||
|
||||
public void writeUTF(String s) throws IOException {
|
||||
utf8out.writeUTF(s);
|
||||
}
|
||||
|
||||
public ChannelBuffer buffer() {
|
||||
return buffer;
|
||||
}
|
||||
}
|
574
src/main/java/net/gleamynode/netty/buffer/ChannelBuffers.java
Normal file
574
src/main/java/net/gleamynode/netty/buffer/ChannelBuffers.java
Normal file
@ -0,0 +1,574 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link ChannelBuffer} by allocating new space or by wrapping
|
||||
* or copying existing byte arrays.
|
||||
*
|
||||
* <h3>Use static import</h3>
|
||||
* This classes is intended to be used with Java 5 static import statement:
|
||||
*
|
||||
* <pre>
|
||||
* import static net.gleamynode.netty.buffer.ChannelBuffers.*;
|
||||
*
|
||||
* ChannelBuffer heapBuffer = buffer(128);
|
||||
* ChannelBuffer directBuffer = directBuffer(256);
|
||||
* ChannelBuffer dynamicBuffer = dynamicBuffer(512);
|
||||
* ChannelBuffer wrappedBuffer = wrappedBuffer(new byte[128], new byte[256]);
|
||||
* ChannelBuffer copiedBuffer = copiedBuffer(ByteBuffer.allocate(128));
|
||||
* </pre>
|
||||
*
|
||||
* <h3>Allocating a new buffer</h3>
|
||||
*
|
||||
* Three buffer types are provided out of the box.
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #buffer(int)} allocates a new fixed-capacity heap buffer.</li>
|
||||
* <li>{@link #directBuffer(int)} allocates a new fixed-capacity direct buffer.</li>
|
||||
* <li>{@link #dynamicBuffer(int)} allocates a new dynamic-capacity heap
|
||||
* buffer, whose capacity increases automatically as needed by a write
|
||||
* operation.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>Creating a wrapped buffer</h3>
|
||||
*
|
||||
* Wrapped buffer is a buffer which is a view of one or more existing
|
||||
* byte arrays or byte buffer. Any changes in the content of the original
|
||||
* array or buffer will be reflected in the wrapped buffer. Various wrapper
|
||||
* methods are provided and their name is all {@code wrappedBuffer()}.
|
||||
* You might want to take a look at this method closely if you want to create
|
||||
* a buffer which is composed of more than one array to reduce the number of
|
||||
* memory copy.
|
||||
*
|
||||
* <h3>Creating a copied buffer</h3>
|
||||
*
|
||||
* Copied buffer is a deep copy of one or more existing byte arrays or byte
|
||||
* buffer. Unlike a wrapped buffer, there's no shared data between the
|
||||
* original arrays and the copied buffer. Various copy methods are provided
|
||||
* and their name is all {@code copiedBuffer()}. It's also convenient to
|
||||
* use this operation to merge multiple buffers into one buffer.
|
||||
*
|
||||
* <h3>Miscellaneous utility methods</h3>
|
||||
*
|
||||
* This class also provides various utility methods to help implementation
|
||||
* of a new buffer type, generation of hex dump and swapping an integer's
|
||||
* byte order.
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
* @apiviz.has net.gleamynode.netty.buffer.ChannelBuffer oneway - - creates
|
||||
*/
|
||||
public class ChannelBuffers {
|
||||
|
||||
public static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN;
|
||||
public static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN;
|
||||
|
||||
private static final char[][] HEXDUMP_TABLE = new char[65536][];
|
||||
|
||||
static {
|
||||
for (int i = 0; i < 65536; i ++) {
|
||||
HEXDUMP_TABLE[i] = String.format("%04x", i).toCharArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static ChannelBuffer buffer(int length) {
|
||||
return buffer(BIG_ENDIAN, length);
|
||||
}
|
||||
|
||||
public static ChannelBuffer buffer(ByteOrder endianness, int length) {
|
||||
if (length == 0) {
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
if (endianness == BIG_ENDIAN) {
|
||||
return new BigEndianHeapChannelBuffer(length);
|
||||
} else if (endianness == LITTLE_ENDIAN) {
|
||||
return new LittleEndianHeapChannelBuffer(length);
|
||||
} else {
|
||||
throw new NullPointerException("endianness");
|
||||
}
|
||||
}
|
||||
|
||||
public static ChannelBuffer directBuffer(int length) {
|
||||
return directBuffer(BIG_ENDIAN, length);
|
||||
}
|
||||
|
||||
public static ChannelBuffer directBuffer(ByteOrder endianness, int length) {
|
||||
if (length == 0) {
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
ChannelBuffer buffer = new ByteBufferBackedChannelBuffer(
|
||||
ByteBuffer.allocateDirect(length).order(endianness));
|
||||
buffer.clear();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static ChannelBuffer dynamicBuffer() {
|
||||
return dynamicBuffer(BIG_ENDIAN, 256);
|
||||
}
|
||||
|
||||
public static ChannelBuffer dynamicBuffer(int estimatedLength) {
|
||||
return dynamicBuffer(BIG_ENDIAN, estimatedLength);
|
||||
}
|
||||
|
||||
public static ChannelBuffer dynamicBuffer(ByteOrder endianness, int estimatedLength) {
|
||||
return new DynamicChannelBuffer(endianness, estimatedLength);
|
||||
}
|
||||
|
||||
public static ChannelBuffer wrappedBuffer(byte[] array) {
|
||||
return wrappedBuffer(BIG_ENDIAN, array);
|
||||
}
|
||||
|
||||
public static ChannelBuffer wrappedBuffer(ByteOrder endianness, byte[] array) {
|
||||
if (array.length == 0) {
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
if (endianness == BIG_ENDIAN) {
|
||||
return new BigEndianHeapChannelBuffer(array);
|
||||
} else if (endianness == LITTLE_ENDIAN) {
|
||||
return new LittleEndianHeapChannelBuffer(array);
|
||||
} else {
|
||||
throw new NullPointerException("endianness");
|
||||
}
|
||||
}
|
||||
|
||||
public static ChannelBuffer wrappedBuffer(byte[] array, int offset, int length) {
|
||||
return wrappedBuffer(BIG_ENDIAN, array, offset, length);
|
||||
}
|
||||
|
||||
public static ChannelBuffer wrappedBuffer(ByteOrder endianness, byte[] array, int offset, int length) {
|
||||
if (length == 0) {
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
if (offset == 0) {
|
||||
if (length == array.length) {
|
||||
return wrappedBuffer(endianness, array);
|
||||
} else {
|
||||
return new TruncatedChannelBuffer(wrappedBuffer(endianness, array), length);
|
||||
}
|
||||
} else {
|
||||
return new SlicedChannelBuffer(wrappedBuffer(endianness, array), offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
public static ChannelBuffer wrappedBuffer(ByteBuffer buffer) {
|
||||
if (!buffer.hasRemaining()) {
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
if (!buffer.isReadOnly() && buffer.hasArray()) {
|
||||
return wrappedBuffer(buffer.array(), buffer.arrayOffset(),buffer.remaining());
|
||||
} else {
|
||||
return new ByteBufferBackedChannelBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static ChannelBuffer wrappedBuffer(ChannelBuffer buffer) {
|
||||
if (buffer.readable()) {
|
||||
return buffer.slice();
|
||||
} else {
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
}
|
||||
|
||||
public static ChannelBuffer wrappedBuffer(byte[]... arrays) {
|
||||
return wrappedBuffer(BIG_ENDIAN, arrays);
|
||||
}
|
||||
|
||||
public static ChannelBuffer wrappedBuffer(ByteOrder endianness, byte[]... arrays) {
|
||||
switch (arrays.length) {
|
||||
case 0:
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
case 1:
|
||||
return wrappedBuffer(endianness, arrays[0]);
|
||||
}
|
||||
ChannelBuffer[] wrappedBuffers = new ChannelBuffer[arrays.length];
|
||||
for (int i = 0; i < arrays.length; i ++) {
|
||||
wrappedBuffers[i] = wrappedBuffer(endianness, arrays[i]);
|
||||
}
|
||||
return wrappedBuffer(wrappedBuffers);
|
||||
}
|
||||
|
||||
public static ChannelBuffer wrappedBuffer(ChannelBuffer... buffers) {
|
||||
switch (buffers.length) {
|
||||
case 0:
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
case 1:
|
||||
return wrappedBuffer(buffers[0]);
|
||||
default:
|
||||
return new CompositeChannelBuffer(buffers);
|
||||
}
|
||||
}
|
||||
|
||||
public static ChannelBuffer wrappedBuffer(ByteBuffer... buffers) {
|
||||
switch (buffers.length) {
|
||||
case 0:
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
case 1:
|
||||
return wrappedBuffer(buffers[0]);
|
||||
}
|
||||
ChannelBuffer[] wrappedBuffers = new ChannelBuffer[buffers.length];
|
||||
for (int i = 0; i < buffers.length; i ++) {
|
||||
wrappedBuffers[i] = wrappedBuffer(buffers[i]);
|
||||
}
|
||||
return wrappedBuffer(wrappedBuffers);
|
||||
}
|
||||
|
||||
public static ChannelBuffer copiedBuffer(byte[] array) {
|
||||
return copiedBuffer(BIG_ENDIAN, array);
|
||||
}
|
||||
|
||||
public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[] array) {
|
||||
if (array.length == 0) {
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
if (endianness == BIG_ENDIAN) {
|
||||
return new BigEndianHeapChannelBuffer(array.clone());
|
||||
} else if (endianness == LITTLE_ENDIAN) {
|
||||
return new LittleEndianHeapChannelBuffer(array.clone());
|
||||
} else {
|
||||
throw new NullPointerException("endianness");
|
||||
}
|
||||
}
|
||||
|
||||
public static ChannelBuffer copiedBuffer(byte[] array, int offset, int length) {
|
||||
return copiedBuffer(BIG_ENDIAN, array, offset, length);
|
||||
}
|
||||
|
||||
public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[] array, int offset, int length) {
|
||||
if (length == 0) {
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
byte[] copy = new byte[length];
|
||||
System.arraycopy(array, offset, copy, 0, length);
|
||||
return wrappedBuffer(endianness, copy);
|
||||
}
|
||||
|
||||
public static ChannelBuffer copiedBuffer(ByteBuffer buffer) {
|
||||
int length = buffer.remaining();
|
||||
if (length == 0) {
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
byte[] copy = new byte[length];
|
||||
int position = buffer.position();
|
||||
try {
|
||||
buffer.get(copy);
|
||||
} finally {
|
||||
buffer.position(position);
|
||||
}
|
||||
return wrappedBuffer(buffer.order(), copy);
|
||||
}
|
||||
|
||||
public static ChannelBuffer copiedBuffer(ChannelBuffer buffer) {
|
||||
return buffer.copy();
|
||||
}
|
||||
|
||||
public static ChannelBuffer copiedBuffer(byte[]... arrays) {
|
||||
return copiedBuffer(BIG_ENDIAN, arrays);
|
||||
}
|
||||
|
||||
public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[]... arrays) {
|
||||
switch (arrays.length) {
|
||||
case 0:
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
case 1:
|
||||
return copiedBuffer(endianness, arrays[0]);
|
||||
}
|
||||
|
||||
// Merge the specified arrays into one array.
|
||||
int length = 0;
|
||||
for (byte[] a: arrays) {
|
||||
if (Integer.MAX_VALUE - length < a.length) {
|
||||
throw new IllegalArgumentException(
|
||||
"The total length of the specified arrays is too big.");
|
||||
}
|
||||
length += a.length;
|
||||
}
|
||||
|
||||
byte[] mergedArray = new byte[length];
|
||||
for (int i = 0, j = 0; i < arrays.length; i ++) {
|
||||
byte[] a = arrays[i];
|
||||
System.arraycopy(a, 0, mergedArray, j, a.length);
|
||||
j += a.length;
|
||||
}
|
||||
|
||||
return wrappedBuffer(endianness, mergedArray);
|
||||
}
|
||||
|
||||
public static ChannelBuffer copiedBuffer(ChannelBuffer... buffers) {
|
||||
switch (buffers.length) {
|
||||
case 0:
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
case 1:
|
||||
return copiedBuffer(buffers[0]);
|
||||
}
|
||||
|
||||
ChannelBuffer[] copiedBuffers = new ChannelBuffer[buffers.length];
|
||||
for (int i = 0; i < buffers.length; i ++) {
|
||||
copiedBuffers[i] = buffers[i].copy();
|
||||
}
|
||||
return wrappedBuffer(copiedBuffers);
|
||||
}
|
||||
|
||||
public static ChannelBuffer copiedBuffer(ByteBuffer... buffers) {
|
||||
switch (buffers.length) {
|
||||
case 0:
|
||||
return ChannelBuffer.EMPTY_BUFFER;
|
||||
case 1:
|
||||
return copiedBuffer(buffers[0]);
|
||||
}
|
||||
|
||||
ChannelBuffer[] copiedBuffers = new ChannelBuffer[buffers.length];
|
||||
for (int i = 0; i < buffers.length; i ++) {
|
||||
copiedBuffers[i] = wrappedBuffer(buffers[i]).copy();
|
||||
}
|
||||
return wrappedBuffer(copiedBuffers);
|
||||
}
|
||||
|
||||
public static ChannelBuffer unmodifiableBuffer(ChannelBuffer buffer) {
|
||||
if (buffer instanceof ReadOnlyChannelBuffer) {
|
||||
buffer = ((ReadOnlyChannelBuffer) buffer).unwrap();
|
||||
}
|
||||
return new ReadOnlyChannelBuffer(buffer);
|
||||
}
|
||||
|
||||
public static String hexDump(ChannelBuffer buffer) {
|
||||
return hexDump(buffer, buffer.readerIndex(), buffer.readableBytes());
|
||||
}
|
||||
|
||||
public static String hexDump(ChannelBuffer buffer, int fromIndex, int length) {
|
||||
if (length < 0) {
|
||||
throw new IllegalArgumentException("length: " + length);
|
||||
}
|
||||
if (length == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int endIndex = fromIndex + (length >>> 1 << 1);
|
||||
boolean oddLength = length % 2 != 0;
|
||||
char[] buf = new char[length << 1];
|
||||
|
||||
int srcIdx = fromIndex;
|
||||
int dstIdx = 0;
|
||||
for (; srcIdx < endIndex; srcIdx += 2, dstIdx += 4) {
|
||||
System.arraycopy(
|
||||
HEXDUMP_TABLE[buffer.getShort(srcIdx) & 0xFFFF],
|
||||
0, buf, dstIdx, 4);
|
||||
}
|
||||
|
||||
if (oddLength) {
|
||||
System.arraycopy(
|
||||
HEXDUMP_TABLE[buffer.getByte(srcIdx) & 0xFF],
|
||||
2, buf, dstIdx, 2);
|
||||
}
|
||||
|
||||
return new String(buf);
|
||||
}
|
||||
|
||||
public static int hashCode(ChannelBuffer buffer) {
|
||||
final int aLen = buffer.readableBytes();
|
||||
final int intCount = aLen >>> 2;
|
||||
final int byteCount = aLen & 3;
|
||||
|
||||
int hashCode = 1;
|
||||
int arrayIndex = buffer.readerIndex();
|
||||
for (int i = intCount; i > 0; i --) {
|
||||
hashCode = 31 * hashCode + buffer.getInt(arrayIndex);
|
||||
arrayIndex += 4;
|
||||
}
|
||||
for (int i = byteCount; i > 0; i --) {
|
||||
hashCode = 31 * hashCode + buffer.getByte(arrayIndex ++);
|
||||
}
|
||||
|
||||
if (hashCode == 0) {
|
||||
hashCode = 1;
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
public static boolean equals(ChannelBuffer bufferA, ChannelBuffer bufferB) {
|
||||
final int aLen = bufferA.readableBytes();
|
||||
if (aLen != bufferB.readableBytes()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int longCount = aLen >>> 3;
|
||||
final int byteCount = aLen & 7;
|
||||
|
||||
int aIndex = bufferA.readerIndex();
|
||||
int bIndex = bufferB.readerIndex();
|
||||
for (int i = longCount; i > 0; i --) {
|
||||
if (bufferA.getLong(aIndex) != bufferB.getLong(bIndex)) {
|
||||
return false;
|
||||
}
|
||||
aIndex += 8;
|
||||
bIndex += 8;
|
||||
}
|
||||
|
||||
for (int i = byteCount; i > 0; i --) {
|
||||
if (bufferA.getByte(aIndex) != bufferB.getByte(bIndex)) {
|
||||
return false;
|
||||
}
|
||||
aIndex ++;
|
||||
bIndex ++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int compare(ChannelBuffer bufferA, ChannelBuffer bufferB) {
|
||||
final int aLen = bufferA.readableBytes();
|
||||
final int bLen = bufferB.readableBytes();
|
||||
final int minLength = Math.min(aLen, bLen);
|
||||
final int longCount = minLength >>> 3;
|
||||
final int byteCount = minLength & 7;
|
||||
|
||||
int aIndex = bufferA.readerIndex();
|
||||
int bIndex = bufferB.readerIndex();
|
||||
for (int i = longCount; i > 0; i --) {
|
||||
long va = bufferA.getLong(aIndex);
|
||||
long vb = bufferB.getLong(bIndex);
|
||||
if (va > vb) {
|
||||
return 1;
|
||||
} else if (va < vb) {
|
||||
return -1;
|
||||
}
|
||||
aIndex += 8;
|
||||
bIndex += 8;
|
||||
}
|
||||
|
||||
for (int i = byteCount; i > 0; i --) {
|
||||
byte va = bufferA.getByte(aIndex);
|
||||
byte vb = bufferB.getByte(bIndex);
|
||||
if (va > vb) {
|
||||
return 1;
|
||||
} else if (va < vb) {
|
||||
return -1;
|
||||
}
|
||||
aIndex ++;
|
||||
bIndex ++;
|
||||
}
|
||||
|
||||
return aLen - bLen;
|
||||
}
|
||||
|
||||
public static int indexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
|
||||
if (fromIndex <= toIndex) {
|
||||
return firstIndexOf(buffer, fromIndex, toIndex, value);
|
||||
} else {
|
||||
return lastIndexOf(buffer, fromIndex, toIndex, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static int indexOf(ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
|
||||
if (fromIndex <= toIndex) {
|
||||
return firstIndexOf(buffer, fromIndex, toIndex, indexFinder);
|
||||
} else {
|
||||
return lastIndexOf(buffer, fromIndex, toIndex, indexFinder);
|
||||
}
|
||||
}
|
||||
|
||||
public static short swapShort(short value) {
|
||||
return (short) (value << 8 | value >>> 8 & 0xff);
|
||||
}
|
||||
|
||||
public static int swapMedium(int value) {
|
||||
return value << 16 & 0xff0000 | value & 0xff00 | value >>> 16 & 0xff;
|
||||
}
|
||||
|
||||
public static int swapInt(int value) {
|
||||
return swapShort((short) value) << 16 |
|
||||
swapShort((short) (value >>> 16)) & 0xffff;
|
||||
}
|
||||
|
||||
public static long swapLong(long value) {
|
||||
return (long) swapInt((int) value) << 32 |
|
||||
swapInt((int) (value >>> 32)) & 0xffffffffL;
|
||||
}
|
||||
|
||||
private static int firstIndexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
|
||||
fromIndex = Math.max(fromIndex, 0);
|
||||
if (fromIndex >= toIndex || buffer.capacity() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = fromIndex; i < toIndex; i ++) {
|
||||
if (buffer.getByte(i) == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int lastIndexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
|
||||
fromIndex = Math.min(fromIndex, buffer.capacity());
|
||||
if (fromIndex < 0 || buffer.capacity() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = fromIndex - 1; i >= toIndex; i --) {
|
||||
if (buffer.getByte(i) == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int firstIndexOf(ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
|
||||
fromIndex = Math.max(fromIndex, 0);
|
||||
if (fromIndex >= toIndex || buffer.capacity() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = fromIndex; i < toIndex; i ++) {
|
||||
if (indexFinder.find(buffer, i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int lastIndexOf(ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
|
||||
fromIndex = Math.min(fromIndex, buffer.capacity());
|
||||
if (fromIndex < 0 || buffer.capacity() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = fromIndex - 1; i >= toIndex; i --) {
|
||||
if (indexFinder.find(buffer, i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private ChannelBuffers() {
|
||||
// Unused
|
||||
}
|
||||
}
|
@ -0,0 +1,474 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
*/
|
||||
public class CompositeChannelBuffer extends AbstractChannelBuffer {
|
||||
|
||||
private final ChannelBuffer[] slices;
|
||||
private final int[] indices;
|
||||
private int lastSliceId;
|
||||
|
||||
public CompositeChannelBuffer(ChannelBuffer... buffers) {
|
||||
if (buffers.length == 0) {
|
||||
throw new IllegalArgumentException("buffers should not be empty.");
|
||||
}
|
||||
|
||||
ByteOrder expectedEndianness = buffers[0].order();
|
||||
slices = new ChannelBuffer[buffers.length];
|
||||
for (int i = 0; i < buffers.length; i ++) {
|
||||
if (buffers[i].order() != expectedEndianness) {
|
||||
throw new IllegalArgumentException(
|
||||
"All buffers must have the same endianness.");
|
||||
}
|
||||
slices[i] = buffers[i].slice();
|
||||
}
|
||||
indices = new int[buffers.length + 1];
|
||||
for (int i = 1; i <= buffers.length; i ++) {
|
||||
indices[i] = indices[i - 1] + slices[i - 1].capacity();
|
||||
}
|
||||
writerIndex(capacity());
|
||||
}
|
||||
|
||||
private CompositeChannelBuffer(CompositeChannelBuffer buffer) {
|
||||
slices = buffer.slices.clone();
|
||||
indices = buffer.indices.clone();
|
||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||
}
|
||||
|
||||
public ByteOrder order() {
|
||||
return slices[0].order();
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return indices[slices.length];
|
||||
}
|
||||
|
||||
public byte getByte(int index) {
|
||||
int sliceId = sliceId(index);
|
||||
return slices[sliceId].getByte(index - indices[sliceId]);
|
||||
}
|
||||
|
||||
public short getShort(int index) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + 2 <= indices[sliceId + 1]) {
|
||||
return slices[sliceId].getShort(index - indices[sliceId]);
|
||||
} else if (order() == ByteOrder.BIG_ENDIAN) {
|
||||
return (short) ((getByte(index) & 0xff) << 8 | getByte(index + 1) & 0xff);
|
||||
} else {
|
||||
return (short) (getByte(index) & 0xff | (getByte(index + 1) & 0xff) << 8);
|
||||
}
|
||||
}
|
||||
|
||||
public int getMedium(int index) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + 3 <= indices[sliceId + 1]) {
|
||||
return slices[sliceId].getMedium(index - indices[sliceId]);
|
||||
} else if (order() == ByteOrder.BIG_ENDIAN) {
|
||||
return (getShort(index) & 0xffff) << 8 | getByte(index + 2) & 0xff;
|
||||
} else {
|
||||
return getShort(index) & 0xFFFF | (getByte(index + 2) & 0xFF) << 16;
|
||||
}
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + 4 <= indices[sliceId + 1]) {
|
||||
return slices[sliceId].getInt(index - indices[sliceId]);
|
||||
} else if (order() == ByteOrder.BIG_ENDIAN) {
|
||||
return (getShort(index) & 0xffff) << 16 | getShort(index + 2) & 0xffff;
|
||||
} else {
|
||||
return getShort(index) & 0xFFFF | (getShort(index + 2) & 0xFFFF) << 16;
|
||||
}
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + 8 <= indices[sliceId + 1]) {
|
||||
return slices[sliceId].getLong(index - indices[sliceId]);
|
||||
} else if (order() == ByteOrder.BIG_ENDIAN) {
|
||||
return (getInt(index) & 0xffffffffL) << 32 | getInt(index + 4) & 0xffffffffL;
|
||||
} else {
|
||||
return getInt(index) & 0xFFFFFFFFL | (getInt(index + 4) & 0xFFFFFFFFL) << 32;
|
||||
}
|
||||
}
|
||||
|
||||
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + length >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
int i = sliceId;
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
s.getBytes(index - adjustment, dst, dstIndex, localLength);
|
||||
index += localLength;
|
||||
dstIndex += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
public void getBytes(int index, ByteBuffer dst) {
|
||||
int sliceId = sliceId(index);
|
||||
int limit = dst.limit();
|
||||
int length = dst.remaining();
|
||||
if (index + length >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
int i = sliceId;
|
||||
try {
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
dst.limit(dst.position() + localLength);
|
||||
s.getBytes(index - adjustment, dst);
|
||||
index += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
} finally {
|
||||
dst.limit(limit);
|
||||
}
|
||||
}
|
||||
|
||||
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + length >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
int i = sliceId;
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
s.getBytes(index - adjustment, dst, dstIndex, localLength);
|
||||
index += localLength;
|
||||
dstIndex += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
// XXX Gathering write is not supported because of a known issue.
|
||||
// See http://bugs.sun.com/view_bug.do?bug_id=6210541
|
||||
return out.write(toByteBuffer());
|
||||
}
|
||||
|
||||
public void getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + length >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
int i = sliceId;
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
s.getBytes(index - adjustment, out, localLength);
|
||||
index += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
public void setByte(int index, byte value) {
|
||||
int sliceId = sliceId(index);
|
||||
slices[sliceId].setByte(index - indices[sliceId], value);
|
||||
}
|
||||
|
||||
public void setShort(int index, short value) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + 2 <= indices[sliceId + 1]) {
|
||||
slices[sliceId].setShort(index - indices[sliceId], value);
|
||||
} else if (order() == ByteOrder.BIG_ENDIAN) {
|
||||
setByte(index, (byte) (value >>> 8));
|
||||
setByte(index + 1, (byte) value);
|
||||
} else {
|
||||
setByte(index , (byte) value);
|
||||
setByte(index + 1, (byte) (value >>> 8));
|
||||
}
|
||||
}
|
||||
|
||||
public void setMedium(int index, int value) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + 3 <= indices[sliceId + 1]) {
|
||||
slices[sliceId].setMedium(index - indices[sliceId], value);
|
||||
} else if (order() == ByteOrder.BIG_ENDIAN) {
|
||||
setShort(index, (short) (value >>> 8));
|
||||
setByte(index + 2, (byte) value);
|
||||
} else {
|
||||
setShort(index , (short) value);
|
||||
setByte (index + 2, (byte) (value >>> 16));
|
||||
}
|
||||
}
|
||||
|
||||
public void setInt(int index, int value) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + 4 <= indices[sliceId + 1]) {
|
||||
slices[sliceId].setInt(index - indices[sliceId], value);
|
||||
} else if (order() == ByteOrder.BIG_ENDIAN) {
|
||||
setShort(index, (short) (value >>> 16));
|
||||
setShort(index + 2, (short) value);
|
||||
} else {
|
||||
setShort(index , (short) value);
|
||||
setShort(index + 2, (short) (value >>> 16));
|
||||
}
|
||||
}
|
||||
|
||||
public void setLong(int index, long value) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + 8 <= indices[sliceId + 1]) {
|
||||
slices[sliceId].setLong(index - indices[sliceId], value);
|
||||
} else if (order() == ByteOrder.BIG_ENDIAN) {
|
||||
setInt(index, (int) (value >>> 32));
|
||||
setInt(index + 4, (int) value);
|
||||
} else {
|
||||
setInt(index , (int) value);
|
||||
setInt(index + 4, (int) (value >>> 32));
|
||||
}
|
||||
}
|
||||
|
||||
public void setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + length >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
int i = sliceId;
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
s.setBytes(index - adjustment, src, srcIndex, localLength);
|
||||
index += localLength;
|
||||
srcIndex += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBytes(int index, ByteBuffer src) {
|
||||
int sliceId = sliceId(index);
|
||||
int limit = src.limit();
|
||||
int length = src.remaining();
|
||||
if (index + length >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
int i = sliceId;
|
||||
try {
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
src.limit(src.position() + localLength);
|
||||
s.setBytes(index - adjustment, src);
|
||||
index += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
} finally {
|
||||
src.limit(limit);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + length >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
int i = sliceId;
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
s.setBytes(index - adjustment, src, srcIndex, localLength);
|
||||
index += localLength;
|
||||
srcIndex += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBytes(int index, InputStream in, int length)
|
||||
throws IOException {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + length >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
int i = sliceId;
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
s.setBytes(index - adjustment, in, localLength);
|
||||
index += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length)
|
||||
throws IOException {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + length >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
int i = sliceId;
|
||||
int writtenBytes = 0;
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
int localWrittenBytes = s.setBytes(index - adjustment, in, localLength);
|
||||
writtenBytes += localWrittenBytes;
|
||||
if (localLength != localWrittenBytes) {
|
||||
break;
|
||||
}
|
||||
index += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
|
||||
return writtenBytes;
|
||||
}
|
||||
|
||||
public ChannelBuffer duplicate() {
|
||||
return new CompositeChannelBuffer(this);
|
||||
}
|
||||
|
||||
public ChannelBuffer copy(int index, int length) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + length >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
ChannelBuffer dst = ChannelBuffers.buffer(length);
|
||||
int dstIndex = 0;
|
||||
int i = sliceId;
|
||||
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
s.getBytes(index - adjustment, dst, dstIndex, localLength);
|
||||
index += localLength;
|
||||
dstIndex += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
|
||||
dst.writerIndex(dst.capacity());
|
||||
return dst;
|
||||
}
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
return new SlicedChannelBuffer(this, index, length);
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBuffer(int index, int length) {
|
||||
ByteBuffer[] buffers = toByteBuffers(index, length);
|
||||
ByteBuffer merged = ByteBuffer.allocate(length);
|
||||
for (ByteBuffer b: buffers) {
|
||||
merged.put(b);
|
||||
}
|
||||
merged.flip();
|
||||
return merged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] toByteBuffers(int index, int length) {
|
||||
int sliceId = sliceId(index);
|
||||
if (index + length > capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
List<ByteBuffer> buffers = new ArrayList<ByteBuffer>(slices.length);
|
||||
|
||||
int i = sliceId;
|
||||
while (length > 0) {
|
||||
ChannelBuffer s = slices[i];
|
||||
int adjustment = indices[i];
|
||||
int localLength = Math.min(length, s.capacity() - (index - adjustment));
|
||||
buffers.add(s.toByteBuffer(index - adjustment, localLength));
|
||||
index += localLength;
|
||||
length -= localLength;
|
||||
i ++;
|
||||
}
|
||||
|
||||
return buffers.toArray(new ByteBuffer[buffers.size()]);
|
||||
}
|
||||
|
||||
private int sliceId(int index) {
|
||||
int lastSliceId = this.lastSliceId;
|
||||
if (index >= indices[lastSliceId]) {
|
||||
if (index < indices[lastSliceId + 1]) {
|
||||
return lastSliceId;
|
||||
}
|
||||
|
||||
// Search right
|
||||
for (int i = lastSliceId + 1; i < slices.length; i ++) {
|
||||
if (index < indices[i + 1]) {
|
||||
this.lastSliceId = i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Search left
|
||||
for (int i = lastSliceId - 1; i >= 0; i --) {
|
||||
if (index >= indices[i]) {
|
||||
this.lastSliceId = i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
*/
|
||||
public class DuplicatedChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
|
||||
|
||||
private final ChannelBuffer buffer;
|
||||
|
||||
public DuplicatedChannelBuffer(ChannelBuffer buffer) {
|
||||
if (buffer == null) {
|
||||
throw new NullPointerException("buffer");
|
||||
}
|
||||
this.buffer = buffer;
|
||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||
}
|
||||
|
||||
private DuplicatedChannelBuffer(DuplicatedChannelBuffer buffer) {
|
||||
this.buffer = buffer.buffer;
|
||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||
}
|
||||
|
||||
public ChannelBuffer unwrap() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public ByteOrder order() {
|
||||
return buffer.order();
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return buffer.capacity();
|
||||
}
|
||||
|
||||
public byte getByte(int index) {
|
||||
return buffer.getByte(index);
|
||||
}
|
||||
|
||||
public short getShort(int index) {
|
||||
return buffer.getShort(index);
|
||||
}
|
||||
|
||||
public int getMedium(int index) {
|
||||
return buffer.getMedium(index);
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
return buffer.getInt(index);
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
return buffer.getLong(index);
|
||||
}
|
||||
|
||||
public ChannelBuffer duplicate() {
|
||||
return new DuplicatedChannelBuffer(this);
|
||||
}
|
||||
|
||||
public ChannelBuffer copy(int index, int length) {
|
||||
return buffer.copy(index, length);
|
||||
}
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
return buffer.slice(index, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ByteBuffer dst) {
|
||||
buffer.getBytes(index, dst);
|
||||
}
|
||||
|
||||
public void setByte(int index, byte value) {
|
||||
buffer.setByte(index, value);
|
||||
}
|
||||
|
||||
public void setShort(int index, short value) {
|
||||
buffer.setShort(index, value);
|
||||
}
|
||||
|
||||
public void setMedium(int index, int value) {
|
||||
buffer.setMedium(index, value);
|
||||
}
|
||||
|
||||
public void setInt(int index, int value) {
|
||||
buffer.setInt(index, value);
|
||||
}
|
||||
|
||||
public void setLong(int index, long value) {
|
||||
buffer.setLong(index, value);
|
||||
}
|
||||
|
||||
public void setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
buffer.setBytes(index, src, srcIndex, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
|
||||
buffer.setBytes(index, src, srcIndex, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ByteBuffer src) {
|
||||
buffer.setBytes(index, src);
|
||||
}
|
||||
|
||||
public void getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
buffer.getBytes(index, out, length);
|
||||
}
|
||||
|
||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
return buffer.getBytes(index, out, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, InputStream in, int length)
|
||||
throws IOException {
|
||||
buffer.setBytes(index, in, length);
|
||||
}
|
||||
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length)
|
||||
throws IOException {
|
||||
return buffer.setBytes(index, in, length);
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBuffer(int index, int length) {
|
||||
return buffer.toByteBuffer(index, length);
|
||||
}
|
||||
}
|
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
*/
|
||||
public class DynamicChannelBuffer extends AbstractChannelBuffer {
|
||||
|
||||
private final int initialCapacity;
|
||||
private final ByteOrder endianness;
|
||||
private ChannelBuffer buffer = ChannelBuffer.EMPTY_BUFFER;
|
||||
|
||||
public DynamicChannelBuffer(int estimatedLength) {
|
||||
this(ByteOrder.BIG_ENDIAN, estimatedLength);
|
||||
}
|
||||
|
||||
public DynamicChannelBuffer(ByteOrder endianness, int estimatedLength) {
|
||||
if (estimatedLength <= 0) {
|
||||
throw new IllegalArgumentException("estimatedLength");
|
||||
}
|
||||
if (endianness == null) {
|
||||
throw new NullPointerException("endianness");
|
||||
}
|
||||
|
||||
initialCapacity = estimatedLength;
|
||||
this.endianness = endianness;
|
||||
}
|
||||
|
||||
public ByteOrder order() {
|
||||
return endianness;
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return buffer.capacity();
|
||||
}
|
||||
|
||||
public byte getByte(int index) {
|
||||
return buffer.getByte(index);
|
||||
}
|
||||
|
||||
public short getShort(int index) {
|
||||
return buffer.getShort(index);
|
||||
}
|
||||
|
||||
public int getMedium(int index) {
|
||||
return buffer.getMedium(index);
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
return buffer.getInt(index);
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
return buffer.getLong(index);
|
||||
}
|
||||
|
||||
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ByteBuffer dst) {
|
||||
buffer.getBytes(index, dst);
|
||||
}
|
||||
|
||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
return buffer.getBytes(index, out, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
buffer.getBytes(index, out, length);
|
||||
}
|
||||
|
||||
public void setByte(int index, byte value) {
|
||||
buffer.setByte(index, value);
|
||||
}
|
||||
|
||||
public void setShort(int index, short value) {
|
||||
buffer.setShort(index, value);
|
||||
}
|
||||
|
||||
public void setMedium(int index, int value) {
|
||||
buffer.setMedium(index, value);
|
||||
}
|
||||
|
||||
public void setInt(int index, int value) {
|
||||
buffer.setInt(index, value);
|
||||
}
|
||||
|
||||
public void setLong(int index, long value) {
|
||||
buffer.setLong(index, value);
|
||||
}
|
||||
|
||||
public void setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
buffer.setBytes(index, src, srcIndex, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
|
||||
buffer.setBytes(index, src, srcIndex, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ByteBuffer src) {
|
||||
buffer.setBytes(index, src);
|
||||
}
|
||||
|
||||
public void setBytes(int index, InputStream in, int length)
|
||||
throws IOException {
|
||||
buffer.setBytes(index, in, length);
|
||||
}
|
||||
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length)
|
||||
throws IOException {
|
||||
return buffer.setBytes(index, in, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeByte(byte value) {
|
||||
ensureWritableBytes(1);
|
||||
super.writeByte(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeShort(short value) {
|
||||
ensureWritableBytes(2);
|
||||
super.writeShort(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeMedium(int value) {
|
||||
ensureWritableBytes(3);
|
||||
super.writeMedium(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeInt(int value) {
|
||||
ensureWritableBytes(4);
|
||||
super.writeInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLong(long value) {
|
||||
ensureWritableBytes(8);
|
||||
super.writeLong(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(byte[] src, int srcIndex, int length) {
|
||||
ensureWritableBytes(length);
|
||||
super.writeBytes(src, srcIndex, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
|
||||
ensureWritableBytes(length);
|
||||
super.writeBytes(src, srcIndex, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer src) {
|
||||
ensureWritableBytes(src.remaining());
|
||||
super.writeBytes(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writePlaceholder(int length) {
|
||||
ensureWritableBytes(length);
|
||||
super.writePlaceholder(length);
|
||||
}
|
||||
|
||||
public ChannelBuffer duplicate() {
|
||||
return new DuplicatedChannelBuffer(this);
|
||||
}
|
||||
|
||||
public ChannelBuffer copy(int index, int length) {
|
||||
DynamicChannelBuffer copiedBuffer = new DynamicChannelBuffer(endianness, Math.max(length, 64));
|
||||
copiedBuffer.buffer = buffer.copy();
|
||||
if (copiedBuffer.buffer.capacity() == 0) {
|
||||
copiedBuffer.buffer = ChannelBuffer.EMPTY_BUFFER;
|
||||
}
|
||||
return copiedBuffer;
|
||||
}
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
if (index == 0) {
|
||||
return new TruncatedChannelBuffer(this, length);
|
||||
} else {
|
||||
return new SlicedChannelBuffer(this, index, length);
|
||||
}
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBuffer(int index, int length) {
|
||||
return buffer.toByteBuffer(index, length);
|
||||
}
|
||||
|
||||
private void ensureWritableBytes(int requestedBytes) {
|
||||
if (requestedBytes <= writableBytes()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int newCapacity;
|
||||
if (capacity() == 0) {
|
||||
newCapacity = initialCapacity;
|
||||
} else {
|
||||
newCapacity = capacity();
|
||||
}
|
||||
int minNewCapacity = writerIndex() + requestedBytes;
|
||||
while (newCapacity < minNewCapacity) {
|
||||
newCapacity <<= 1;
|
||||
}
|
||||
|
||||
ChannelBuffer newBuffer = ChannelBuffers.buffer(endianness, newCapacity);
|
||||
newBuffer.writeBytes(buffer, readerIndex(), readableBytes());
|
||||
buffer = newBuffer;
|
||||
}
|
||||
}
|
149
src/main/java/net/gleamynode/netty/buffer/HeapChannelBuffer.java
Normal file
149
src/main/java/net/gleamynode/netty/buffer/HeapChannelBuffer.java
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public abstract class HeapChannelBuffer extends AbstractChannelBuffer {
|
||||
|
||||
protected final byte[] array;
|
||||
|
||||
public HeapChannelBuffer(int length) {
|
||||
this(new byte[length], 0, 0);
|
||||
}
|
||||
|
||||
public HeapChannelBuffer(byte[] array) {
|
||||
this(array, 0, array.length);
|
||||
}
|
||||
|
||||
protected HeapChannelBuffer(byte[] array, int readerIndex, int writerIndex) {
|
||||
if (array == null) {
|
||||
throw new NullPointerException("array");
|
||||
}
|
||||
this.array = array;
|
||||
setIndex(readerIndex, writerIndex);
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
public byte getByte(int index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
|
||||
if (dst instanceof HeapChannelBuffer) {
|
||||
getBytes(index, ((HeapChannelBuffer) dst).array, dstIndex, length);
|
||||
} else {
|
||||
dst.setBytes(dstIndex, array, index, length);
|
||||
}
|
||||
}
|
||||
|
||||
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
System.arraycopy(array, index, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ByteBuffer dst) {
|
||||
dst.put(array, index, Math.min(capacity() - index, dst.remaining()));
|
||||
}
|
||||
|
||||
public void getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
out.write(array, index, length);
|
||||
}
|
||||
|
||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
return out.write(ByteBuffer.wrap(array, index, length));
|
||||
}
|
||||
|
||||
public void setByte(int index, byte value) {
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
|
||||
if (src instanceof HeapChannelBuffer) {
|
||||
setBytes(index, ((HeapChannelBuffer) src).array, srcIndex, length);
|
||||
} else {
|
||||
src.getBytes(srcIndex, array, index, length);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
System.arraycopy(src, srcIndex, array, index, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ByteBuffer src) {
|
||||
src.get(array, index, src.remaining());
|
||||
}
|
||||
|
||||
public void setBytes(int index, InputStream in, int length) throws IOException {
|
||||
while (length > 0) {
|
||||
int readBytes = in.read(array, index, length);
|
||||
if (readBytes < 0) {
|
||||
throw new EOFException();
|
||||
}
|
||||
index += readBytes;
|
||||
length -= readBytes;
|
||||
}
|
||||
}
|
||||
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
||||
ByteBuffer buf = ByteBuffer.wrap(array, index, length);
|
||||
while (length > 0) {
|
||||
int readBytes = in.read(buf);
|
||||
if (readBytes < 0) {
|
||||
throw new EOFException();
|
||||
} else if (readBytes == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buf.flip().remaining();
|
||||
}
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
if (index == 0) {
|
||||
if (length == array.length) {
|
||||
return duplicate();
|
||||
} else {
|
||||
return new TruncatedChannelBuffer(this, length);
|
||||
}
|
||||
} else {
|
||||
return new SlicedChannelBuffer(this, index, length);
|
||||
}
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBuffer(int index, int length) {
|
||||
return ByteBuffer.wrap(array, index, length);
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public class LittleEndianHeapChannelBuffer extends HeapChannelBuffer {
|
||||
|
||||
public LittleEndianHeapChannelBuffer(int length) {
|
||||
super(length);
|
||||
}
|
||||
|
||||
public LittleEndianHeapChannelBuffer(byte[] array) {
|
||||
super(array);
|
||||
}
|
||||
|
||||
private LittleEndianHeapChannelBuffer(byte[] array, int readerIndex, int writerIndex) {
|
||||
super(array, readerIndex, writerIndex);
|
||||
}
|
||||
|
||||
public ByteOrder order() {
|
||||
return ByteOrder.LITTLE_ENDIAN;
|
||||
}
|
||||
|
||||
public short getShort(int index) {
|
||||
return (short) (array[index] & 0xFF | array[index+1] << 8);
|
||||
}
|
||||
|
||||
public int getMedium(int index) {
|
||||
return (array[index ] & 0xff) << 0 |
|
||||
(array[index+1] & 0xff) << 8 |
|
||||
(array[index+2] & 0xff) << 16;
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
return (array[index ] & 0xff) << 0 |
|
||||
(array[index+1] & 0xff) << 8 |
|
||||
(array[index+2] & 0xff) << 16 |
|
||||
(array[index+3] & 0xff) << 24;
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
return ((long) array[index] & 0xff) << 0 |
|
||||
((long) array[index+1] & 0xff) << 8 |
|
||||
((long) array[index+2] & 0xff) << 16 |
|
||||
((long) array[index+3] & 0xff) << 24 |
|
||||
((long) array[index+4] & 0xff) << 32 |
|
||||
((long) array[index+5] & 0xff) << 40 |
|
||||
((long) array[index+6] & 0xff) << 48 |
|
||||
((long) array[index+7] & 0xff) << 56;
|
||||
}
|
||||
|
||||
public void setShort(int index, short value) {
|
||||
array[index ] = (byte) (value >>> 0);
|
||||
array[index+1] = (byte) (value >>> 8);
|
||||
}
|
||||
|
||||
public void setMedium(int index, int value) {
|
||||
array[index ] = (byte) (value >>> 0);
|
||||
array[index+1] = (byte) (value >>> 8);
|
||||
array[index+2] = (byte) (value >>> 16);
|
||||
}
|
||||
|
||||
public void setInt(int index, int value) {
|
||||
array[index ] = (byte) (value >>> 0);
|
||||
array[index+1] = (byte) (value >>> 8);
|
||||
array[index+2] = (byte) (value >>> 16);
|
||||
array[index+3] = (byte) (value >>> 24);
|
||||
}
|
||||
|
||||
public void setLong(int index, long value) {
|
||||
array[index ] = (byte) (value >>> 0);
|
||||
array[index+1] = (byte) (value >>> 8);
|
||||
array[index+2] = (byte) (value >>> 16);
|
||||
array[index+3] = (byte) (value >>> 24);
|
||||
array[index+4] = (byte) (value >>> 32);
|
||||
array[index+5] = (byte) (value >>> 40);
|
||||
array[index+6] = (byte) (value >>> 48);
|
||||
array[index+7] = (byte) (value >>> 56);
|
||||
}
|
||||
|
||||
public ChannelBuffer duplicate() {
|
||||
return new LittleEndianHeapChannelBuffer(array, readerIndex(), writerIndex());
|
||||
}
|
||||
|
||||
public ChannelBuffer copy(int index, int length) {
|
||||
if (index < 0 || length < 0 || index + length > array.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
byte[] copiedArray = new byte[length];
|
||||
System.arraycopy(array, index, copiedArray, 0, length);
|
||||
return new LittleEndianHeapChannelBuffer(copiedArray);
|
||||
}
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
public class ReadOnlyChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
|
||||
|
||||
private final ChannelBuffer buffer;
|
||||
|
||||
public ReadOnlyChannelBuffer(ChannelBuffer buffer) {
|
||||
if (buffer == null) {
|
||||
throw new NullPointerException("buffer");
|
||||
}
|
||||
this.buffer = buffer;
|
||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||
}
|
||||
|
||||
private ReadOnlyChannelBuffer(ReadOnlyChannelBuffer buffer) {
|
||||
this.buffer = buffer.buffer;
|
||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||
}
|
||||
|
||||
public ChannelBuffer unwrap() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public ByteOrder order() {
|
||||
return buffer.order();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardReadBytes() {
|
||||
rejectModification();
|
||||
}
|
||||
|
||||
public void setByte(int index, byte value) {
|
||||
rejectModification();
|
||||
}
|
||||
|
||||
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
|
||||
rejectModification();
|
||||
}
|
||||
|
||||
public void setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
rejectModification();
|
||||
}
|
||||
|
||||
public void setBytes(int index, ByteBuffer src) {
|
||||
rejectModification();
|
||||
}
|
||||
|
||||
public void setShort(int index, short value) {
|
||||
rejectModification();
|
||||
}
|
||||
|
||||
public void setMedium(int index, int value) {
|
||||
rejectModification();
|
||||
}
|
||||
|
||||
public void setInt(int index, int value) {
|
||||
rejectModification();
|
||||
}
|
||||
|
||||
public void setLong(int index, long value) {
|
||||
rejectModification();
|
||||
}
|
||||
|
||||
public void setBytes(int index, InputStream in, int length)
|
||||
throws IOException {
|
||||
rejectModification();
|
||||
}
|
||||
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length)
|
||||
throws IOException {
|
||||
rejectModification();
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected void rejectModification() {
|
||||
throw new UnsupportedOperationException("read-only");
|
||||
}
|
||||
|
||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
return buffer.getBytes(index, out, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
buffer.getBytes(index, out, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ByteBuffer dst) {
|
||||
buffer.getBytes(index, dst);
|
||||
}
|
||||
|
||||
public ChannelBuffer duplicate() {
|
||||
return new ReadOnlyChannelBuffer(this);
|
||||
}
|
||||
|
||||
public ChannelBuffer copy(int index, int length) {
|
||||
return new ReadOnlyChannelBuffer(buffer.copy(index, length));
|
||||
}
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
return new ReadOnlyChannelBuffer(buffer.slice(index, length));
|
||||
}
|
||||
|
||||
public byte getByte(int index) {
|
||||
return buffer.getByte(index);
|
||||
}
|
||||
|
||||
public short getShort(int index) {
|
||||
return buffer.getShort(index);
|
||||
}
|
||||
|
||||
public int getMedium(int index) {
|
||||
return buffer.getMedium(index);
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
return buffer.getInt(index);
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
return buffer.getLong(index);
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBuffer(int index, int length) {
|
||||
return buffer.toByteBuffer(index, length).asReadOnlyBuffer();
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return buffer.capacity();
|
||||
}
|
||||
}
|
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
*/
|
||||
public class SlicedChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
|
||||
|
||||
private final ChannelBuffer buffer;
|
||||
private final int adjustment;
|
||||
private final int length;
|
||||
|
||||
public SlicedChannelBuffer(ChannelBuffer buffer, int index, int length) {
|
||||
if (index < 0 || index > buffer.capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
if (index + length > buffer.capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
this.buffer = buffer;
|
||||
adjustment = index;
|
||||
this.length = length;
|
||||
writerIndex(length);
|
||||
}
|
||||
|
||||
public ChannelBuffer unwrap() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public ByteOrder order() {
|
||||
return buffer.order();
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public byte getByte(int index) {
|
||||
checkIndex(index);
|
||||
return buffer.getByte(index + adjustment);
|
||||
}
|
||||
|
||||
public short getShort(int index) {
|
||||
checkIndex(index, 2);
|
||||
return buffer.getShort(index + adjustment);
|
||||
}
|
||||
|
||||
public int getMedium(int index) {
|
||||
checkIndex(index, 3);
|
||||
return buffer.getMedium(index + adjustment);
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
checkIndex(index, 4);
|
||||
return buffer.getInt(index + adjustment);
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
checkIndex(index, 8);
|
||||
return buffer.getLong(index + adjustment);
|
||||
}
|
||||
|
||||
public ChannelBuffer duplicate() {
|
||||
return new SlicedChannelBuffer(buffer, adjustment, length);
|
||||
}
|
||||
|
||||
public ChannelBuffer copy(int index, int length) {
|
||||
return buffer.copy(index + adjustment, length);
|
||||
}
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
checkIndex(index, length);
|
||||
return new SlicedChannelBuffer(buffer, index + adjustment, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.getBytes(index + adjustment, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.getBytes(index + adjustment, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ByteBuffer dst) {
|
||||
checkIndex(index, dst.remaining());
|
||||
buffer.getBytes(index + adjustment, dst);
|
||||
}
|
||||
|
||||
public void setByte(int index, byte value) {
|
||||
checkIndex(index);
|
||||
buffer.setByte(index + adjustment, value);
|
||||
}
|
||||
|
||||
public void setShort(int index, short value) {
|
||||
checkIndex(index, 2);
|
||||
buffer.setShort(index + adjustment, value);
|
||||
}
|
||||
|
||||
public void setMedium(int index, int value) {
|
||||
checkIndex(index, 3);
|
||||
buffer.setMedium(index + adjustment, value);
|
||||
}
|
||||
|
||||
public void setInt(int index, int value) {
|
||||
checkIndex(index, 4);
|
||||
buffer.setInt(index + adjustment, value);
|
||||
}
|
||||
|
||||
public void setLong(int index, long value) {
|
||||
checkIndex(index, 8);
|
||||
buffer.setLong(index + adjustment, value);
|
||||
}
|
||||
|
||||
public void setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.setBytes(index + adjustment, src, srcIndex, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.setBytes(index + adjustment, src, srcIndex, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ByteBuffer src) {
|
||||
checkIndex(index, src.remaining());
|
||||
buffer.setBytes(index + adjustment, src);
|
||||
}
|
||||
|
||||
public void getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
checkIndex(index, length);
|
||||
buffer.getBytes(index + adjustment, out, length);
|
||||
}
|
||||
|
||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
checkIndex(index, length);
|
||||
return buffer.getBytes(index + adjustment, out, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, InputStream in, int length)
|
||||
throws IOException {
|
||||
checkIndex(index, length);
|
||||
buffer.setBytes(index + adjustment, in, length);
|
||||
}
|
||||
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length)
|
||||
throws IOException {
|
||||
checkIndex(index, length);
|
||||
return buffer.setBytes(index + adjustment, in, length);
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBuffer(int index, int length) {
|
||||
checkIndex(index, length);
|
||||
return buffer.toByteBuffer(index + adjustment, length);
|
||||
}
|
||||
|
||||
private void checkIndex(int index) {
|
||||
if (index < 0 || index >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIndex(int startIndex, int length) {
|
||||
if (length < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"length is negative: " + length);
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
if (startIndex + length > capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
*/
|
||||
public class TruncatedChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
|
||||
|
||||
private final ChannelBuffer buffer;
|
||||
private final int length;
|
||||
|
||||
public TruncatedChannelBuffer(ChannelBuffer buffer, int length) {
|
||||
if (length > buffer.capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
this.buffer = buffer;
|
||||
this.length = length;
|
||||
writerIndex(length);
|
||||
}
|
||||
|
||||
public ChannelBuffer unwrap() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public ByteOrder order() {
|
||||
return buffer.order();
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public byte getByte(int index) {
|
||||
checkIndex(index);
|
||||
return buffer.getByte(index);
|
||||
}
|
||||
|
||||
public short getShort(int index) {
|
||||
checkIndex(index, 2);
|
||||
return buffer.getShort(index);
|
||||
}
|
||||
|
||||
public int getMedium(int index) {
|
||||
checkIndex(index, 3);
|
||||
return buffer.getMedium(index);
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
checkIndex(index, 4);
|
||||
return buffer.getInt(index);
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
checkIndex(index, 8);
|
||||
return buffer.getLong(index);
|
||||
}
|
||||
|
||||
public ChannelBuffer duplicate() {
|
||||
return new TruncatedChannelBuffer(buffer, length);
|
||||
}
|
||||
|
||||
public ChannelBuffer copy(int index, int length) {
|
||||
return buffer.copy(index, length);
|
||||
}
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
checkIndex(index, length);
|
||||
return buffer.slice(index, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.getBytes(index, dst, dstIndex, length);
|
||||
}
|
||||
|
||||
public void getBytes(int index, ByteBuffer dst) {
|
||||
checkIndex(index, dst.remaining());
|
||||
buffer.getBytes(index, dst);
|
||||
}
|
||||
|
||||
public void setByte(int index, byte value) {
|
||||
checkIndex(index);
|
||||
buffer.setByte(index, value);
|
||||
}
|
||||
|
||||
public void setShort(int index, short value) {
|
||||
checkIndex(index, 2);
|
||||
buffer.setShort(index, value);
|
||||
}
|
||||
|
||||
public void setMedium(int index, int value) {
|
||||
checkIndex(index, 3);
|
||||
buffer.setMedium(index, value);
|
||||
}
|
||||
|
||||
public void setInt(int index, int value) {
|
||||
checkIndex(index, 4);
|
||||
buffer.setInt(index, value);
|
||||
}
|
||||
|
||||
public void setLong(int index, long value) {
|
||||
checkIndex(index, 8);
|
||||
buffer.setLong(index, value);
|
||||
}
|
||||
|
||||
public void setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.setBytes(index, src, srcIndex, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
|
||||
checkIndex(index, length);
|
||||
buffer.setBytes(index, src, srcIndex, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, ByteBuffer src) {
|
||||
checkIndex(index, src.remaining());
|
||||
buffer.setBytes(index, src);
|
||||
}
|
||||
|
||||
public void getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
checkIndex(index, length);
|
||||
buffer.getBytes(index, out, length);
|
||||
}
|
||||
|
||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
checkIndex(index, length);
|
||||
return buffer.getBytes(index, out, length);
|
||||
}
|
||||
|
||||
public void setBytes(int index, InputStream in, int length)
|
||||
throws IOException {
|
||||
checkIndex(index, length);
|
||||
buffer.setBytes(index, in, length);
|
||||
}
|
||||
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length)
|
||||
throws IOException {
|
||||
checkIndex(index, length);
|
||||
return buffer.setBytes(index, in, length);
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBuffer(int index, int length) {
|
||||
checkIndex(index, length);
|
||||
return buffer.toByteBuffer(index, length);
|
||||
}
|
||||
|
||||
private void checkIndex(int index) {
|
||||
if (index < 0 || index >= capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIndex(int index, int length) {
|
||||
if (length < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"length is negative: " + length);
|
||||
}
|
||||
if (index + length > capacity()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
*/
|
||||
public interface WrappedChannelBuffer extends ChannelBuffer {
|
||||
ChannelBuffer unwrap();
|
||||
}
|
26
src/main/java/net/gleamynode/netty/buffer/package-info.java
Normal file
26
src/main/java/net/gleamynode/netty/buffer/package-info.java
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstraction of a byte-level buffer - the fundamental data structure
|
||||
* to represent low-level binary and text messages.
|
||||
*
|
||||
* @apiviz.landmark
|
||||
* @apiviz.exclude ^java\.io\.[^\.]+Stream$
|
||||
*/
|
||||
package net.gleamynode.netty.buffer;
|
187
src/main/java/net/gleamynode/netty/channel/AbstractChannel.java
Normal file
187
src/main/java/net/gleamynode/netty/channel/AbstractChannel.java
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.gleamynode.netty.util.TimeBasedUuidGenerator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractChannel implements Channel, Comparable<Channel> {
|
||||
|
||||
private final UUID id = TimeBasedUuidGenerator.generate();
|
||||
private final Channel parent;
|
||||
private final ChannelFactory factory;
|
||||
private final ChannelPipeline pipeline;
|
||||
private final ChannelFuture succeededFuture = new SucceededChannelFuture(this);
|
||||
|
||||
private final AtomicBoolean closed = new AtomicBoolean();
|
||||
private volatile int interestOps = OP_READ;
|
||||
|
||||
/** Cache for the string representation of this channel */
|
||||
private String strVal;
|
||||
|
||||
protected AbstractChannel(
|
||||
Channel parent, ChannelFactory factory,
|
||||
ChannelPipeline pipeline, ChannelSink sink) {
|
||||
|
||||
this.parent = parent;
|
||||
this.factory = factory;
|
||||
this.pipeline = pipeline;
|
||||
pipeline.attach(this, sink);
|
||||
}
|
||||
|
||||
public final UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Channel getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public ChannelFactory getFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
protected ChannelFuture getSucceededFuture() {
|
||||
return succeededFuture;
|
||||
}
|
||||
|
||||
protected ChannelFuture getUnsupportedOperationFuture() {
|
||||
return new FailedChannelFuture(this, new UnsupportedOperationException());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return System.identityHashCode(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
return this == o;
|
||||
}
|
||||
|
||||
public int compareTo(Channel o) {
|
||||
return System.identityHashCode(this) - System.identityHashCode(o);
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return !closed.get();
|
||||
}
|
||||
|
||||
protected boolean setClosed() {
|
||||
return closed.compareAndSet(false, true);
|
||||
}
|
||||
|
||||
public ChannelFuture bind(SocketAddress localAddress) {
|
||||
return Channels.bind(this, localAddress);
|
||||
}
|
||||
|
||||
public ChannelFuture close() {
|
||||
return Channels.close(this);
|
||||
}
|
||||
|
||||
public ChannelFuture connect(SocketAddress remoteAddress) {
|
||||
return Channels.connect(this, remoteAddress);
|
||||
}
|
||||
|
||||
public ChannelFuture disconnect() {
|
||||
return Channels.disconnect(this);
|
||||
}
|
||||
|
||||
public int getInterestOps() {
|
||||
return interestOps;
|
||||
}
|
||||
|
||||
public ChannelFuture setInterestOps(int interestOps) {
|
||||
return Channels.setInterestOps(this, interestOps);
|
||||
}
|
||||
|
||||
protected void setInterestOpsNow(int interestOps) {
|
||||
this.interestOps = interestOps;
|
||||
}
|
||||
|
||||
public boolean isReadable() {
|
||||
return (getInterestOps() & OP_READ) != 0;
|
||||
}
|
||||
|
||||
public boolean isWritable() {
|
||||
return (getInterestOps() & OP_WRITE) == 0;
|
||||
}
|
||||
|
||||
public ChannelFuture setReadable(boolean readable) {
|
||||
if (readable) {
|
||||
return setInterestOps(getInterestOps() | OP_READ);
|
||||
} else {
|
||||
return setInterestOps(getInterestOps() & ~OP_READ);
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelFuture write(Object message) {
|
||||
return Channels.write(this, message);
|
||||
}
|
||||
|
||||
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
|
||||
return Channels.write(this, message, remoteAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (strVal != null) {
|
||||
return strVal;
|
||||
}
|
||||
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
buf.append(getClass().getSimpleName());
|
||||
buf.append("(id: ");
|
||||
buf.append(id.toString());
|
||||
|
||||
if (isConnected()) {
|
||||
buf.append(", ");
|
||||
if (getParent() == null) {
|
||||
buf.append(getLocalAddress());
|
||||
buf.append(" => ");
|
||||
buf.append(getRemoteAddress());
|
||||
} else {
|
||||
buf.append(getRemoteAddress());
|
||||
buf.append(" => ");
|
||||
buf.append(getLocalAddress());
|
||||
}
|
||||
} else if (isBound()) {
|
||||
buf.append(", ");
|
||||
buf.append(getLocalAddress());
|
||||
}
|
||||
|
||||
buf.append(')');
|
||||
|
||||
return strVal = buf.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public abstract class AbstractChannelSink implements ChannelSink {
|
||||
|
||||
public void exceptionCaught(ChannelPipeline pipeline,
|
||||
ChannelEvent event, ChannelPipelineException cause) throws Exception {
|
||||
Throwable actualCause = cause.getCause();
|
||||
if (actualCause == null) {
|
||||
actualCause = cause;
|
||||
}
|
||||
|
||||
fireExceptionCaught(event.getChannel(), actualCause);
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractServerChannel extends AbstractChannel {
|
||||
|
||||
protected AbstractServerChannel(
|
||||
ChannelFactory factory,
|
||||
ChannelPipeline pipeline,
|
||||
ChannelSink sink) {
|
||||
super(null, factory, pipeline, sink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture connect(SocketAddress remoteAddress) {
|
||||
return getUnsupportedOperationFuture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture disconnect() {
|
||||
return getUnsupportedOperationFuture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInterestOps() {
|
||||
return OP_NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture setInterestOps(int interestOps) {
|
||||
return getUnsupportedOperationFuture();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setInterestOpsNow(int interestOps) {
|
||||
// Ignore.
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture write(Object message) {
|
||||
return getUnsupportedOperationFuture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
|
||||
return getUnsupportedOperationFuture();
|
||||
}
|
||||
|
||||
}
|
67
src/main/java/net/gleamynode/netty/channel/Channel.java
Normal file
67
src/main/java/net/gleamynode/netty/channel/Channel.java
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
* @apiviz.composedOf net.gleamynode.netty.channel.ChannelConfig
|
||||
* @apiviz.composedOf net.gleamynode.netty.channel.ChannelPipeline
|
||||
*/
|
||||
public interface Channel {
|
||||
static int OP_NONE = 0;
|
||||
static int OP_READ = 1;
|
||||
static int OP_WRITE = 4;
|
||||
static int OP_READ_WRITE = OP_READ | OP_WRITE;
|
||||
|
||||
UUID getId();
|
||||
ChannelFactory getFactory();
|
||||
Channel getParent();
|
||||
ChannelConfig getConfig();
|
||||
ChannelPipeline getPipeline();
|
||||
|
||||
boolean isOpen();
|
||||
boolean isBound();
|
||||
boolean isConnected();
|
||||
|
||||
SocketAddress getLocalAddress();
|
||||
SocketAddress getRemoteAddress();
|
||||
|
||||
ChannelFuture write(Object message);
|
||||
ChannelFuture write(Object message, SocketAddress remoteAddress);
|
||||
|
||||
ChannelFuture bind(SocketAddress localAddress);
|
||||
ChannelFuture connect(SocketAddress remoteAddress);
|
||||
ChannelFuture disconnect();
|
||||
ChannelFuture close();
|
||||
|
||||
int getInterestOps();
|
||||
boolean isReadable();
|
||||
boolean isWritable();
|
||||
ChannelFuture setInterestOps(int interestOps);
|
||||
ChannelFuture setReadable(boolean readable);
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.has net.gleamynode.netty.channel.ChannelPipelineFactory
|
||||
*/
|
||||
public interface ChannelConfig {
|
||||
void setOptions(Map<String, Object> options);
|
||||
ChannelPipelineFactory getPipelineFactory();
|
||||
void setPipelineFactory(ChannelPipelineFactory pipelineFactory);
|
||||
int getConnectTimeoutMillis();
|
||||
void setConnectTimeoutMillis(int connectTimeoutMillis);
|
||||
int getWriteTimeoutMillis();
|
||||
void setWriteTimeoutMillis(int writeTimeoutMillis);
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
*/
|
||||
public interface ChannelDownstreamHandler extends ChannelHandler {
|
||||
void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception;
|
||||
}
|
33
src/main/java/net/gleamynode/netty/channel/ChannelEvent.java
Normal file
33
src/main/java/net/gleamynode/netty/channel/ChannelEvent.java
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
* @apiviz.composedOf net.gleamynode.netty.channel.ChannelFuture
|
||||
*/
|
||||
public interface ChannelEvent {
|
||||
Channel getChannel();
|
||||
ChannelFuture getFuture();
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.hidden
|
||||
*/
|
||||
public class ChannelException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 2908618315971075004L;
|
||||
|
||||
public ChannelException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ChannelException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ChannelException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ChannelException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
* @apiviz.has net.gleamynode.netty.channel.Channel oneway - - creates
|
||||
*/
|
||||
public interface ChannelFactory {
|
||||
Channel newChannel(ChannelPipeline pipeline);
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
* @apiviz.owns net.gleamynode.netty.channel.ChannelFutureListener - - notifies
|
||||
*/
|
||||
public interface ChannelFuture {
|
||||
Channel getChannel();
|
||||
|
||||
boolean isDone();
|
||||
boolean isCancelled();
|
||||
boolean isSuccess();
|
||||
Throwable getCause();
|
||||
|
||||
boolean cancel();
|
||||
|
||||
void setSuccess();
|
||||
void setFailure(Throwable cause);
|
||||
|
||||
void addListener(ChannelFutureListener listener);
|
||||
void removeListener(ChannelFutureListener listener);
|
||||
|
||||
ChannelFuture await() throws InterruptedException;
|
||||
ChannelFuture awaitUninterruptibly();
|
||||
boolean await(long timeout, TimeUnit unit) throws InterruptedException;
|
||||
boolean await(long timeoutMillis) throws InterruptedException;
|
||||
boolean awaitUninterruptibly(long timeout, TimeUnit unit);
|
||||
boolean awaitUninterruptibly(long timeoutMillis);
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
*/
|
||||
public interface ChannelFutureListener extends EventListener {
|
||||
/**
|
||||
* An {@link ChannelFutureListener} that closes the {@link Channel} which is
|
||||
* associated with the specified {@link ChannelFuture}.
|
||||
*/
|
||||
static ChannelFutureListener CLOSE = new ChannelFutureListener() {
|
||||
public void operationComplete(ChannelFuture future) {
|
||||
future.getChannel().close();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Invoked when the operation associated with the {@link ChannelFuture}
|
||||
* has been completed.
|
||||
*
|
||||
* @param future The source {@link ChannelFuture} which called this
|
||||
* callback.
|
||||
*/
|
||||
void operationComplete(ChannelFuture future) throws Exception;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public interface ChannelHandler {
|
||||
// Thsi is a tag interface.
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.owns net.gleamynode.netty.channel.ChannelHandler
|
||||
*/
|
||||
public interface ChannelHandlerContext {
|
||||
ChannelPipeline getPipeline();
|
||||
|
||||
String getName();
|
||||
ChannelHandler getHandler();
|
||||
boolean canHandleUpstream();
|
||||
boolean canHandleDownstream();
|
||||
|
||||
void sendUpstream(ChannelEvent e);
|
||||
void sendDownstream(ChannelEvent e);
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
* @apiviz.composedOf net.gleamynode.netty.channel.ChannelHandlerContext
|
||||
* @apiviz.owns net.gleamynode.netty.channel.ChannelHandler
|
||||
* @apiviz.uses net.gleamynode.netty.channel.ChannelSink - - sends events downstream
|
||||
*/
|
||||
public interface ChannelPipeline {
|
||||
void addFirst (String name, ChannelHandler handler);
|
||||
void addLast (String name, ChannelHandler handler);
|
||||
void addBefore(String baseName, String name, ChannelHandler handler);
|
||||
void addAfter (String baseName, String name, ChannelHandler handler);
|
||||
|
||||
void remove(ChannelHandler handler);
|
||||
ChannelHandler remove(String name);
|
||||
<T extends ChannelHandler> T remove(Class<T> handlerType);
|
||||
ChannelHandler removeFirst();
|
||||
ChannelHandler removeLast();
|
||||
|
||||
void replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
|
||||
ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);
|
||||
<T extends ChannelHandler> T replace(Class<T> oldHandlerType, String newName, ChannelHandler newHandler);
|
||||
|
||||
ChannelHandler getFirst();
|
||||
ChannelHandler getLast();
|
||||
|
||||
ChannelHandler get(String name);
|
||||
<T extends ChannelHandler> T get(Class<T> handlerType);
|
||||
|
||||
ChannelHandlerContext getContext(ChannelHandler handler);
|
||||
ChannelHandlerContext getContext(String name);
|
||||
ChannelHandlerContext getContext(Class<? extends ChannelHandler> handlerType);
|
||||
|
||||
void sendUpstream(ChannelEvent e);
|
||||
void sendDownstream(ChannelEvent e);
|
||||
|
||||
Channel getChannel();
|
||||
ChannelSink getSink();
|
||||
void attach(Channel channel, ChannelSink sink);
|
||||
|
||||
Map<String, ChannelHandler> toMap();
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ChannelPipelineCoverage {
|
||||
public static final String ALL = "all";
|
||||
public static final String ONE = "one";
|
||||
|
||||
String value();
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.hidden
|
||||
*/
|
||||
public class ChannelPipelineException extends ChannelException {
|
||||
|
||||
private static final long serialVersionUID = 3379174210419885980L;
|
||||
|
||||
public ChannelPipelineException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ChannelPipelineException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ChannelPipelineException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ChannelPipelineException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.has net.gleamynode.netty.channel.ChannelPipeline oneway - - creates
|
||||
*/
|
||||
public interface ChannelPipelineFactory {
|
||||
ChannelPipeline getPipeline() throws Exception;
|
||||
}
|
33
src/main/java/net/gleamynode/netty/channel/ChannelSink.java
Normal file
33
src/main/java/net/gleamynode/netty/channel/ChannelSink.java
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.uses net.gleamynode.netty.channel.ChannelPipeline - - sends events upstream
|
||||
*/
|
||||
public interface ChannelSink {
|
||||
void eventSunk(ChannelPipeline pipeline, ChannelEvent e) throws Exception;
|
||||
void exceptionCaught(ChannelPipeline pipeline, ChannelEvent e, ChannelPipelineException cause) throws Exception;
|
||||
}
|
32
src/main/java/net/gleamynode/netty/channel/ChannelState.java
Normal file
32
src/main/java/net/gleamynode/netty/channel/ChannelState.java
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public enum ChannelState {
|
||||
OPEN,
|
||||
BOUND,
|
||||
CONNECTED,
|
||||
INTEREST_OPS,
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.has net.gleamynode.netty.channel.ChannelState
|
||||
*/
|
||||
public interface ChannelStateEvent extends ChannelEvent {
|
||||
ChannelState getState();
|
||||
Object getValue();
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
*/
|
||||
public interface ChannelUpstreamHandler extends ChannelHandler {
|
||||
void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception;
|
||||
}
|
369
src/main/java/net/gleamynode/netty/channel/Channels.java
Normal file
369
src/main/java/net/gleamynode/netty/channel/Channels.java
Normal file
@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.landmark
|
||||
*/
|
||||
public class Channels {
|
||||
|
||||
// pipeline factory methods
|
||||
|
||||
public static ChannelPipeline pipeline() {
|
||||
return new DefaultChannelPipeline();
|
||||
}
|
||||
|
||||
public static ChannelPipeline pipeline(ChannelPipeline pipeline) {
|
||||
ChannelPipeline newPipeline = pipeline();
|
||||
for (Map.Entry<String, ChannelHandler> e: pipeline.toMap().entrySet()) {
|
||||
newPipeline.addLast(e.getKey(), e.getValue());
|
||||
}
|
||||
return newPipeline;
|
||||
}
|
||||
|
||||
public static ChannelPipelineFactory pipelineFactory(
|
||||
final ChannelPipeline pipeline) {
|
||||
return new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() {
|
||||
return pipeline(pipeline);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// future factory methods
|
||||
|
||||
public static ChannelFuture future(Channel channel) {
|
||||
return future(channel, false);
|
||||
}
|
||||
|
||||
public static ChannelFuture future(Channel channel, boolean cancellable) {
|
||||
return new DefaultChannelFuture(channel, cancellable);
|
||||
}
|
||||
|
||||
public static ChannelFuture succeededFuture(Channel channel) {
|
||||
if (channel instanceof AbstractChannel) {
|
||||
return ((AbstractChannel) channel).getSucceededFuture();
|
||||
} else {
|
||||
return new SucceededChannelFuture(channel);
|
||||
}
|
||||
}
|
||||
|
||||
public static ChannelFuture failedFuture(Channel channel, Throwable cause) {
|
||||
return new FailedChannelFuture(channel, cause);
|
||||
}
|
||||
|
||||
// event factory methods
|
||||
|
||||
public static MessageEvent messageEvent(Channel channel, ChannelFuture future, Object message) {
|
||||
return messageEvent(channel, future, message, null);
|
||||
}
|
||||
|
||||
public static MessageEvent messageEvent(Channel channel, ChannelFuture future, Object message, SocketAddress remoteAddress) {
|
||||
return new DefaultMessageEvent(channel, future, message, remoteAddress);
|
||||
}
|
||||
|
||||
// event emission methods
|
||||
|
||||
public static void fireChannelOpen(Channel channel) {
|
||||
if (channel.getParent() != null) {
|
||||
fireChildChannelStateChanged(channel.getParent(), channel);
|
||||
}
|
||||
channel.getPipeline().sendUpstream(
|
||||
new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.OPEN, Boolean.TRUE));
|
||||
}
|
||||
|
||||
public static void fireChannelOpen(
|
||||
ChannelHandlerContext ctx, Channel channel) {
|
||||
|
||||
ctx.sendUpstream(new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.OPEN, Boolean.TRUE));
|
||||
}
|
||||
|
||||
public static void fireChannelBound(Channel channel, SocketAddress localAddress) {
|
||||
channel.getPipeline().sendUpstream(
|
||||
new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.BOUND, localAddress));
|
||||
}
|
||||
|
||||
public static void fireChannelBound(
|
||||
ChannelHandlerContext ctx, Channel channel, SocketAddress localAddress) {
|
||||
|
||||
ctx.sendUpstream(new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.BOUND, localAddress));
|
||||
}
|
||||
|
||||
public static void fireChannelConnected(Channel channel, SocketAddress remoteAddress) {
|
||||
channel.getPipeline().sendUpstream(
|
||||
new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.CONNECTED, remoteAddress));
|
||||
}
|
||||
|
||||
public static void fireChannelConnected(
|
||||
ChannelHandlerContext ctx, Channel channel, SocketAddress remoteAddress) {
|
||||
|
||||
ctx.sendUpstream(new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.CONNECTED, remoteAddress));
|
||||
}
|
||||
|
||||
public static void fireMessageReceived(Channel channel, Object message) {
|
||||
fireMessageReceived(channel, message, null);
|
||||
}
|
||||
|
||||
public static void fireMessageReceived(Channel channel, Object message, SocketAddress remoteAddress) {
|
||||
channel.getPipeline().sendUpstream(
|
||||
new DefaultMessageEvent(
|
||||
channel, succeededFuture(channel),
|
||||
message, remoteAddress));
|
||||
}
|
||||
|
||||
public static void fireMessageReceived(
|
||||
ChannelHandlerContext ctx, Channel channel, Object message) {
|
||||
ctx.sendUpstream(new DefaultMessageEvent(
|
||||
channel, succeededFuture(channel), message, null));
|
||||
}
|
||||
|
||||
public static void fireMessageReceived(
|
||||
ChannelHandlerContext ctx, Channel channel,
|
||||
Object message, SocketAddress remoteAddress) {
|
||||
ctx.sendUpstream(new DefaultMessageEvent(
|
||||
channel, succeededFuture(channel), message, remoteAddress));
|
||||
}
|
||||
|
||||
public static void fireChannelInterestChanged(Channel channel, int interestOps) {
|
||||
validateInterestOps(interestOps);
|
||||
channel.getPipeline().sendUpstream(
|
||||
new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.INTEREST_OPS, Integer.valueOf(interestOps)));
|
||||
}
|
||||
|
||||
public static void fireChannelInterestChanged(
|
||||
ChannelHandlerContext ctx, Channel channel, int interestOps) {
|
||||
|
||||
validateInterestOps(interestOps);
|
||||
ctx.sendUpstream(
|
||||
new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.INTEREST_OPS, Integer.valueOf(interestOps)));
|
||||
}
|
||||
|
||||
public static void fireChannelDisconnected(Channel channel) {
|
||||
channel.getPipeline().sendUpstream(
|
||||
new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.CONNECTED, null));
|
||||
}
|
||||
|
||||
public static void fireChannelDisconnected(
|
||||
ChannelHandlerContext ctx, Channel channel) {
|
||||
ctx.sendUpstream(new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.CONNECTED, null));
|
||||
}
|
||||
|
||||
public static void fireChannelUnbound(Channel channel) {
|
||||
channel.getPipeline().sendUpstream(new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel), ChannelState.BOUND, null));
|
||||
}
|
||||
|
||||
public static void fireChannelUnbound(
|
||||
ChannelHandlerContext ctx, Channel channel) {
|
||||
|
||||
ctx.sendUpstream(new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel), ChannelState.BOUND, null));
|
||||
}
|
||||
|
||||
public static void fireChannelClosed(Channel channel) {
|
||||
channel.getPipeline().sendUpstream(
|
||||
new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.OPEN, Boolean.FALSE));
|
||||
if (channel.getParent() != null) {
|
||||
fireChildChannelStateChanged(channel.getParent(), channel);
|
||||
}
|
||||
}
|
||||
|
||||
public static void fireChannelClosed(
|
||||
ChannelHandlerContext ctx, Channel channel) {
|
||||
ctx.sendUpstream(
|
||||
new DefaultChannelStateEvent(
|
||||
channel, succeededFuture(channel),
|
||||
ChannelState.OPEN, Boolean.FALSE));
|
||||
}
|
||||
|
||||
public static void fireExceptionCaught(Channel channel, Throwable cause) {
|
||||
channel.getPipeline().sendUpstream(
|
||||
new DefaultExceptionEvent(
|
||||
channel, succeededFuture(channel), cause));
|
||||
}
|
||||
|
||||
public static void fireExceptionCaught(
|
||||
ChannelHandlerContext ctx, Channel channel, Throwable cause) {
|
||||
ctx.sendUpstream(new DefaultExceptionEvent(
|
||||
channel, succeededFuture(channel), cause));
|
||||
}
|
||||
|
||||
private static void fireChildChannelStateChanged(
|
||||
Channel channel, Channel childChannel) {
|
||||
channel.getPipeline().sendUpstream(
|
||||
new DefaultChildChannelStateEvent(
|
||||
channel, succeededFuture(channel), childChannel));
|
||||
}
|
||||
|
||||
public static ChannelFuture bind(Channel channel, SocketAddress localAddress) {
|
||||
ChannelFuture future = future(channel);
|
||||
channel.getPipeline().sendDownstream(new DefaultChannelStateEvent(
|
||||
channel, future, ChannelState.BOUND, localAddress));
|
||||
return future;
|
||||
}
|
||||
|
||||
public static void bind(
|
||||
ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelFuture future, SocketAddress localAddress) {
|
||||
|
||||
ctx.sendDownstream(new DefaultChannelStateEvent(
|
||||
channel, future, ChannelState.BOUND, localAddress));
|
||||
}
|
||||
|
||||
public static ChannelFuture connect(Channel channel, SocketAddress remoteAddress) {
|
||||
ChannelFuture future = future(channel, true);
|
||||
channel.getPipeline().sendDownstream(new DefaultChannelStateEvent(
|
||||
channel, future, ChannelState.CONNECTED, remoteAddress));
|
||||
return future;
|
||||
}
|
||||
|
||||
public static void connect(
|
||||
ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelFuture future, SocketAddress remoteAddress) {
|
||||
|
||||
ctx.sendDownstream(new DefaultChannelStateEvent(
|
||||
channel, future, ChannelState.CONNECTED, remoteAddress));
|
||||
}
|
||||
|
||||
public static ChannelFuture write(Channel channel, Object message) {
|
||||
return write(channel, message, null);
|
||||
}
|
||||
|
||||
public static void write(
|
||||
ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelFuture future, Object message) {
|
||||
write(ctx, channel, future, message, null);
|
||||
}
|
||||
|
||||
public static ChannelFuture write(Channel channel, Object message, SocketAddress remoteAddress) {
|
||||
ChannelFuture future = future(channel);
|
||||
channel.getPipeline().sendDownstream(
|
||||
new DefaultMessageEvent(channel, future, message, remoteAddress));
|
||||
return future;
|
||||
}
|
||||
|
||||
public static void write(
|
||||
ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelFuture future, Object message, SocketAddress remoteAddress) {
|
||||
ctx.sendDownstream(
|
||||
new DefaultMessageEvent(channel, future, message, remoteAddress));
|
||||
}
|
||||
|
||||
public static ChannelFuture setInterestOps(Channel channel, int interestOps) {
|
||||
validateInterestOps(interestOps);
|
||||
validateDownstreamInterestOps(channel, interestOps);
|
||||
|
||||
ChannelFuture future = future(channel);
|
||||
channel.getPipeline().sendDownstream(new DefaultChannelStateEvent(
|
||||
channel, future, ChannelState.INTEREST_OPS, Integer.valueOf(interestOps)));
|
||||
return future;
|
||||
}
|
||||
|
||||
public static void setInterestOps(
|
||||
ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelFuture future, int interestOps) {
|
||||
validateInterestOps(interestOps);
|
||||
validateDownstreamInterestOps(channel, interestOps);
|
||||
|
||||
ctx.sendDownstream(
|
||||
new DefaultChannelStateEvent(
|
||||
channel, future, ChannelState.INTEREST_OPS,
|
||||
Integer.valueOf(interestOps)));
|
||||
}
|
||||
|
||||
public static ChannelFuture disconnect(Channel channel) {
|
||||
ChannelFuture future = future(channel);
|
||||
channel.getPipeline().sendDownstream(new DefaultChannelStateEvent(
|
||||
channel, future, ChannelState.CONNECTED, null));
|
||||
return future;
|
||||
}
|
||||
|
||||
public static void disconnect(
|
||||
ChannelHandlerContext ctx, Channel channel, ChannelFuture future) {
|
||||
ctx.sendDownstream(new DefaultChannelStateEvent(
|
||||
channel, future, ChannelState.CONNECTED, null));
|
||||
}
|
||||
|
||||
public static ChannelFuture close(Channel channel) {
|
||||
ChannelFuture future = future(channel);
|
||||
channel.getPipeline().sendDownstream(new DefaultChannelStateEvent(
|
||||
channel, future, ChannelState.OPEN, Boolean.FALSE));
|
||||
return future;
|
||||
}
|
||||
|
||||
public static void close(
|
||||
ChannelHandlerContext ctx, Channel channel, ChannelFuture future) {
|
||||
ctx.sendDownstream(new DefaultChannelStateEvent(
|
||||
channel, future, ChannelState.OPEN, Boolean.FALSE));
|
||||
}
|
||||
|
||||
private static void validateInterestOps(int interestOps) {
|
||||
switch (interestOps) {
|
||||
case Channel.OP_NONE:
|
||||
case Channel.OP_READ:
|
||||
case Channel.OP_WRITE:
|
||||
case Channel.OP_READ_WRITE:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid interestOps: " + interestOps);
|
||||
}
|
||||
}
|
||||
|
||||
private static void validateDownstreamInterestOps(Channel channel, int interestOps) {
|
||||
if (((channel.getInterestOps() ^ interestOps) & Channel.OP_WRITE) != 0) {
|
||||
throw new IllegalArgumentException("OP_WRITE can't be modified by user.");
|
||||
}
|
||||
}
|
||||
|
||||
private Channels() {
|
||||
// Unused
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public interface ChildChannelStateEvent extends ChannelEvent {
|
||||
Channel getChildChannel();
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
|
||||
public abstract class CompleteChannelFuture implements ChannelFuture {
|
||||
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(CompleteChannelFuture.class);
|
||||
|
||||
private final Channel channel;
|
||||
|
||||
protected CompleteChannelFuture(Channel channel) {
|
||||
if (channel == null) {
|
||||
throw new NullPointerException("channel");
|
||||
}
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public void addListener(ChannelFutureListener listener) {
|
||||
try {
|
||||
listener.operationComplete(this);
|
||||
} catch (Throwable t) {
|
||||
logger.warn(
|
||||
"An exception was thrown by " +
|
||||
ChannelFutureListener.class.getSimpleName() + ".", t);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeListener(ChannelFutureListener listener) {
|
||||
// NOOP
|
||||
}
|
||||
|
||||
public ChannelFuture await() throws InterruptedException {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean await(long timeoutMillis) throws InterruptedException {
|
||||
return true;
|
||||
}
|
||||
|
||||
public ChannelFuture awaitUninterruptibly() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean awaitUninterruptibly(long timeoutMillis) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setFailure(Throwable cause) {
|
||||
// Unused
|
||||
}
|
||||
|
||||
public void setSuccess() {
|
||||
// Unused
|
||||
}
|
||||
|
||||
public boolean cancel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
public class DefaultChannelEvent implements ChannelEvent {
|
||||
|
||||
private final Channel channel;
|
||||
private final ChannelFuture future;
|
||||
|
||||
public DefaultChannelEvent(Channel channel, ChannelFuture future) {
|
||||
if (channel == null) {
|
||||
throw new NullPointerException("channel");
|
||||
}
|
||||
if (future == null) {
|
||||
throw new NullPointerException("future");
|
||||
}
|
||||
this.channel = channel;
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
public final Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public final ChannelFuture getFuture() {
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return channel.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
|
||||
|
||||
public class DefaultChannelFuture implements ChannelFuture {
|
||||
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(DefaultChannelFuture.class);
|
||||
private static final int DEAD_LOCK_CHECK_INTERVAL = 5000;
|
||||
private static final Throwable CANCELLED = new Throwable();
|
||||
|
||||
private final Channel channel;
|
||||
private final boolean cancellable;
|
||||
|
||||
private ChannelFutureListener firstListener;
|
||||
private List<ChannelFutureListener> otherListeners;
|
||||
private boolean done;
|
||||
private Throwable cause;
|
||||
private int waiters;
|
||||
|
||||
public DefaultChannelFuture(Channel channel, boolean cancellable) {
|
||||
this.channel = channel;
|
||||
this.cancellable = cancellable;
|
||||
}
|
||||
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public synchronized boolean isDone() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public synchronized boolean isSuccess() {
|
||||
return cause == null;
|
||||
}
|
||||
|
||||
public synchronized Throwable getCause() {
|
||||
if (cause != CANCELLED) {
|
||||
return cause;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean isCancelled() {
|
||||
return cause == CANCELLED;
|
||||
}
|
||||
|
||||
public void addListener(ChannelFutureListener listener) {
|
||||
if (listener == null) {
|
||||
throw new NullPointerException("listener");
|
||||
}
|
||||
|
||||
boolean notifyNow = false;
|
||||
synchronized (this) {
|
||||
if (done) {
|
||||
notifyNow = true;
|
||||
} else {
|
||||
if (firstListener == null) {
|
||||
firstListener = listener;
|
||||
} else {
|
||||
if (otherListeners == null) {
|
||||
otherListeners = new ArrayList<ChannelFutureListener>(1);
|
||||
}
|
||||
otherListeners.add(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (notifyNow) {
|
||||
notifyListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeListener(ChannelFutureListener listener) {
|
||||
if (listener == null) {
|
||||
throw new NullPointerException("listener");
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (!done) {
|
||||
if (listener == firstListener) {
|
||||
if (otherListeners != null && !otherListeners.isEmpty()) {
|
||||
firstListener = otherListeners.remove(0);
|
||||
} else {
|
||||
firstListener = null;
|
||||
}
|
||||
} else if (otherListeners != null) {
|
||||
otherListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelFuture await() throws InterruptedException {
|
||||
synchronized (this) {
|
||||
while (!done) {
|
||||
waiters++;
|
||||
try {
|
||||
this.wait(DEAD_LOCK_CHECK_INTERVAL);
|
||||
checkDeadLock();
|
||||
} finally {
|
||||
waiters--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean await(long timeout, TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
return await(unit.toMillis(timeout));
|
||||
}
|
||||
|
||||
public boolean await(long timeoutMillis) throws InterruptedException {
|
||||
return await0(timeoutMillis, true);
|
||||
}
|
||||
|
||||
public ChannelFuture awaitUninterruptibly() {
|
||||
synchronized (this) {
|
||||
while (!done) {
|
||||
waiters++;
|
||||
try {
|
||||
this.wait(DEAD_LOCK_CHECK_INTERVAL);
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore.
|
||||
} finally {
|
||||
waiters--;
|
||||
if (!done) {
|
||||
checkDeadLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
|
||||
return awaitUninterruptibly(unit.toMillis(timeout));
|
||||
}
|
||||
|
||||
public boolean awaitUninterruptibly(long timeoutMillis) {
|
||||
try {
|
||||
return await0(timeoutMillis, false);
|
||||
} catch (InterruptedException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean await0(long timeoutMillis, boolean interruptable) throws InterruptedException {
|
||||
long startTime = timeoutMillis <= 0 ? 0 : System.currentTimeMillis();
|
||||
long waitTime = timeoutMillis;
|
||||
|
||||
synchronized (this) {
|
||||
if (done) {
|
||||
return done;
|
||||
} else if (waitTime <= 0) {
|
||||
return done;
|
||||
}
|
||||
|
||||
waiters++;
|
||||
try {
|
||||
for (;;) {
|
||||
try {
|
||||
this.wait(Math.min(waitTime, DEAD_LOCK_CHECK_INTERVAL));
|
||||
} catch (InterruptedException e) {
|
||||
if (interruptable) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (done) {
|
||||
return true;
|
||||
} else {
|
||||
waitTime = timeoutMillis
|
||||
- (System.currentTimeMillis() - startTime);
|
||||
if (waitTime <= 0) {
|
||||
return done;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
waiters--;
|
||||
if (!done) {
|
||||
checkDeadLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDeadLock() {
|
||||
// IllegalStateException e = new IllegalStateException(
|
||||
// "DEAD LOCK: " + ChannelFuture.class.getSimpleName() +
|
||||
// ".await() was invoked from an I/O processor thread. " +
|
||||
// "Please use " + ChannelFutureListener.class.getSimpleName() +
|
||||
// " or configure a proper thread model alternatively.");
|
||||
//
|
||||
// StackTraceElement[] stackTrace = e.getStackTrace();
|
||||
//
|
||||
// // Simple and quick check.
|
||||
// for (StackTraceElement s: stackTrace) {
|
||||
// if (AbstractPollingIoProcessor.class.getName().equals(s.getClassName())) {
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // And then more precisely.
|
||||
// for (StackTraceElement s: stackTrace) {
|
||||
// try {
|
||||
// Class<?> cls = DefaultChannelFuture.class.getClassLoader().loadClass(s.getClassName());
|
||||
// if (IoProcessor.class.isAssignableFrom(cls)) {
|
||||
// throw e;
|
||||
// }
|
||||
// } catch (Exception cnfe) {
|
||||
// // Ignore
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public void setSuccess() {
|
||||
synchronized (this) {
|
||||
// Allow only once.
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
done = true;
|
||||
if (waiters > 0) {
|
||||
this.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public void setFailure(Throwable cause) {
|
||||
synchronized (this) {
|
||||
// Allow only once.
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.cause = cause;
|
||||
done = true;
|
||||
if (waiters > 0) {
|
||||
this.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public boolean cancel() {
|
||||
if (!cancellable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
// Allow only once.
|
||||
if (done) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cause = CANCELLED;
|
||||
done = true;
|
||||
if (waiters > 0) {
|
||||
this.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
// There won't be any visibility problem or concurrent modification
|
||||
// because 'ready' flag will be checked against both addListener and
|
||||
// removeListener calls.
|
||||
if (firstListener != null) {
|
||||
notifyListener(firstListener);
|
||||
firstListener = null;
|
||||
|
||||
if (otherListeners != null) {
|
||||
for (ChannelFutureListener l: otherListeners) {
|
||||
notifyListener(l);
|
||||
}
|
||||
otherListeners = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyListener(ChannelFutureListener l) {
|
||||
try {
|
||||
l.operationComplete(this);
|
||||
} catch (Throwable t) {
|
||||
logger.warn(
|
||||
"An exception was thrown by " +
|
||||
ChannelFutureListener.class.getSimpleName() + ".", t);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,548 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import static net.gleamynode.netty.channel.ChannelPipelineCoverage.*;
|
||||
|
||||
import java.lang.annotation.AnnotationFormatError;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
|
||||
|
||||
public class DefaultChannelPipeline implements ChannelPipeline {
|
||||
|
||||
static final Logger logger = Logger.getLogger(DefaultChannelPipeline.class);
|
||||
|
||||
private final ChannelSink discardingSink = new ChannelSink() {
|
||||
public void eventSunk(ChannelPipeline pipeline, ChannelEvent e) {
|
||||
logger.warn("Not attached yet; discarding: " + e);
|
||||
}
|
||||
|
||||
public void exceptionCaught(ChannelPipeline pipeline,
|
||||
ChannelEvent e, ChannelPipelineException cause) throws Exception {
|
||||
throw cause;
|
||||
}
|
||||
};
|
||||
|
||||
private volatile Channel channel;
|
||||
private volatile ChannelSink sink;
|
||||
private volatile DefaultChannelHandlerContext head;
|
||||
private volatile DefaultChannelHandlerContext tail;
|
||||
private final Map<String, DefaultChannelHandlerContext> name2ctx =
|
||||
new HashMap<String, DefaultChannelHandlerContext>(4);
|
||||
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public ChannelSink getSink() {
|
||||
ChannelSink sink = this.sink;
|
||||
if (sink == null) {
|
||||
return discardingSink;
|
||||
}
|
||||
return sink;
|
||||
}
|
||||
|
||||
public void attach(Channel channel, ChannelSink sink) {
|
||||
if (channel == null) {
|
||||
throw new NullPointerException("channel");
|
||||
}
|
||||
if (sink == null) {
|
||||
throw new NullPointerException("sink");
|
||||
}
|
||||
if (this.channel != null || this.sink != null) {
|
||||
throw new IllegalStateException("attached already");
|
||||
}
|
||||
this.channel = channel;
|
||||
this.sink = sink;
|
||||
}
|
||||
|
||||
public synchronized void addFirst(String name, ChannelHandler handler) {
|
||||
if (name2ctx.isEmpty()) {
|
||||
init(name, handler);
|
||||
} else {
|
||||
checkDuplicateName(name);
|
||||
DefaultChannelHandlerContext oldHead = head;
|
||||
DefaultChannelHandlerContext newHead = new DefaultChannelHandlerContext(null, oldHead, name, handler);
|
||||
oldHead.prev = newHead;
|
||||
head = newHead;
|
||||
name2ctx.put(name, newHead);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void addLast(String name, ChannelHandler handler) {
|
||||
if (name2ctx.isEmpty()) {
|
||||
init(name, handler);
|
||||
} else {
|
||||
checkDuplicateName(name);
|
||||
DefaultChannelHandlerContext oldTail = tail;
|
||||
DefaultChannelHandlerContext newTail = new DefaultChannelHandlerContext(oldTail, null, name, handler);
|
||||
oldTail.next = newTail;
|
||||
tail = newTail;
|
||||
name2ctx.put(name, newTail);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void addBefore(String baseName, String name, ChannelHandler handler) {
|
||||
DefaultChannelHandlerContext ctx = getContextOrDie(baseName);
|
||||
if (ctx == head) {
|
||||
addFirst(name, handler);
|
||||
} else {
|
||||
checkDuplicateName(name);
|
||||
DefaultChannelHandlerContext newCtx = new DefaultChannelHandlerContext(ctx.prev, ctx, name, handler);
|
||||
ctx.prev.next = newCtx;
|
||||
ctx.prev = newCtx;
|
||||
name2ctx.put(name, newCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void addAfter(String baseName, String name, ChannelHandler handler) {
|
||||
DefaultChannelHandlerContext ctx = getContextOrDie(baseName);
|
||||
if (ctx == tail) {
|
||||
addLast(name, handler);
|
||||
} else {
|
||||
checkDuplicateName(name);
|
||||
DefaultChannelHandlerContext newCtx = new DefaultChannelHandlerContext(ctx, ctx.next, name, handler);
|
||||
ctx.next.prev = newCtx;
|
||||
ctx.next = newCtx;
|
||||
name2ctx.put(name, newCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void remove(ChannelHandler handler) {
|
||||
remove(getContextOrDie(handler));
|
||||
}
|
||||
|
||||
public synchronized ChannelHandler remove(String name) {
|
||||
return remove(getContextOrDie(name)).getHandler();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized <T extends ChannelHandler> T remove(Class<T> handlerType) {
|
||||
return (T) remove(getContextOrDie(handlerType)).getHandler();
|
||||
}
|
||||
|
||||
private DefaultChannelHandlerContext remove(DefaultChannelHandlerContext ctx) {
|
||||
if (head == tail) {
|
||||
head = tail = null;
|
||||
name2ctx.clear();
|
||||
} else if (ctx == head) {
|
||||
removeFirst();
|
||||
} else if (ctx == tail) {
|
||||
removeLast();
|
||||
} else {
|
||||
DefaultChannelHandlerContext prev = ctx.prev;
|
||||
DefaultChannelHandlerContext next = ctx.next;
|
||||
prev.next = next;
|
||||
next.prev = prev;
|
||||
name2ctx.remove(ctx.getName());
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public synchronized ChannelHandler removeFirst() {
|
||||
if (name2ctx.isEmpty()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
DefaultChannelHandlerContext oldHead = head;
|
||||
oldHead.next.prev = null;
|
||||
head = oldHead.next;
|
||||
name2ctx.remove(oldHead.getName());
|
||||
return oldHead.getHandler();
|
||||
}
|
||||
|
||||
public synchronized ChannelHandler removeLast() {
|
||||
if (name2ctx.isEmpty()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
DefaultChannelHandlerContext oldTail = tail;
|
||||
oldTail.prev.next = null;
|
||||
tail = oldTail.prev;
|
||||
name2ctx.remove(oldTail.getName());
|
||||
return oldTail.getHandler();
|
||||
}
|
||||
|
||||
public synchronized void replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler) {
|
||||
replace(getContextOrDie(oldHandler), newName, newHandler);
|
||||
}
|
||||
|
||||
public synchronized ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler) {
|
||||
return replace(getContextOrDie(oldName), newName, newHandler);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized <T extends ChannelHandler> T replace(
|
||||
Class<T> oldHandlerType, String newName, ChannelHandler newHandler) {
|
||||
return (T) replace(getContextOrDie(oldHandlerType), newName, newHandler);
|
||||
}
|
||||
|
||||
private ChannelHandler replace(DefaultChannelHandlerContext ctx, String newName, ChannelHandler newHandler) {
|
||||
if (ctx == head) {
|
||||
removeFirst();
|
||||
addFirst(newName, newHandler);
|
||||
} else if (ctx == tail) {
|
||||
removeLast();
|
||||
addLast(newName, newHandler);
|
||||
} else {
|
||||
boolean sameName = ctx.getName().equals(newName);
|
||||
if (!sameName) {
|
||||
checkDuplicateName(newName);
|
||||
}
|
||||
DefaultChannelHandlerContext prev = ctx.prev;
|
||||
DefaultChannelHandlerContext next = ctx.next;
|
||||
DefaultChannelHandlerContext newCtx = new DefaultChannelHandlerContext(prev, next, newName, newHandler);
|
||||
prev.next = newCtx;
|
||||
next.prev = newCtx;
|
||||
if (!sameName) {
|
||||
name2ctx.remove(ctx.getName());
|
||||
name2ctx.put(newName, newCtx);
|
||||
}
|
||||
}
|
||||
return ctx.getHandler();
|
||||
}
|
||||
|
||||
public synchronized ChannelHandler getFirst() {
|
||||
return head.getHandler();
|
||||
}
|
||||
|
||||
public synchronized ChannelHandler getLast() {
|
||||
return tail.getHandler();
|
||||
}
|
||||
|
||||
public synchronized ChannelHandler get(String name) {
|
||||
DefaultChannelHandlerContext ctx = name2ctx.get(name);
|
||||
if (ctx == null) {
|
||||
return null;
|
||||
} else {
|
||||
return ctx.getHandler();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized <T extends ChannelHandler> T get(Class<T> handlerType) {
|
||||
ChannelHandlerContext ctx = getContext(handlerType);
|
||||
if (ctx == null) {
|
||||
return null;
|
||||
} else {
|
||||
return (T) ctx.getHandler();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized ChannelHandlerContext getContext(String name) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
return name2ctx.get(name);
|
||||
}
|
||||
|
||||
public synchronized ChannelHandlerContext getContext(ChannelHandler handler) {
|
||||
if (handler == null) {
|
||||
throw new NullPointerException("handler");
|
||||
}
|
||||
if (name2ctx.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
DefaultChannelHandlerContext ctx = head;
|
||||
for (;;) {
|
||||
if (ctx.getHandler() == handler) {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
ctx = ctx.next;
|
||||
if (ctx == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized ChannelHandlerContext getContext(
|
||||
Class<? extends ChannelHandler> handlerType) {
|
||||
if (name2ctx.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
DefaultChannelHandlerContext ctx = head;
|
||||
for (;;) {
|
||||
if (handlerType.isAssignableFrom(ctx.getHandler().getClass())) {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
ctx = ctx.next;
|
||||
if (ctx == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, ChannelHandler> toMap() {
|
||||
Map<String, ChannelHandler> map = new LinkedHashMap<String, ChannelHandler>();
|
||||
if (name2ctx.isEmpty()) {
|
||||
return map;
|
||||
}
|
||||
|
||||
DefaultChannelHandlerContext ctx = head;
|
||||
for (;;) {
|
||||
map.put(ctx.getName(), ctx.getHandler());
|
||||
ctx = ctx.next;
|
||||
if (ctx == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public void sendUpstream(ChannelEvent e) {
|
||||
DefaultChannelHandlerContext head = getActualUpstreamContext(this.head);
|
||||
if (head == null) {
|
||||
logger.warn(
|
||||
"The pipeline contains no upstream handlers; discarding: " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
sendUpstream(head, e);
|
||||
}
|
||||
|
||||
void sendUpstream(DefaultChannelHandlerContext ctx, ChannelEvent e) {
|
||||
try {
|
||||
((ChannelUpstreamHandler) ctx.getHandler()).handleUpstream(ctx, e);
|
||||
} catch (Throwable t) {
|
||||
notifyException(e, t);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendDownstream(ChannelEvent e) {
|
||||
DefaultChannelHandlerContext tail = getActualDownstreamContext(this.tail);
|
||||
if (tail == null) {
|
||||
try {
|
||||
getSink().eventSunk(this, e);
|
||||
return;
|
||||
} catch (Throwable t) {
|
||||
notifyException(e, t);
|
||||
}
|
||||
}
|
||||
|
||||
sendDownstream(tail, e);
|
||||
}
|
||||
|
||||
void sendDownstream(DefaultChannelHandlerContext ctx, ChannelEvent e) {
|
||||
try {
|
||||
((ChannelDownstreamHandler) ctx.getHandler()).handleDownstream(ctx, e);
|
||||
} catch (Throwable t) {
|
||||
notifyException(e, t);
|
||||
}
|
||||
}
|
||||
|
||||
DefaultChannelHandlerContext getActualUpstreamContext(DefaultChannelHandlerContext ctx) {
|
||||
if (ctx == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DefaultChannelHandlerContext realCtx = ctx;
|
||||
while (!realCtx.canHandleUpstream()) {
|
||||
realCtx = realCtx.next;
|
||||
if (realCtx == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return realCtx;
|
||||
}
|
||||
|
||||
DefaultChannelHandlerContext getActualDownstreamContext(DefaultChannelHandlerContext ctx) {
|
||||
if (ctx == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DefaultChannelHandlerContext realCtx = ctx;
|
||||
while (!realCtx.canHandleDownstream()) {
|
||||
realCtx = realCtx.prev;
|
||||
if (realCtx == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return realCtx;
|
||||
}
|
||||
|
||||
void notifyException(ChannelEvent e, Throwable t) {
|
||||
ChannelPipelineException pe;
|
||||
if (t instanceof ChannelPipelineException) {
|
||||
pe = (ChannelPipelineException) t;
|
||||
} else {
|
||||
pe = new ChannelPipelineException(t);
|
||||
}
|
||||
|
||||
try {
|
||||
sink.exceptionCaught(this, e, pe);
|
||||
} catch (Exception e1) {
|
||||
logger.warn("An exception was thrown by an exception handler.", e1);
|
||||
}
|
||||
}
|
||||
|
||||
private void init(String name, ChannelHandler handler) {
|
||||
DefaultChannelHandlerContext ctx = new DefaultChannelHandlerContext(null, null, name, handler);
|
||||
head = tail = ctx;
|
||||
name2ctx.clear();
|
||||
name2ctx.put(name, ctx);
|
||||
}
|
||||
|
||||
private void checkDuplicateName(String name) {
|
||||
if (name2ctx.containsKey(name)) {
|
||||
throw new IllegalArgumentException("Duplicate handler name.");
|
||||
}
|
||||
}
|
||||
|
||||
private DefaultChannelHandlerContext getContextOrDie(String name) {
|
||||
DefaultChannelHandlerContext ctx = (DefaultChannelHandlerContext) getContext(name);
|
||||
if (ctx == null) {
|
||||
throw new NoSuchElementException(name);
|
||||
} else {
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
|
||||
private DefaultChannelHandlerContext getContextOrDie(ChannelHandler handler) {
|
||||
DefaultChannelHandlerContext ctx = (DefaultChannelHandlerContext) getContext(handler);
|
||||
if (ctx == null) {
|
||||
throw new NoSuchElementException(handler.getClass().getName());
|
||||
} else {
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
|
||||
private DefaultChannelHandlerContext getContextOrDie(Class<? extends ChannelHandler> handlerType) {
|
||||
DefaultChannelHandlerContext ctx = (DefaultChannelHandlerContext) getContext(handlerType);
|
||||
if (ctx == null) {
|
||||
throw new NoSuchElementException(handlerType.getName());
|
||||
} else {
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultChannelHandlerContext implements ChannelHandlerContext {
|
||||
volatile DefaultChannelHandlerContext next;
|
||||
volatile DefaultChannelHandlerContext prev;
|
||||
private final String name;
|
||||
private final ChannelHandler handler;
|
||||
private final boolean canHandleUpstream;
|
||||
private final boolean canHandleDownstream;
|
||||
|
||||
DefaultChannelHandlerContext(
|
||||
DefaultChannelHandlerContext prev, DefaultChannelHandlerContext next,
|
||||
String name, ChannelHandler handler) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
if (handler == null) {
|
||||
throw new NullPointerException("handler");
|
||||
}
|
||||
canHandleUpstream = handler instanceof ChannelUpstreamHandler;
|
||||
canHandleDownstream = handler instanceof ChannelDownstreamHandler;
|
||||
|
||||
|
||||
if (!canHandleUpstream && !canHandleDownstream) {
|
||||
throw new IllegalArgumentException(
|
||||
"handler must be either " +
|
||||
ChannelUpstreamHandler.class.getName() + " or " +
|
||||
ChannelDownstreamHandler.class.getName() + '.');
|
||||
}
|
||||
|
||||
|
||||
ChannelPipelineCoverage coverage = handler.getClass().getAnnotation(ChannelPipelineCoverage.class);
|
||||
if (coverage == null) {
|
||||
logger.warn(
|
||||
"Handler '" + handler.getClass().getName() +
|
||||
"' doesn't have a '" +
|
||||
ChannelPipelineCoverage.class.getSimpleName() +
|
||||
"' annotation with its class declaration. " +
|
||||
"It is recommended to add the annotation to tell if " +
|
||||
"one handler instance can handle more than one pipeline " +
|
||||
"(\"" + ALL + "\") or not (\"" + ONE + "\")");
|
||||
} else {
|
||||
String coverageValue = coverage.value();
|
||||
if (coverageValue == null) {
|
||||
throw new AnnotationFormatError(
|
||||
ChannelPipelineCoverage.class.getSimpleName() +
|
||||
" annotation value is undefined for type: " +
|
||||
handler.getClass().getName());
|
||||
}
|
||||
|
||||
|
||||
if (!coverageValue.equals(ALL) && !coverageValue.equals(ONE)) {
|
||||
throw new AnnotationFormatError(
|
||||
ChannelPipelineCoverage.class.getSimpleName() +
|
||||
" annotation value: " + coverageValue +
|
||||
" (must be either \"" + ALL + "\" or \"" + ONE + ")");
|
||||
}
|
||||
}
|
||||
|
||||
this.prev = prev;
|
||||
this.next = next;
|
||||
this.name = name;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
return DefaultChannelPipeline.this;
|
||||
}
|
||||
|
||||
public boolean canHandleDownstream() {
|
||||
return canHandleDownstream;
|
||||
}
|
||||
|
||||
public boolean canHandleUpstream() {
|
||||
return canHandleUpstream;
|
||||
}
|
||||
|
||||
public ChannelHandler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void sendDownstream(ChannelEvent e) {
|
||||
DefaultChannelHandlerContext prev = getActualDownstreamContext(this.prev);
|
||||
if (prev == null) {
|
||||
try {
|
||||
getSink().eventSunk(DefaultChannelPipeline.this, e);
|
||||
} catch (Throwable t) {
|
||||
notifyException(e, t);
|
||||
}
|
||||
} else {
|
||||
DefaultChannelPipeline.this.sendDownstream(prev, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendUpstream(ChannelEvent e) {
|
||||
DefaultChannelHandlerContext next = getActualUpstreamContext(this.next);
|
||||
if (next != null) {
|
||||
DefaultChannelPipeline.this.sendUpstream(next, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
public class DefaultChannelStateEvent extends DefaultChannelEvent implements
|
||||
ChannelStateEvent {
|
||||
|
||||
private final ChannelState state;
|
||||
private final Object value;
|
||||
|
||||
public DefaultChannelStateEvent(
|
||||
Channel channel, ChannelFuture future,
|
||||
ChannelState state, Object value) {
|
||||
|
||||
super(channel, future);
|
||||
if (state == null) {
|
||||
throw new NullPointerException("state");
|
||||
}
|
||||
this.state = state;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public ChannelState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String parentString = super.toString();
|
||||
StringBuilder buf = new StringBuilder(parentString.length() + 64);
|
||||
buf.append(parentString);
|
||||
buf.append(" - (state: ");
|
||||
switch (getState()) {
|
||||
case OPEN:
|
||||
if (Boolean.TRUE.equals(getValue())) {
|
||||
buf.append("OPEN");
|
||||
} else {
|
||||
buf.append("CLOSED");
|
||||
}
|
||||
break;
|
||||
case BOUND:
|
||||
if (getValue() != null) {
|
||||
buf.append("BOUND");
|
||||
} else {
|
||||
buf.append("UNBOUND");
|
||||
}
|
||||
break;
|
||||
case CONNECTED:
|
||||
if (getValue() != null) {
|
||||
buf.append("CONNECTED");
|
||||
} else {
|
||||
buf.append("DISCONNECTED");
|
||||
}
|
||||
break;
|
||||
case INTEREST_OPS:
|
||||
switch (((Integer) getValue()).intValue()) {
|
||||
case Channel.OP_NONE:
|
||||
buf.append("OP_NONE");
|
||||
break;
|
||||
case Channel.OP_READ:
|
||||
buf.append("OP_READ");
|
||||
break;
|
||||
case Channel.OP_WRITE:
|
||||
buf.append("OP_WRITE");
|
||||
break;
|
||||
case Channel.OP_READ_WRITE:
|
||||
buf.append("OP_READ_WRITE");
|
||||
break;
|
||||
default:
|
||||
buf.append("OP_");
|
||||
buf.append(getValue());
|
||||
buf.append(" (?)");
|
||||
}
|
||||
}
|
||||
buf.append(')');
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
public class DefaultChildChannelStateEvent extends DefaultChannelEvent implements
|
||||
ChildChannelStateEvent {
|
||||
|
||||
private final Channel childChannel;
|
||||
|
||||
public DefaultChildChannelStateEvent(
|
||||
Channel channel, ChannelFuture future, Channel childChannel) {
|
||||
|
||||
super(channel, future);
|
||||
if (childChannel == null) {
|
||||
throw new NullPointerException("childChannel");
|
||||
}
|
||||
this.childChannel = childChannel;
|
||||
}
|
||||
|
||||
public Channel getChildChannel() {
|
||||
return childChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String parentString = super.toString();
|
||||
StringBuilder buf = new StringBuilder(parentString.length() + 32);
|
||||
buf.append(parentString);
|
||||
buf.append(" - (childId: ");
|
||||
buf.append(getChildChannel().getId().toString());
|
||||
buf.append(", childState: ");
|
||||
buf.append(getChildChannel().isOpen()? "OPEN" : "CLOSE");
|
||||
buf.append(')');
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
|
||||
public class DefaultExceptionEvent extends DefaultChannelEvent implements
|
||||
ExceptionEvent {
|
||||
|
||||
private final Throwable cause;
|
||||
|
||||
public DefaultExceptionEvent(Channel channel, ChannelFuture future, Throwable cause) {
|
||||
super(channel, future);
|
||||
if (cause == null) {
|
||||
throw new NullPointerException("cause");
|
||||
}
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
public Throwable getCause() {
|
||||
return cause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " - (cause: " + cause.getClass().getSimpleName() + ')';
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
public class DefaultMessageEvent extends DefaultChannelEvent implements
|
||||
MessageEvent {
|
||||
|
||||
private final Object message;
|
||||
private final SocketAddress remoteAddress;
|
||||
|
||||
public DefaultMessageEvent(
|
||||
Channel channel, ChannelFuture future,
|
||||
Object message, SocketAddress remoteAddress) {
|
||||
|
||||
super(channel, future);
|
||||
if (message == null) {
|
||||
throw new NullPointerException("message");
|
||||
}
|
||||
this.message = message;
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
public Object getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public SocketAddress getRemoteAddress() {
|
||||
return remoteAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (remoteAddress == null) {
|
||||
return super.toString() + " - (message: " + message + ')';
|
||||
} else {
|
||||
return super.toString() + " - (message: " + message + ", " + remoteAddress + ')';
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public interface ExceptionEvent extends ChannelEvent {
|
||||
Throwable getCause();
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
|
||||
public class FailedChannelFuture extends CompleteChannelFuture {
|
||||
|
||||
private final Throwable cause;
|
||||
|
||||
public FailedChannelFuture(Channel channel, Throwable cause) {
|
||||
super(channel);
|
||||
if (cause == null) {
|
||||
throw new NullPointerException("cause");
|
||||
}
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
public Throwable getCause() {
|
||||
return cause;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return false;
|
||||
}
|
||||
}
|
32
src/main/java/net/gleamynode/netty/channel/MessageEvent.java
Normal file
32
src/main/java/net/gleamynode/netty/channel/MessageEvent.java
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public interface MessageEvent extends ChannelEvent {
|
||||
Object getMessage();
|
||||
SocketAddress getRemoteAddress();
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
public class SimpleChannelHandler implements ChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(SimpleChannelHandler.class.getName());
|
||||
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
|
||||
if (e instanceof MessageEvent) {
|
||||
messageReceived(ctx, (MessageEvent) e);
|
||||
} else if (e instanceof ChildChannelStateEvent) {
|
||||
ChildChannelStateEvent evt = (ChildChannelStateEvent) e;
|
||||
if (evt.getChildChannel().isOpen()) {
|
||||
childChannelOpen(ctx, evt);
|
||||
} else {
|
||||
childChannelClosed(ctx, evt);
|
||||
}
|
||||
} else if (e instanceof ChannelStateEvent) {
|
||||
ChannelStateEvent evt = (ChannelStateEvent) e;
|
||||
switch (evt.getState()) {
|
||||
case OPEN:
|
||||
if (Boolean.TRUE.equals(evt.getValue())) {
|
||||
channelOpen(ctx, evt);
|
||||
} else {
|
||||
channelClosed(ctx, evt);
|
||||
}
|
||||
break;
|
||||
case BOUND:
|
||||
if (evt.getValue() != null) {
|
||||
channelBound(ctx, evt);
|
||||
} else {
|
||||
channelUnbound(ctx, evt);
|
||||
}
|
||||
break;
|
||||
case CONNECTED:
|
||||
if (evt.getValue() != null) {
|
||||
channelConnected(ctx, evt);
|
||||
} else {
|
||||
channelDisconnected(ctx, evt);
|
||||
}
|
||||
break;
|
||||
case INTEREST_OPS:
|
||||
channelInterestChanged(ctx, evt);
|
||||
break;
|
||||
}
|
||||
} else if (e instanceof ExceptionEvent) {
|
||||
exceptionCaught(ctx, (ExceptionEvent) e);
|
||||
} else {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void channelBound(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void channelClosed(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void channelConnected(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void channelInterestChanged(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void channelDisconnected(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void channelOpen(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void channelUnbound(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||
if (this == ctx.getPipeline().getLast()) {
|
||||
logger.warn(
|
||||
"EXCEPTION, please implement " + getClass().getName() +
|
||||
".exceptionCaught() for proper handling.", e.getCause());
|
||||
}
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void childChannelClosed(
|
||||
ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void childChannelOpen(
|
||||
ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
||||
|
||||
|
||||
public class SucceededChannelFuture extends CompleteChannelFuture {
|
||||
|
||||
public SucceededChannelFuture(Channel channel) {
|
||||
super(channel);
|
||||
}
|
||||
|
||||
public Throwable getCause() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return true;
|
||||
}
|
||||
}
|
32
src/main/java/net/gleamynode/netty/channel/package-info.java
Normal file
32
src/main/java/net/gleamynode/netty/channel/package-info.java
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* The core channel API which is asynchronous and event-driven abstraction of
|
||||
* various transports such as a
|
||||
* <a href="http://en.wikipedia.org/wiki/New_I/O#Channels">NIO Channel</a>.
|
||||
*
|
||||
* @apiviz.landmark
|
||||
* @apiviz.exclude ^java
|
||||
* @apiviz.exclude ^net\.gleamynode\.netty\.channel\.[^\.]+\.
|
||||
* @apiviz.exclude ^net\.gleamynode\.netty\.(bootstrap|handler)\.
|
||||
* @apiviz.exclude \.(Abstract|Default).*$
|
||||
* @apiviz.exclude \.[A-Za-z]+ChannelFuture$
|
||||
* @apiviz.exclude \.ChannelState$
|
||||
*/
|
||||
package net.gleamynode.netty.channel;
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.has net.gleamynode.netty.channel.socket.SocketChannel oneway - - creates
|
||||
*/
|
||||
public interface ClientSocketChannelFactory extends ChannelFactory {
|
||||
SocketChannel newChannel(ChannelPipeline pipeline);
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket;
|
||||
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketException;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelException;
|
||||
import net.gleamynode.netty.channel.ChannelPipelineFactory;
|
||||
import net.gleamynode.netty.util.ConvertUtil;
|
||||
|
||||
public class DefaultServerSocketChannelConfig implements ServerSocketChannelConfig {
|
||||
|
||||
private final ServerSocket socket;
|
||||
private volatile int backlog;
|
||||
private volatile ChannelPipelineFactory pipelineFactory;
|
||||
|
||||
public DefaultServerSocketChannelConfig(ServerSocket socket) {
|
||||
if (socket == null) {
|
||||
throw new NullPointerException("socket");
|
||||
}
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
public void setOptions(Map<String, Object> options) {
|
||||
for (Entry<String, Object> e: options.entrySet()) {
|
||||
setOption(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean setOption(String key, Object value) {
|
||||
if (key.equals("receiveBufferSize")) {
|
||||
setReceiveBufferSize(ConvertUtil.toInt(value));
|
||||
} else if (key.equals("reuseAddress")) {
|
||||
setReuseAddress(ConvertUtil.toBoolean(value));
|
||||
} else if (key.equals("backlog")) {
|
||||
setBacklog(ConvertUtil.toInt(value));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isReuseAddress() {
|
||||
try {
|
||||
return socket.getReuseAddress();
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setReuseAddress(boolean reuseAddress) {
|
||||
try {
|
||||
socket.setReuseAddress(reuseAddress);
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getReceiveBufferSize() {
|
||||
try {
|
||||
return socket.getReceiveBufferSize();
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setReceiveBufferSize(int receiveBufferSize) {
|
||||
try {
|
||||
socket.setReceiveBufferSize(receiveBufferSize);
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
|
||||
socket.setPerformancePreferences(connectionTime, latency, bandwidth);
|
||||
}
|
||||
|
||||
public ChannelPipelineFactory getPipelineFactory() {
|
||||
return pipelineFactory;
|
||||
}
|
||||
|
||||
public void setPipelineFactory(ChannelPipelineFactory pipelineFactory) {
|
||||
if (pipelineFactory == null) {
|
||||
throw new NullPointerException("pipelineFactory");
|
||||
}
|
||||
this.pipelineFactory = pipelineFactory;
|
||||
}
|
||||
|
||||
public int getBacklog() {
|
||||
return backlog;
|
||||
}
|
||||
|
||||
public void setBacklog(int backlog) {
|
||||
if (backlog < 1) {
|
||||
throw new IllegalArgumentException("backlog: " + backlog);
|
||||
}
|
||||
this.backlog = backlog;
|
||||
}
|
||||
|
||||
public int getConnectTimeoutMillis() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setConnectTimeoutMillis(int connectTimeoutMillis) {
|
||||
// Unused
|
||||
}
|
||||
|
||||
public int getWriteTimeoutMillis() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setWriteTimeoutMillis(int writeTimeoutMillis) {
|
||||
// Unused
|
||||
}
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelException;
|
||||
import net.gleamynode.netty.channel.ChannelPipelineFactory;
|
||||
import net.gleamynode.netty.util.ConvertUtil;
|
||||
|
||||
public class DefaultSocketChannelConfig implements SocketChannelConfig {
|
||||
|
||||
private final Socket socket;
|
||||
private volatile int connectTimeoutMillis = 10000; // 10 seconds
|
||||
|
||||
public DefaultSocketChannelConfig(Socket socket) {
|
||||
if (socket == null) {
|
||||
throw new NullPointerException("socket");
|
||||
}
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
public void setOptions(Map<String, Object> options) {
|
||||
for (Entry<String, Object> e: options.entrySet()) {
|
||||
setOption(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean setOption(String key, Object value) {
|
||||
if (key.equals("receiveBufferSize")) {
|
||||
setReceiveBufferSize(ConvertUtil.toInt(value));
|
||||
} else if (key.equals("sendBufferSize")) {
|
||||
setSendBufferSize(ConvertUtil.toInt(value));
|
||||
} else if (key.equals("tcpNoDelay")) {
|
||||
setTcpNoDelay(ConvertUtil.toBoolean(value));
|
||||
} else if (key.equals("keepAlive")) {
|
||||
setKeepAlive(ConvertUtil.toBoolean(value));
|
||||
} else if (key.equals("reuseAddress")) {
|
||||
setReuseAddress(ConvertUtil.toBoolean(value));
|
||||
} else if (key.equals("soLinger")) {
|
||||
setSoLinger(ConvertUtil.toInt(value));
|
||||
} else if (key.equals("trafficClass")) {
|
||||
setTrafficClass(ConvertUtil.toInt(value));
|
||||
} else if (key.equals("writeTimeoutMillis")) {
|
||||
setWriteTimeoutMillis(ConvertUtil.toInt(value));
|
||||
} else if (key.equals("connectTimeoutMillis")) {
|
||||
setConnectTimeoutMillis(ConvertUtil.toInt(value));
|
||||
} else if (key.equals("pipelineFactory")) {
|
||||
setPipelineFactory((ChannelPipelineFactory) value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getReceiveBufferSize() {
|
||||
try {
|
||||
return socket.getReceiveBufferSize();
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getSendBufferSize() {
|
||||
try {
|
||||
return socket.getSendBufferSize();
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getSoLinger() {
|
||||
try {
|
||||
return socket.getSoLinger();
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getTrafficClass() {
|
||||
try {
|
||||
return socket.getTrafficClass();
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isKeepAlive() {
|
||||
try {
|
||||
return socket.getKeepAlive();
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReuseAddress() {
|
||||
try {
|
||||
return socket.getReuseAddress();
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTcpNoDelay() {
|
||||
try {
|
||||
return socket.getTcpNoDelay();
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setKeepAlive(boolean keepAlive) {
|
||||
try {
|
||||
socket.setKeepAlive(keepAlive);
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPerformancePreferences(
|
||||
int connectionTime, int latency, int bandwidth) {
|
||||
socket.setPerformancePreferences(connectionTime, latency, bandwidth);
|
||||
}
|
||||
|
||||
public void setReceiveBufferSize(int receiveBufferSize) {
|
||||
try {
|
||||
socket.setReceiveBufferSize(receiveBufferSize);
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setReuseAddress(boolean reuseAddress) {
|
||||
try {
|
||||
socket.setReuseAddress(reuseAddress);
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSendBufferSize(int sendBufferSize) {
|
||||
try {
|
||||
socket.setSendBufferSize(sendBufferSize);
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSoLinger(int soLinger) {
|
||||
try {
|
||||
if (soLinger < 0) {
|
||||
socket.setSoLinger(false, 0);
|
||||
} else {
|
||||
socket.setSoLinger(true, soLinger);
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTcpNoDelay(boolean tcpNoDelay) {
|
||||
try {
|
||||
socket.setTcpNoDelay(tcpNoDelay);
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTrafficClass(int trafficClass) {
|
||||
try {
|
||||
socket.setTrafficClass(trafficClass);
|
||||
} catch (SocketException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getConnectTimeoutMillis() {
|
||||
return connectTimeoutMillis;
|
||||
}
|
||||
|
||||
public ChannelPipelineFactory getPipelineFactory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getWriteTimeoutMillis() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setConnectTimeoutMillis(int connectTimeoutMillis) {
|
||||
if (connectTimeoutMillis < 0) {
|
||||
throw new IllegalArgumentException("connectTimeoutMillis: " + connectTimeoutMillis);
|
||||
}
|
||||
this.connectTimeoutMillis = connectTimeoutMillis;
|
||||
}
|
||||
|
||||
public void setPipelineFactory(ChannelPipelineFactory pipelineFactory) {
|
||||
// Unused
|
||||
}
|
||||
|
||||
public void setWriteTimeoutMillis(int writeTimeoutMillis) {
|
||||
// Unused
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.composedOf net.gleamynode.netty.channel.socket.ServerSocketChannelConfig
|
||||
*/
|
||||
public interface ServerSocketChannel extends Channel {
|
||||
ServerSocketChannelConfig getConfig();
|
||||
InetSocketAddress getLocalAddress();
|
||||
InetSocketAddress getRemoteAddress();
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelConfig;
|
||||
|
||||
public interface ServerSocketChannelConfig extends ChannelConfig {
|
||||
int getBacklog();
|
||||
void setBacklog(int backlog);
|
||||
boolean isReuseAddress();
|
||||
void setReuseAddress(boolean reuseAddress);
|
||||
int getReceiveBufferSize();
|
||||
void setReceiveBufferSize(int receiveBufferSize);
|
||||
void setPerformancePreferences(int connectionTime, int latency, int bandwidth);
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.has net.gleamynode.netty.channel.socket.ServerSocketChannel oneway - - creates
|
||||
*/
|
||||
public interface ServerSocketChannelFactory extends ChannelFactory {
|
||||
ServerSocketChannel newChannel(ChannelPipeline pipeline);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.composedOf net.gleamynode.netty.channel.socket.SocketChannelConfig
|
||||
*/
|
||||
public interface SocketChannel extends Channel {
|
||||
SocketChannelConfig getConfig();
|
||||
InetSocketAddress getLocalAddress();
|
||||
InetSocketAddress getRemoteAddress();
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelConfig;
|
||||
|
||||
public interface SocketChannelConfig extends ChannelConfig {
|
||||
boolean isTcpNoDelay();
|
||||
void setTcpNoDelay(boolean tcpNoDelay);
|
||||
int getSoLinger();
|
||||
void setSoLinger(int soLinger);
|
||||
int getSendBufferSize();
|
||||
void setSendBufferSize(int sendBufferSize);
|
||||
int getReceiveBufferSize();
|
||||
void setReceiveBufferSize(int receiveBufferSize);
|
||||
boolean isKeepAlive();
|
||||
void setKeepAlive(boolean keepAlive);
|
||||
int getTrafficClass();
|
||||
void setTrafficClass(int trafficClass);
|
||||
boolean isReuseAddress();
|
||||
void setReuseAddress(boolean reuseAddress);
|
||||
void setPerformancePreferences(
|
||||
int connectionTime, int latency, int bandwidth);
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
import net.gleamynode.netty.channel.socket.DefaultSocketChannelConfig;
|
||||
import net.gleamynode.netty.util.ConvertUtil;
|
||||
|
||||
class DefaultNioSocketChannelConfig extends DefaultSocketChannelConfig
|
||||
implements NioSocketChannelConfig {
|
||||
|
||||
private volatile ReceiveBufferSizePredictor predictor =
|
||||
new DefaultReceiveBufferSizePredictor();
|
||||
private volatile int writeSpinCount = 16;
|
||||
private volatile boolean readWriteFair;
|
||||
|
||||
DefaultNioSocketChannelConfig(Socket socket) {
|
||||
super(socket);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setOption(String key, Object value) {
|
||||
if (super.setOption(key, value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.equals("readWriteFair")) {
|
||||
setReadWriteFair(ConvertUtil.toBoolean(value));
|
||||
} else if (key.equals("writeSpinCount")) {
|
||||
setWriteSpinCount(ConvertUtil.toInt(value));
|
||||
} else if (key.equals("receiveBufferSizePredictor")) {
|
||||
setReceiveBufferSizePredictor((ReceiveBufferSizePredictor) value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getWriteSpinCount() {
|
||||
return writeSpinCount;
|
||||
}
|
||||
|
||||
public void setWriteSpinCount(int writeSpinCount) {
|
||||
if (writeSpinCount <= 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"writeSpinCount must be a positive integer.");
|
||||
}
|
||||
}
|
||||
|
||||
public ReceiveBufferSizePredictor getReceiveBufferSizePredictor() {
|
||||
return predictor;
|
||||
}
|
||||
|
||||
public void setReceiveBufferSizePredictor(
|
||||
ReceiveBufferSizePredictor predictor) {
|
||||
if (predictor == null) {
|
||||
throw new NullPointerException("predictor");
|
||||
}
|
||||
this.predictor = predictor;
|
||||
}
|
||||
|
||||
public boolean isReadWriteFair() {
|
||||
return readWriteFair;
|
||||
}
|
||||
|
||||
public void setReadWriteFair(boolean readWriteFair) {
|
||||
this.readWriteFair = readWriteFair;
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
public class DefaultReceiveBufferSizePredictor implements
|
||||
ReceiveBufferSizePredictor {
|
||||
private static final int DEFAULT_MINIMUM = 256;
|
||||
private static final int DEFAULT_INITIAL = 1024;
|
||||
private static final int DEFAULT_MAXIMUM = 1048576;
|
||||
|
||||
private final int minimum;
|
||||
private final int maximum;
|
||||
private int nextReceiveBufferSize = 1024;
|
||||
private boolean shouldHalveNow;
|
||||
|
||||
public DefaultReceiveBufferSizePredictor() {
|
||||
this(DEFAULT_MINIMUM, DEFAULT_INITIAL, DEFAULT_MAXIMUM);
|
||||
}
|
||||
|
||||
public DefaultReceiveBufferSizePredictor(int minimum, int initial, int maximum) {
|
||||
if (minimum <= 0) {
|
||||
throw new IllegalArgumentException("minimum: " + minimum);
|
||||
}
|
||||
if (initial < minimum) {
|
||||
throw new IllegalArgumentException("initial: " + initial);
|
||||
}
|
||||
if (maximum < initial) {
|
||||
throw new IllegalArgumentException("maximum: " + maximum);
|
||||
}
|
||||
this.minimum = minimum;
|
||||
nextReceiveBufferSize = initial;
|
||||
this.maximum = maximum;
|
||||
}
|
||||
|
||||
public int nextReceiveBufferSize() {
|
||||
return nextReceiveBufferSize;
|
||||
}
|
||||
|
||||
public void previousReceiveBufferSize(int previousReceiveBufferSize) {
|
||||
if (previousReceiveBufferSize < nextReceiveBufferSize >>> 1) {
|
||||
if (shouldHalveNow) {
|
||||
nextReceiveBufferSize = Math.max(minimum, nextReceiveBufferSize >>> 1);
|
||||
shouldHalveNow = false;
|
||||
} else {
|
||||
shouldHalveNow = true;
|
||||
}
|
||||
} else if (previousReceiveBufferSize == nextReceiveBufferSize) {
|
||||
nextReceiveBufferSize = Math.min(maximum, nextReceiveBufferSize << 1);
|
||||
shouldHalveNow = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
import net.gleamynode.netty.channel.ChannelException;
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
|
||||
class NioAcceptedSocketChannel extends NioSocketChannel {
|
||||
|
||||
final NioWorker worker;
|
||||
|
||||
NioAcceptedSocketChannel(
|
||||
ChannelFactory factory, ChannelPipeline pipeline,
|
||||
Channel parent, ChannelSink sink,
|
||||
SocketChannel socket, NioWorker worker) {
|
||||
|
||||
super(parent, factory, pipeline, sink, socket);
|
||||
|
||||
this.worker = worker;
|
||||
try {
|
||||
socket.configureBlocking(false);
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException("Failed to enter non-blocking mode.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
NioWorker getWorker() {
|
||||
return worker;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setWorker(NioWorker worker) {
|
||||
// worker never changes.
|
||||
if (this.worker != worker) {
|
||||
throw new IllegalStateException("Should not reach here.");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelException;
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
|
||||
class NioClientSocketChannel extends NioSocketChannel {
|
||||
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(NioClientSocketChannel.class);
|
||||
|
||||
private static SocketChannel newSocket() {
|
||||
SocketChannel socket;
|
||||
try {
|
||||
socket = SocketChannel.open();
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException("Failed to open a socket.", e);
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
socket.configureBlocking(false);
|
||||
success = true;
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException("Failed to enter non-blocking mode.", e);
|
||||
} finally {
|
||||
if (!success) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
logger.warn(
|
||||
"Failed to close a partially initialized socket.",
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
volatile NioWorker worker;
|
||||
volatile ChannelFuture connectFuture;
|
||||
volatile boolean boundManually;
|
||||
|
||||
NioClientSocketChannel(
|
||||
ChannelFactory factory, ChannelPipeline pipeline, ChannelSink sink) {
|
||||
|
||||
super(null, factory, pipeline, sink, newSocket());
|
||||
fireChannelOpen(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
NioWorker getWorker() {
|
||||
return worker;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setWorker(NioWorker worker) {
|
||||
if (this.worker == null) {
|
||||
this.worker = worker;
|
||||
} else if (this.worker != worker) {
|
||||
// worker never changes.
|
||||
throw new IllegalStateException("Should not reach here.");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
import net.gleamynode.netty.channel.socket.ClientSocketChannelFactory;
|
||||
import net.gleamynode.netty.channel.socket.SocketChannel;
|
||||
|
||||
public class NioClientSocketChannelFactory implements ClientSocketChannelFactory {
|
||||
|
||||
private final ChannelSink sink;
|
||||
|
||||
public NioClientSocketChannelFactory(
|
||||
Executor bossExecutor, Executor workerExecutor) {
|
||||
this(bossExecutor, workerExecutor, Runtime.getRuntime().availableProcessors());
|
||||
}
|
||||
|
||||
public NioClientSocketChannelFactory(
|
||||
Executor bossExecutor, Executor workerExecutor,
|
||||
int workerCount) {
|
||||
if (bossExecutor == null) {
|
||||
throw new NullPointerException("bossExecutor");
|
||||
}
|
||||
if (workerExecutor == null) {
|
||||
throw new NullPointerException("workerExecutor");
|
||||
}
|
||||
if (workerCount <= 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"workerCount (" + workerCount + ") " +
|
||||
"must be a positive integer.");
|
||||
}
|
||||
sink = new NioClientSocketPipelineSink(bossExecutor, workerExecutor, workerCount);
|
||||
}
|
||||
|
||||
public SocketChannel newChannel(ChannelPipeline pipeline) {
|
||||
return new NioClientSocketChannel(this, pipeline, sink);
|
||||
}
|
||||
}
|
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.gleamynode.netty.channel.AbstractChannelSink;
|
||||
import net.gleamynode.netty.channel.ChannelEvent;
|
||||
import net.gleamynode.netty.channel.ChannelException;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelFutureListener;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelState;
|
||||
import net.gleamynode.netty.channel.ChannelStateEvent;
|
||||
import net.gleamynode.netty.channel.MessageEvent;
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
import net.gleamynode.netty.util.NamePreservingRunnable;
|
||||
|
||||
class NioClientSocketPipelineSink extends AbstractChannelSink {
|
||||
|
||||
static final Logger logger =
|
||||
Logger.getLogger(NioClientSocketPipelineSink.class);
|
||||
private static final AtomicInteger nextId = new AtomicInteger();
|
||||
|
||||
final int id = nextId.incrementAndGet();
|
||||
final Executor bossExecutor;
|
||||
private final Boss boss = new Boss();
|
||||
private final NioWorker[] workers;
|
||||
private final AtomicInteger workerIndex = new AtomicInteger();
|
||||
|
||||
NioClientSocketPipelineSink(
|
||||
Executor bossExecutor, Executor workerExecutor, int workerCount) {
|
||||
this.bossExecutor = bossExecutor;
|
||||
workers = new NioWorker[workerCount];
|
||||
for (int i = 0; i < workers.length; i ++) {
|
||||
workers[i] = new NioWorker(id, i + 1, workerExecutor);
|
||||
}
|
||||
}
|
||||
|
||||
public void eventSunk(
|
||||
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
ChannelStateEvent event = (ChannelStateEvent) e;
|
||||
NioClientSocketChannel channel =
|
||||
(NioClientSocketChannel) event.getChannel();
|
||||
ChannelFuture future = event.getFuture();
|
||||
ChannelState state = event.getState();
|
||||
Object value = event.getValue();
|
||||
|
||||
switch (state) {
|
||||
case OPEN:
|
||||
if (Boolean.FALSE.equals(value)) {
|
||||
NioWorker.close(channel, future);
|
||||
}
|
||||
break;
|
||||
case BOUND:
|
||||
if (value != null) {
|
||||
bind(channel, future, (SocketAddress) value);
|
||||
} else {
|
||||
NioWorker.close(channel, future);
|
||||
}
|
||||
break;
|
||||
case CONNECTED:
|
||||
if (value != null) {
|
||||
connect(channel, future, (SocketAddress) value);
|
||||
} else {
|
||||
NioWorker.close(channel, future);
|
||||
}
|
||||
break;
|
||||
case INTEREST_OPS:
|
||||
NioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
|
||||
break;
|
||||
}
|
||||
} else if (e instanceof MessageEvent) {
|
||||
MessageEvent event = (MessageEvent) e;
|
||||
NioSocketChannel channel = (NioSocketChannel) event.getChannel();
|
||||
channel.writeBuffer.offer(event);
|
||||
NioWorker.write(channel);
|
||||
}
|
||||
}
|
||||
|
||||
private void bind(
|
||||
NioClientSocketChannel channel, ChannelFuture future,
|
||||
SocketAddress localAddress) {
|
||||
try {
|
||||
channel.socket.socket().bind(localAddress);
|
||||
channel.boundManually = true;
|
||||
future.setSuccess();
|
||||
fireChannelBound(channel, channel.getLocalAddress());
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
}
|
||||
|
||||
private void connect(
|
||||
final NioClientSocketChannel channel, ChannelFuture future,
|
||||
SocketAddress remoteAddress) {
|
||||
try {
|
||||
if (channel.socket.connect(remoteAddress)) {
|
||||
NioWorker worker = nextWorker();
|
||||
channel.setWorker(worker);
|
||||
worker.register(channel, future);
|
||||
} else {
|
||||
future.addListener(new ChannelFutureListener() {
|
||||
public void operationComplete(ChannelFuture future) {
|
||||
if (future.isCancelled()) {
|
||||
channel.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
channel.connectFuture = future;
|
||||
boss.register(channel);
|
||||
}
|
||||
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
}
|
||||
|
||||
NioWorker nextWorker() {
|
||||
return workers[Math.abs(
|
||||
workerIndex.getAndIncrement() % workers.length)];
|
||||
}
|
||||
|
||||
private class Boss implements Runnable {
|
||||
|
||||
private final AtomicBoolean started = new AtomicBoolean();
|
||||
private volatile Selector selector;
|
||||
private final Object selectorGuard = new Object();
|
||||
|
||||
Boss() {
|
||||
super();
|
||||
}
|
||||
|
||||
void register(NioSocketChannel channel) {
|
||||
boolean firstChannel = started.compareAndSet(false, true);
|
||||
Selector selector;
|
||||
if (firstChannel) {
|
||||
try {
|
||||
this.selector = selector = Selector.open();
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(
|
||||
"Failed to create a selector.", e);
|
||||
}
|
||||
} else {
|
||||
selector = this.selector;
|
||||
if (selector == null) {
|
||||
do {
|
||||
Thread.yield();
|
||||
selector = this.selector;
|
||||
} while (selector == null);
|
||||
}
|
||||
}
|
||||
|
||||
if (firstChannel) {
|
||||
try {
|
||||
channel.socket.register(selector, SelectionKey.OP_CONNECT, channel);
|
||||
} catch (ClosedChannelException e) {
|
||||
throw new ChannelException(
|
||||
"Failed to register a socket to the selector.", e);
|
||||
}
|
||||
bossExecutor.execute(new NamePreservingRunnable(
|
||||
this,
|
||||
"New I/O client boss #" + id));
|
||||
} else {
|
||||
synchronized (selectorGuard) {
|
||||
selector.wakeup();
|
||||
try {
|
||||
channel.socket.register(selector, SelectionKey.OP_CONNECT, channel);
|
||||
} catch (ClosedChannelException e) {
|
||||
throw new ChannelException(
|
||||
"Failed to register a socket to the selector.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
boolean shutdown = false;
|
||||
Selector selector = this.selector;
|
||||
for (;;) {
|
||||
synchronized (selectorGuard) {
|
||||
// This empty synchronization block prevents the selector
|
||||
// from acquiring its lock.
|
||||
}
|
||||
try {
|
||||
int selectedKeyCount = selector.select(500);
|
||||
if (selectedKeyCount > 0) {
|
||||
processSelectedKeys(selector.selectedKeys());
|
||||
}
|
||||
|
||||
// Exit the loop when there's nothing to handle.
|
||||
// The shutdown flag is used to delay the shutdown of this
|
||||
// loop to avoid excessive Selector creation when
|
||||
// connection attempts are made in a one-by-one manner
|
||||
// instead of concurrent manner.
|
||||
if (selector.keys().isEmpty()) {
|
||||
if (shutdown) {
|
||||
synchronized (selectorGuard) {
|
||||
if (selector.keys().isEmpty()) {
|
||||
try {
|
||||
selector.close();
|
||||
} catch (IOException e) {
|
||||
logger.warn(
|
||||
"Failed to close a selector.",
|
||||
e);
|
||||
} finally {
|
||||
this.selector = null;
|
||||
}
|
||||
started.set(false);
|
||||
break;
|
||||
} else {
|
||||
shutdown = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Give one more second.
|
||||
shutdown = true;
|
||||
}
|
||||
} else {
|
||||
shutdown = false;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
logger.warn(
|
||||
"Unexpected exception in the selector loop.", t);
|
||||
|
||||
// Prevent possible consecutive immediate failures.
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processSelectedKeys(Set<SelectionKey> selectedKeys) {
|
||||
for (Iterator<SelectionKey> i = selectedKeys.iterator(); i.hasNext();) {
|
||||
SelectionKey k = i.next();
|
||||
i.remove();
|
||||
|
||||
if (!k.isValid()) {
|
||||
close(k);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k.isConnectable()) {
|
||||
connect(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void connect(SelectionKey k) {
|
||||
NioClientSocketChannel ch = (NioClientSocketChannel) k.attachment();
|
||||
try {
|
||||
if (ch.socket.finishConnect()) {
|
||||
k.cancel();
|
||||
NioWorker worker = nextWorker();
|
||||
ch.setWorker(worker);
|
||||
worker.register(ch, ch.connectFuture);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
k.cancel();
|
||||
ch.connectFuture.setFailure(t);
|
||||
fireExceptionCaught(ch, t);
|
||||
close(k);
|
||||
}
|
||||
}
|
||||
|
||||
private void close(SelectionKey k) {
|
||||
NioSocketChannel ch = (NioSocketChannel) k.attachment();
|
||||
NioWorker.close(ch, ch.getSucceededFuture());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
|
||||
import net.gleamynode.netty.channel.AbstractServerChannel;
|
||||
import net.gleamynode.netty.channel.ChannelException;
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
import net.gleamynode.netty.channel.socket.DefaultServerSocketChannelConfig;
|
||||
import net.gleamynode.netty.channel.socket.ServerSocketChannelConfig;
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
|
||||
class NioServerSocketChannel extends AbstractServerChannel
|
||||
implements net.gleamynode.netty.channel.socket.ServerSocketChannel {
|
||||
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(NioServerSocketChannel.class);
|
||||
|
||||
final ServerSocketChannel socket;
|
||||
private final ServerSocketChannelConfig config;
|
||||
|
||||
NioServerSocketChannel(
|
||||
ChannelFactory factory,
|
||||
ChannelPipeline pipeline,
|
||||
ChannelSink sink) {
|
||||
|
||||
super(factory, pipeline, sink);
|
||||
|
||||
try {
|
||||
socket = ServerSocketChannel.open();
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(
|
||||
"Failed to open a server socket.", e);
|
||||
}
|
||||
|
||||
try {
|
||||
socket.socket().setSoTimeout(1000);
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e2) {
|
||||
logger.warn(
|
||||
"Failed to close a partially initialized socket.", e2);
|
||||
}
|
||||
throw new ChannelException(
|
||||
"Failed to set the server socket timeout.", e);
|
||||
}
|
||||
|
||||
config = new DefaultServerSocketChannelConfig(socket.socket());
|
||||
|
||||
fireChannelOpen(this);
|
||||
}
|
||||
|
||||
public ServerSocketChannelConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public InetSocketAddress getLocalAddress() {
|
||||
return (InetSocketAddress) socket.socket().getLocalSocketAddress();
|
||||
}
|
||||
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isBound() {
|
||||
return isOpen() && socket.socket().isBound();
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setClosed() {
|
||||
return super.setClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChannelFuture getSucceededFuture() {
|
||||
return super.getSucceededFuture();
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
import net.gleamynode.netty.channel.socket.ServerSocketChannel;
|
||||
import net.gleamynode.netty.channel.socket.ServerSocketChannelFactory;
|
||||
|
||||
public class NioServerSocketChannelFactory implements ServerSocketChannelFactory {
|
||||
|
||||
final Executor bossExecutor;
|
||||
private final ChannelSink sink;
|
||||
|
||||
public NioServerSocketChannelFactory(
|
||||
Executor bossExecutor, Executor workerExecutor) {
|
||||
this(bossExecutor, workerExecutor, Runtime.getRuntime().availableProcessors());
|
||||
}
|
||||
|
||||
public NioServerSocketChannelFactory(
|
||||
Executor bossExecutor, Executor workerExecutor,
|
||||
int workerCount) {
|
||||
if (bossExecutor == null) {
|
||||
throw new NullPointerException("bossExecutor");
|
||||
}
|
||||
if (workerExecutor == null) {
|
||||
throw new NullPointerException("workerExecutor");
|
||||
}
|
||||
if (workerCount <= 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"workerCount (" + workerCount + ") " +
|
||||
"must be a positive integer.");
|
||||
}
|
||||
this.bossExecutor = bossExecutor;
|
||||
sink = new NioServerSocketPipelineSink(workerExecutor, workerCount);
|
||||
}
|
||||
|
||||
public ServerSocketChannel newChannel(ChannelPipeline pipeline) {
|
||||
return new NioServerSocketChannel(this, pipeline, sink);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.gleamynode.netty.channel.AbstractChannelSink;
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
import net.gleamynode.netty.channel.ChannelEvent;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelState;
|
||||
import net.gleamynode.netty.channel.ChannelStateEvent;
|
||||
import net.gleamynode.netty.channel.MessageEvent;
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
import net.gleamynode.netty.util.NamePreservingRunnable;
|
||||
|
||||
class NioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
|
||||
static final Logger logger =
|
||||
Logger.getLogger(NioServerSocketPipelineSink.class);
|
||||
private static final AtomicInteger nextId = new AtomicInteger();
|
||||
|
||||
private final int id = nextId.incrementAndGet();
|
||||
private final NioWorker[] workers;
|
||||
private final AtomicInteger workerIndex = new AtomicInteger();
|
||||
|
||||
NioServerSocketPipelineSink(Executor workerExecutor, int workerCount) {
|
||||
workers = new NioWorker[workerCount];
|
||||
for (int i = 0; i < workers.length; i ++) {
|
||||
workers[i] = new NioWorker(id, i + 1, workerExecutor);
|
||||
}
|
||||
}
|
||||
|
||||
public void eventSunk(
|
||||
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
|
||||
Channel channel = e.getChannel();
|
||||
if (channel instanceof NioServerSocketChannel) {
|
||||
handleServerSocket(e);
|
||||
} else if (channel instanceof NioSocketChannel) {
|
||||
handleAcceptedSocket(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleServerSocket(ChannelEvent e) {
|
||||
if (!(e instanceof ChannelStateEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ChannelStateEvent event = (ChannelStateEvent) e;
|
||||
NioServerSocketChannel channel =
|
||||
(NioServerSocketChannel) event.getChannel();
|
||||
ChannelFuture future = event.getFuture();
|
||||
ChannelState state = event.getState();
|
||||
Object value = event.getValue();
|
||||
|
||||
switch (state) {
|
||||
case OPEN:
|
||||
if (Boolean.FALSE.equals(value)) {
|
||||
close(channel, future);
|
||||
}
|
||||
break;
|
||||
case BOUND:
|
||||
if (value != null) {
|
||||
bind(channel, future, (SocketAddress) value);
|
||||
} else {
|
||||
close(channel, future);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAcceptedSocket(ChannelEvent e) {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
ChannelStateEvent event = (ChannelStateEvent) e;
|
||||
NioSocketChannel channel = (NioSocketChannel) event.getChannel();
|
||||
ChannelFuture future = event.getFuture();
|
||||
ChannelState state = event.getState();
|
||||
Object value = event.getValue();
|
||||
|
||||
switch (state) {
|
||||
case OPEN:
|
||||
if (Boolean.FALSE.equals(value)) {
|
||||
NioWorker.close(channel, future);
|
||||
}
|
||||
break;
|
||||
case BOUND:
|
||||
case CONNECTED:
|
||||
if (value == null) {
|
||||
NioWorker.close(channel, future);
|
||||
}
|
||||
break;
|
||||
case INTEREST_OPS:
|
||||
NioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
|
||||
break;
|
||||
}
|
||||
} else if (e instanceof MessageEvent) {
|
||||
MessageEvent event = (MessageEvent) e;
|
||||
NioSocketChannel channel = (NioSocketChannel) event.getChannel();
|
||||
channel.writeBuffer.offer(event);
|
||||
NioWorker.write(channel);
|
||||
}
|
||||
}
|
||||
|
||||
private void bind(
|
||||
NioServerSocketChannel channel, ChannelFuture future,
|
||||
SocketAddress localAddress) {
|
||||
|
||||
boolean bound = false;
|
||||
boolean bossStarted = false;
|
||||
try {
|
||||
channel.socket.socket().bind(localAddress, channel.getConfig().getBacklog());
|
||||
bound = true;
|
||||
|
||||
future.setSuccess();
|
||||
fireChannelBound(channel, channel.getLocalAddress());
|
||||
|
||||
Executor bossExecutor =
|
||||
((NioServerSocketChannelFactory) channel.getFactory()).bossExecutor;
|
||||
bossExecutor.execute(new NamePreservingRunnable(
|
||||
new Boss(channel),
|
||||
"New I/O server boss #" + id +" (channelId: " + channel.getId() +
|
||||
", " + channel.getLocalAddress() + ')'));
|
||||
bossStarted = true;
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
} finally {
|
||||
if (!bossStarted && bound) {
|
||||
close(channel, future);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void close(NioServerSocketChannel channel, ChannelFuture future) {
|
||||
boolean bound = channel.isBound();
|
||||
try {
|
||||
channel.socket.close();
|
||||
future.setSuccess();
|
||||
if (channel.setClosed()) {
|
||||
if (bound) {
|
||||
fireChannelUnbound(channel);
|
||||
}
|
||||
fireChannelClosed(channel);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
}
|
||||
|
||||
NioWorker nextWorker() {
|
||||
return workers[Math.abs(
|
||||
workerIndex.getAndIncrement() % workers.length)];
|
||||
}
|
||||
|
||||
private class Boss implements Runnable {
|
||||
private final NioServerSocketChannel channel;
|
||||
|
||||
Boss(NioServerSocketChannel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
for (;;) {
|
||||
try {
|
||||
SocketChannel acceptedSocket = channel.socket.accept();
|
||||
try {
|
||||
ChannelPipeline pipeline =
|
||||
channel.getConfig().getPipelineFactory().getPipeline();
|
||||
NioWorker worker = nextWorker();
|
||||
worker.register(new NioAcceptedSocketChannel(
|
||||
channel.getFactory(), pipeline, channel,
|
||||
NioServerSocketPipelineSink.this,
|
||||
acceptedSocket, worker), null);
|
||||
} catch (Exception e) {
|
||||
logger.warn(
|
||||
"Failed to initialize an accepted socket.", e);
|
||||
try {
|
||||
acceptedSocket.close();
|
||||
} catch (IOException e2) {
|
||||
logger.warn(
|
||||
"Failed to close a partially accepted socket.",
|
||||
e2);
|
||||
}
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
// Thrown every second to get ClosedChannelException
|
||||
// raised.
|
||||
} catch (ClosedChannelException e) {
|
||||
// Closed as requested.
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
logger.warn(
|
||||
"Failed to accept a connection.", e);
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e1) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import net.gleamynode.netty.channel.AbstractChannel;
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
import net.gleamynode.netty.channel.MessageEvent;
|
||||
|
||||
/**
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
*/
|
||||
abstract class NioSocketChannel extends AbstractChannel
|
||||
implements net.gleamynode.netty.channel.socket.SocketChannel {
|
||||
|
||||
final SocketChannel socket;
|
||||
private final NioSocketChannelConfig config;
|
||||
|
||||
final Queue<MessageEvent> writeBuffer =
|
||||
new ConcurrentLinkedQueue<MessageEvent>();
|
||||
MessageEvent currentWriteEvent;
|
||||
int currentWriteIndex;
|
||||
|
||||
public NioSocketChannel(
|
||||
Channel parent, ChannelFactory factory,
|
||||
ChannelPipeline pipeline, ChannelSink sink,
|
||||
SocketChannel socket) {
|
||||
super(parent, factory, pipeline, sink);
|
||||
|
||||
this.socket = socket;
|
||||
config = new DefaultNioSocketChannelConfig(socket.socket());
|
||||
}
|
||||
|
||||
abstract NioWorker getWorker();
|
||||
abstract void setWorker(NioWorker worker);
|
||||
|
||||
public NioSocketChannelConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public InetSocketAddress getLocalAddress() {
|
||||
return (InetSocketAddress) socket.socket().getLocalSocketAddress();
|
||||
}
|
||||
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
return (InetSocketAddress) socket.socket().getRemoteSocketAddress();
|
||||
}
|
||||
|
||||
public boolean isBound() {
|
||||
return isOpen() && socket.socket().isBound();
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return isOpen() && socket.socket().isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setClosed() {
|
||||
return super.setClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setInterestOpsNow(int interestOps) {
|
||||
super.setInterestOpsNow(interestOps);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChannelFuture getSucceededFuture() {
|
||||
return super.getSucceededFuture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
|
||||
if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) {
|
||||
return super.write(message, null);
|
||||
} else {
|
||||
return getUnsupportedOperationFuture();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
|
||||
import net.gleamynode.netty.channel.socket.SocketChannelConfig;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author The Netty Project (netty@googlegroups.com)
|
||||
* @author Trustin Lee (trustin@gmail.com)
|
||||
*
|
||||
* @version $Rev$, $Date$
|
||||
*
|
||||
* @apiviz.has net.gleamynode.netty.channel.socket.nio.ReceiveBufferSizePredictor
|
||||
*/
|
||||
public interface NioSocketChannelConfig extends SocketChannelConfig {
|
||||
|
||||
int getWriteSpinCount();
|
||||
|
||||
/**
|
||||
* The maximum loop count for a write operation until
|
||||
* {@link WritableByteChannel#write(ByteBuffer)} returns a non-zero value.
|
||||
* It is similar to what a spin lock is for in concurrency programming.
|
||||
* It improves memory utilization and write throughput significantly.
|
||||
*/
|
||||
void setWriteSpinCount(int writeSpinCount);
|
||||
|
||||
ReceiveBufferSizePredictor getReceiveBufferSizePredictor();
|
||||
void setReceiveBufferSizePredictor(ReceiveBufferSizePredictor predictor);
|
||||
|
||||
boolean isReadWriteFair();
|
||||
void setReadWriteFair(boolean fair);
|
||||
}
|
@ -0,0 +1,480 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.gleamynode.netty.buffer.ChannelBuffer;
|
||||
import net.gleamynode.netty.buffer.ChannelBuffers;
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
import net.gleamynode.netty.channel.ChannelException;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
import net.gleamynode.netty.util.NamePreservingRunnable;
|
||||
|
||||
class NioWorker implements Runnable {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(NioWorker.class);
|
||||
|
||||
private final int bossId;
|
||||
private final int id;
|
||||
private final Executor executor;
|
||||
private final AtomicBoolean started = new AtomicBoolean();
|
||||
volatile Thread thread;
|
||||
volatile Selector selector;
|
||||
final Object selectorGuard = new Object();
|
||||
|
||||
NioWorker(int bossId, int id, Executor executor) {
|
||||
this.bossId = bossId;
|
||||
this.id = id;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
void register(NioSocketChannel channel, ChannelFuture future) {
|
||||
boolean firstChannel = started.compareAndSet(false, true);
|
||||
Selector selector;
|
||||
if (firstChannel) {
|
||||
try {
|
||||
this.selector = selector = Selector.open();
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(
|
||||
"Failed to create a selector.", e);
|
||||
}
|
||||
} else {
|
||||
selector = this.selector;
|
||||
if (selector == null) {
|
||||
do {
|
||||
Thread.yield();
|
||||
selector = this.selector;
|
||||
} while (selector == null);
|
||||
}
|
||||
}
|
||||
|
||||
if (firstChannel) {
|
||||
try {
|
||||
channel.socket.register(selector, SelectionKey.OP_READ, channel);
|
||||
if (future != null) {
|
||||
future.setSuccess();
|
||||
}
|
||||
} catch (ClosedChannelException e) {
|
||||
future.setFailure(e);
|
||||
throw new ChannelException(
|
||||
"Failed to register a socket to the selector.", e);
|
||||
}
|
||||
|
||||
boolean server = !(channel instanceof NioClientSocketChannel);
|
||||
if (server) {
|
||||
fireChannelOpen(channel);
|
||||
}
|
||||
|
||||
fireChannelBound(channel, channel.getLocalAddress());
|
||||
fireChannelConnected(channel, channel.getRemoteAddress());
|
||||
|
||||
String threadName =
|
||||
(server ? "New I/O server worker #"
|
||||
: "New I/O client worker #") + bossId + '-' + id;
|
||||
|
||||
executor.execute(new NamePreservingRunnable(this, threadName));
|
||||
} else {
|
||||
synchronized (selectorGuard) {
|
||||
selector.wakeup();
|
||||
try {
|
||||
channel.socket.register(selector, SelectionKey.OP_READ, channel);
|
||||
if (future != null) {
|
||||
future.setSuccess();
|
||||
}
|
||||
} catch (ClosedChannelException e) {
|
||||
future.setFailure(e);
|
||||
throw new ChannelException(
|
||||
"Failed to register a socket to the selector.", e);
|
||||
}
|
||||
|
||||
fireChannelOpen(channel);
|
||||
fireChannelBound(channel, channel.getLocalAddress());
|
||||
fireChannelConnected(channel, channel.getRemoteAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
thread = Thread.currentThread();
|
||||
|
||||
boolean shutdown = false;
|
||||
Selector selector = this.selector;
|
||||
for (;;) {
|
||||
synchronized (selectorGuard) {
|
||||
// This empty synchronization block prevents the selector
|
||||
// from acquiring its lock.
|
||||
}
|
||||
try {
|
||||
int selectedKeyCount = selector.select(500);
|
||||
if (selectedKeyCount > 0) {
|
||||
processSelectedKeys(selector.selectedKeys());
|
||||
}
|
||||
|
||||
// Exit the loop when there's nothing to handle.
|
||||
// The shutdown flag is used to delay the shutdown of this
|
||||
// loop to avoid excessive Selector creation when
|
||||
// connections are registered in a one-by-one manner instead of
|
||||
// concurrent manner.
|
||||
if (selector.keys().isEmpty()) {
|
||||
if (shutdown) {
|
||||
synchronized (selectorGuard) {
|
||||
if (selector.keys().isEmpty()) {
|
||||
try {
|
||||
selector.close();
|
||||
} catch (IOException e) {
|
||||
logger.warn(
|
||||
"Failed to close a selector.", e);
|
||||
} finally {
|
||||
this.selector = null;
|
||||
}
|
||||
started.set(false);
|
||||
break;
|
||||
} else {
|
||||
shutdown = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Give one more second.
|
||||
shutdown = true;
|
||||
}
|
||||
} else {
|
||||
shutdown = false;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
logger.warn(
|
||||
"Unexpected exception in the selector loop.", t);
|
||||
|
||||
// Prevent possible consecutive immediate failures.
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processSelectedKeys(Set<SelectionKey> selectedKeys) {
|
||||
for (Iterator<SelectionKey> i = selectedKeys.iterator(); i.hasNext();) {
|
||||
SelectionKey k = i.next();
|
||||
i.remove();
|
||||
|
||||
if (!k.isValid()) {
|
||||
close(k);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k.isReadable()) {
|
||||
read(k);
|
||||
}
|
||||
|
||||
if (!k.isValid()) {
|
||||
close(k);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k.isWritable()) {
|
||||
write(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void read(SelectionKey k) {
|
||||
ReadableByteChannel ch = (ReadableByteChannel) k.channel();
|
||||
NioSocketChannel channel = (NioSocketChannel) k.attachment();
|
||||
|
||||
ReceiveBufferSizePredictor predictor =
|
||||
channel.getConfig().getReceiveBufferSizePredictor();
|
||||
ByteBuffer buf = ByteBuffer.allocate(predictor.nextReceiveBufferSize());
|
||||
|
||||
int ret = 0;
|
||||
int readBytes = 0;
|
||||
boolean failure = true;
|
||||
try {
|
||||
while ((ret = ch.read(buf)) > 0) {
|
||||
readBytes += ret;
|
||||
if (!buf.hasRemaining()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
failure = false;
|
||||
} catch (Throwable t) {
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
|
||||
if (readBytes > 0) {
|
||||
// Update the predictor.
|
||||
predictor.previousReceiveBufferSize(readBytes);
|
||||
|
||||
// Fire the event.
|
||||
ChannelBuffer buffer;
|
||||
if (readBytes == buf.capacity()) {
|
||||
buffer = ChannelBuffers.wrappedBuffer(buf.array());
|
||||
} else {
|
||||
buffer = ChannelBuffers.wrappedBuffer(buf.array(), 0, readBytes);
|
||||
}
|
||||
fireMessageReceived(channel, buffer);
|
||||
}
|
||||
|
||||
if (ret < 0 || failure) {
|
||||
close(k);
|
||||
}
|
||||
}
|
||||
|
||||
private static void write(SelectionKey k) {
|
||||
NioSocketChannel ch = (NioSocketChannel) k.attachment();
|
||||
write(ch);
|
||||
}
|
||||
|
||||
private static void close(SelectionKey k) {
|
||||
NioSocketChannel ch = (NioSocketChannel) k.attachment();
|
||||
close(ch, ch.getSucceededFuture());
|
||||
}
|
||||
|
||||
static void write(NioSocketChannel channel) {
|
||||
if (channel.writeBuffer.isEmpty() && channel.currentWriteEvent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean addOpWrite = false;
|
||||
boolean removeOpWrite = false;
|
||||
|
||||
final int maxWrittenBytes;
|
||||
if (channel.getConfig().isReadWriteFair()) {
|
||||
// Set limitation for the number of written bytes for read-write
|
||||
// fairness. I used maxReadBufferSize * 3 / 2, which yields best
|
||||
// performance in my experience while not breaking fairness much.
|
||||
int previousReceiveBufferSize =
|
||||
channel.getConfig().getReceiveBufferSizePredictor().nextReceiveBufferSize();
|
||||
maxWrittenBytes = previousReceiveBufferSize + previousReceiveBufferSize >>> 1;
|
||||
} else {
|
||||
maxWrittenBytes = Integer.MAX_VALUE;
|
||||
}
|
||||
int writtenBytes = 0;
|
||||
|
||||
synchronized (channel.writeBuffer) {
|
||||
for (;;) {
|
||||
if (channel.writeBuffer.isEmpty() && channel.currentWriteEvent == null) {
|
||||
removeOpWrite = true;
|
||||
break;
|
||||
}
|
||||
|
||||
ChannelBuffer a;
|
||||
if (channel.currentWriteEvent == null) {
|
||||
channel.currentWriteEvent = channel.writeBuffer.poll();
|
||||
a = (ChannelBuffer) channel.currentWriteEvent.getMessage();
|
||||
channel.currentWriteIndex = a.readerIndex();
|
||||
} else {
|
||||
a = (ChannelBuffer) channel.currentWriteEvent.getMessage();
|
||||
}
|
||||
|
||||
int localWrittenBytes = 0;
|
||||
try {
|
||||
for (int i = channel.getConfig().getWriteSpinCount(); i > 0; i --) {
|
||||
localWrittenBytes = a.getBytes(
|
||||
channel.currentWriteIndex,
|
||||
channel.socket,
|
||||
Math.min(maxWrittenBytes - writtenBytes, a.writerIndex() - channel.currentWriteIndex));
|
||||
if (localWrittenBytes != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
channel.currentWriteEvent.getFuture().setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
|
||||
writtenBytes += localWrittenBytes;
|
||||
channel.currentWriteIndex += localWrittenBytes;
|
||||
if (channel.currentWriteIndex == a.writerIndex()) {
|
||||
// Successful write - proceed to the next message.
|
||||
channel.currentWriteEvent.getFuture().setSuccess();
|
||||
channel.currentWriteEvent = null;
|
||||
} else {
|
||||
// Not written fully - perhaps the kernel buffer is full.
|
||||
addOpWrite = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (addOpWrite) {
|
||||
setOpWrite(channel, true);
|
||||
} else if (removeOpWrite) {
|
||||
setOpWrite(channel, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setOpWrite(NioSocketChannel channel, boolean opWrite) {
|
||||
NioWorker worker = channel.getWorker();
|
||||
if (worker == null) {
|
||||
IllegalStateException cause =
|
||||
new IllegalStateException("Channel not connected yet (null worker)");
|
||||
fireExceptionCaught(channel, cause);
|
||||
return;
|
||||
}
|
||||
|
||||
Selector selector = worker.selector;
|
||||
SelectionKey key = channel.socket.keyFor(selector);
|
||||
if (!key.isValid()) {
|
||||
close(key);
|
||||
return;
|
||||
}
|
||||
int interestOps;
|
||||
boolean changed = false;
|
||||
if (opWrite) {
|
||||
if (Thread.currentThread() == worker.thread) {
|
||||
interestOps = key.interestOps();
|
||||
if ((interestOps & SelectionKey.OP_WRITE) == 0) {
|
||||
interestOps |= SelectionKey.OP_WRITE;
|
||||
key.interestOps(interestOps);
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
synchronized (worker.selectorGuard) {
|
||||
selector.wakeup();
|
||||
interestOps = key.interestOps();
|
||||
if ((interestOps & SelectionKey.OP_WRITE) == 0) {
|
||||
interestOps |= SelectionKey.OP_WRITE;
|
||||
key.interestOps(interestOps);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Thread.currentThread() == worker.thread) {
|
||||
interestOps = key.interestOps();
|
||||
if ((interestOps & SelectionKey.OP_WRITE) != 0) {
|
||||
interestOps &= ~SelectionKey.OP_WRITE;
|
||||
key.interestOps(interestOps);
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
synchronized (worker.selectorGuard) {
|
||||
selector.wakeup();
|
||||
interestOps = key.interestOps();
|
||||
if ((interestOps & SelectionKey.OP_WRITE) != 0) {
|
||||
interestOps &= ~SelectionKey.OP_WRITE;
|
||||
key.interestOps(interestOps);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
channel.setInterestOpsNow(interestOps);
|
||||
fireChannelInterestChanged(channel, interestOps);
|
||||
}
|
||||
}
|
||||
|
||||
static void close(NioSocketChannel channel, ChannelFuture future) {
|
||||
NioWorker worker = channel.getWorker();
|
||||
if (worker != null) {
|
||||
Selector selector = worker.selector;
|
||||
SelectionKey key = channel.socket.keyFor(selector);
|
||||
if (key != null) {
|
||||
key.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
boolean connected = channel.isConnected();
|
||||
boolean bound = channel.isBound();
|
||||
try {
|
||||
channel.socket.close();
|
||||
future.setSuccess();
|
||||
if (channel.setClosed()) {
|
||||
if (connected) {
|
||||
if (channel.getInterestOps() != Channel.OP_WRITE) {
|
||||
channel.setInterestOpsNow(Channel.OP_WRITE);
|
||||
fireChannelInterestChanged(channel, Channel.OP_WRITE);
|
||||
}
|
||||
fireChannelDisconnected(channel);
|
||||
}
|
||||
if (bound) {
|
||||
fireChannelUnbound(channel);
|
||||
}
|
||||
fireChannelClosed(channel);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
}
|
||||
|
||||
static void setInterestOps(
|
||||
NioSocketChannel channel, ChannelFuture future, int interestOps) {
|
||||
NioWorker worker = channel.getWorker();
|
||||
if (worker == null) {
|
||||
IllegalStateException cause =
|
||||
new IllegalStateException("Channel not connected yet (null worker)");
|
||||
future.setFailure(cause);
|
||||
fireExceptionCaught(channel, cause);
|
||||
return;
|
||||
}
|
||||
|
||||
Selector selector = worker.selector;
|
||||
SelectionKey key = channel.socket.keyFor(selector);
|
||||
if (key == null || selector == null) {
|
||||
IllegalStateException cause =
|
||||
new IllegalStateException("Channel not connected yet (SelectionKey not found)");
|
||||
future.setFailure(cause);
|
||||
fireExceptionCaught(channel, cause);
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
try {
|
||||
if (Thread.currentThread() == worker.thread) {
|
||||
if (key.interestOps() != interestOps) {
|
||||
key.interestOps(interestOps);
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
synchronized (worker.selectorGuard) {
|
||||
selector.wakeup();
|
||||
if (key.interestOps() != interestOps) {
|
||||
key.interestOps(interestOps);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
future.setSuccess();
|
||||
if (changed) {
|
||||
channel.setInterestOpsNow(interestOps);
|
||||
fireChannelInterestChanged(channel, interestOps);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
||||
|
||||
public interface ReceiveBufferSizePredictor {
|
||||
int nextReceiveBufferSize();
|
||||
void previousReceiveBufferSize(int previousReceiveBufferSize);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* <a href="http://en.wikipedia.org/wiki/New_I/O">NIO</a>-based socket channel
|
||||
* API implementation - recommended for large number of connections (> 1000).
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.nio;
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.oio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
import net.gleamynode.netty.channel.ChannelException;
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
|
||||
class OioAcceptedSocketChannel extends OioSocketChannel {
|
||||
|
||||
private final PushbackInputStream in;
|
||||
private final OutputStream out;
|
||||
|
||||
OioAcceptedSocketChannel(
|
||||
Channel parent,
|
||||
ChannelFactory factory,
|
||||
ChannelPipeline pipeline,
|
||||
ChannelSink sink,
|
||||
Socket socket) {
|
||||
|
||||
super(parent, factory, pipeline, sink, socket);
|
||||
|
||||
try {
|
||||
in = new PushbackInputStream(socket.getInputStream(), 1);
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException("Failed to obtain an InputStream.", e);
|
||||
}
|
||||
try {
|
||||
out = socket.getOutputStream();
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException("Failed to obtain an OutputStream.", e);
|
||||
}
|
||||
|
||||
fireChannelOpen(this);
|
||||
fireChannelBound(this, getLocalAddress());
|
||||
fireChannelConnected(this, getRemoteAddress());
|
||||
}
|
||||
|
||||
@Override
|
||||
PushbackInputStream getInputStream() {
|
||||
return in;
|
||||
}
|
||||
|
||||
@Override
|
||||
OutputStream getOutputStream() {
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setInputStream(PushbackInputStream in) {
|
||||
if (this.in != in) {
|
||||
throw new IllegalStateException("Should not reach here.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void setOutputStream(OutputStream out) {
|
||||
if (this.out != out) {
|
||||
throw new IllegalStateException("Should not reach here.");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.oio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
|
||||
class OioClientSocketChannel extends OioSocketChannel {
|
||||
|
||||
volatile PushbackInputStream in;
|
||||
volatile OutputStream out;
|
||||
|
||||
OioClientSocketChannel(
|
||||
ChannelFactory factory,
|
||||
ChannelPipeline pipeline,
|
||||
ChannelSink sink) {
|
||||
|
||||
super(null, factory, pipeline, sink, new Socket());
|
||||
|
||||
fireChannelOpen(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
PushbackInputStream getInputStream() {
|
||||
return in;
|
||||
}
|
||||
|
||||
@Override
|
||||
OutputStream getOutputStream() {
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setInputStream(PushbackInputStream in) {
|
||||
if (this.in == null) {
|
||||
this.in = in;
|
||||
} else if (this.in != in) {
|
||||
throw new IllegalStateException("Shouldn't reach here.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void setOutputStream(OutputStream out) {
|
||||
if (this.out == null) {
|
||||
this.out = out;
|
||||
} else if (this.out != out) {
|
||||
throw new IllegalStateException("Shouldn't reach here.");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.oio;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.socket.ClientSocketChannelFactory;
|
||||
import net.gleamynode.netty.channel.socket.SocketChannel;
|
||||
|
||||
public class OioClientSocketChannelFactory implements ClientSocketChannelFactory {
|
||||
|
||||
final OioClientSocketPipelineSink sink;
|
||||
|
||||
public OioClientSocketChannelFactory(Executor workerExecutor) {
|
||||
if (workerExecutor == null) {
|
||||
throw new NullPointerException("workerExecutor");
|
||||
}
|
||||
sink = new OioClientSocketPipelineSink(workerExecutor);
|
||||
}
|
||||
|
||||
public SocketChannel newChannel(ChannelPipeline pipeline) {
|
||||
return new OioClientSocketChannel(this, pipeline, sink);
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.oio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.PushbackInputStream;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import net.gleamynode.netty.channel.AbstractChannelSink;
|
||||
import net.gleamynode.netty.channel.ChannelEvent;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelFutureListener;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelState;
|
||||
import net.gleamynode.netty.channel.ChannelStateEvent;
|
||||
import net.gleamynode.netty.channel.MessageEvent;
|
||||
import net.gleamynode.netty.util.NamePreservingRunnable;
|
||||
|
||||
class OioClientSocketPipelineSink extends AbstractChannelSink {
|
||||
|
||||
private final Executor workerExecutor;
|
||||
|
||||
OioClientSocketPipelineSink(Executor workerExecutor) {
|
||||
this.workerExecutor = workerExecutor;
|
||||
}
|
||||
|
||||
public void eventSunk(
|
||||
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
|
||||
OioClientSocketChannel channel = (OioClientSocketChannel) e.getChannel();
|
||||
ChannelFuture future = e.getFuture();
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
ChannelStateEvent stateEvent = (ChannelStateEvent) e;
|
||||
ChannelState state = stateEvent.getState();
|
||||
Object value = stateEvent.getValue();
|
||||
switch (state) {
|
||||
case OPEN:
|
||||
if (Boolean.FALSE.equals(value)) {
|
||||
OioWorker.close(channel, future);
|
||||
}
|
||||
break;
|
||||
case BOUND:
|
||||
if (value != null) {
|
||||
bind(channel, future, (SocketAddress) value);
|
||||
} else {
|
||||
OioWorker.close(channel, future);
|
||||
}
|
||||
break;
|
||||
case CONNECTED:
|
||||
if (value != null) {
|
||||
connect(channel, future, (SocketAddress) value);
|
||||
} else {
|
||||
OioWorker.close(channel, future);
|
||||
}
|
||||
break;
|
||||
case INTEREST_OPS:
|
||||
OioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
|
||||
break;
|
||||
}
|
||||
} else if (e instanceof MessageEvent) {
|
||||
OioWorker.write(
|
||||
channel, future,
|
||||
((MessageEvent) e).getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void bind(
|
||||
OioClientSocketChannel channel, ChannelFuture future,
|
||||
SocketAddress localAddress) {
|
||||
try {
|
||||
channel.socket.bind(localAddress);
|
||||
future.setSuccess();
|
||||
fireChannelBound(channel, channel.getLocalAddress());
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
}
|
||||
|
||||
private void connect(
|
||||
OioClientSocketChannel channel, ChannelFuture future,
|
||||
SocketAddress remoteAddress) {
|
||||
|
||||
boolean bound = channel.isBound();
|
||||
boolean connected = false;
|
||||
boolean workerStarted = false;
|
||||
|
||||
future.addListener(new ChannelFutureListener() {
|
||||
public void operationComplete(ChannelFuture future) {
|
||||
if (future.isCancelled()) {
|
||||
future.getChannel().close();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
channel.socket.connect(
|
||||
remoteAddress, channel.getConfig().getConnectTimeoutMillis());
|
||||
connected = true;
|
||||
|
||||
// Obtain I/O stream.
|
||||
channel.in = new PushbackInputStream(channel.socket.getInputStream(), 1);
|
||||
channel.out = channel.socket.getOutputStream();
|
||||
|
||||
// Fire events.
|
||||
future.setSuccess();
|
||||
if (!bound) {
|
||||
fireChannelBound(channel, channel.getLocalAddress());
|
||||
}
|
||||
fireChannelConnected(channel, channel.getRemoteAddress());
|
||||
|
||||
// Start the business.
|
||||
workerExecutor.execute(new NamePreservingRunnable(
|
||||
new OioWorker(channel),
|
||||
"Old I/O client worker (channelId: " + channel.getId() + ", " +
|
||||
channel.getLocalAddress() + " => " +
|
||||
channel.getRemoteAddress() + ')'));
|
||||
|
||||
workerStarted = true;
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
} finally {
|
||||
if (connected && !workerStarted) {
|
||||
OioWorker.close(channel, future);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.oio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import net.gleamynode.netty.channel.AbstractServerChannel;
|
||||
import net.gleamynode.netty.channel.ChannelException;
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
import net.gleamynode.netty.channel.socket.DefaultServerSocketChannelConfig;
|
||||
import net.gleamynode.netty.channel.socket.ServerSocketChannel;
|
||||
import net.gleamynode.netty.channel.socket.ServerSocketChannelConfig;
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
|
||||
class OioServerSocketChannel extends AbstractServerChannel
|
||||
implements ServerSocketChannel {
|
||||
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(OioServerSocketChannel.class);
|
||||
|
||||
final ServerSocket socket;
|
||||
private final ServerSocketChannelConfig config;
|
||||
|
||||
OioServerSocketChannel(
|
||||
ChannelFactory factory,
|
||||
ChannelPipeline pipeline,
|
||||
ChannelSink sink) {
|
||||
|
||||
super(factory, pipeline, sink);
|
||||
|
||||
try {
|
||||
socket = new ServerSocket();
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(
|
||||
"Failed to open a server socket.", e);
|
||||
}
|
||||
|
||||
try {
|
||||
socket.setSoTimeout(1000);
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e2) {
|
||||
logger.warn(
|
||||
"Failed to close a partially initialized socket.", e2);
|
||||
}
|
||||
throw new ChannelException(
|
||||
"Failed to set the server socket timeout.", e);
|
||||
}
|
||||
|
||||
config = new DefaultServerSocketChannelConfig(socket);
|
||||
|
||||
fireChannelOpen(this);
|
||||
}
|
||||
|
||||
public ServerSocketChannelConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public InetSocketAddress getLocalAddress() {
|
||||
return (InetSocketAddress) socket.getLocalSocketAddress();
|
||||
}
|
||||
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isBound() {
|
||||
return isOpen() & socket.isBound();
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setClosed() {
|
||||
return super.setClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChannelFuture getSucceededFuture() {
|
||||
return super.getSucceededFuture();
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.oio;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
import net.gleamynode.netty.channel.socket.ServerSocketChannel;
|
||||
import net.gleamynode.netty.channel.socket.ServerSocketChannelFactory;
|
||||
|
||||
public class OioServerSocketChannelFactory implements ServerSocketChannelFactory {
|
||||
|
||||
final Executor bossExecutor;
|
||||
private final ChannelSink sink;
|
||||
|
||||
public OioServerSocketChannelFactory(
|
||||
Executor bossExecutor, Executor workerExecutor) {
|
||||
if (bossExecutor == null) {
|
||||
throw new NullPointerException("bossExecutor");
|
||||
}
|
||||
if (workerExecutor == null) {
|
||||
throw new NullPointerException("workerExecutor");
|
||||
}
|
||||
this.bossExecutor = bossExecutor;
|
||||
sink = new OioServerSocketPipelineSink(workerExecutor);
|
||||
}
|
||||
|
||||
public ServerSocketChannel newChannel(ChannelPipeline pipeline) {
|
||||
return new OioServerSocketChannel(this, pipeline, sink);
|
||||
}
|
||||
}
|
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.oio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import net.gleamynode.netty.channel.AbstractChannelSink;
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
import net.gleamynode.netty.channel.ChannelEvent;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelState;
|
||||
import net.gleamynode.netty.channel.ChannelStateEvent;
|
||||
import net.gleamynode.netty.channel.MessageEvent;
|
||||
import net.gleamynode.netty.logging.Logger;
|
||||
import net.gleamynode.netty.util.NamePreservingRunnable;
|
||||
|
||||
class OioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
|
||||
static final Logger logger =
|
||||
Logger.getLogger(OioServerSocketPipelineSink.class);
|
||||
|
||||
final Executor workerExecutor;
|
||||
|
||||
OioServerSocketPipelineSink(Executor workerExecutor) {
|
||||
this.workerExecutor = workerExecutor;
|
||||
}
|
||||
|
||||
public void eventSunk(
|
||||
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
|
||||
Channel channel = e.getChannel();
|
||||
if (channel instanceof OioServerSocketChannel) {
|
||||
handleServerSocket(e);
|
||||
} else if (channel instanceof OioAcceptedSocketChannel) {
|
||||
handleAcceptedSocket(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleServerSocket(ChannelEvent e) {
|
||||
if (!(e instanceof ChannelStateEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ChannelStateEvent event = (ChannelStateEvent) e;
|
||||
OioServerSocketChannel channel =
|
||||
(OioServerSocketChannel) event.getChannel();
|
||||
ChannelFuture future = event.getFuture();
|
||||
ChannelState state = event.getState();
|
||||
Object value = event.getValue();
|
||||
|
||||
switch (state) {
|
||||
case OPEN:
|
||||
if (Boolean.FALSE.equals(value)) {
|
||||
close(channel, future);
|
||||
}
|
||||
break;
|
||||
case BOUND:
|
||||
if (value != null) {
|
||||
bind(channel, future, (SocketAddress) value);
|
||||
} else {
|
||||
close(channel, future);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAcceptedSocket(ChannelEvent e) {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
ChannelStateEvent event = (ChannelStateEvent) e;
|
||||
OioAcceptedSocketChannel channel =
|
||||
(OioAcceptedSocketChannel) event.getChannel();
|
||||
ChannelFuture future = event.getFuture();
|
||||
ChannelState state = event.getState();
|
||||
Object value = event.getValue();
|
||||
|
||||
switch (state) {
|
||||
case OPEN:
|
||||
if (Boolean.FALSE.equals(value)) {
|
||||
OioWorker.close(channel, future);
|
||||
}
|
||||
break;
|
||||
case BOUND:
|
||||
case CONNECTED:
|
||||
if (value == null) {
|
||||
OioWorker.close(channel, future);
|
||||
}
|
||||
break;
|
||||
case INTEREST_OPS:
|
||||
OioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
|
||||
break;
|
||||
}
|
||||
} else if (e instanceof MessageEvent) {
|
||||
MessageEvent event = (MessageEvent) e;
|
||||
OioSocketChannel channel = (OioSocketChannel) event.getChannel();
|
||||
ChannelFuture future = event.getFuture();
|
||||
Object message = event.getMessage();
|
||||
OioWorker.write(channel, future, message);
|
||||
}
|
||||
}
|
||||
|
||||
private void bind(
|
||||
OioServerSocketChannel channel, ChannelFuture future,
|
||||
SocketAddress localAddress) {
|
||||
|
||||
boolean bound = false;
|
||||
boolean bossStarted = false;
|
||||
try {
|
||||
channel.socket.bind(localAddress, channel.getConfig().getBacklog());
|
||||
bound = true;
|
||||
|
||||
future.setSuccess();
|
||||
localAddress = channel.getLocalAddress();
|
||||
fireChannelBound(channel, localAddress);
|
||||
|
||||
Executor bossExecutor =
|
||||
((OioServerSocketChannelFactory) channel.getFactory()).bossExecutor;
|
||||
bossExecutor.execute(new NamePreservingRunnable(
|
||||
new Boss(channel),
|
||||
"Old I/O server boss (channelId: " + channel.getId() +
|
||||
", " + localAddress + ')'));
|
||||
bossStarted = true;
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
} finally {
|
||||
if (!bossStarted && bound) {
|
||||
close(channel, future);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void close(OioServerSocketChannel channel, ChannelFuture future) {
|
||||
boolean bound = channel.isBound();
|
||||
try {
|
||||
channel.socket.close();
|
||||
future.setSuccess();
|
||||
if (channel.setClosed()) {
|
||||
if (bound) {
|
||||
fireChannelUnbound(channel);
|
||||
}
|
||||
fireChannelClosed(channel);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
}
|
||||
|
||||
private class Boss implements Runnable {
|
||||
private final OioServerSocketChannel channel;
|
||||
|
||||
Boss(OioServerSocketChannel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (channel.isBound()) {
|
||||
try {
|
||||
Socket acceptedSocket = channel.socket.accept();
|
||||
try {
|
||||
ChannelPipeline pipeline =
|
||||
channel.getConfig().getPipelineFactory().getPipeline();
|
||||
final OioAcceptedSocketChannel acceptedChannel =
|
||||
new OioAcceptedSocketChannel(
|
||||
channel,
|
||||
channel.getFactory(),
|
||||
pipeline,
|
||||
OioServerSocketPipelineSink.this,
|
||||
acceptedSocket);
|
||||
workerExecutor.execute(
|
||||
new NamePreservingRunnable(
|
||||
new OioWorker(acceptedChannel),
|
||||
"Old I/O server worker (parentId: " +
|
||||
channel.getId() +
|
||||
", channelId: " + acceptedChannel.getId() + ", " +
|
||||
channel.getRemoteAddress() + " => " +
|
||||
channel.getLocalAddress() + ')'));
|
||||
} catch (Exception e) {
|
||||
logger.warn(
|
||||
"Failed to initialize an accepted socket.", e);
|
||||
try {
|
||||
acceptedSocket.close();
|
||||
} catch (IOException e2) {
|
||||
logger.warn(
|
||||
"Failed to close a partially accepted socket.",
|
||||
e2);
|
||||
}
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
// Thrown every second to stop when requested.
|
||||
} catch (IOException e) {
|
||||
logger.warn(
|
||||
"Failed to accept a connection.", e);
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e1) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.oio;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
import net.gleamynode.netty.channel.AbstractChannel;
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
import net.gleamynode.netty.channel.ChannelFactory;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
import net.gleamynode.netty.channel.ChannelPipeline;
|
||||
import net.gleamynode.netty.channel.ChannelSink;
|
||||
import net.gleamynode.netty.channel.socket.DefaultSocketChannelConfig;
|
||||
import net.gleamynode.netty.channel.socket.SocketChannel;
|
||||
import net.gleamynode.netty.channel.socket.SocketChannelConfig;
|
||||
|
||||
abstract class OioSocketChannel extends AbstractChannel
|
||||
implements SocketChannel {
|
||||
|
||||
final Socket socket;
|
||||
private final SocketChannelConfig config;
|
||||
volatile Thread workerThread;
|
||||
|
||||
OioSocketChannel(
|
||||
Channel parent,
|
||||
ChannelFactory factory,
|
||||
ChannelPipeline pipeline,
|
||||
ChannelSink sink,
|
||||
Socket socket) {
|
||||
|
||||
super(parent, factory, pipeline, sink);
|
||||
|
||||
this.socket = socket;
|
||||
config = new DefaultSocketChannelConfig(socket);
|
||||
}
|
||||
|
||||
public SocketChannelConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public InetSocketAddress getLocalAddress() {
|
||||
return (InetSocketAddress) socket.getLocalSocketAddress();
|
||||
}
|
||||
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
return (InetSocketAddress) socket.getRemoteSocketAddress();
|
||||
}
|
||||
|
||||
public boolean isBound() {
|
||||
return isOpen() & socket.isBound();
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return isOpen() & socket.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setClosed() {
|
||||
return super.setClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setInterestOpsNow(int interestOps) {
|
||||
super.setInterestOpsNow(interestOps);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChannelFuture getSucceededFuture() {
|
||||
return super.getSucceededFuture();
|
||||
}
|
||||
|
||||
abstract PushbackInputStream getInputStream();
|
||||
abstract void setInputStream(PushbackInputStream in);
|
||||
abstract OutputStream getOutputStream();
|
||||
abstract void setOutputStream(OutputStream out);
|
||||
|
||||
@Override
|
||||
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
|
||||
if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) {
|
||||
return super.write(message, null);
|
||||
} else {
|
||||
return getUnsupportedOperationFuture();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.oio;
|
||||
|
||||
import static net.gleamynode.netty.channel.Channels.*;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
|
||||
import net.gleamynode.netty.buffer.ChannelBuffer;
|
||||
import net.gleamynode.netty.buffer.ChannelBuffers;
|
||||
import net.gleamynode.netty.channel.Channel;
|
||||
import net.gleamynode.netty.channel.ChannelFuture;
|
||||
|
||||
class OioWorker implements Runnable {
|
||||
|
||||
private final OioSocketChannel channel;
|
||||
|
||||
OioWorker(OioSocketChannel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
channel.workerThread = Thread.currentThread();
|
||||
final PushbackInputStream in = channel.getInputStream();
|
||||
|
||||
for (;;) {
|
||||
synchronized (this) {
|
||||
while (!channel.isReadable()) {
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
if (!channel.isOpen()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte[] buf;
|
||||
int readBytes;
|
||||
try {
|
||||
int bytesToRead = in.available();
|
||||
if (bytesToRead > 0) {
|
||||
buf = new byte[bytesToRead];
|
||||
readBytes = in.read(buf);
|
||||
} else {
|
||||
int b = in.read();
|
||||
if (b < 0) {
|
||||
break;
|
||||
}
|
||||
in.unread(b);
|
||||
continue;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (!channel.socket.isClosed()) {
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ChannelBuffer buffer;
|
||||
if (readBytes == buf.length) {
|
||||
buffer = ChannelBuffers.wrappedBuffer(buf);
|
||||
} else {
|
||||
buffer = ChannelBuffers.wrappedBuffer(buf, 0, readBytes);
|
||||
}
|
||||
fireMessageReceived(channel, buffer);
|
||||
}
|
||||
close(channel, channel.getSucceededFuture());
|
||||
}
|
||||
|
||||
static void write(
|
||||
OioSocketChannel channel, ChannelFuture future,
|
||||
Object message) {
|
||||
OutputStream out = channel.getOutputStream();
|
||||
try {
|
||||
ChannelBuffer a = (ChannelBuffer) message;
|
||||
synchronized (out) {
|
||||
a.getBytes(a.readerIndex(), out, a.readableBytes());
|
||||
}
|
||||
future.setSuccess();
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
}
|
||||
|
||||
static void setInterestOps(
|
||||
OioSocketChannel channel, ChannelFuture future, int interestOps) {
|
||||
|
||||
boolean changed = false;
|
||||
try {
|
||||
if (channel.getInterestOps() != interestOps) {
|
||||
if ((interestOps & Channel.OP_READ) != 0) {
|
||||
channel.setInterestOpsNow(Channel.OP_READ);
|
||||
} else {
|
||||
channel.setInterestOpsNow(Channel.OP_NONE);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
future.setSuccess();
|
||||
if (changed) {
|
||||
// Notify the worker so it stops reading.
|
||||
Thread currentThread = Thread.currentThread();
|
||||
Thread workerThread = channel.workerThread;
|
||||
if (workerThread != null && currentThread != workerThread) {
|
||||
workerThread.interrupt();
|
||||
}
|
||||
|
||||
channel.setInterestOpsNow(interestOps);
|
||||
fireChannelInterestChanged(channel, interestOps);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
}
|
||||
|
||||
static void close(OioSocketChannel channel, ChannelFuture future) {
|
||||
boolean connected = channel.isConnected();
|
||||
boolean bound = channel.isBound();
|
||||
try {
|
||||
channel.socket.close();
|
||||
future.setSuccess();
|
||||
if (channel.setClosed()) {
|
||||
if (connected) {
|
||||
if (channel.getInterestOps() != Channel.OP_WRITE) {
|
||||
channel.setInterestOpsNow(Channel.OP_WRITE);
|
||||
fireChannelInterestChanged(channel, Channel.OP_WRITE);
|
||||
}
|
||||
fireChannelDisconnected(channel);
|
||||
}
|
||||
if (bound) {
|
||||
fireChannelUnbound(channel);
|
||||
}
|
||||
fireChannelClosed(channel);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Old blocking I/O based socket channel API implementation - recommended for
|
||||
* small number of connections (< 1000).
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket.oio;
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Trustin Heuiseung Lee
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract TCP and UDP socket interfaces which extend the core channel API.
|
||||
*/
|
||||
package net.gleamynode.netty.channel.socket;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user