Source Code Cross Referenced for RequestHandler.java in  » Sevlet-Container » tomcat-connectors » org » apache » ajp » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Sevlet Container » tomcat connectors » org.apache.ajp 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  Copyright 1999-2004 The Apache Software Foundation
003:         *
004:         *  Licensed under the Apache License, Version 2.0 (the "License");
005:         *  you may not use this file except in compliance with the License.
006:         *  You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         *  Unless required by applicable law or agreed to in writing, software
011:         *  distributed under the License is distributed on an "AS IS" BASIS,
012:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         *  See the License for the specific language governing permissions and
014:         *  limitations under the License.
015:         */
016:
017:        package org.apache.ajp;
018:
019:        import java.io.ByteArrayInputStream;
020:        import java.io.IOException;
021:        import java.security.cert.CertificateFactory;
022:        import java.security.cert.X509Certificate;
023:
024:        import org.apache.tomcat.util.buf.ByteChunk;
025:        import org.apache.tomcat.util.buf.MessageBytes;
026:        import org.apache.tomcat.util.http.BaseRequest;
027:        import org.apache.tomcat.util.http.HttpMessages;
028:        import org.apache.tomcat.util.http.MimeHeaders;
029:
030:        /**
031:         * Handle messages related with basic request information.
032:         *
033:         * This object can handle the following incoming messages:
034:         * - "FORWARD_REQUEST" input message ( sent when a request is passed from the web server )
035:         * - "PING REQUEST" input message (sent by the web server to determine if tomcat is not frozen,
036:         *                                 a PONG REPLY will be sent back)
037:         * - "RECEIVE_BODY_CHUNK" input ( sent by container to pass more body, in response to GET_BODY_CHUNK )
038:         *
039:         * It can handle the following outgoing messages:
040:         * - SEND_HEADERS. Pass the status code and headers.
041:         * - SEND_BODY_CHUNK. Send a chunk of body
042:         * - GET_BODY_CHUNK. Request a chunk of body data
043:         * - END_RESPONSE. Notify the end of a request processing.
044:         *
045:         * @author Henri Gomez [hgomez@apache.org]
046:         * @author Dan Milstein [danmil@shore.net]
047:         * @author Keith Wannamaker [Keith@Wannamaker.org]
048:         * @author Costin Manolache
049:         */
050:        public class RequestHandler extends AjpHandler {
051:            // XXX Will move to a registry system.
052:
053:            // Prefix codes for message types from server to container
054:            public static final byte JK_AJP13_FORWARD_REQUEST = 2;
055:            public static final byte JK_AJP13_SHUTDOWN = 7;
056:            public static final byte JK_AJP13_PING_REQUEST = 8;
057:            public static final byte JK_AJP13_CPING_REQUEST = 10;
058:
059:            // Prefix codes for message types from container to server
060:            public static final byte JK_AJP13_SEND_BODY_CHUNK = 3;
061:            public static final byte JK_AJP13_SEND_HEADERS = 4;
062:            public static final byte JK_AJP13_END_RESPONSE = 5;
063:            public static final byte JK_AJP13_GET_BODY_CHUNK = 6;
064:            public static final byte JK_AJP13_CPONG_REPLY = 9;
065:
066:            // Integer codes for common response header strings
067:            public static final int SC_RESP_CONTENT_TYPE = 0xA001;
068:            public static final int SC_RESP_CONTENT_LANGUAGE = 0xA002;
069:            public static final int SC_RESP_CONTENT_LENGTH = 0xA003;
070:            public static final int SC_RESP_DATE = 0xA004;
071:            public static final int SC_RESP_LAST_MODIFIED = 0xA005;
072:            public static final int SC_RESP_LOCATION = 0xA006;
073:            public static final int SC_RESP_SET_COOKIE = 0xA007;
074:            public static final int SC_RESP_SET_COOKIE2 = 0xA008;
075:            public static final int SC_RESP_SERVLET_ENGINE = 0xA009;
076:            public static final int SC_RESP_STATUS = 0xA00A;
077:            public static final int SC_RESP_WWW_AUTHENTICATE = 0xA00B;
078:
079:            // Integer codes for common (optional) request attribute names
080:            public static final byte SC_A_CONTEXT = 1; // XXX Unused
081:            public static final byte SC_A_SERVLET_PATH = 2; // XXX Unused
082:            public static final byte SC_A_REMOTE_USER = 3;
083:            public static final byte SC_A_AUTH_TYPE = 4;
084:            public static final byte SC_A_QUERY_STRING = 5;
085:            public static final byte SC_A_JVM_ROUTE = 6;
086:            public static final byte SC_A_SSL_CERT = 7;
087:            public static final byte SC_A_SSL_CIPHER = 8;
088:            public static final byte SC_A_SSL_SESSION = 9;
089:            public static final byte SC_A_SSL_KEY_SIZE = 11; // ajp14 originally, now in ajp13 with jk 1.2/2.0
090:            public static final byte SC_A_SECRET = 12;
091:            public static final byte SC_A_STORED_METHOD = 13;
092:
093:            // Used for attributes which are not in the list above
094:            public static final byte SC_A_REQ_ATTRIBUTE = 10;
095:
096:            // Terminates list of attributes
097:            public static final byte SC_A_ARE_DONE = (byte) 0xFF;
098:
099:            // Translates integer codes to names of HTTP methods
100:            public static final String[] methodTransArray = { "OPTIONS", "GET",
101:                    "HEAD", "POST", "PUT", "DELETE", "TRACE", "PROPFIND",
102:                    "PROPPATCH", "MKCOL", "COPY", "MOVE", "LOCK", "UNLOCK",
103:                    "ACL", "REPORT", "VERSION-CONTROL", "CHECKIN", "CHECKOUT",
104:                    "UNCHECKOUT", "SEARCH", "MKWORKSPACE", "UPDATE", "LABEL",
105:                    "MERGE", "BASELINE-CONTROL", "MKACTIVITY" };
106:            public static final int SC_M_JK_STORED = (byte) 0xFF;
107:
108:            // id's for common request headers
109:            public static final int SC_REQ_ACCEPT = 1;
110:            public static final int SC_REQ_ACCEPT_CHARSET = 2;
111:            public static final int SC_REQ_ACCEPT_ENCODING = 3;
112:            public static final int SC_REQ_ACCEPT_LANGUAGE = 4;
113:            public static final int SC_REQ_AUTHORIZATION = 5;
114:            public static final int SC_REQ_CONNECTION = 6;
115:            public static final int SC_REQ_CONTENT_TYPE = 7;
116:            public static final int SC_REQ_CONTENT_LENGTH = 8;
117:            public static final int SC_REQ_COOKIE = 9;
118:            public static final int SC_REQ_COOKIE2 = 10;
119:            public static final int SC_REQ_HOST = 11;
120:            public static final int SC_REQ_PRAGMA = 12;
121:            public static final int SC_REQ_REFERER = 13;
122:            public static final int SC_REQ_USER_AGENT = 14;
123:
124:            // Translates integer codes to request header names    
125:            public static final String[] headerTransArray = { "accept",
126:                    "accept-charset", "accept-encoding", "accept-language",
127:                    "authorization", "connection", "content-type",
128:                    "content-length", "cookie", "cookie2", "host", "pragma",
129:                    "referer", "user-agent" };
130:
131:            public RequestHandler() {
132:            }
133:
134:            public void init(Ajp13 ajp14) {
135:                // register incoming message handlers
136:                ajp14.registerMessageType(JK_AJP13_FORWARD_REQUEST,
137:                        "JK_AJP13_FORWARD_REQUEST", this , null); // 2
138:                // register outgoing messages handler
139:                ajp14.registerMessageType(JK_AJP13_SEND_BODY_CHUNK, // 3
140:                        "JK_AJP13_SEND_BODY_CHUNK", this , null);
141:                ajp14.registerMessageType(JK_AJP13_SEND_HEADERS, // 4
142:                        "JK_AJP13_SEND_HEADERS", this , null);
143:                ajp14.registerMessageType(JK_AJP13_END_RESPONSE, // 5
144:                        "JK_AJP13_END_RESPONSE", this , null);
145:                ajp14.registerMessageType(JK_AJP13_GET_BODY_CHUNK, // 6
146:                        "JK_AJP13_GET_BODY_CHUNK", this , null);
147:                ajp14.registerMessageType(JK_AJP13_CPING_REQUEST,
148:                        "JK_AJP13_PING_REQUEST", this , null); // 10
149:                ajp14.registerMessageType(JK_AJP13_CPONG_REPLY,
150:                        "JK_AJP13_PONG_REPLY", this , null); // 9
151:            }
152:
153:            /**
154:             * Send a CPONG REPLY to web server to its CPING request
155:             * 
156:             * @param ch the Ajp13 channel
157:             * @param outBuf the Ajp13Packet output packet to use
158:             */
159:            public int sendCPong(Ajp13 ch, Ajp13Packet outBuf) {
160:                outBuf.reset();
161:                outBuf.appendByte(JK_AJP13_CPONG_REPLY);
162:
163:                try {
164:                    ch.send(outBuf);
165:                } catch (IOException ioe) {
166:                    log("can't send pong reply");
167:                }
168:
169:                return (999); // success but no need to process farther
170:            }
171:
172:            // -------------------- Incoming message --------------------
173:            public int handleAjpMessage(int type, Ajp13 channel,
174:                    Ajp13Packet ajp, BaseRequest req) throws IOException {
175:                switch (type) {
176:                case RequestHandler.JK_AJP13_FORWARD_REQUEST:
177:                    return decodeRequest(channel, channel.hBuf, req);
178:
179:                default:
180:                    return UNKNOWN;
181:                }
182:            }
183:
184:            /**
185:             * Parse a FORWARD_REQUEST packet from the web server and store its
186:             * properties in the passed-in request object.
187:             *
188:             * @param req An empty (newly-recycled) request object.
189:             * @param msg Holds the packet which has just been sent by the web
190:             * server, with its read position just past the packet header (which in
191:             * this case includes the prefix code for FORWARD_REQUEST).
192:             *
193:             * @return 200 in case of a successful decoduing, 500 in case of error.  
194:             */
195:            protected int decodeRequest(Ajp13 ch, Ajp13Packet msg,
196:                    BaseRequest req) throws IOException {
197:
198:                if (debug > 0) {
199:                    log("decodeRequest()");
200:                }
201:
202:                // XXX Awful return values
203:
204:                boolean isSSL = false;
205:
206:                // Translate the HTTP method code to a String.
207:                byte methodCode = msg.getByte();
208:                if (methodCode != SC_M_JK_STORED)
209:                    req.method().setString(
210:                            methodTransArray[(int) methodCode - 1]);
211:
212:                msg.getMessageBytes(req.protocol());
213:                msg.getMessageBytes(req.requestURI());
214:
215:                msg.getMessageBytes(req.remoteAddr());
216:                msg.getMessageBytes(req.remoteHost());
217:                msg.getMessageBytes(req.serverName());
218:                req.setServerPort(msg.getInt());
219:
220:                isSSL = msg.getBool();
221:
222:                // Decode headers
223:                MimeHeaders headers = req.headers();
224:                int hCount = msg.getInt();
225:                for (int i = 0; i < hCount; i++) {
226:                    String hName = null;
227:
228:                    // Header names are encoded as either an integer code starting
229:                    // with 0xA0, or as a normal string (in which case the first
230:                    // two bytes are the length).
231:                    int isc = msg.peekInt();
232:                    int hId = isc & 0xFF;
233:
234:                    MessageBytes vMB = null;
235:                    isc &= 0xFF00;
236:                    if (0xA000 == isc) {
237:                        //
238:                        // header name is encoded as an int
239:                        //
240:                        msg.getInt(); // To advance the read position
241:                        hName = headerTransArray[hId - 1];
242:                        vMB = headers.addValue(hName);
243:                        msg.getMessageBytes(vMB);
244:
245:                        if (hId == SC_REQ_CONTENT_LENGTH) {
246:                            // just read content-length header
247:                            int contentLength = (vMB == null) ? -1 : vMB
248:                                    .getInt();
249:                            req.setContentLength(contentLength);
250:                        } else if (hId == SC_REQ_CONTENT_TYPE) {
251:                            // just read content-type header
252:                            ByteChunk bchunk = vMB.getByteChunk();
253:                            req.contentType().setBytes(bchunk.getBytes(),
254:                                    bchunk.getOffset(), bchunk.getLength());
255:                        } else if (hId == SC_REQ_AUTHORIZATION) {
256:                            ByteChunk bchunk = vMB.getByteChunk();
257:                            req.authorization().setBytes(bchunk.getBytes(),
258:                                    bchunk.getOffset(), bchunk.getLength());
259:                        }
260:                    } else {
261:                        //
262:                        // header name is a string
263:                        //
264:                        // XXX Not very elegant
265:                        vMB = msg.addHeader(headers);
266:                        if (vMB == null) {
267:                            return 500; // wrong packet
268:                        }
269:                        msg.getMessageBytes(vMB);
270:                    }
271:                }
272:
273:                byte attributeCode;
274:                for (attributeCode = msg.getByte(); attributeCode != SC_A_ARE_DONE; attributeCode = msg
275:                        .getByte()) {
276:                    switch (attributeCode) {
277:                    case SC_A_CONTEXT:
278:                        break;
279:
280:                    case SC_A_SERVLET_PATH:
281:                        break;
282:
283:                    case SC_A_REMOTE_USER:
284:                        msg.getMessageBytes(req.remoteUser());
285:                        break;
286:
287:                    case SC_A_AUTH_TYPE:
288:                        msg.getMessageBytes(req.authType());
289:                        break;
290:
291:                    case SC_A_QUERY_STRING:
292:                        msg.getMessageBytes(req.queryString());
293:                        break;
294:
295:                    case SC_A_JVM_ROUTE:
296:                        msg.getMessageBytes(req.jvmRoute());
297:                        break;
298:
299:                    case SC_A_SSL_CERT:
300:                        isSSL = true;
301:                        // Transform the string into certificate.
302:                        String certString = msg.getString();
303:                        byte[] certData = certString.getBytes();
304:                        ByteArrayInputStream bais = new ByteArrayInputStream(
305:                                certData);
306:
307:                        // Fill the first element.
308:                        X509Certificate jsseCerts[] = null;
309:                        try {
310:                            CertificateFactory cf = CertificateFactory
311:                                    .getInstance("X.509");
312:                            X509Certificate cert = (X509Certificate) cf
313:                                    .generateCertificate(bais);
314:                            jsseCerts = new X509Certificate[1];
315:                            jsseCerts[0] = cert;
316:                        } catch (java.security.cert.CertificateException e) {
317:                            log("Certificate convertion failed" + e);
318:                        }
319:
320:                        req.setAttribute(
321:                                "javax.servlet.request.X509Certificate",
322:                                jsseCerts);
323:                        break;
324:
325:                    case SC_A_SSL_CIPHER:
326:                        isSSL = true;
327:                        req.setAttribute("javax.servlet.request.cipher_suite",
328:                                msg.getString());
329:                        break;
330:
331:                    case SC_A_SECRET:
332:                        // If a request has a secret attribute, set it on
333:                        // channel - it'll be visible to the caller ( Interceptor,
334:                        // Connector ) and it can check it against its settings before
335:                        // trusting us.
336:                        String secret = msg.getString();
337:                        if (secret != null) {
338:                            ch.setSecret(secret);
339:                        }
340:                        break;
341:
342:                    case SC_A_SSL_SESSION:
343:                        isSSL = true;
344:                        req.setAttribute("javax.servlet.request.ssl_session",
345:                                msg.getString());
346:                        break;
347:
348:                    case SC_A_REQ_ATTRIBUTE:
349:                        req.setAttribute(msg.getString(), msg.getString());
350:                        break;
351:
352:                    case SC_A_SSL_KEY_SIZE: // Ajp13 !
353:                        isSSL = true;
354:                        req.setAttribute("javax.servlet.request.key_size",
355:                                Integer.toString(msg.getInt()));
356:                        break;
357:
358:                    case SC_A_STORED_METHOD:
359:                        req.method().setString(msg.getString());
360:                        break;
361:
362:                    default:
363:                        // Ignore. Assume a single-string value - we shouldn't
364:                        // allow anything else.
365:                        msg.getString();
366:                        break;
367:                    }
368:                }
369:
370:                if (isSSL) {
371:                    req.setScheme(req.SCHEME_HTTPS);
372:                    req.setSecure(true);
373:                }
374:
375:                // set cookies on request now that we have all headers
376:                req.cookies().setHeaders(req.headers());
377:
378:                // Check to see if there should be a body packet coming along
379:                // immediately after
380:                if (req.getContentLength() > 0) {
381:
382:                    /* Read present data */
383:                    int err = ch.receive(ch.inBuf);
384:                    if (err < 0) {
385:                        return 500;
386:                    }
387:
388:                    ch.blen = ch.inBuf.peekInt();
389:                    ch.pos = 0;
390:                    ch.inBuf.getBytes(ch.bodyBuff);
391:                }
392:
393:                if (debug > 5) {
394:                    log(req.toString());
395:                }
396:
397:                return 200; // Success
398:            }
399:
400:            // -------------------- Messages from container to server ------------------
401:
402:            /**
403:             * Send the HTTP headers back to the web server and on to the browser.
404:             *
405:             * @param status The HTTP status code to send.
406:             * @param statusMessage the HTTP status message to send.
407:             * @param headers The set of all headers.
408:             */
409:            public void sendHeaders(Ajp13 ch, Ajp13Packet outBuf, int status,
410:                    String statusMessage, MimeHeaders headers)
411:                    throws IOException {
412:                // XXX if more headers that MAX_SIZE, send 2 packets!
413:                if (statusMessage == null)
414:                    statusMessage = HttpMessages.getMessage(status);
415:                outBuf.reset();
416:                outBuf.appendByte(JK_AJP13_SEND_HEADERS);
417:                outBuf.appendInt(status);
418:
419:                outBuf.appendString(statusMessage);
420:
421:                int numHeaders = headers.size();
422:                outBuf.appendInt(numHeaders);
423:
424:                for (int i = 0; i < numHeaders; i++) {
425:                    String headerName = headers.getName(i).toString();
426:                    int sc = headerNameToSc(headerName);
427:                    if (-1 != sc) {
428:                        outBuf.appendInt(sc);
429:                    } else {
430:                        outBuf.appendString(headerName);
431:                    }
432:                    outBuf.appendString(headers.getValue(i).toString());
433:                }
434:
435:                outBuf.end();
436:                ch.send(outBuf);
437:            }
438:
439:            /**
440:             * Signal the web server that the servlet has finished handling this
441:             * request, and that the connection can be reused.
442:             */
443:            public void finish(Ajp13 ch, Ajp13Packet outBuf) throws IOException {
444:                if (debug > 0)
445:                    log("finish()");
446:
447:                outBuf.reset();
448:                outBuf.appendByte(JK_AJP13_END_RESPONSE);
449:                outBuf.appendBool(true); // Reuse this connection
450:                outBuf.end();
451:                ch.send(outBuf);
452:            }
453:
454:            /**
455:             * Send a chunk of response body data to the web server and on to the
456:             * browser.
457:             *
458:             * @param b A huffer of bytes to send.
459:             * @param off The offset into the buffer from which to start sending.
460:             * @param len The number of bytes to send.
461:             */
462:            public void doWrite(Ajp13 ch, Ajp13Packet outBuf, byte b[],
463:                    int off, int len) throws IOException {
464:                if (debug > 0)
465:                    log("doWrite(byte[], " + off + ", " + len + ")");
466:
467:                int sent = 0;
468:                while (sent < len) {
469:                    int to_send = len - sent;
470:                    to_send = to_send > Ajp13.MAX_SEND_SIZE ? Ajp13.MAX_SEND_SIZE
471:                            : to_send;
472:
473:                    outBuf.reset();
474:                    outBuf.appendByte(JK_AJP13_SEND_BODY_CHUNK);
475:                    outBuf.appendBytes(b, off + sent, to_send);
476:                    ch.send(outBuf);
477:                    sent += to_send;
478:                }
479:            }
480:
481:            // -------------------- Utils -------------------- 
482:
483:            /**
484:             * Translate an HTTP response header name to an integer code if
485:             * possible.  Case is ignored.
486:             * 
487:             * @param name The name of the response header to translate.
488:             *
489:             * @return The code for that header name, or -1 if no code exists.
490:             */
491:            protected int headerNameToSc(String name) {
492:                switch (name.charAt(0)) {
493:                case 'c':
494:                case 'C':
495:                    if (name.equalsIgnoreCase("Content-Type")) {
496:                        return SC_RESP_CONTENT_TYPE;
497:                    } else if (name.equalsIgnoreCase("Content-Language")) {
498:                        return SC_RESP_CONTENT_LANGUAGE;
499:                    } else if (name.equalsIgnoreCase("Content-Length")) {
500:                        return SC_RESP_CONTENT_LENGTH;
501:                    }
502:                    break;
503:
504:                case 'd':
505:                case 'D':
506:                    if (name.equalsIgnoreCase("Date")) {
507:                        return SC_RESP_DATE;
508:                    }
509:                    break;
510:
511:                case 'l':
512:                case 'L':
513:                    if (name.equalsIgnoreCase("Last-Modified")) {
514:                        return SC_RESP_LAST_MODIFIED;
515:                    } else if (name.equalsIgnoreCase("Location")) {
516:                        return SC_RESP_LOCATION;
517:                    }
518:                    break;
519:
520:                case 's':
521:                case 'S':
522:                    if (name.equalsIgnoreCase("Set-Cookie")) {
523:                        return SC_RESP_SET_COOKIE;
524:                    } else if (name.equalsIgnoreCase("Set-Cookie2")) {
525:                        return SC_RESP_SET_COOKIE2;
526:                    }
527:                    break;
528:
529:                case 'w':
530:                case 'W':
531:                    if (name.equalsIgnoreCase("WWW-Authenticate")) {
532:                        return SC_RESP_WWW_AUTHENTICATE;
533:                    }
534:                    break;
535:                }
536:
537:                return -1;
538:            }
539:
540:            private int debug = 0;
541:            private Logger logger = new Logger();
542:
543:            public void setDebug(int debug) {
544:                this .debug = debug;
545:            }
546:
547:            public void setLogger(Logger l) {
548:                this .logger = l;
549:            }
550:
551:            void log(String s) {
552:                logger.log("[RequestHandler] " + s);
553:            }
554:
555:            // ==================== Servlet Input Support =================
556:            // XXX DEPRECATED
557:
558:            public int available(Ajp13 ch) throws IOException {
559:                if (debug > 0) {
560:                    log("available()");
561:                }
562:
563:                if (ch.pos >= ch.blen) {
564:                    if (!refillReadBuffer(ch)) {
565:                        return 0;
566:                    }
567:                }
568:                return ch.blen - ch.pos;
569:            }
570:
571:            /**
572:             * Return the next byte of request body data (to a servlet).
573:             *
574:             * @see Request#doRead
575:             */
576:            public int doRead(Ajp13 ch) throws IOException {
577:                if (debug > 0) {
578:                    log("doRead()");
579:                }
580:
581:                if (ch.pos >= ch.blen) {
582:                    if (!refillReadBuffer(ch)) {
583:                        return -1;
584:                    }
585:                }
586:                return ch.bodyBuff[ch.pos++] & 0xFF;
587:            }
588:
589:            /**
590:             * Store a chunk of request data into the passed-in byte buffer.
591:             *
592:             * @param b A buffer to fill with data from the request.
593:             * @param off The offset in the buffer at which to start filling.
594:             * @param len The number of bytes to copy into the buffer.
595:             *
596:             * @return The number of bytes actually copied into the buffer, or -1
597:             * if the end of the stream has been reached.
598:             *
599:             * @see Request#doRead
600:             */
601:            public int doRead(Ajp13 ch, byte[] b, int off, int len)
602:                    throws IOException {
603:                if (debug > 0) {
604:                    log("doRead(byte[], int, int)");
605:                }
606:
607:                if (ch.pos >= ch.blen) {
608:                    if (!refillReadBuffer(ch)) {
609:                        return -1;
610:                    }
611:                }
612:
613:                if (ch.pos + len <= ch.blen) { // Fear the off by one error
614:                    // Sanity check b.length > off + len?
615:                    System.arraycopy(ch.bodyBuff, ch.pos, b, off, len);
616:                    ch.pos += len;
617:                    return len;
618:                }
619:
620:                // Not enough data (blen < pos + len)
621:                int toCopy = len;
622:                while (toCopy > 0) {
623:                    int bytesRemaining = ch.blen - ch.pos;
624:                    if (bytesRemaining < 0)
625:                        bytesRemaining = 0;
626:                    int c = bytesRemaining < toCopy ? bytesRemaining : toCopy;
627:
628:                    System.arraycopy(ch.bodyBuff, ch.pos, b, off, c);
629:
630:                    toCopy -= c;
631:
632:                    off += c;
633:                    ch.pos += c; // In case we exactly consume the buffer
634:
635:                    if (toCopy > 0)
636:                        if (!refillReadBuffer(ch)) { // Resets blen and pos
637:                            break;
638:                        }
639:                }
640:
641:                return len - toCopy;
642:            }
643:
644:            /**
645:             * Get more request body data from the web server and store it in the 
646:             * internal buffer.
647:             *
648:             * @return true if there is more data, false if not.    
649:             */
650:            public boolean refillReadBuffer(Ajp13 ch) throws IOException {
651:                if (debug > 0) {
652:                    log("refillReadBuffer()");
653:                }
654:
655:                // If the server returns an empty packet, assume that that end of
656:                // the stream has been reached (yuck -- fix protocol??).
657:
658:                // Why not use outBuf??
659:                ch.inBuf.reset();
660:                ch.inBuf.appendByte(JK_AJP13_GET_BODY_CHUNK);
661:                ch.inBuf.appendInt(Ajp13.MAX_READ_SIZE);
662:                ch.send(ch.inBuf);
663:
664:                int err = ch.receive(ch.inBuf);
665:                if (err < 0) {
666:                    throw new IOException();
667:                }
668:
669:                // check for empty packet, which means end of stream
670:                if (ch.inBuf.getLen() == 0) {
671:                    if (debug > 0) {
672:                        log("refillReadBuffer():  "
673:                                + "received empty packet -> end of stream");
674:                    }
675:                    ch.blen = 0;
676:                    ch.pos = 0;
677:                    return false;
678:                }
679:
680:                ch.blen = ch.inBuf.peekInt();
681:                ch.pos = 0;
682:                ch.inBuf.getBytes(ch.bodyBuff);
683:
684:                return (ch.blen > 0);
685:            }
686:
687:            // ==================== Servlet Output Support =================
688:
689:            /**
690:             */
691:            public void beginSendHeaders(Ajp13 ch, Ajp13Packet outBuf,
692:                    int status, String statusMessage, int numHeaders)
693:                    throws IOException {
694:
695:                if (debug > 0) {
696:                    log("sendHeaders()");
697:                }
698:
699:                // XXX if more headers that MAX_SIZE, send 2 packets!
700:
701:                outBuf.reset();
702:                outBuf.appendByte(JK_AJP13_SEND_HEADERS);
703:
704:                if (debug > 0) {
705:                    log("status is:  " + status + "(" + statusMessage + ")");
706:                }
707:
708:                // set status code and message
709:                outBuf.appendInt(status);
710:                outBuf.appendString(statusMessage);
711:
712:                // write the number of headers...
713:                outBuf.appendInt(numHeaders);
714:            }
715:
716:            public void sendHeader(Ajp13Packet outBuf, String name, String value)
717:                    throws IOException {
718:                int sc = headerNameToSc(name);
719:                if (-1 != sc) {
720:                    outBuf.appendInt(sc);
721:                } else {
722:                    outBuf.appendString(name);
723:                }
724:                outBuf.appendString(value);
725:            }
726:
727:            public void endSendHeaders(Ajp13 ch, Ajp13Packet outBuf)
728:                    throws IOException {
729:                outBuf.end();
730:                ch.send(outBuf);
731:            }
732:
733:            /**
734:             * Send the HTTP headers back to the web server and on to the browser.
735:             *
736:             * @param status The HTTP status code to send.
737:             * @param headers The set of all headers.
738:             */
739:            public void sendHeaders(Ajp13 ch, Ajp13Packet outBuf, int status,
740:                    MimeHeaders headers) throws IOException {
741:                sendHeaders(ch, outBuf, status,
742:                        HttpMessages.getMessage(status), headers);
743:            }
744:
745:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.