blob: 2ef691bca61e555fd97b047e96a05acc00dd9f93 [file] [log] [blame]
Cheng Tang07b30872014-04-27 16:37:18 +08001<html><head><META http-equiv="Content-Type" content="text/html; charset=iso-8859-1"><title>Apache Tomcat 7 (7.0.42) - Advanced IO and Tomcat</title><meta name="author" content="Remy Maucherat"><style type="text/css" media="print">
2 .noPrint {display: none;}
3 td#mainBody {width: 100%;}
4 </style><style type="text/css">
5 code {background-color:rgb(224,255,255);padding:0 0.1em;}
6 code.attributeName, code.propertyName {background-color:transparent;}
7 </style><style type="text/css">
8 .wrapped-source code { display: block; background-color: transparent; }
9 .wrapped-source div { margin: 0 0 0 1.25em; }
10 .wrapped-source p { margin: 0 0 0 1.25em; text-indent: -1.25em; }
11 </style><style type="text/css">
12 p.notice {
13 border: 1px solid rgb(255, 0, 0);
14 background-color: rgb(238, 238, 238);
15 color: rgb(0, 51, 102);
16 padding: 0.5em;
17 margin: 1em 2em 1em 1em;
18 }
19 </style></head><body bgcolor="#ffffff" text="#000000" link="#525D76" alink="#525D76" vlink="#525D76"><table border="0" width="100%" cellspacing="0"><!--PAGE HEADER--><tr><td><!--PROJECT LOGO--><a href="http://tomcat.apache.org/"><img src="./images/tomcat.gif" align="right" alt="
20 The Apache Tomcat Servlet/JSP Container
21 " border="0"></a></td><td><h1><font face="arial,helvetica,sanserif">Apache Tomcat 7</font></h1><font face="arial,helvetica,sanserif">Version 7.0.42, Jul 2 2013</font></td><td><!--APACHE LOGO--><a href="http://www.apache.org/"><img src="./images/asf-logo.gif" align="right" alt="Apache Logo" border="0"></a></td></tr></table><table border="0" width="100%" cellspacing="4"><!--HEADER SEPARATOR--><tr><td colspan="2"><hr noshade size="1"></td></tr><tr><!--LEFT SIDE NAVIGATION--><td width="20%" valign="top" nowrap class="noPrint"><p><strong>Links</strong></p><ul><li><a href="index.html">Docs Home</a></li><li><a href="http://wiki.apache.org/tomcat/FAQ">FAQ</a></li><li><a href="#comments_section">User Comments</a></li></ul><p><strong>User Guide</strong></p><ul><li><a href="introduction.html">1) Introduction</a></li><li><a href="setup.html">2) Setup</a></li><li><a href="appdev/index.html">3) First webapp</a></li><li><a href="deployer-howto.html">4) Deployer</a></li><li><a href="manager-howto.html">5) Manager</a></li><li><a href="realm-howto.html">6) Realms and AAA</a></li><li><a href="security-manager-howto.html">7) Security Manager</a></li><li><a href="jndi-resources-howto.html">8) JNDI Resources</a></li><li><a href="jndi-datasource-examples-howto.html">9) JDBC DataSources</a></li><li><a href="class-loader-howto.html">10) Classloading</a></li><li><a href="jasper-howto.html">11) JSPs</a></li><li><a href="ssl-howto.html">12) SSL</a></li><li><a href="ssi-howto.html">13) SSI</a></li><li><a href="cgi-howto.html">14) CGI</a></li><li><a href="proxy-howto.html">15) Proxy Support</a></li><li><a href="mbeans-descriptor-howto.html">16) MBean Descriptor</a></li><li><a href="default-servlet.html">17) Default Servlet</a></li><li><a href="cluster-howto.html">18) Clustering</a></li><li><a href="balancer-howto.html">19) Load Balancer</a></li><li><a href="connectors.html">20) Connectors</a></li><li><a href="monitoring.html">21) Monitoring and Management</a></li><li><a href="logging.html">22) Logging</a></li><li><a href="apr.html">23) APR/Native</a></li><li><a href="virtual-hosting-howto.html">24) Virtual Hosting</a></li><li><a href="aio.html">25) Advanced IO</a></li><li><a href="extras.html">26) Additional Components</a></li><li><a href="maven-jars.html">27) Mavenized</a></li><li><a href="security-howto.html">28) Security Considerations</a></li><li><a href="windows-service-howto.html">29) Windows Service</a></li><li><a href="windows-auth-howto.html">30) Windows Authentication</a></li><li><a href="jdbc-pool.html">31) Tomcat's JDBC Pool</a></li><li><a href="web-socket-howto.html">32) WebSocket</a></li></ul><p><strong>Reference</strong></p><ul><li><a href="RELEASE-NOTES.txt">Release Notes</a></li><li><a href="config/index.html">Configuration</a></li><li><a href="api/index.html">Tomcat Javadocs</a></li><li><a href="servletapi/index.html">Servlet Javadocs</a></li><li><a href="jspapi/index.html">JSP 2.2 Javadocs</a></li><li><a href="elapi/index.html">EL 2.2 Javadocs</a></li><li><a href="http://tomcat.apache.org/connectors-doc/">JK 1.2 Documentation</a></li></ul><p><strong>Apache Tomcat Development</strong></p><ul><li><a href="building.html">Building</a></li><li><a href="changelog.html">Changelog</a></li><li><a href="http://wiki.apache.org/tomcat/TomcatVersions">Status</a></li><li><a href="developers.html">Developers</a></li><li><a href="architecture/index.html">Architecture</a></li><li><a href="funcspecs/index.html">Functional Specs.</a></li><li><a href="tribes/introduction.html">Tribes</a></li></ul></td><!--RIGHT SIDE MAIN BODY--><td width="80%" valign="top" align="left" id="mainBody"><h1>Advanced IO and Tomcat</h1><table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#525D76"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Table of Contents"><!--()--></a><a name="Table_of_Contents"><strong>Table of Contents</strong></a></font></td></tr><tr><td><blockquote>
22<ul><li><a href="#Introduction">Introduction</a></li><li><a href="#Comet_support">Comet support</a><ol><li><a href="#CometEvent">CometEvent</a></li><li><a href="#CometFilter">CometFilter</a></li><li><a href="#Example_code">Example code</a></li><li><a href="#Comet_timeouts">Comet timeouts</a></li></ol></li><li><a href="#Asynchronous_writes">Asynchronous writes</a></li></ul>
23</blockquote></td></tr></table><table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#525D76"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Introduction"><strong>Introduction</strong></a></font></td></tr><tr><td><blockquote>
24
25 <p>
26 With usage of APR or NIO APIs as the basis of its connectors, Tomcat is
27 able to provide a number of extensions over the regular blocking IO
28 as provided with support for the Servlet API.
29 </p>
30
31 <p>
32 <b>IMPORTANT NOTE: Usage of these features requires using the APR or NIO
33 HTTP connectors. The classic java.io HTTP connector and the AJP connectors
34 do not support them.</b>
35 </p>
36
37 </blockquote></td></tr></table><table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#525D76"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Comet support"><!--()--></a><a name="Comet_support"><strong>Comet support</strong></a></font></td></tr><tr><td><blockquote>
38
39 <p>
40 Comet support allows a servlet to process IO asynchronously, receiving
41 events when data is available for reading on the connection (rather than
42 always using a blocking read), and writing data back on connections
43 asynchronously (most likely responding to some event raised from some
44 other source).
45 </p>
46
47 <table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#828DA6"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="CometEvent"><strong>CometEvent</strong></a></font></td></tr><tr><td><blockquote>
48
49 <p>
50 Servlets which implement the <code>org.apache.catalina.comet.CometProcessor</code>
51 interface will have their event method invoked rather than the usual service
52 method, according to the event which occurred. The event object gives
53 access to the usual request and response objects, which may be used in the
54 usual way. The main difference is that those objects remain valid and fully
55 functional at any time between processing of the BEGIN event until processing
56 an END or ERROR event.
57 The following event types exist:
58 </p>
59
60 <ul>
61 <li>EventType.BEGIN: will be called at the beginning
62 of the processing of the connection. It can be used to initialize any relevant
63 fields using the request and response objects. Between the end of the processing
64 of this event, and the beginning of the processing of the end or error events,
65 it is possible to use the response object to write data on the open connection.
66 Note that the response object and dependent OutputStream and Writer are still
67 not synchronized, so when they are accessed by multiple threads,
68 synchronization is mandatory. After processing the initial event, the request
69 is considered to be committed.</li>
70 <li>EventType.READ: This indicates that input data is available, and that one read can be made
71 without blocking. The available and ready methods of the InputStream or
72 Reader may be used to determine if there is a risk of blocking: the servlet
73 should read while data is reported available. When encountering a read error,
74 the servlet should report it by propagating the exception properly. Throwing
75 an exception will cause the error event to be invoked, and the connection
76 will be closed.
77 Alternately, it is also possible to catch any exception, perform clean up
78 on any data structure the servlet may be using, and using the close method
79 of the event. It is not allowed to attempt reading data from the request
80 object outside of the execution of this method.<br>
81 On some platforms, like Windows, a client disconnect is indicated by a READ event.
82 Reading from the stream may result in -1, an IOException or an EOFException.
83 Make sure you properly handle all these three cases.
84 If you don't catch the IOException, Tomcat will instantly invoke your event chain with an ERROR as
85 it catches the error for you, and you will be notified of the error at that time.
86 </li>
87 <li>EventType.END: End may be called to end the processing of the request. Fields that have
88 been initialized in the begin method should be reset. After this event has
89 been processed, the request and response objects, as well as all their dependent
90 objects will be recycled and used to process other requests. End will also be
91 called when data is available and the end of file is reached on the request input
92 (this usually indicates the client has pipelined a request).</li>
93 <li>EventType.ERROR: Error will be called by the container in the case where an IO exception
94 or a similar unrecoverable error occurs on the connection. Fields that have
95 been initialized in the begin method should be reset. After this event has
96 been processed, the request and response objects, as well as all their dependent
97 objects will be recycled and used to process other requests.</li>
98 </ul>
99
100 <p>
101 There are some event subtypes which allow finer processing of events (note: some of these
102 events require usage of the org.apache.catalina.valves.CometConnectionManagerValve valve):
103 </p>
104
105 <ul>
106 <li>EventSubType.TIMEOUT: The connection timed out (sub type of ERROR); note that this ERROR
107 type is not fatal, and the connection will not be closed unless the servlet uses the close
108 method of the event.
109 </li>
110 <li>EventSubType.CLIENT_DISCONNECT: The client connection was closed (sub type of ERROR).
111 </li>
112 <li>EventSubType.IOEXCEPTION: An IO exception occurred, such as invalid content, for example,
113 an invalid chunk block (sub type of ERROR).
114 </li>
115 <li>EventSubType.WEBAPP_RELOAD: The web application is being reloaded (sub type of END).
116 </li>
117 <li>EventSubType.SESSION_END: The servlet ended the session (sub type of END).
118 </li>
119 </ul>
120
121 <p>
122 As described above, the typical lifecycle of a Comet request will consist in a series of
123 events such as: BEGIN -&gt; READ -&gt; READ -&gt; READ -&gt; ERROR/TIMEOUT. At any time, the servlet
124 may end processing of the request by using the close method of the event object.
125 </p>
126
127 </blockquote></td></tr></table>
128
129 <table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#828DA6"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="CometFilter"><strong>CometFilter</strong></a></font></td></tr><tr><td><blockquote>
130
131 <p>
132 Similar to regular filters, a filter chain is invoked when comet events are processed.
133 These filters should implement the CometFilter interface (which works in the same way as
134 the regular Filter interface), and should be declared and mapped in the deployment
135 descriptor in the same way as a regular filter. The filter chain when processing an event
136 will only include filters which match all the usual mapping rules, and also implement
137 the CometFiler interface.
138 </p>
139
140 </blockquote></td></tr></table>
141
142 <table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#828DA6"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Example code"><!--()--></a><a name="Example_code"><strong>Example code</strong></a></font></td></tr><tr><td><blockquote>
143
144 <p>
145 The following pseudo code servlet implements asynchronous chat functionality using the API
146 described above:
147 </p>
148
149 <div align="left"><table cellspacing="4" cellpadding="0" border="0"><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#ffffff" height="1"><pre>
150public class ChatServlet
151 extends HttpServlet implements CometProcessor {
152
153 protected ArrayList&lt;HttpServletResponse&gt; connections =
154 new ArrayList&lt;HttpServletResponse&gt;();
155 protected MessageSender messageSender = null;
156
157 public void init() throws ServletException {
158 messageSender = new MessageSender();
159 Thread messageSenderThread =
160 new Thread(messageSender, "MessageSender[" + getServletContext().getContextPath() + "]");
161 messageSenderThread.setDaemon(true);
162 messageSenderThread.start();
163 }
164
165 public void destroy() {
166 connections.clear();
167 messageSender.stop();
168 messageSender = null;
169 }
170
171 /**
172 * Process the given Comet event.
173 *
174 * @param event The Comet event that will be processed
175 * @throws IOException
176 * @throws ServletException
177 */
178 public void event(CometEvent event)
179 throws IOException, ServletException {
180 HttpServletRequest request = event.getHttpServletRequest();
181 HttpServletResponse response = event.getHttpServletResponse();
182 if (event.getEventType() == CometEvent.EventType.BEGIN) {
183 log("Begin for session: " + request.getSession(true).getId());
184 PrintWriter writer = response.getWriter();
185 writer.println("&lt;!doctype html public \"-//w3c//dtd html 4.0 transitional//en\"&gt;");
186 writer.println("&lt;head&gt;&lt;title&gt;JSP Chat&lt;/title&gt;&lt;/head&gt;&lt;body bgcolor=\"#FFFFFF\"&gt;");
187 writer.flush();
188 synchronized(connections) {
189 connections.add(response);
190 }
191 } else if (event.getEventType() == CometEvent.EventType.ERROR) {
192 log("Error for session: " + request.getSession(true).getId());
193 synchronized(connections) {
194 connections.remove(response);
195 }
196 event.close();
197 } else if (event.getEventType() == CometEvent.EventType.END) {
198 log("End for session: " + request.getSession(true).getId());
199 synchronized(connections) {
200 connections.remove(response);
201 }
202 PrintWriter writer = response.getWriter();
203 writer.println("&lt;/body&gt;&lt;/html&gt;");
204 event.close();
205 } else if (event.getEventType() == CometEvent.EventType.READ) {
206 InputStream is = request.getInputStream();
207 byte[] buf = new byte[512];
208 do {
209 int n = is.read(buf); //can throw an IOException
210 if (n &gt; 0) {
211 log("Read " + n + " bytes: " + new String(buf, 0, n)
212 + " for session: " + request.getSession(true).getId());
213 } else if (n &lt; 0) {
214 error(event, request, response);
215 return;
216 }
217 } while (is.available() &gt; 0);
218 }
219 }
220
221 public class MessageSender implements Runnable {
222
223 protected boolean running = true;
224 protected ArrayList&lt;String&gt; messages = new ArrayList&lt;String&gt;();
225
226 public MessageSender() {
227 }
228
229 public void stop() {
230 running = false;
231 }
232
233 /**
234 * Add message for sending.
235 */
236 public void send(String user, String message) {
237 synchronized (messages) {
238 messages.add("[" + user + "]: " + message);
239 messages.notify();
240 }
241 }
242
243 public void run() {
244
245 while (running) {
246
247 if (messages.size() == 0) {
248 try {
249 synchronized (messages) {
250 messages.wait();
251 }
252 } catch (InterruptedException e) {
253 // Ignore
254 }
255 }
256
257 synchronized (connections) {
258 String[] pendingMessages = null;
259 synchronized (messages) {
260 pendingMessages = messages.toArray(new String[0]);
261 messages.clear();
262 }
263 // Send any pending message on all the open connections
264 for (int i = 0; i &lt; connections.size(); i++) {
265 try {
266 PrintWriter writer = connections.get(i).getWriter();
267 for (int j = 0; j &lt; pendingMessages.length; j++) {
268 writer.println(pendingMessages[j] + "&lt;br&gt;");
269 }
270 writer.flush();
271 } catch (IOException e) {
272 log("IOExeption sending message", e);
273 }
274 }
275 }
276
277 }
278
279 }
280
281 }
282
283}
284 </pre></td><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr></table></div>
285
286 </blockquote></td></tr></table>
287 <table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#828DA6"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Comet timeouts"><!--()--></a><a name="Comet_timeouts"><strong>Comet timeouts</strong></a></font></td></tr><tr><td><blockquote>
288 <p>If you are using the NIO connector, you can set individual timeouts for your different comet connections.
289 To set a timeout, simply set a request attribute like the following code shows:
290 <div align="left"><table cellspacing="4" cellpadding="0" border="0"><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#ffffff" height="1"><pre>CometEvent event.... event.setTimeout(30*1000);</pre></td><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr></table></div> or
291 <div align="left"><table cellspacing="4" cellpadding="0" border="0"><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#ffffff" height="1"><pre>event.getHttpServletRequest().setAttribute("org.apache.tomcat.comet.timeout", new Integer(30 * 1000));</pre></td><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr></table></div>
292 This sets the timeout to 30 seconds.
293 Important note: in order to set this timeout, it has to be done on the <code>BEGIN</code> event.
294 The default value is <code>soTimeout</code>
295 </p>
296 <p>If you are using the APR connector, all Comet connections will have the same timeout value. It is <code>soTimeout*50</code>
297 </p>
298 </blockquote></td></tr></table>
299
300 </blockquote></td></tr></table><table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#525D76"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Asynchronous writes"><!--()--></a><a name="Asynchronous_writes"><strong>Asynchronous writes</strong></a></font></td></tr><tr><td><blockquote>
301
302 <p>
303 When APR or NIO is enabled, Tomcat supports using sendfile to send large static files.
304 These writes, as soon as the system load increases, will be performed
305 asynchronously in the most efficient way. Instead of sending a large response using
306 blocking writes, it is possible to write content to a static file, and write it
307 using a sendfile code. A caching valve could take advantage of this to cache the
308 response data in a file rather than store it in memory. Sendfile support is
309 available if the request attribute <code>org.apache.tomcat.sendfile.support</code>
310 is set to <code>Boolean.TRUE</code>.
311 </p>
312
313 <p>
314 Any servlet can instruct Tomcat to perform a sendfile call by setting the appropriate
315 request attributes. It is also necessary to correctly set the content length
316 for the response. When using sendfile, it is best to ensure that neither the
317 request or response have been wrapped, since as the response body will be sent later
318 by the connector itself, it cannot be filtered. Other than setting the 3 needed
319 request attributes, the servlet should not send any response data, but it may use
320 any method which will result in modifying the response header (like setting cookies).
321 </p>
322
323 <ul>
324 <li><code>org.apache.tomcat.sendfile.filename</code>: Canonical filename of the file which will be sent as
325 a String</li>
326 <li><code>org.apache.tomcat.sendfile.start</code>: Start offset as a Long</li>
327 <li><code>org.apache.tomcat.sendfile.end</code>: End offset as a Long</li>
328 </ul>
329
330 </blockquote></td></tr></table></td></tr><tr class="noPrint"><td width="20%" valign="top" nowrap class="noPrint"></td><td width="80%" valign="top" align="left"><table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#525D76"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="comments_section" id="comments_section"><strong>Comments</strong></a></font></td></tr><tr><td><blockquote><p class="notice"><strong>Notice: </strong>This comments section collects your suggestions
331 on improving documentation for Apache Tomcat.<br><br>
332 If you have trouble and need help, read
333 <a href="http://tomcat.apache.org/findhelp.html">Find Help</a> page
334 and ask your question on the tomcat-users
335 <a href="http://tomcat.apache.org/lists.html">mailing list</a>.
336 Do not ask such questions here. This is not a Q&amp;A section.<br><br>
337 The Apache Comments System is explained <a href="/tomcat-7.0-doc/comments.html">here</a>.
338 Comments may be removed by our moderators if they are either
339 implemented or considered invalid/off-topic.</p><script type="text/javascript"><!--//--><![CDATA[//><!--
340 var comments_shortname = 'tomcat';
341 var comments_identifier = 'http://tomcat.apache.org/tomcat-7.0-doc/aio.html';
342 (function(w, d) {
343 if (w.location.hostname.toLowerCase() == "tomcat.apache.org") {
344 d.write('<div id="comments_thread"><\/div>');
345 var s = d.createElement('script');
346 s.type = 'text/javascript';
347 s.async = true;
348 s.src = 'https://comments.apache.org/show_comments.lua?site=' + comments_shortname + '&page=' + comments_identifier;
349 (d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(s);
350 }
351 else {
352 d.write('<div id="comments_thread"><strong>Comments are disabled for this page at the moment.<\/strong><\/div>');
353 }
354 })(window, document);
355 //--><!]]></script></blockquote></td></tr></table></td></tr><!--FOOTER SEPARATOR--><tr><td colspan="2"><hr noshade size="1"></td></tr><!--PAGE FOOTER--><tr><td colspan="2"><div align="center"><font color="#525D76" size="-1"><em>
356 Copyright &copy; 1999-2013, Apache Software Foundation
357 </em></font></div></td></tr></table></body></html>