Source Code Cross Referenced for AjpProcessor.java in  » Sevlet-Container » apache-tomcat-6.0.14 » org » apache » coyote » 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 » apache tomcat 6.0.14 » org.apache.coyote.ajp 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:
0018:        package org.apache.coyote.ajp;
0019:
0020:        import java.io.ByteArrayInputStream;
0021:        import java.io.IOException;
0022:        import java.io.InputStream;
0023:        import java.io.InterruptedIOException;
0024:        import java.io.OutputStream;
0025:        import java.net.InetAddress;
0026:        import java.net.Socket;
0027:        import java.security.cert.CertificateFactory;
0028:        import java.security.cert.X509Certificate;
0029:
0030:        import org.apache.coyote.ActionCode;
0031:        import org.apache.coyote.ActionHook;
0032:        import org.apache.coyote.Adapter;
0033:        import org.apache.coyote.InputBuffer;
0034:        import org.apache.coyote.OutputBuffer;
0035:        import org.apache.coyote.Request;
0036:        import org.apache.coyote.RequestInfo;
0037:        import org.apache.coyote.Response;
0038:        import org.apache.tomcat.util.buf.ByteChunk;
0039:        import org.apache.tomcat.util.buf.HexUtils;
0040:        import org.apache.tomcat.util.buf.MessageBytes;
0041:        import org.apache.tomcat.util.http.HttpMessages;
0042:        import org.apache.tomcat.util.http.MimeHeaders;
0043:        import org.apache.tomcat.util.net.JIoEndpoint;
0044:        import org.apache.tomcat.util.res.StringManager;
0045:
0046:        /**
0047:         * Processes HTTP requests.
0048:         *
0049:         * @author Remy Maucherat
0050:         * @author Henri Gomez
0051:         * @author Dan Milstein
0052:         * @author Keith Wannamaker
0053:         * @author Kevin Seguin
0054:         * @author Costin Manolache
0055:         * @author Bill Barker
0056:         */
0057:        public class AjpProcessor implements  ActionHook {
0058:
0059:            /**
0060:             * Logger.
0061:             */
0062:            protected static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
0063:                    .getLog(AjpProcessor.class);
0064:
0065:            /**
0066:             * The string manager for this package.
0067:             */
0068:            protected static StringManager sm = StringManager
0069:                    .getManager(Constants.Package);
0070:
0071:            // ----------------------------------------------------------- Constructors
0072:
0073:            public AjpProcessor(int packetSize, JIoEndpoint endpoint) {
0074:
0075:                this .endpoint = endpoint;
0076:
0077:                request = new Request();
0078:                request.setInputBuffer(new SocketInputBuffer());
0079:
0080:                response = new Response();
0081:                response.setHook(this );
0082:                response.setOutputBuffer(new SocketOutputBuffer());
0083:                request.setResponse(response);
0084:
0085:                requestHeaderMessage = new AjpMessage(packetSize);
0086:                responseHeaderMessage = new AjpMessage(packetSize);
0087:                bodyMessage = new AjpMessage(packetSize);
0088:
0089:                // Cause loading of HexUtils
0090:                int foo = HexUtils.DEC[0];
0091:
0092:                // Cause loading of HttpMessages
0093:                HttpMessages.getMessage(200);
0094:
0095:            }
0096:
0097:            // ----------------------------------------------------- Instance Variables
0098:
0099:            /**
0100:             * Associated adapter.
0101:             */
0102:            protected Adapter adapter = null;
0103:
0104:            /**
0105:             * Request object.
0106:             */
0107:            protected Request request = null;
0108:
0109:            /**
0110:             * Response object.
0111:             */
0112:            protected Response response = null;
0113:
0114:            /**
0115:             * Header message. Note that this header is merely the one used during the
0116:             * processing of the first message of a "request", so it might not be a request
0117:             * header. It will stay unchanged during the processing of the whole request.
0118:             */
0119:            protected AjpMessage requestHeaderMessage = null;
0120:
0121:            /**
0122:             * Message used for response header composition.
0123:             */
0124:            protected AjpMessage responseHeaderMessage = null;
0125:
0126:            /**
0127:             * Body message.
0128:             */
0129:            protected AjpMessage bodyMessage = null;
0130:
0131:            /**
0132:             * Body message.
0133:             */
0134:            protected MessageBytes bodyBytes = MessageBytes.newInstance();
0135:
0136:            /**
0137:             * State flag.
0138:             */
0139:            protected boolean started = false;
0140:
0141:            /**
0142:             * Error flag.
0143:             */
0144:            protected boolean error = false;
0145:
0146:            /**
0147:             * Socket associated with the current connection.
0148:             */
0149:            protected Socket socket;
0150:
0151:            /**
0152:             * Input stream.
0153:             */
0154:            protected InputStream input;
0155:
0156:            /**
0157:             * Output stream.
0158:             */
0159:            protected OutputStream output;
0160:
0161:            /**
0162:             * Host name (used to avoid useless B2C conversion on the host name).
0163:             */
0164:            protected char[] hostNameC = new char[0];
0165:
0166:            /**
0167:             * Associated endpoint.
0168:             */
0169:            protected JIoEndpoint endpoint;
0170:
0171:            /**
0172:             * The socket timeout used when reading the first block of the request
0173:             * header.
0174:             */
0175:            protected long readTimeout;
0176:
0177:            /**
0178:             * Temp message bytes used for processing.
0179:             */
0180:            protected MessageBytes tmpMB = MessageBytes.newInstance();
0181:
0182:            /**
0183:             * Byte chunk for certs.
0184:             */
0185:            protected MessageBytes certificates = MessageBytes.newInstance();
0186:
0187:            /**
0188:             * End of stream flag.
0189:             */
0190:            protected boolean endOfStream = false;
0191:
0192:            /**
0193:             * Body empty flag.
0194:             */
0195:            protected boolean empty = true;
0196:
0197:            /**
0198:             * First read.
0199:             */
0200:            protected boolean first = true;
0201:
0202:            /**
0203:             * Replay read.
0204:             */
0205:            protected boolean replay = false;
0206:
0207:            /**
0208:             * Finished response.
0209:             */
0210:            protected boolean finished = false;
0211:
0212:            /**
0213:             * Direct buffer used for sending right away a get body message.
0214:             */
0215:            protected static final byte[] getBodyMessageArray;
0216:
0217:            /**
0218:             * Direct buffer used for sending right away a pong message.
0219:             */
0220:            protected static final byte[] pongMessageArray;
0221:
0222:            /**
0223:             * End message array.
0224:             */
0225:            protected static final byte[] endMessageArray;
0226:
0227:            /**
0228:             * Flush message array.
0229:             */
0230:            protected static final byte[] flushMessageArray;
0231:
0232:            // ----------------------------------------------------- Static Initializer
0233:
0234:            static {
0235:
0236:                // Set the get body message buffer
0237:
0238:                AjpMessage getBodyMessage = new AjpMessage(16);
0239:                getBodyMessage.reset();
0240:                getBodyMessage.appendByte(Constants.JK_AJP13_GET_BODY_CHUNK);
0241:                getBodyMessage.appendInt(Constants.MAX_READ_SIZE);
0242:                getBodyMessage.end();
0243:                getBodyMessageArray = new byte[getBodyMessage.getLen()];
0244:                System.arraycopy(getBodyMessage.getBuffer(), 0,
0245:                        getBodyMessageArray, 0, getBodyMessage.getLen());
0246:
0247:                // Set the read body message buffer
0248:                AjpMessage pongMessage = new AjpMessage(16);
0249:                pongMessage.reset();
0250:                pongMessage.appendByte(Constants.JK_AJP13_CPONG_REPLY);
0251:                pongMessage.end();
0252:                pongMessageArray = new byte[pongMessage.getLen()];
0253:                System.arraycopy(pongMessage.getBuffer(), 0, pongMessageArray,
0254:                        0, pongMessage.getLen());
0255:
0256:                // Allocate the end message array
0257:                AjpMessage endMessage = new AjpMessage(16);
0258:                endMessage.reset();
0259:                endMessage.appendByte(Constants.JK_AJP13_END_RESPONSE);
0260:                endMessage.appendByte(1);
0261:                endMessage.end();
0262:                endMessageArray = new byte[endMessage.getLen()];
0263:                System.arraycopy(endMessage.getBuffer(), 0, endMessageArray, 0,
0264:                        endMessage.getLen());
0265:
0266:                // Allocate the flush message array
0267:                AjpMessage flushMessage = new AjpMessage(16);
0268:                flushMessage.reset();
0269:                flushMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK);
0270:                flushMessage.appendInt(0);
0271:                flushMessage.appendByte(0);
0272:                flushMessage.end();
0273:                flushMessageArray = new byte[flushMessage.getLen()];
0274:                System.arraycopy(flushMessage.getBuffer(), 0,
0275:                        flushMessageArray, 0, flushMessage.getLen());
0276:
0277:            }
0278:
0279:            // ------------------------------------------------------------- Properties
0280:
0281:            /**
0282:             * Use Tomcat authentication ?
0283:             */
0284:            protected boolean tomcatAuthentication = true;
0285:
0286:            public boolean getTomcatAuthentication() {
0287:                return tomcatAuthentication;
0288:            }
0289:
0290:            public void setTomcatAuthentication(boolean tomcatAuthentication) {
0291:                this .tomcatAuthentication = tomcatAuthentication;
0292:            }
0293:
0294:            /**
0295:             * Required secret.
0296:             */
0297:            protected String requiredSecret = null;
0298:
0299:            public void setRequiredSecret(String requiredSecret) {
0300:                this .requiredSecret = requiredSecret;
0301:            }
0302:
0303:            /**
0304:             * The number of milliseconds Tomcat will wait for a subsequent request
0305:             * before closing the connection. The default is the same as for
0306:             * Apache HTTP Server (15 000 milliseconds).
0307:             */
0308:            protected int keepAliveTimeout = -1;
0309:
0310:            public int getKeepAliveTimeout() {
0311:                return keepAliveTimeout;
0312:            }
0313:
0314:            public void setKeepAliveTimeout(int timeout) {
0315:                keepAliveTimeout = timeout;
0316:            }
0317:
0318:            // --------------------------------------------------------- Public Methods
0319:
0320:            /** Get the request associated with this processor.
0321:             *
0322:             * @return The request
0323:             */
0324:            public Request getRequest() {
0325:                return request;
0326:            }
0327:
0328:            /**
0329:             * Process pipelined HTTP requests using the specified input and output
0330:             * streams.
0331:             *
0332:             * @throws IOException error during an I/O operation
0333:             */
0334:            public boolean process(Socket socket) throws IOException {
0335:                RequestInfo rp = request.getRequestProcessor();
0336:                rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
0337:
0338:                // Setting up the socket
0339:                this .socket = socket;
0340:                input = socket.getInputStream();
0341:                output = socket.getOutputStream();
0342:                int soTimeout = -1;
0343:                if (keepAliveTimeout > 0) {
0344:                    soTimeout = socket.getSoTimeout();
0345:                }
0346:
0347:                // Error flag
0348:                error = false;
0349:
0350:                while (started && !error) {
0351:
0352:                    // Parsing the request header
0353:                    try {
0354:                        // Set keep alive timeout if enabled
0355:                        if (keepAliveTimeout > 0) {
0356:                            socket.setSoTimeout(keepAliveTimeout);
0357:                        }
0358:                        // Get first message of the request
0359:                        if (!readMessage(requestHeaderMessage)) {
0360:                            // This means a connection timeout
0361:                            rp
0362:                                    .setStage(org.apache.coyote.Constants.STAGE_ENDED);
0363:                            break;
0364:                        }
0365:                        // Set back timeout if keep alive timeout is enabled
0366:                        if (keepAliveTimeout > 0) {
0367:                            socket.setSoTimeout(soTimeout);
0368:                        }
0369:                        // Check message type, process right away and break if
0370:                        // not regular request processing
0371:                        int type = requestHeaderMessage.getByte();
0372:                        if (type == Constants.JK_AJP13_CPING_REQUEST) {
0373:                            try {
0374:                                output.write(pongMessageArray);
0375:                            } catch (IOException e) {
0376:                                error = true;
0377:                            }
0378:                            continue;
0379:                        } else if (type != Constants.JK_AJP13_FORWARD_REQUEST) {
0380:                            // Usually the servlet didn't read the previous request body
0381:                            if (log.isDebugEnabled()) {
0382:                                log.debug("Unexpected message: " + type);
0383:                            }
0384:                            continue;
0385:                        }
0386:
0387:                        request.setStartTime(System.currentTimeMillis());
0388:                    } catch (IOException e) {
0389:                        error = true;
0390:                        break;
0391:                    } catch (Throwable t) {
0392:                        log.debug(sm.getString("ajpprocessor.header.error"), t);
0393:                        // 400 - Bad Request
0394:                        response.setStatus(400);
0395:                        error = true;
0396:                    }
0397:
0398:                    // Setting up filters, and parse some request headers
0399:                    rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
0400:                    try {
0401:                        prepareRequest();
0402:                    } catch (Throwable t) {
0403:                        log.debug(sm.getString("ajpprocessor.request.prepare"),
0404:                                t);
0405:                        // 400 - Internal Server Error
0406:                        response.setStatus(400);
0407:                        error = true;
0408:                    }
0409:
0410:                    // Process the request in the adapter
0411:                    if (!error) {
0412:                        try {
0413:                            rp
0414:                                    .setStage(org.apache.coyote.Constants.STAGE_SERVICE);
0415:                            adapter.service(request, response);
0416:                        } catch (InterruptedIOException e) {
0417:                            error = true;
0418:                        } catch (Throwable t) {
0419:                            log.error(sm
0420:                                    .getString("ajpprocessor.request.process"),
0421:                                    t);
0422:                            // 500 - Internal Server Error
0423:                            response.setStatus(500);
0424:                            error = true;
0425:                        }
0426:                    }
0427:
0428:                    // Finish the response if not done yet
0429:                    if (!finished) {
0430:                        try {
0431:                            finish();
0432:                        } catch (Throwable t) {
0433:                            error = true;
0434:                        }
0435:                    }
0436:
0437:                    // If there was an error, make sure the request is counted as
0438:                    // and error, and update the statistics counter
0439:                    if (error) {
0440:                        response.setStatus(500);
0441:                    }
0442:                    request.updateCounters();
0443:
0444:                    rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
0445:                    recycle();
0446:
0447:                }
0448:
0449:                rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
0450:                recycle();
0451:                input = null;
0452:                output = null;
0453:
0454:                return true;
0455:
0456:            }
0457:
0458:            // ----------------------------------------------------- ActionHook Methods
0459:
0460:            /**
0461:             * Send an action to the connector.
0462:             *
0463:             * @param actionCode Type of the action
0464:             * @param param Action parameter
0465:             */
0466:            public void action(ActionCode actionCode, Object param) {
0467:
0468:                if (actionCode == ActionCode.ACTION_COMMIT) {
0469:
0470:                    if (response.isCommitted())
0471:                        return;
0472:
0473:                    // Validate and write response headers
0474:                    try {
0475:                        prepareResponse();
0476:                    } catch (IOException e) {
0477:                        // Set error flag
0478:                        error = true;
0479:                    }
0480:
0481:                } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) {
0482:
0483:                    if (!response.isCommitted()) {
0484:                        // Validate and write response headers
0485:                        try {
0486:                            prepareResponse();
0487:                        } catch (IOException e) {
0488:                            // Set error flag
0489:                            error = true;
0490:                            return;
0491:                        }
0492:                    }
0493:
0494:                    try {
0495:                        flush();
0496:                    } catch (IOException e) {
0497:                        // Set error flag
0498:                        error = true;
0499:                    }
0500:
0501:                } else if (actionCode == ActionCode.ACTION_CLOSE) {
0502:                    // Close
0503:
0504:                    // End the processing of the current request, and stop any further
0505:                    // transactions with the client
0506:
0507:                    try {
0508:                        finish();
0509:                    } catch (IOException e) {
0510:                        // Set error flag
0511:                        error = true;
0512:                    }
0513:
0514:                } else if (actionCode == ActionCode.ACTION_START) {
0515:
0516:                    started = true;
0517:
0518:                } else if (actionCode == ActionCode.ACTION_STOP) {
0519:
0520:                    started = false;
0521:
0522:                } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE) {
0523:
0524:                    if (!certificates.isNull()) {
0525:                        ByteChunk certData = certificates.getByteChunk();
0526:                        X509Certificate jsseCerts[] = null;
0527:                        ByteArrayInputStream bais = new ByteArrayInputStream(
0528:                                certData.getBytes(), certData.getStart(),
0529:                                certData.getLength());
0530:                        // Fill the first element.
0531:                        try {
0532:                            CertificateFactory cf = CertificateFactory
0533:                                    .getInstance("X.509");
0534:                            X509Certificate cert = (X509Certificate) cf
0535:                                    .generateCertificate(bais);
0536:                            jsseCerts = new X509Certificate[1];
0537:                            jsseCerts[0] = cert;
0538:                            request.setAttribute(JIoEndpoint.CERTIFICATE_KEY,
0539:                                    jsseCerts);
0540:                        } catch (java.security.cert.CertificateException e) {
0541:                            log.error(sm.getString("ajpprocessor.certs.fail"),
0542:                                    e);
0543:                            return;
0544:                        }
0545:                    }
0546:
0547:                } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) {
0548:
0549:                    // Get remote host name using a DNS resolution
0550:                    if (request.remoteHost().isNull()) {
0551:                        try {
0552:                            request.remoteHost().setString(
0553:                                    InetAddress.getByName(
0554:                                            request.remoteAddr().toString())
0555:                                            .getHostName());
0556:                        } catch (IOException iex) {
0557:                            // Ignore
0558:                        }
0559:                    }
0560:
0561:                } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) {
0562:
0563:                    // Copy from local name for now, which should simply be an address
0564:                    request.localAddr().setString(
0565:                            request.localName().toString());
0566:
0567:                } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) {
0568:
0569:                    // Set the given bytes as the content
0570:                    ByteChunk bc = (ByteChunk) param;
0571:                    int length = bc.getLength();
0572:                    bodyBytes.setBytes(bc.getBytes(), bc.getStart(), length);
0573:                    request.setContentLength(length);
0574:                    first = false;
0575:                    empty = false;
0576:                    replay = true;
0577:
0578:                }
0579:
0580:            }
0581:
0582:            // ------------------------------------------------------ Connector Methods
0583:
0584:            /**
0585:             * Set the associated adapter.
0586:             *
0587:             * @param adapter the new adapter
0588:             */
0589:            public void setAdapter(Adapter adapter) {
0590:                this .adapter = adapter;
0591:            }
0592:
0593:            /**
0594:             * Get the associated adapter.
0595:             *
0596:             * @return the associated adapter
0597:             */
0598:            public Adapter getAdapter() {
0599:                return adapter;
0600:            }
0601:
0602:            // ------------------------------------------------------ Protected Methods
0603:
0604:            /**
0605:             * After reading the request headers, we have to setup the request filters.
0606:             */
0607:            protected void prepareRequest() {
0608:
0609:                // Translate the HTTP method code to a String.
0610:                byte methodCode = requestHeaderMessage.getByte();
0611:                if (methodCode != Constants.SC_M_JK_STORED) {
0612:                    String methodName = Constants.methodTransArray[(int) methodCode - 1];
0613:                    request.method().setString(methodName);
0614:                }
0615:
0616:                requestHeaderMessage.getBytes(request.protocol());
0617:                requestHeaderMessage.getBytes(request.requestURI());
0618:
0619:                requestHeaderMessage.getBytes(request.remoteAddr());
0620:                requestHeaderMessage.getBytes(request.remoteHost());
0621:                requestHeaderMessage.getBytes(request.localName());
0622:                request.setLocalPort(requestHeaderMessage.getInt());
0623:
0624:                boolean isSSL = requestHeaderMessage.getByte() != 0;
0625:                if (isSSL) {
0626:                    request.scheme().setString("https");
0627:                }
0628:
0629:                // Decode headers
0630:                MimeHeaders headers = request.getMimeHeaders();
0631:
0632:                int hCount = requestHeaderMessage.getInt();
0633:                for (int i = 0; i < hCount; i++) {
0634:                    String hName = null;
0635:
0636:                    // Header names are encoded as either an integer code starting
0637:                    // with 0xA0, or as a normal string (in which case the first
0638:                    // two bytes are the length).
0639:                    int isc = requestHeaderMessage.peekInt();
0640:                    int hId = isc & 0xFF;
0641:
0642:                    MessageBytes vMB = null;
0643:                    isc &= 0xFF00;
0644:                    if (0xA000 == isc) {
0645:                        requestHeaderMessage.getInt(); // To advance the read position
0646:                        hName = Constants.headerTransArray[hId - 1];
0647:                        vMB = headers.addValue(hName);
0648:                    } else {
0649:                        // reset hId -- if the header currently being read
0650:                        // happens to be 7 or 8 bytes long, the code below
0651:                        // will think it's the content-type header or the
0652:                        // content-length header - SC_REQ_CONTENT_TYPE=7,
0653:                        // SC_REQ_CONTENT_LENGTH=8 - leading to unexpected
0654:                        // behaviour.  see bug 5861 for more information.
0655:                        hId = -1;
0656:                        requestHeaderMessage.getBytes(tmpMB);
0657:                        ByteChunk bc = tmpMB.getByteChunk();
0658:                        vMB = headers.addValue(bc.getBuffer(), bc.getStart(),
0659:                                bc.getLength());
0660:                    }
0661:
0662:                    requestHeaderMessage.getBytes(vMB);
0663:
0664:                    if (hId == Constants.SC_REQ_CONTENT_LENGTH
0665:                            || (hId == -1 && tmpMB
0666:                                    .equalsIgnoreCase("Content-Length"))) {
0667:                        // just read the content-length header, so set it
0668:                        long cl = vMB.getLong();
0669:                        if (cl < Integer.MAX_VALUE)
0670:                            request.setContentLength((int) cl);
0671:                    } else if (hId == Constants.SC_REQ_CONTENT_TYPE
0672:                            || (hId == -1 && tmpMB
0673:                                    .equalsIgnoreCase("Content-Type"))) {
0674:                        // just read the content-type header, so set it
0675:                        ByteChunk bchunk = vMB.getByteChunk();
0676:                        request.contentType().setBytes(bchunk.getBytes(),
0677:                                bchunk.getOffset(), bchunk.getLength());
0678:                    }
0679:                }
0680:
0681:                // Decode extra attributes
0682:                boolean secret = false;
0683:                byte attributeCode;
0684:                while ((attributeCode = requestHeaderMessage.getByte()) != Constants.SC_A_ARE_DONE) {
0685:
0686:                    switch (attributeCode) {
0687:
0688:                    case Constants.SC_A_REQ_ATTRIBUTE:
0689:                        requestHeaderMessage.getBytes(tmpMB);
0690:                        String n = tmpMB.toString();
0691:                        requestHeaderMessage.getBytes(tmpMB);
0692:                        String v = tmpMB.toString();
0693:                        request.setAttribute(n, v);
0694:                        break;
0695:
0696:                    case Constants.SC_A_CONTEXT:
0697:                        requestHeaderMessage.getBytes(tmpMB);
0698:                        // nothing
0699:                        break;
0700:
0701:                    case Constants.SC_A_SERVLET_PATH:
0702:                        requestHeaderMessage.getBytes(tmpMB);
0703:                        // nothing
0704:                        break;
0705:
0706:                    case Constants.SC_A_REMOTE_USER:
0707:                        if (tomcatAuthentication) {
0708:                            // ignore server
0709:                            requestHeaderMessage.getBytes(tmpMB);
0710:                        } else {
0711:                            requestHeaderMessage.getBytes(request
0712:                                    .getRemoteUser());
0713:                        }
0714:                        break;
0715:
0716:                    case Constants.SC_A_AUTH_TYPE:
0717:                        if (tomcatAuthentication) {
0718:                            // ignore server
0719:                            requestHeaderMessage.getBytes(tmpMB);
0720:                        } else {
0721:                            requestHeaderMessage
0722:                                    .getBytes(request.getAuthType());
0723:                        }
0724:                        break;
0725:
0726:                    case Constants.SC_A_QUERY_STRING:
0727:                        requestHeaderMessage.getBytes(request.queryString());
0728:                        break;
0729:
0730:                    case Constants.SC_A_JVM_ROUTE:
0731:                        requestHeaderMessage.getBytes(request.instanceId());
0732:                        break;
0733:
0734:                    case Constants.SC_A_SSL_CERT:
0735:                        request.scheme().setString("https");
0736:                        // SSL certificate extraction is lazy, moved to JkCoyoteHandler
0737:                        requestHeaderMessage.getBytes(certificates);
0738:                        break;
0739:
0740:                    case Constants.SC_A_SSL_CIPHER:
0741:                        request.scheme().setString("https");
0742:                        requestHeaderMessage.getBytes(tmpMB);
0743:                        request.setAttribute(JIoEndpoint.CIPHER_SUITE_KEY,
0744:                                tmpMB.toString());
0745:                        break;
0746:
0747:                    case Constants.SC_A_SSL_SESSION:
0748:                        request.scheme().setString("https");
0749:                        requestHeaderMessage.getBytes(tmpMB);
0750:                        request.setAttribute(JIoEndpoint.SESSION_ID_KEY, tmpMB
0751:                                .toString());
0752:                        break;
0753:
0754:                    case Constants.SC_A_SSL_KEY_SIZE:
0755:                        request.setAttribute(JIoEndpoint.KEY_SIZE_KEY,
0756:                                new Integer(requestHeaderMessage.getInt()));
0757:                        break;
0758:
0759:                    case Constants.SC_A_STORED_METHOD:
0760:                        requestHeaderMessage.getBytes(request.method());
0761:                        break;
0762:
0763:                    case Constants.SC_A_SECRET:
0764:                        requestHeaderMessage.getBytes(tmpMB);
0765:                        if (requiredSecret != null) {
0766:                            secret = true;
0767:                            if (!tmpMB.equals(requiredSecret)) {
0768:                                response.setStatus(403);
0769:                                error = true;
0770:                            }
0771:                        }
0772:                        break;
0773:
0774:                    default:
0775:                        // Ignore unknown attribute for backward compatibility
0776:                        break;
0777:
0778:                    }
0779:
0780:                }
0781:
0782:                // Check if secret was submitted if required
0783:                if ((requiredSecret != null) && !secret) {
0784:                    response.setStatus(403);
0785:                    error = true;
0786:                }
0787:
0788:                // Check for a full URI (including protocol://host:port/)
0789:                ByteChunk uriBC = request.requestURI().getByteChunk();
0790:                if (uriBC.startsWithIgnoreCase("http", 0)) {
0791:
0792:                    int pos = uriBC.indexOf("://", 0, 3, 4);
0793:                    int uriBCStart = uriBC.getStart();
0794:                    int slashPos = -1;
0795:                    if (pos != -1) {
0796:                        byte[] uriB = uriBC.getBytes();
0797:                        slashPos = uriBC.indexOf('/', pos + 3);
0798:                        if (slashPos == -1) {
0799:                            slashPos = uriBC.getLength();
0800:                            // Set URI as "/"
0801:                            request.requestURI().setBytes(uriB,
0802:                                    uriBCStart + pos + 1, 1);
0803:                        } else {
0804:                            request.requestURI().setBytes(uriB,
0805:                                    uriBCStart + slashPos,
0806:                                    uriBC.getLength() - slashPos);
0807:                        }
0808:                        MessageBytes hostMB = headers.setValue("host");
0809:                        hostMB.setBytes(uriB, uriBCStart + pos + 3, slashPos
0810:                                - pos - 3);
0811:                    }
0812:
0813:                }
0814:
0815:                MessageBytes valueMB = request.getMimeHeaders()
0816:                        .getValue("host");
0817:                parseHost(valueMB);
0818:
0819:            }
0820:
0821:            /**
0822:             * Parse host.
0823:             */
0824:            public void parseHost(MessageBytes valueMB) {
0825:
0826:                if (valueMB == null || (valueMB != null && valueMB.isNull())) {
0827:                    // HTTP/1.0
0828:                    // Default is what the socket tells us. Overriden if a host is
0829:                    // found/parsed
0830:                    request.setServerPort(endpoint.getPort());
0831:                    return;
0832:                }
0833:
0834:                ByteChunk valueBC = valueMB.getByteChunk();
0835:                byte[] valueB = valueBC.getBytes();
0836:                int valueL = valueBC.getLength();
0837:                int valueS = valueBC.getStart();
0838:                int colonPos = -1;
0839:                if (hostNameC.length < valueL) {
0840:                    hostNameC = new char[valueL];
0841:                }
0842:
0843:                boolean ipv6 = (valueB[valueS] == '[');
0844:                boolean bracketClosed = false;
0845:                for (int i = 0; i < valueL; i++) {
0846:                    char b = (char) valueB[i + valueS];
0847:                    hostNameC[i] = b;
0848:                    if (b == ']') {
0849:                        bracketClosed = true;
0850:                    } else if (b == ':') {
0851:                        if (!ipv6 || bracketClosed) {
0852:                            colonPos = i;
0853:                            break;
0854:                        }
0855:                    }
0856:                }
0857:
0858:                if (colonPos < 0) {
0859:                    if (request.scheme().equalsIgnoreCase("https")) {
0860:                        // 443 - Default HTTPS port
0861:                        request.setServerPort(443);
0862:                    } else {
0863:                        // 80 - Default HTTTP port
0864:                        request.setServerPort(80);
0865:                    }
0866:                    request.serverName().setChars(hostNameC, 0, valueL);
0867:                } else {
0868:
0869:                    request.serverName().setChars(hostNameC, 0, colonPos);
0870:
0871:                    int port = 0;
0872:                    int mult = 1;
0873:                    for (int i = valueL - 1; i > colonPos; i--) {
0874:                        int charValue = HexUtils.DEC[(int) valueB[i + valueS]];
0875:                        if (charValue == -1) {
0876:                            // Invalid character
0877:                            error = true;
0878:                            // 400 - Bad request
0879:                            response.setStatus(400);
0880:                            break;
0881:                        }
0882:                        port = port + (charValue * mult);
0883:                        mult = 10 * mult;
0884:                    }
0885:                    request.setServerPort(port);
0886:
0887:                }
0888:
0889:            }
0890:
0891:            /**
0892:             * When committing the response, we have to validate the set of headers, as
0893:             * well as setup the response filters.
0894:             */
0895:            protected void prepareResponse() throws IOException {
0896:
0897:                response.setCommitted(true);
0898:
0899:                responseHeaderMessage.reset();
0900:                responseHeaderMessage
0901:                        .appendByte(Constants.JK_AJP13_SEND_HEADERS);
0902:
0903:                // HTTP header contents
0904:                responseHeaderMessage.appendInt(response.getStatus());
0905:                String message = response.getMessage();
0906:                if (message == null) {
0907:                    message = HttpMessages.getMessage(response.getStatus());
0908:                } else {
0909:                    message = message.replace('\n', ' ').replace('\r', ' ');
0910:                }
0911:                tmpMB.setString(message);
0912:                responseHeaderMessage.appendBytes(tmpMB);
0913:
0914:                // Special headers
0915:                MimeHeaders headers = response.getMimeHeaders();
0916:                String contentType = response.getContentType();
0917:                if (contentType != null) {
0918:                    headers.setValue("Content-Type").setString(contentType);
0919:                }
0920:                String contentLanguage = response.getContentLanguage();
0921:                if (contentLanguage != null) {
0922:                    headers.setValue("Content-Language").setString(
0923:                            contentLanguage);
0924:                }
0925:                long contentLength = response.getContentLengthLong();
0926:                if (contentLength >= 0) {
0927:                    headers.setValue("Content-Length").setLong(contentLength);
0928:                }
0929:
0930:                // Other headers
0931:                int numHeaders = headers.size();
0932:                responseHeaderMessage.appendInt(numHeaders);
0933:                for (int i = 0; i < numHeaders; i++) {
0934:                    MessageBytes hN = headers.getName(i);
0935:                    int hC = Constants.getResponseAjpIndex(hN.toString());
0936:                    if (hC > 0) {
0937:                        responseHeaderMessage.appendInt(hC);
0938:                    } else {
0939:                        responseHeaderMessage.appendBytes(hN);
0940:                    }
0941:                    MessageBytes hV = headers.getValue(i);
0942:                    responseHeaderMessage.appendBytes(hV);
0943:                }
0944:
0945:                // Write to buffer
0946:                responseHeaderMessage.end();
0947:                output.write(responseHeaderMessage.getBuffer(), 0,
0948:                        responseHeaderMessage.getLen());
0949:
0950:            }
0951:
0952:            /**
0953:             * Finish AJP response.
0954:             */
0955:            protected void finish() throws IOException {
0956:
0957:                if (!response.isCommitted()) {
0958:                    // Validate and write response headers
0959:                    try {
0960:                        prepareResponse();
0961:                    } catch (IOException e) {
0962:                        // Set error flag
0963:                        error = true;
0964:                    }
0965:                }
0966:
0967:                if (finished)
0968:                    return;
0969:
0970:                finished = true;
0971:
0972:                // Add the end message
0973:                output.write(endMessageArray);
0974:
0975:            }
0976:
0977:            /**
0978:             * Read at least the specified amount of bytes, and place them
0979:             * in the input buffer.
0980:             */
0981:            protected boolean read(byte[] buf, int pos, int n)
0982:                    throws IOException {
0983:
0984:                int read = 0;
0985:                int res = 0;
0986:                while (read < n) {
0987:                    res = input.read(buf, read + pos, n - read);
0988:                    if (res > 0) {
0989:                        read += res;
0990:                    } else {
0991:                        throw new IOException(sm
0992:                                .getString("ajpprotocol.failedread"));
0993:                    }
0994:                }
0995:
0996:                return true;
0997:
0998:            }
0999:
1000:            /** Receive a chunk of data. Called to implement the
1001:             *  'special' packet in ajp13 and to receive the data
1002:             *  after we send a GET_BODY packet
1003:             */
1004:            public boolean receive() throws IOException {
1005:
1006:                first = false;
1007:                bodyMessage.reset();
1008:                readMessage(bodyMessage);
1009:
1010:                // No data received.
1011:                if (bodyMessage.getLen() == 0) {
1012:                    // just the header
1013:                    // Don't mark 'end of stream' for the first chunk.
1014:                    return false;
1015:                }
1016:                int blen = bodyMessage.peekInt();
1017:                if (blen == 0) {
1018:                    return false;
1019:                }
1020:
1021:                bodyMessage.getBytes(bodyBytes);
1022:                empty = false;
1023:                return true;
1024:            }
1025:
1026:            /**
1027:             * Get more request body data from the web server and store it in the
1028:             * internal buffer.
1029:             *
1030:             * @return true if there is more data, false if not.
1031:             */
1032:            private boolean refillReadBuffer() throws IOException {
1033:                // If the server returns an empty packet, assume that that end of
1034:                // the stream has been reached (yuck -- fix protocol??).
1035:                // FORM support
1036:                if (replay) {
1037:                    endOfStream = true; // we've read everything there is
1038:                }
1039:                if (endOfStream) {
1040:                    return false;
1041:                }
1042:
1043:                // Request more data immediately
1044:                output.write(getBodyMessageArray);
1045:
1046:                boolean moreData = receive();
1047:                if (!moreData) {
1048:                    endOfStream = true;
1049:                }
1050:                return moreData;
1051:            }
1052:
1053:            /**
1054:             * Read an AJP message.
1055:             *
1056:             * @return true if the message has been read, false if the short read
1057:             *         didn't return anything
1058:             * @throws IOException any other failure, including incomplete reads
1059:             */
1060:            protected boolean readMessage(AjpMessage message)
1061:                    throws IOException {
1062:
1063:                byte[] buf = message.getBuffer();
1064:
1065:                read(buf, 0, message.getHeaderLength());
1066:
1067:                message.processHeader();
1068:                read(buf, message.getHeaderLength(), message.getLen());
1069:
1070:                return true;
1071:
1072:            }
1073:
1074:            /**
1075:             * Recycle the processor.
1076:             */
1077:            public void recycle() {
1078:
1079:                // Recycle Request object
1080:                first = true;
1081:                endOfStream = false;
1082:                empty = true;
1083:                replay = false;
1084:                finished = false;
1085:                request.recycle();
1086:                response.recycle();
1087:                certificates.recycle();
1088:
1089:            }
1090:
1091:            /**
1092:             * Callback to write data from the buffer.
1093:             */
1094:            protected void flush() throws IOException {
1095:                // Send the flush message
1096:                output.write(flushMessageArray);
1097:            }
1098:
1099:            // ------------------------------------- InputStreamInputBuffer Inner Class
1100:
1101:            /**
1102:             * This class is an input buffer which will read its data from an input
1103:             * stream.
1104:             */
1105:            protected class SocketInputBuffer implements  InputBuffer {
1106:
1107:                /**
1108:                 * Read bytes into the specified chunk.
1109:                 */
1110:                public int doRead(ByteChunk chunk, Request req)
1111:                        throws IOException {
1112:
1113:                    if (endOfStream) {
1114:                        return -1;
1115:                    }
1116:                    if (first && req.getContentLengthLong() > 0) {
1117:                        // Handle special first-body-chunk
1118:                        if (!receive()) {
1119:                            return 0;
1120:                        }
1121:                    } else if (empty) {
1122:                        if (!refillReadBuffer()) {
1123:                            return -1;
1124:                        }
1125:                    }
1126:                    ByteChunk bc = bodyBytes.getByteChunk();
1127:                    chunk.setBytes(bc.getBuffer(), bc.getStart(), bc
1128:                            .getLength());
1129:                    empty = true;
1130:                    return chunk.getLength();
1131:
1132:                }
1133:
1134:            }
1135:
1136:            // ----------------------------------- OutputStreamOutputBuffer Inner Class
1137:
1138:            /**
1139:             * This class is an output buffer which will write data to an output
1140:             * stream.
1141:             */
1142:            protected class SocketOutputBuffer implements  OutputBuffer {
1143:
1144:                /**
1145:                 * Write chunk.
1146:                 */
1147:                public int doWrite(ByteChunk chunk, Response res)
1148:                        throws IOException {
1149:
1150:                    if (!response.isCommitted()) {
1151:                        // Validate and write response headers
1152:                        try {
1153:                            prepareResponse();
1154:                        } catch (IOException e) {
1155:                            // Set error flag
1156:                            error = true;
1157:                        }
1158:                    }
1159:
1160:                    int len = chunk.getLength();
1161:                    // 4 - hardcoded, byte[] marshalling overhead
1162:                    int chunkSize = Constants.MAX_SEND_SIZE;
1163:                    int off = 0;
1164:                    while (len > 0) {
1165:                        int this Time = len;
1166:                        if (this Time > chunkSize) {
1167:                            this Time = chunkSize;
1168:                        }
1169:                        len -= this Time;
1170:                        responseHeaderMessage.reset();
1171:                        responseHeaderMessage
1172:                                .appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK);
1173:                        responseHeaderMessage.appendBytes(chunk.getBytes(),
1174:                                chunk.getOffset() + off, this Time);
1175:                        responseHeaderMessage.end();
1176:                        output.write(responseHeaderMessage.getBuffer(), 0,
1177:                                responseHeaderMessage.getLen());
1178:
1179:                        off += thisTime;
1180:                    }
1181:
1182:                    return chunk.getLength();
1183:
1184:                }
1185:
1186:            }
1187:
1188:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.