Source Code Cross Referenced for Http11AprProcessor.java in  » Sevlet-Container » apache-tomcat-6.0.14 » org » apache » coyote » http11 » 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.http11 
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.http11;
0019:
0020:        import java.io.ByteArrayInputStream;
0021:        import java.io.IOException;
0022:        import java.io.InterruptedIOException;
0023:        import java.util.StringTokenizer;
0024:        import java.util.regex.Pattern;
0025:        import java.util.regex.PatternSyntaxException;
0026:        import java.security.cert.CertificateFactory;
0027:        import java.security.cert.X509Certificate;
0028:
0029:        import org.apache.coyote.ActionCode;
0030:        import org.apache.coyote.ActionHook;
0031:        import org.apache.coyote.Adapter;
0032:        import org.apache.coyote.Request;
0033:        import org.apache.coyote.RequestInfo;
0034:        import org.apache.coyote.Response;
0035:        import org.apache.coyote.http11.filters.ChunkedInputFilter;
0036:        import org.apache.coyote.http11.filters.ChunkedOutputFilter;
0037:        import org.apache.coyote.http11.filters.GzipOutputFilter;
0038:        import org.apache.coyote.http11.filters.IdentityInputFilter;
0039:        import org.apache.coyote.http11.filters.IdentityOutputFilter;
0040:        import org.apache.coyote.http11.filters.SavedRequestInputFilter;
0041:        import org.apache.coyote.http11.filters.VoidInputFilter;
0042:        import org.apache.coyote.http11.filters.VoidOutputFilter;
0043:        import org.apache.coyote.http11.filters.BufferedInputFilter;
0044:        import org.apache.tomcat.jni.Address;
0045:        import org.apache.tomcat.jni.SSL;
0046:        import org.apache.tomcat.jni.SSLSocket;
0047:        import org.apache.tomcat.jni.Sockaddr;
0048:        import org.apache.tomcat.jni.Socket;
0049:        import org.apache.tomcat.util.buf.Ascii;
0050:        import org.apache.tomcat.util.buf.ByteChunk;
0051:        import org.apache.tomcat.util.buf.HexUtils;
0052:        import org.apache.tomcat.util.buf.MessageBytes;
0053:        import org.apache.tomcat.util.http.FastHttpDateFormat;
0054:        import org.apache.tomcat.util.http.MimeHeaders;
0055:        import org.apache.tomcat.util.net.AprEndpoint;
0056:        import org.apache.tomcat.util.net.SocketStatus;
0057:        import org.apache.tomcat.util.net.AprEndpoint.Handler.SocketState;
0058:        import org.apache.tomcat.util.res.StringManager;
0059:
0060:        /**
0061:         * Processes HTTP requests.
0062:         *
0063:         * @author Remy Maucherat
0064:         */
0065:        public class Http11AprProcessor implements  ActionHook {
0066:
0067:            /**
0068:             * Logger.
0069:             */
0070:            protected static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
0071:                    .getLog(Http11AprProcessor.class);
0072:
0073:            /**
0074:             * The string manager for this package.
0075:             */
0076:            protected static StringManager sm = StringManager
0077:                    .getManager(Constants.Package);
0078:
0079:            // ----------------------------------------------------------- Constructors
0080:
0081:            public Http11AprProcessor(int headerBufferSize, AprEndpoint endpoint) {
0082:
0083:                this .endpoint = endpoint;
0084:
0085:                request = new Request();
0086:                inputBuffer = new InternalAprInputBuffer(request,
0087:                        headerBufferSize);
0088:                request.setInputBuffer(inputBuffer);
0089:
0090:                response = new Response();
0091:                response.setHook(this );
0092:                outputBuffer = new InternalAprOutputBuffer(response,
0093:                        headerBufferSize);
0094:                response.setOutputBuffer(outputBuffer);
0095:                request.setResponse(response);
0096:
0097:                ssl = endpoint.isSSLEnabled();
0098:
0099:                initializeFilters();
0100:
0101:                // Cause loading of HexUtils
0102:                int foo = HexUtils.DEC[0];
0103:
0104:                // Cause loading of FastHttpDateFormat
0105:                FastHttpDateFormat.getCurrentDate();
0106:
0107:            }
0108:
0109:            // ----------------------------------------------------- Instance Variables
0110:
0111:            /**
0112:             * Associated adapter.
0113:             */
0114:            protected Adapter adapter = null;
0115:
0116:            /**
0117:             * Request object.
0118:             */
0119:            protected Request request = null;
0120:
0121:            /**
0122:             * Response object.
0123:             */
0124:            protected Response response = null;
0125:
0126:            /**
0127:             * Input.
0128:             */
0129:            protected InternalAprInputBuffer inputBuffer = null;
0130:
0131:            /**
0132:             * Output.
0133:             */
0134:            protected InternalAprOutputBuffer outputBuffer = null;
0135:
0136:            /**
0137:             * Error flag.
0138:             */
0139:            protected boolean error = false;
0140:
0141:            /**
0142:             * Keep-alive.
0143:             */
0144:            protected boolean keepAlive = true;
0145:
0146:            /**
0147:             * HTTP/1.1 flag.
0148:             */
0149:            protected boolean http11 = true;
0150:
0151:            /**
0152:             * HTTP/0.9 flag.
0153:             */
0154:            protected boolean http09 = false;
0155:
0156:            /**
0157:             * Sendfile data.
0158:             */
0159:            protected AprEndpoint.SendfileData sendfileData = null;
0160:
0161:            /**
0162:             * Comet used.
0163:             */
0164:            protected boolean comet = false;
0165:
0166:            /**
0167:             * Content delimitator for the request (if false, the connection will
0168:             * be closed at the end of the request).
0169:             */
0170:            protected boolean contentDelimitation = true;
0171:
0172:            /**
0173:             * Is there an expectation ?
0174:             */
0175:            protected boolean expectation = false;
0176:
0177:            /**
0178:             * List of restricted user agents.
0179:             */
0180:            protected Pattern[] restrictedUserAgents = null;
0181:
0182:            /**
0183:             * Maximum number of Keep-Alive requests to honor.
0184:             */
0185:            protected int maxKeepAliveRequests = -1;
0186:
0187:            /**
0188:             * SSL enabled ?
0189:             */
0190:            protected boolean ssl = false;
0191:
0192:            /**
0193:             * Socket associated with the current connection.
0194:             */
0195:            protected long socket = 0;
0196:
0197:            /**
0198:             * Remote Address associated with the current connection.
0199:             */
0200:            protected String remoteAddr = null;
0201:
0202:            /**
0203:             * Remote Host associated with the current connection.
0204:             */
0205:            protected String remoteHost = null;
0206:
0207:            /**
0208:             * Local Host associated with the current connection.
0209:             */
0210:            protected String localName = null;
0211:
0212:            /**
0213:             * Local port to which the socket is connected
0214:             */
0215:            protected int localPort = -1;
0216:
0217:            /**
0218:             * Remote port to which the socket is connected
0219:             */
0220:            protected int remotePort = -1;
0221:
0222:            /**
0223:             * The local Host address.
0224:             */
0225:            protected String localAddr = null;
0226:
0227:            /**
0228:             * Maximum timeout on uploads. 5 minutes as in Apache HTTPD server.
0229:             */
0230:            protected int timeout = 300000;
0231:
0232:            /**
0233:             * Flag to disable setting a different time-out on uploads.
0234:             */
0235:            protected boolean disableUploadTimeout = false;
0236:
0237:            /**
0238:             * Allowed compression level.
0239:             */
0240:            protected int compressionLevel = 0;
0241:
0242:            /**
0243:             * Minimum contentsize to make compression.
0244:             */
0245:            protected int compressionMinSize = 2048;
0246:
0247:            /**
0248:             * Socket buffering.
0249:             */
0250:            protected int socketBuffer = -1;
0251:
0252:            /**
0253:             * Max save post size.
0254:             */
0255:            protected int maxSavePostSize = 4 * 1024;
0256:
0257:            /**
0258:             * List of user agents to not use gzip with
0259:             */
0260:            protected Pattern noCompressionUserAgents[] = null;
0261:
0262:            /**
0263:             * List of MIMES which could be gzipped
0264:             */
0265:            protected String[] compressableMimeTypes = { "text/html",
0266:                    "text/xml", "text/plain" };
0267:
0268:            /**
0269:             * Host name (used to avoid useless B2C conversion on the host name).
0270:             */
0271:            protected char[] hostNameC = new char[0];
0272:
0273:            /**
0274:             * Associated endpoint.
0275:             */
0276:            protected AprEndpoint endpoint;
0277:
0278:            /**
0279:             * Allow a customized the server header for the tin-foil hat folks.
0280:             */
0281:            protected String server = null;
0282:
0283:            // ------------------------------------------------------------- Properties
0284:
0285:            /**
0286:             * Return compression level.
0287:             */
0288:            public String getCompression() {
0289:                switch (compressionLevel) {
0290:                case 0:
0291:                    return "off";
0292:                case 1:
0293:                    return "on";
0294:                case 2:
0295:                    return "force";
0296:                }
0297:                return "off";
0298:            }
0299:
0300:            /**
0301:             * Set compression level.
0302:             */
0303:            public void setCompression(String compression) {
0304:                if (compression.equals("on")) {
0305:                    this .compressionLevel = 1;
0306:                } else if (compression.equals("force")) {
0307:                    this .compressionLevel = 2;
0308:                } else if (compression.equals("off")) {
0309:                    this .compressionLevel = 0;
0310:                } else {
0311:                    try {
0312:                        // Try to parse compression as an int, which would give the
0313:                        // minimum compression size
0314:                        compressionMinSize = Integer.parseInt(compression);
0315:                        this .compressionLevel = 1;
0316:                    } catch (Exception e) {
0317:                        this .compressionLevel = 0;
0318:                    }
0319:                }
0320:            }
0321:
0322:            /**
0323:             * Set Minimum size to trigger compression.
0324:             */
0325:            public void setCompressionMinSize(int compressionMinSize) {
0326:                this .compressionMinSize = compressionMinSize;
0327:            }
0328:
0329:            /**
0330:             * Add user-agent for which gzip compression didn't works
0331:             * The user agent String given will be exactly matched
0332:             * to the user-agent header submitted by the client.
0333:             *
0334:             * @param userAgent user-agent string
0335:             */
0336:            public void addNoCompressionUserAgent(String userAgent) {
0337:                try {
0338:                    Pattern nRule = Pattern.compile(userAgent);
0339:                    noCompressionUserAgents = addREArray(
0340:                            noCompressionUserAgents, nRule);
0341:                } catch (PatternSyntaxException pse) {
0342:                    log.error(sm.getString("http11processor.regexp.error",
0343:                            userAgent), pse);
0344:                }
0345:            }
0346:
0347:            /**
0348:             * Set no compression user agent list (this method is best when used with
0349:             * a large number of connectors, where it would be better to have all of
0350:             * them referenced a single array).
0351:             */
0352:            public void setNoCompressionUserAgents(
0353:                    Pattern[] noCompressionUserAgents) {
0354:                this .noCompressionUserAgents = noCompressionUserAgents;
0355:            }
0356:
0357:            /**
0358:             * Set no compression user agent list.
0359:             * List contains users agents separated by ',' :
0360:             *
0361:             * ie: "gorilla,desesplorer,tigrus"
0362:             */
0363:            public void setNoCompressionUserAgents(
0364:                    String noCompressionUserAgents) {
0365:                if (noCompressionUserAgents != null) {
0366:                    StringTokenizer st = new StringTokenizer(
0367:                            noCompressionUserAgents, ",");
0368:
0369:                    while (st.hasMoreTokens()) {
0370:                        addNoCompressionUserAgent(st.nextToken().trim());
0371:                    }
0372:                }
0373:            }
0374:
0375:            /**
0376:             * Add a mime-type which will be compressable
0377:             * The mime-type String will be exactly matched
0378:             * in the response mime-type header .
0379:             *
0380:             * @param mimeType mime-type string
0381:             */
0382:            public void addCompressableMimeType(String mimeType) {
0383:                compressableMimeTypes = addStringArray(compressableMimeTypes,
0384:                        mimeType);
0385:            }
0386:
0387:            /**
0388:             * Set compressable mime-type list (this method is best when used with
0389:             * a large number of connectors, where it would be better to have all of
0390:             * them referenced a single array).
0391:             */
0392:            public void setCompressableMimeTypes(String[] compressableMimeTypes) {
0393:                this .compressableMimeTypes = compressableMimeTypes;
0394:            }
0395:
0396:            /**
0397:             * Set compressable mime-type list
0398:             * List contains users agents separated by ',' :
0399:             *
0400:             * ie: "text/html,text/xml,text/plain"
0401:             */
0402:            public void setCompressableMimeTypes(String compressableMimeTypes) {
0403:                if (compressableMimeTypes != null) {
0404:                    StringTokenizer st = new StringTokenizer(
0405:                            compressableMimeTypes, ",");
0406:
0407:                    while (st.hasMoreTokens()) {
0408:                        addCompressableMimeType(st.nextToken().trim());
0409:                    }
0410:                }
0411:            }
0412:
0413:            /**
0414:             * Return the list of restricted user agents.
0415:             */
0416:            public String[] findCompressableMimeTypes() {
0417:                return (compressableMimeTypes);
0418:            }
0419:
0420:            // --------------------------------------------------------- Public Methods
0421:
0422:            /**
0423:             * Add input or output filter.
0424:             *
0425:             * @param className class name of the filter
0426:             */
0427:            protected void addFilter(String className) {
0428:                try {
0429:                    Class clazz = Class.forName(className);
0430:                    Object obj = clazz.newInstance();
0431:                    if (obj instanceof  InputFilter) {
0432:                        inputBuffer.addFilter((InputFilter) obj);
0433:                    } else if (obj instanceof  OutputFilter) {
0434:                        outputBuffer.addFilter((OutputFilter) obj);
0435:                    } else {
0436:                        log.warn(sm.getString("http11processor.filter.unknown",
0437:                                className));
0438:                    }
0439:                } catch (Exception e) {
0440:                    log.error(sm.getString("http11processor.filter.error",
0441:                            className), e);
0442:                }
0443:            }
0444:
0445:            /**
0446:             * General use method
0447:             *
0448:             * @param sArray the StringArray
0449:             * @param value string
0450:             */
0451:            private String[] addStringArray(String sArray[], String value) {
0452:                String[] result = null;
0453:                if (sArray == null) {
0454:                    result = new String[1];
0455:                    result[0] = value;
0456:                } else {
0457:                    result = new String[sArray.length + 1];
0458:                    for (int i = 0; i < sArray.length; i++)
0459:                        result[i] = sArray[i];
0460:                    result[sArray.length] = value;
0461:                }
0462:                return result;
0463:            }
0464:
0465:            /**
0466:             * General use method
0467:             *
0468:             * @param rArray the REArray
0469:             * @param value Obj
0470:             */
0471:            private Pattern[] addREArray(Pattern rArray[], Pattern value) {
0472:                Pattern[] result = null;
0473:                if (rArray == null) {
0474:                    result = new Pattern[1];
0475:                    result[0] = value;
0476:                } else {
0477:                    result = new Pattern[rArray.length + 1];
0478:                    for (int i = 0; i < rArray.length; i++)
0479:                        result[i] = rArray[i];
0480:                    result[rArray.length] = value;
0481:                }
0482:                return result;
0483:            }
0484:
0485:            /**
0486:             * General use method
0487:             *
0488:             * @param sArray the StringArray
0489:             * @param value string
0490:             */
0491:            private boolean inStringArray(String sArray[], String value) {
0492:                for (int i = 0; i < sArray.length; i++) {
0493:                    if (sArray[i].equals(value)) {
0494:                        return true;
0495:                    }
0496:                }
0497:                return false;
0498:            }
0499:
0500:            /**
0501:             * Checks if any entry in the string array starts with the specified value
0502:             *
0503:             * @param sArray the StringArray
0504:             * @param value string
0505:             */
0506:            private boolean startsWithStringArray(String sArray[], String value) {
0507:                if (value == null)
0508:                    return false;
0509:                for (int i = 0; i < sArray.length; i++) {
0510:                    if (value.startsWith(sArray[i])) {
0511:                        return true;
0512:                    }
0513:                }
0514:                return false;
0515:            }
0516:
0517:            /**
0518:             * Add restricted user-agent (which will downgrade the connector
0519:             * to HTTP/1.0 mode). The user agent String given will be matched
0520:             * via regexp to the user-agent header submitted by the client.
0521:             *
0522:             * @param userAgent user-agent string
0523:             */
0524:            public void addRestrictedUserAgent(String userAgent) {
0525:                try {
0526:                    Pattern nRule = Pattern.compile(userAgent);
0527:                    restrictedUserAgents = addREArray(restrictedUserAgents,
0528:                            nRule);
0529:                } catch (PatternSyntaxException pse) {
0530:                    log.error(sm.getString("http11processor.regexp.error",
0531:                            userAgent), pse);
0532:                }
0533:            }
0534:
0535:            /**
0536:             * Set restricted user agent list (this method is best when used with
0537:             * a large number of connectors, where it would be better to have all of
0538:             * them referenced a single array).
0539:             */
0540:            public void setRestrictedUserAgents(Pattern[] restrictedUserAgents) {
0541:                this .restrictedUserAgents = restrictedUserAgents;
0542:            }
0543:
0544:            /**
0545:             * Set restricted user agent list (which will downgrade the connector
0546:             * to HTTP/1.0 mode). List contains users agents separated by ',' :
0547:             *
0548:             * ie: "gorilla,desesplorer,tigrus"
0549:             */
0550:            public void setRestrictedUserAgents(String restrictedUserAgents) {
0551:                if (restrictedUserAgents != null) {
0552:                    StringTokenizer st = new StringTokenizer(
0553:                            restrictedUserAgents, ",");
0554:                    while (st.hasMoreTokens()) {
0555:                        addRestrictedUserAgent(st.nextToken().trim());
0556:                    }
0557:                }
0558:            }
0559:
0560:            /**
0561:             * Return the list of restricted user agents.
0562:             */
0563:            public String[] findRestrictedUserAgents() {
0564:                String[] sarr = new String[restrictedUserAgents.length];
0565:
0566:                for (int i = 0; i < restrictedUserAgents.length; i++)
0567:                    sarr[i] = restrictedUserAgents[i].toString();
0568:
0569:                return (sarr);
0570:            }
0571:
0572:            /**
0573:             * Set the maximum number of Keep-Alive requests to honor.
0574:             * This is to safeguard from DoS attacks.  Setting to a negative
0575:             * value disables the check.
0576:             */
0577:            public void setMaxKeepAliveRequests(int mkar) {
0578:                maxKeepAliveRequests = mkar;
0579:            }
0580:
0581:            /**
0582:             * Return the number of Keep-Alive requests that we will honor.
0583:             */
0584:            public int getMaxKeepAliveRequests() {
0585:                return maxKeepAliveRequests;
0586:            }
0587:
0588:            /**
0589:             * Set the maximum size of a POST which will be buffered in SSL mode.
0590:             */
0591:            public void setMaxSavePostSize(int msps) {
0592:                maxSavePostSize = msps;
0593:            }
0594:
0595:            /**
0596:             * Return the maximum size of a POST which will be buffered in SSL mode.
0597:             */
0598:            public int getMaxSavePostSize() {
0599:                return maxSavePostSize;
0600:            }
0601:
0602:            /**
0603:             * Set the flag to control upload time-outs.
0604:             */
0605:            public void setDisableUploadTimeout(boolean isDisabled) {
0606:                disableUploadTimeout = isDisabled;
0607:            }
0608:
0609:            /**
0610:             * Get the flag that controls upload time-outs.
0611:             */
0612:            public boolean getDisableUploadTimeout() {
0613:                return disableUploadTimeout;
0614:            }
0615:
0616:            /**
0617:             * Set the socket buffer flag.
0618:             */
0619:            public void setSocketBuffer(int socketBuffer) {
0620:                this .socketBuffer = socketBuffer;
0621:                outputBuffer.setSocketBuffer(socketBuffer);
0622:            }
0623:
0624:            /**
0625:             * Get the socket buffer flag.
0626:             */
0627:            public int getSocketBuffer() {
0628:                return socketBuffer;
0629:            }
0630:
0631:            /**
0632:             * Set the upload timeout.
0633:             */
0634:            public void setTimeout(int timeouts) {
0635:                timeout = timeouts;
0636:            }
0637:
0638:            /**
0639:             * Get the upload timeout.
0640:             */
0641:            public int getTimeout() {
0642:                return timeout;
0643:            }
0644:
0645:            /**
0646:             * Set the server header name.
0647:             */
0648:            public void setServer(String server) {
0649:                if (server == null || server.equals("")) {
0650:                    this .server = null;
0651:                } else {
0652:                    this .server = server;
0653:                }
0654:            }
0655:
0656:            /**
0657:             * Get the server header name.
0658:             */
0659:            public String getServer() {
0660:                return server;
0661:            }
0662:
0663:            /** Get the request associated with this processor.
0664:             *
0665:             * @return The request
0666:             */
0667:            public Request getRequest() {
0668:                return request;
0669:            }
0670:
0671:            /**
0672:             * Process pipelined HTTP requests using the specified input and output
0673:             * streams.
0674:             *
0675:             * @throws IOException error during an I/O operation
0676:             */
0677:            public SocketState event(SocketStatus status) throws IOException {
0678:
0679:                RequestInfo rp = request.getRequestProcessor();
0680:
0681:                try {
0682:                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
0683:                    error = !adapter.event(request, response, status);
0684:                } catch (InterruptedIOException e) {
0685:                    error = true;
0686:                } catch (Throwable t) {
0687:                    log.error(sm.getString("http11processor.request.process"),
0688:                            t);
0689:                    // 500 - Internal Server Error
0690:                    response.setStatus(500);
0691:                    error = true;
0692:                }
0693:
0694:                rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
0695:
0696:                if (error) {
0697:                    recycle();
0698:                    return SocketState.CLOSED;
0699:                } else if (!comet) {
0700:                    recycle();
0701:                    return SocketState.OPEN;
0702:                } else {
0703:                    return SocketState.LONG;
0704:                }
0705:            }
0706:
0707:            /**
0708:             * Process pipelined HTTP requests using the specified input and output
0709:             * streams.
0710:             *
0711:             * @throws IOException error during an I/O operation
0712:             */
0713:            public SocketState process(long socket) throws IOException {
0714:                RequestInfo rp = request.getRequestProcessor();
0715:                rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
0716:
0717:                // Set the remote address
0718:                remoteAddr = null;
0719:                remoteHost = null;
0720:                localAddr = null;
0721:                localName = null;
0722:                remotePort = -1;
0723:                localPort = -1;
0724:
0725:                // Setting up the socket
0726:                this .socket = socket;
0727:                inputBuffer.setSocket(socket);
0728:                outputBuffer.setSocket(socket);
0729:
0730:                // Error flag
0731:                error = false;
0732:                comet = false;
0733:                keepAlive = true;
0734:
0735:                int keepAliveLeft = maxKeepAliveRequests;
0736:                long soTimeout = endpoint.getSoTimeout();
0737:
0738:                boolean keptAlive = false;
0739:                boolean openSocket = false;
0740:
0741:                while (!error && keepAlive && !comet) {
0742:
0743:                    // Parsing the request header
0744:                    try {
0745:                        if (!disableUploadTimeout && keptAlive && soTimeout > 0) {
0746:                            Socket.timeoutSet(socket, soTimeout * 1000);
0747:                        }
0748:                        if (!inputBuffer.parseRequestLine(keptAlive)) {
0749:                            // This means that no data is available right now
0750:                            // (long keepalive), so that the processor should be recycled
0751:                            // and the method should return true
0752:                            openSocket = true;
0753:                            // Add the socket to the poller
0754:                            endpoint.getPoller().add(socket);
0755:                            break;
0756:                        }
0757:                        request.setStartTime(System.currentTimeMillis());
0758:                        keptAlive = true;
0759:                        if (!disableUploadTimeout) {
0760:                            Socket.timeoutSet(socket, timeout * 1000);
0761:                        }
0762:                        inputBuffer.parseHeaders();
0763:                    } catch (IOException e) {
0764:                        error = true;
0765:                        break;
0766:                    } catch (Throwable t) {
0767:                        if (log.isDebugEnabled()) {
0768:                            log.debug(sm
0769:                                    .getString("http11processor.header.parse"),
0770:                                    t);
0771:                        }
0772:                        // 400 - Bad Request
0773:                        response.setStatus(400);
0774:                        error = true;
0775:                    }
0776:
0777:                    // Setting up filters, and parse some request headers
0778:                    rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
0779:                    try {
0780:                        prepareRequest();
0781:                    } catch (Throwable t) {
0782:                        if (log.isDebugEnabled()) {
0783:                            log
0784:                                    .debug(
0785:                                            sm
0786:                                                    .getString("http11processor.request.prepare"),
0787:                                            t);
0788:                        }
0789:                        // 400 - Internal Server Error
0790:                        response.setStatus(400);
0791:                        error = true;
0792:                    }
0793:
0794:                    if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)
0795:                        keepAlive = false;
0796:
0797:                    // Process the request in the adapter
0798:                    if (!error) {
0799:                        try {
0800:                            rp
0801:                                    .setStage(org.apache.coyote.Constants.STAGE_SERVICE);
0802:                            adapter.service(request, response);
0803:                            // Handle when the response was committed before a serious
0804:                            // error occurred.  Throwing a ServletException should both
0805:                            // set the status to 500 and set the errorException.
0806:                            // If we fail here, then the response is likely already
0807:                            // committed, so we can't try and set headers.
0808:                            if (keepAlive && !error) { // Avoid checking twice.
0809:                                error = response.getErrorException() != null
0810:                                        || statusDropsConnection(response
0811:                                                .getStatus());
0812:                            }
0813:                        } catch (InterruptedIOException e) {
0814:                            error = true;
0815:                        } catch (Throwable t) {
0816:                            log
0817:                                    .error(
0818:                                            sm
0819:                                                    .getString("http11processor.request.process"),
0820:                                            t);
0821:                            // 500 - Internal Server Error
0822:                            response.setStatus(500);
0823:                            error = true;
0824:                        }
0825:                    }
0826:
0827:                    // Finish the handling of the request
0828:                    if (!comet) {
0829:                        endRequest();
0830:                    }
0831:
0832:                    // If there was an error, make sure the request is counted as
0833:                    // and error, and update the statistics counter
0834:                    if (error) {
0835:                        response.setStatus(500);
0836:                    }
0837:                    request.updateCounters();
0838:
0839:                    if (!comet) {
0840:                        // Next request
0841:                        inputBuffer.nextRequest();
0842:                        outputBuffer.nextRequest();
0843:                    }
0844:
0845:                    // Do sendfile as needed: add socket to sendfile and end
0846:                    if (sendfileData != null && !error) {
0847:                        sendfileData.socket = socket;
0848:                        sendfileData.keepAlive = keepAlive;
0849:                        if (!endpoint.getSendfile().add(sendfileData)) {
0850:                            openSocket = true;
0851:                            break;
0852:                        }
0853:                    }
0854:
0855:                    rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
0856:
0857:                }
0858:
0859:                rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
0860:
0861:                if (comet) {
0862:                    if (error) {
0863:                        recycle();
0864:                        return SocketState.CLOSED;
0865:                    } else {
0866:                        return SocketState.LONG;
0867:                    }
0868:                } else {
0869:                    recycle();
0870:                    return (openSocket) ? SocketState.OPEN : SocketState.CLOSED;
0871:                }
0872:
0873:            }
0874:
0875:            public void endRequest() {
0876:
0877:                // Finish the handling of the request
0878:                try {
0879:                    inputBuffer.endRequest();
0880:                } catch (IOException e) {
0881:                    error = true;
0882:                } catch (Throwable t) {
0883:                    log
0884:                            .error(
0885:                                    sm
0886:                                            .getString("http11processor.request.finish"),
0887:                                    t);
0888:                    // 500 - Internal Server Error
0889:                    response.setStatus(500);
0890:                    error = true;
0891:                }
0892:                try {
0893:                    outputBuffer.endRequest();
0894:                } catch (IOException e) {
0895:                    error = true;
0896:                } catch (Throwable t) {
0897:                    log.error(sm.getString("http11processor.response.finish"),
0898:                            t);
0899:                    error = true;
0900:                }
0901:
0902:            }
0903:
0904:            public void recycle() {
0905:                inputBuffer.recycle();
0906:                outputBuffer.recycle();
0907:                this .socket = 0;
0908:            }
0909:
0910:            // ----------------------------------------------------- ActionHook Methods
0911:
0912:            /**
0913:             * Send an action to the connector.
0914:             *
0915:             * @param actionCode Type of the action
0916:             * @param param Action parameter
0917:             */
0918:            public void action(ActionCode actionCode, Object param) {
0919:
0920:                if (actionCode == ActionCode.ACTION_COMMIT) {
0921:                    // Commit current response
0922:
0923:                    if (response.isCommitted())
0924:                        return;
0925:
0926:                    // Validate and write response headers
0927:                    prepareResponse();
0928:                    try {
0929:                        outputBuffer.commit();
0930:                    } catch (IOException e) {
0931:                        // Set error flag
0932:                        error = true;
0933:                    }
0934:
0935:                } else if (actionCode == ActionCode.ACTION_ACK) {
0936:
0937:                    // Acknowlege request
0938:
0939:                    // Send a 100 status back if it makes sense (response not committed
0940:                    // yet, and client specified an expectation for 100-continue)
0941:
0942:                    if ((response.isCommitted()) || !expectation)
0943:                        return;
0944:
0945:                    inputBuffer.setSwallowInput(true);
0946:                    try {
0947:                        outputBuffer.sendAck();
0948:                    } catch (IOException e) {
0949:                        // Set error flag
0950:                        error = true;
0951:                    }
0952:
0953:                } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) {
0954:
0955:                    try {
0956:                        outputBuffer.flush();
0957:                    } catch (IOException e) {
0958:                        // Set error flag
0959:                        error = true;
0960:                        response.setErrorException(e);
0961:                    }
0962:
0963:                } else if (actionCode == ActionCode.ACTION_CLOSE) {
0964:                    // Close
0965:
0966:                    // End the processing of the current request, and stop any further
0967:                    // transactions with the client
0968:
0969:                    comet = false;
0970:                    try {
0971:                        outputBuffer.endRequest();
0972:                    } catch (IOException e) {
0973:                        // Set error flag
0974:                        error = true;
0975:                    }
0976:
0977:                } else if (actionCode == ActionCode.ACTION_RESET) {
0978:
0979:                    // Reset response
0980:
0981:                    // Note: This must be called before the response is committed
0982:
0983:                    outputBuffer.reset();
0984:
0985:                } else if (actionCode == ActionCode.ACTION_CUSTOM) {
0986:
0987:                    // Do nothing
0988:
0989:                } else if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) {
0990:
0991:                    // Get remote host address
0992:                    if (remoteAddr == null && (socket != 0)) {
0993:                        try {
0994:                            long sa = Address.get(Socket.APR_REMOTE, socket);
0995:                            remoteAddr = Address.getip(sa);
0996:                        } catch (Exception e) {
0997:                            log.warn(sm
0998:                                    .getString("http11processor.socket.info"),
0999:                                    e);
1000:                        }
1001:                    }
1002:                    request.remoteAddr().setString(remoteAddr);
1003:
1004:                } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_NAME_ATTRIBUTE) {
1005:
1006:                    // Get local host name
1007:                    if (localName == null && (socket != 0)) {
1008:                        try {
1009:                            long sa = Address.get(Socket.APR_LOCAL, socket);
1010:                            localName = Address.getnameinfo(sa, 0);
1011:                        } catch (Exception e) {
1012:                            log.warn(sm
1013:                                    .getString("http11processor.socket.info"),
1014:                                    e);
1015:                        }
1016:                    }
1017:                    request.localName().setString(localName);
1018:
1019:                } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) {
1020:
1021:                    // Get remote host name
1022:                    if (remoteHost == null && (socket != 0)) {
1023:                        try {
1024:                            long sa = Address.get(Socket.APR_REMOTE, socket);
1025:                            remoteHost = Address.getnameinfo(sa, 0);
1026:                        } catch (Exception e) {
1027:                            log.warn(sm
1028:                                    .getString("http11processor.socket.info"),
1029:                                    e);
1030:                        }
1031:                    }
1032:                    request.remoteHost().setString(remoteHost);
1033:
1034:                } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) {
1035:
1036:                    // Get local host address
1037:                    if (localAddr == null && (socket != 0)) {
1038:                        try {
1039:                            long sa = Address.get(Socket.APR_LOCAL, socket);
1040:                            localAddr = Address.getip(sa);
1041:                        } catch (Exception e) {
1042:                            log.warn(sm
1043:                                    .getString("http11processor.socket.info"),
1044:                                    e);
1045:                        }
1046:                    }
1047:
1048:                    request.localAddr().setString(localAddr);
1049:
1050:                } else if (actionCode == ActionCode.ACTION_REQ_REMOTEPORT_ATTRIBUTE) {
1051:
1052:                    // Get remote port
1053:                    if (remotePort == -1 && (socket != 0)) {
1054:                        try {
1055:                            long sa = Address.get(Socket.APR_REMOTE, socket);
1056:                            Sockaddr addr = Address.getInfo(sa);
1057:                            remotePort = addr.port;
1058:                        } catch (Exception e) {
1059:                            log.warn(sm
1060:                                    .getString("http11processor.socket.info"),
1061:                                    e);
1062:                        }
1063:                    }
1064:                    request.setRemotePort(remotePort);
1065:
1066:                } else if (actionCode == ActionCode.ACTION_REQ_LOCALPORT_ATTRIBUTE) {
1067:
1068:                    // Get local port
1069:                    if (localPort == -1 && (socket != 0)) {
1070:                        try {
1071:                            long sa = Address.get(Socket.APR_LOCAL, socket);
1072:                            Sockaddr addr = Address.getInfo(sa);
1073:                            localPort = addr.port;
1074:                        } catch (Exception e) {
1075:                            log.warn(sm
1076:                                    .getString("http11processor.socket.info"),
1077:                                    e);
1078:                        }
1079:                    }
1080:                    request.setLocalPort(localPort);
1081:
1082:                } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE) {
1083:
1084:                    if (ssl && (socket != 0)) {
1085:                        try {
1086:                            // Cipher suite
1087:                            Object sslO = SSLSocket.getInfoS(socket,
1088:                                    SSL.SSL_INFO_CIPHER);
1089:                            if (sslO != null) {
1090:                                request.setAttribute(
1091:                                        AprEndpoint.CIPHER_SUITE_KEY, sslO);
1092:                            }
1093:                            // Get client certificate and the certificate chain if present
1094:                            int certLength = SSLSocket.getInfoI(socket,
1095:                                    SSL.SSL_INFO_CLIENT_CERT_CHAIN);
1096:                            byte[] clientCert = SSLSocket.getInfoB(socket,
1097:                                    SSL.SSL_INFO_CLIENT_CERT);
1098:                            X509Certificate[] certs = null;
1099:                            if (clientCert != null) {
1100:                                certs = new X509Certificate[certLength + 1];
1101:                                CertificateFactory cf = CertificateFactory
1102:                                        .getInstance("X.509");
1103:                                certs[0] = (X509Certificate) cf
1104:                                        .generateCertificate(new ByteArrayInputStream(
1105:                                                clientCert));
1106:                                for (int i = 0; i < certLength; i++) {
1107:                                    byte[] data = SSLSocket.getInfoB(socket,
1108:                                            SSL.SSL_INFO_CLIENT_CERT_CHAIN + i);
1109:                                    certs[i + 1] = (X509Certificate) cf
1110:                                            .generateCertificate(new ByteArrayInputStream(
1111:                                                    data));
1112:                                }
1113:                            }
1114:                            if (certs != null) {
1115:                                request.setAttribute(
1116:                                        AprEndpoint.CERTIFICATE_KEY, certs);
1117:                            }
1118:                            // User key size
1119:                            sslO = new Integer(SSLSocket.getInfoI(socket,
1120:                                    SSL.SSL_INFO_CIPHER_USEKEYSIZE));
1121:                            if (sslO != null) {
1122:                                request.setAttribute(AprEndpoint.KEY_SIZE_KEY,
1123:                                        sslO);
1124:                            }
1125:                            // SSL session ID
1126:                            sslO = SSLSocket.getInfoS(socket,
1127:                                    SSL.SSL_INFO_SESSION_ID);
1128:                            if (sslO != null) {
1129:                                request.setAttribute(
1130:                                        AprEndpoint.SESSION_ID_KEY, sslO);
1131:                            }
1132:                        } catch (Exception e) {
1133:                            log.warn(
1134:                                    sm.getString("http11processor.socket.ssl"),
1135:                                    e);
1136:                        }
1137:                    }
1138:
1139:                } else if (actionCode == ActionCode.ACTION_REQ_SSL_CERTIFICATE) {
1140:
1141:                    if (ssl && (socket != 0)) {
1142:                        // Consume and buffer the request body, so that it does not
1143:                        // interfere with the client's handshake messages
1144:                        InputFilter[] inputFilters = inputBuffer.getFilters();
1145:                        ((BufferedInputFilter) inputFilters[Constants.BUFFERED_FILTER])
1146:                                .setLimit(maxSavePostSize);
1147:                        inputBuffer
1148:                                .addActiveFilter(inputFilters[Constants.BUFFERED_FILTER]);
1149:                        try {
1150:                            // Renegociate certificates
1151:                            SSLSocket.renegotiate(socket);
1152:                            // Get client certificate and the certificate chain if present
1153:                            int certLength = SSLSocket.getInfoI(socket,
1154:                                    SSL.SSL_INFO_CLIENT_CERT_CHAIN);
1155:                            byte[] clientCert = SSLSocket.getInfoB(socket,
1156:                                    SSL.SSL_INFO_CLIENT_CERT);
1157:                            X509Certificate[] certs = null;
1158:                            if (clientCert != null) {
1159:                                certs = new X509Certificate[certLength + 1];
1160:                                CertificateFactory cf = CertificateFactory
1161:                                        .getInstance("X.509");
1162:                                certs[0] = (X509Certificate) cf
1163:                                        .generateCertificate(new ByteArrayInputStream(
1164:                                                clientCert));
1165:                                for (int i = 0; i < certLength; i++) {
1166:                                    byte[] data = SSLSocket.getInfoB(socket,
1167:                                            SSL.SSL_INFO_CLIENT_CERT_CHAIN + i);
1168:                                    certs[i + 1] = (X509Certificate) cf
1169:                                            .generateCertificate(new ByteArrayInputStream(
1170:                                                    data));
1171:                                }
1172:                            }
1173:                            if (certs != null) {
1174:                                request.setAttribute(
1175:                                        AprEndpoint.CERTIFICATE_KEY, certs);
1176:                            }
1177:                        } catch (Exception e) {
1178:                            log.warn(
1179:                                    sm.getString("http11processor.socket.ssl"),
1180:                                    e);
1181:                        }
1182:                    }
1183:
1184:                } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) {
1185:                    ByteChunk body = (ByteChunk) param;
1186:
1187:                    InputFilter savedBody = new SavedRequestInputFilter(body);
1188:                    savedBody.setRequest(request);
1189:
1190:                    InternalAprInputBuffer internalBuffer = (InternalAprInputBuffer) request
1191:                            .getInputBuffer();
1192:                    internalBuffer.addActiveFilter(savedBody);
1193:
1194:                } else if (actionCode == ActionCode.ACTION_AVAILABLE) {
1195:                    request.setAvailable(inputBuffer.available());
1196:                } else if (actionCode == ActionCode.ACTION_COMET_BEGIN) {
1197:                    comet = true;
1198:                } else if (actionCode == ActionCode.ACTION_COMET_END) {
1199:                    comet = false;
1200:                }
1201:
1202:            }
1203:
1204:            // ------------------------------------------------------ Connector Methods
1205:
1206:            /**
1207:             * Set the associated adapter.
1208:             *
1209:             * @param adapter the new adapter
1210:             */
1211:            public void setAdapter(Adapter adapter) {
1212:                this .adapter = adapter;
1213:            }
1214:
1215:            /**
1216:             * Get the associated adapter.
1217:             *
1218:             * @return the associated adapter
1219:             */
1220:            public Adapter getAdapter() {
1221:                return adapter;
1222:            }
1223:
1224:            // ------------------------------------------------------ Protected Methods
1225:
1226:            /**
1227:             * After reading the request headers, we have to setup the request filters.
1228:             */
1229:            protected void prepareRequest() {
1230:
1231:                http11 = true;
1232:                http09 = false;
1233:                contentDelimitation = false;
1234:                expectation = false;
1235:                sendfileData = null;
1236:                if (ssl) {
1237:                    request.scheme().setString("https");
1238:                }
1239:                MessageBytes protocolMB = request.protocol();
1240:                if (protocolMB.equals(Constants.HTTP_11)) {
1241:                    http11 = true;
1242:                    protocolMB.setString(Constants.HTTP_11);
1243:                } else if (protocolMB.equals(Constants.HTTP_10)) {
1244:                    http11 = false;
1245:                    keepAlive = false;
1246:                    protocolMB.setString(Constants.HTTP_10);
1247:                } else if (protocolMB.equals("")) {
1248:                    // HTTP/0.9
1249:                    http09 = true;
1250:                    http11 = false;
1251:                    keepAlive = false;
1252:                } else {
1253:                    // Unsupported protocol
1254:                    http11 = false;
1255:                    error = true;
1256:                    // Send 505; Unsupported HTTP version
1257:                    response.setStatus(505);
1258:                }
1259:
1260:                MessageBytes methodMB = request.method();
1261:                if (methodMB.equals(Constants.GET)) {
1262:                    methodMB.setString(Constants.GET);
1263:                } else if (methodMB.equals(Constants.POST)) {
1264:                    methodMB.setString(Constants.POST);
1265:                }
1266:
1267:                MimeHeaders headers = request.getMimeHeaders();
1268:
1269:                // Check connection header
1270:                MessageBytes connectionValueMB = headers.getValue("connection");
1271:                if (connectionValueMB != null) {
1272:                    ByteChunk connectionValueBC = connectionValueMB
1273:                            .getByteChunk();
1274:                    if (findBytes(connectionValueBC, Constants.CLOSE_BYTES) != -1) {
1275:                        keepAlive = false;
1276:                    } else if (findBytes(connectionValueBC,
1277:                            Constants.KEEPALIVE_BYTES) != -1) {
1278:                        keepAlive = true;
1279:                    }
1280:                }
1281:
1282:                MessageBytes expectMB = null;
1283:                if (http11)
1284:                    expectMB = headers.getValue("expect");
1285:                if ((expectMB != null)
1286:                        && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) {
1287:                    inputBuffer.setSwallowInput(false);
1288:                    expectation = true;
1289:                }
1290:
1291:                // Check user-agent header
1292:                if ((restrictedUserAgents != null) && ((http11) || (keepAlive))) {
1293:                    MessageBytes userAgentValueMB = headers
1294:                            .getValue("user-agent");
1295:                    // Check in the restricted list, and adjust the http11
1296:                    // and keepAlive flags accordingly
1297:                    if (userAgentValueMB != null) {
1298:                        String userAgentValue = userAgentValueMB.toString();
1299:                        for (int i = 0; i < restrictedUserAgents.length; i++) {
1300:                            if (restrictedUserAgents[i].matcher(userAgentValue)
1301:                                    .matches()) {
1302:                                http11 = false;
1303:                                keepAlive = false;
1304:                                break;
1305:                            }
1306:                        }
1307:                    }
1308:                }
1309:
1310:                // Check for a full URI (including protocol://host:port/)
1311:                ByteChunk uriBC = request.requestURI().getByteChunk();
1312:                if (uriBC.startsWithIgnoreCase("http", 0)) {
1313:
1314:                    int pos = uriBC.indexOf("://", 0, 3, 4);
1315:                    int uriBCStart = uriBC.getStart();
1316:                    int slashPos = -1;
1317:                    if (pos != -1) {
1318:                        byte[] uriB = uriBC.getBytes();
1319:                        slashPos = uriBC.indexOf('/', pos + 3);
1320:                        if (slashPos == -1) {
1321:                            slashPos = uriBC.getLength();
1322:                            // Set URI as "/"
1323:                            request.requestURI().setBytes(uriB,
1324:                                    uriBCStart + pos + 1, 1);
1325:                        } else {
1326:                            request.requestURI().setBytes(uriB,
1327:                                    uriBCStart + slashPos,
1328:                                    uriBC.getLength() - slashPos);
1329:                        }
1330:                        MessageBytes hostMB = headers.setValue("host");
1331:                        hostMB.setBytes(uriB, uriBCStart + pos + 3, slashPos
1332:                                - pos - 3);
1333:                    }
1334:
1335:                }
1336:
1337:                // Input filter setup
1338:                InputFilter[] inputFilters = inputBuffer.getFilters();
1339:
1340:                // Parse transfer-encoding header
1341:                MessageBytes transferEncodingValueMB = null;
1342:                if (http11)
1343:                    transferEncodingValueMB = headers
1344:                            .getValue("transfer-encoding");
1345:                if (transferEncodingValueMB != null) {
1346:                    String transferEncodingValue = transferEncodingValueMB
1347:                            .toString();
1348:                    // Parse the comma separated list. "identity" codings are ignored
1349:                    int startPos = 0;
1350:                    int commaPos = transferEncodingValue.indexOf(',');
1351:                    String encodingName = null;
1352:                    while (commaPos != -1) {
1353:                        encodingName = transferEncodingValue.substring(
1354:                                startPos, commaPos).toLowerCase().trim();
1355:                        if (!addInputFilter(inputFilters, encodingName)) {
1356:                            // Unsupported transfer encoding
1357:                            error = true;
1358:                            // 501 - Unimplemented
1359:                            response.setStatus(501);
1360:                        }
1361:                        startPos = commaPos + 1;
1362:                        commaPos = transferEncodingValue.indexOf(',', startPos);
1363:                    }
1364:                    encodingName = transferEncodingValue.substring(startPos)
1365:                            .toLowerCase().trim();
1366:                    if (!addInputFilter(inputFilters, encodingName)) {
1367:                        // Unsupported transfer encoding
1368:                        error = true;
1369:                        // 501 - Unimplemented
1370:                        response.setStatus(501);
1371:                    }
1372:                }
1373:
1374:                // Parse content-length header
1375:                long contentLength = request.getContentLengthLong();
1376:                if (contentLength >= 0 && !contentDelimitation) {
1377:                    inputBuffer
1378:                            .addActiveFilter(inputFilters[Constants.IDENTITY_FILTER]);
1379:                    contentDelimitation = true;
1380:                }
1381:
1382:                MessageBytes valueMB = headers.getValue("host");
1383:
1384:                // Check host header
1385:                if (http11 && (valueMB == null)) {
1386:                    error = true;
1387:                    // 400 - Bad request
1388:                    response.setStatus(400);
1389:                }
1390:
1391:                parseHost(valueMB);
1392:
1393:                if (!contentDelimitation) {
1394:                    // If there's no content length 
1395:                    // (broken HTTP/1.0 or HTTP/1.1), assume
1396:                    // the client is not broken and didn't send a body
1397:                    inputBuffer
1398:                            .addActiveFilter(inputFilters[Constants.VOID_FILTER]);
1399:                    contentDelimitation = true;
1400:                }
1401:
1402:                // Advertise sendfile support through a request attribute
1403:                if (endpoint.getUseSendfile()) {
1404:                    request.setAttribute("org.apache.tomcat.sendfile.support",
1405:                            Boolean.TRUE);
1406:                }
1407:                // Advertise comet support through a request attribute
1408:                request.setAttribute("org.apache.tomcat.comet.support",
1409:                        Boolean.TRUE);
1410:
1411:            }
1412:
1413:            /**
1414:             * Parse host.
1415:             */
1416:            public void parseHost(MessageBytes valueMB) {
1417:
1418:                if (valueMB == null || valueMB.isNull()) {
1419:                    // HTTP/1.0
1420:                    // Default is what the socket tells us. Overriden if a host is
1421:                    // found/parsed
1422:                    request.setServerPort(endpoint.getPort());
1423:                    return;
1424:                }
1425:
1426:                ByteChunk valueBC = valueMB.getByteChunk();
1427:                byte[] valueB = valueBC.getBytes();
1428:                int valueL = valueBC.getLength();
1429:                int valueS = valueBC.getStart();
1430:                int colonPos = -1;
1431:                if (hostNameC.length < valueL) {
1432:                    hostNameC = new char[valueL];
1433:                }
1434:
1435:                boolean ipv6 = (valueB[valueS] == '[');
1436:                boolean bracketClosed = false;
1437:                for (int i = 0; i < valueL; i++) {
1438:                    char b = (char) valueB[i + valueS];
1439:                    hostNameC[i] = b;
1440:                    if (b == ']') {
1441:                        bracketClosed = true;
1442:                    } else if (b == ':') {
1443:                        if (!ipv6 || bracketClosed) {
1444:                            colonPos = i;
1445:                            break;
1446:                        }
1447:                    }
1448:                }
1449:
1450:                if (colonPos < 0) {
1451:                    if (!ssl) {
1452:                        // 80 - Default HTTP port
1453:                        request.setServerPort(80);
1454:                    } else {
1455:                        // 443 - Default HTTPS port
1456:                        request.setServerPort(443);
1457:                    }
1458:                    request.serverName().setChars(hostNameC, 0, valueL);
1459:                } else {
1460:
1461:                    request.serverName().setChars(hostNameC, 0, colonPos);
1462:
1463:                    int port = 0;
1464:                    int mult = 1;
1465:                    for (int i = valueL - 1; i > colonPos; i--) {
1466:                        int charValue = HexUtils.DEC[(int) valueB[i + valueS]];
1467:                        if (charValue == -1) {
1468:                            // Invalid character
1469:                            error = true;
1470:                            // 400 - Bad request
1471:                            response.setStatus(400);
1472:                            break;
1473:                        }
1474:                        port = port + (charValue * mult);
1475:                        mult = 10 * mult;
1476:                    }
1477:                    request.setServerPort(port);
1478:
1479:                }
1480:
1481:            }
1482:
1483:            /**
1484:             * Check for compression
1485:             */
1486:            private boolean isCompressable() {
1487:
1488:                // Nope Compression could works in HTTP 1.0 also
1489:                // cf: mod_deflate
1490:
1491:                // Compression only since HTTP 1.1
1492:                // if (! http11)
1493:                //    return false;
1494:
1495:                // Check if browser support gzip encoding
1496:                MessageBytes acceptEncodingMB = request.getMimeHeaders()
1497:                        .getValue("accept-encoding");
1498:
1499:                if ((acceptEncodingMB == null)
1500:                        || (acceptEncodingMB.indexOf("gzip") == -1))
1501:                    return false;
1502:
1503:                // Check if content is not allready gzipped
1504:                MessageBytes contentEncodingMB = response.getMimeHeaders()
1505:                        .getValue("Content-Encoding");
1506:
1507:                if ((contentEncodingMB != null)
1508:                        && (contentEncodingMB.indexOf("gzip") != -1))
1509:                    return false;
1510:
1511:                // If force mode, allways compress (test purposes only)
1512:                if (compressionLevel == 2)
1513:                    return true;
1514:
1515:                // Check for incompatible Browser
1516:                if (noCompressionUserAgents != null) {
1517:                    MessageBytes userAgentValueMB = request.getMimeHeaders()
1518:                            .getValue("user-agent");
1519:                    if (userAgentValueMB != null) {
1520:                        String userAgentValue = userAgentValueMB.toString();
1521:
1522:                        // If one Regexp rule match, disable compression
1523:                        for (int i = 0; i < noCompressionUserAgents.length; i++)
1524:                            if (noCompressionUserAgents[i].matcher(
1525:                                    userAgentValue).matches())
1526:                                return false;
1527:                    }
1528:                }
1529:
1530:                // Check if suffisant len to trig the compression
1531:                long contentLength = response.getContentLengthLong();
1532:                if ((contentLength == -1)
1533:                        || (contentLength > compressionMinSize)) {
1534:                    // Check for compatible MIME-TYPE
1535:                    if (compressableMimeTypes != null) {
1536:                        return (startsWithStringArray(compressableMimeTypes,
1537:                                response.getContentType()));
1538:                    }
1539:                }
1540:
1541:                return false;
1542:            }
1543:
1544:            /**
1545:             * When committing the response, we have to validate the set of headers, as
1546:             * well as setup the response filters.
1547:             */
1548:            protected void prepareResponse() {
1549:
1550:                boolean entityBody = true;
1551:                contentDelimitation = false;
1552:
1553:                OutputFilter[] outputFilters = outputBuffer.getFilters();
1554:
1555:                if (http09 == true) {
1556:                    // HTTP/0.9
1557:                    outputBuffer
1558:                            .addActiveFilter(outputFilters[Constants.IDENTITY_FILTER]);
1559:                    return;
1560:                }
1561:
1562:                int statusCode = response.getStatus();
1563:                if ((statusCode == 204) || (statusCode == 205)
1564:                        || (statusCode == 304)) {
1565:                    // No entity body
1566:                    outputBuffer
1567:                            .addActiveFilter(outputFilters[Constants.VOID_FILTER]);
1568:                    entityBody = false;
1569:                    contentDelimitation = true;
1570:                }
1571:
1572:                MessageBytes methodMB = request.method();
1573:                if (methodMB.equals("HEAD")) {
1574:                    // No entity body
1575:                    outputBuffer
1576:                            .addActiveFilter(outputFilters[Constants.VOID_FILTER]);
1577:                    contentDelimitation = true;
1578:                }
1579:
1580:                // Sendfile support
1581:                if (endpoint.getUseSendfile()) {
1582:                    String fileName = (String) request
1583:                            .getAttribute("org.apache.tomcat.sendfile.filename");
1584:                    if (fileName != null) {
1585:                        // No entity body sent here
1586:                        outputBuffer
1587:                                .addActiveFilter(outputFilters[Constants.VOID_FILTER]);
1588:                        contentDelimitation = true;
1589:                        sendfileData = new AprEndpoint.SendfileData();
1590:                        sendfileData.fileName = fileName;
1591:                        sendfileData.start = ((Long) request
1592:                                .getAttribute("org.apache.tomcat.sendfile.start"))
1593:                                .longValue();
1594:                        sendfileData.end = ((Long) request
1595:                                .getAttribute("org.apache.tomcat.sendfile.end"))
1596:                                .longValue();
1597:                    }
1598:                }
1599:
1600:                // Check for compression
1601:                boolean useCompression = false;
1602:                if (entityBody && (compressionLevel > 0)
1603:                        && (sendfileData == null)) {
1604:                    useCompression = isCompressable();
1605:                    // Change content-length to -1 to force chunking
1606:                    if (useCompression) {
1607:                        response.setContentLength(-1);
1608:                    }
1609:                }
1610:
1611:                MimeHeaders headers = response.getMimeHeaders();
1612:                if (!entityBody) {
1613:                    response.setContentLength(-1);
1614:                } else {
1615:                    String contentType = response.getContentType();
1616:                    if (contentType != null) {
1617:                        headers.setValue("Content-Type").setString(contentType);
1618:                    }
1619:                    String contentLanguage = response.getContentLanguage();
1620:                    if (contentLanguage != null) {
1621:                        headers.setValue("Content-Language").setString(
1622:                                contentLanguage);
1623:                    }
1624:                }
1625:
1626:                long contentLength = response.getContentLengthLong();
1627:                if (contentLength != -1) {
1628:                    headers.setValue("Content-Length").setLong(contentLength);
1629:                    outputBuffer
1630:                            .addActiveFilter(outputFilters[Constants.IDENTITY_FILTER]);
1631:                    contentDelimitation = true;
1632:                } else {
1633:                    if (entityBody && http11 && keepAlive) {
1634:                        outputBuffer
1635:                                .addActiveFilter(outputFilters[Constants.CHUNKED_FILTER]);
1636:                        contentDelimitation = true;
1637:                        headers.addValue(Constants.TRANSFERENCODING).setString(
1638:                                Constants.CHUNKED);
1639:                    } else {
1640:                        outputBuffer
1641:                                .addActiveFilter(outputFilters[Constants.IDENTITY_FILTER]);
1642:                    }
1643:                }
1644:
1645:                if (useCompression) {
1646:                    outputBuffer
1647:                            .addActiveFilter(outputFilters[Constants.GZIP_FILTER]);
1648:                    headers.setValue("Content-Encoding").setString("gzip");
1649:                    // Make Proxies happy via Vary (from mod_deflate)
1650:                    headers.setValue("Vary").setString("Accept-Encoding");
1651:                }
1652:
1653:                // Add date header
1654:                headers.setValue("Date").setString(
1655:                        FastHttpDateFormat.getCurrentDate());
1656:
1657:                // FIXME: Add transfer encoding header
1658:
1659:                if ((entityBody) && (!contentDelimitation)) {
1660:                    // Mark as close the connection after the request, and add the
1661:                    // connection: close header
1662:                    keepAlive = false;
1663:                }
1664:
1665:                // If we know that the request is bad this early, add the
1666:                // Connection: close header.
1667:                keepAlive = keepAlive && !statusDropsConnection(statusCode);
1668:                if (!keepAlive) {
1669:                    headers.addValue(Constants.CONNECTION).setString(
1670:                            Constants.CLOSE);
1671:                } else if (!http11 && !error) {
1672:                    headers.addValue(Constants.CONNECTION).setString(
1673:                            Constants.KEEPALIVE);
1674:                }
1675:
1676:                // Build the response header
1677:                outputBuffer.sendStatus();
1678:
1679:                // Add server header
1680:                if (server != null) {
1681:                    headers.setValue("Server").setString(server);
1682:                } else {
1683:                    outputBuffer.write(Constants.SERVER_BYTES);
1684:                }
1685:
1686:                int size = headers.size();
1687:                for (int i = 0; i < size; i++) {
1688:                    outputBuffer.sendHeader(headers.getName(i), headers
1689:                            .getValue(i));
1690:                }
1691:                outputBuffer.endHeaders();
1692:
1693:            }
1694:
1695:            /**
1696:             * Initialize standard input and output filters.
1697:             */
1698:            protected void initializeFilters() {
1699:
1700:                // Create and add the identity filters.
1701:                inputBuffer.addFilter(new IdentityInputFilter());
1702:                outputBuffer.addFilter(new IdentityOutputFilter());
1703:
1704:                // Create and add the chunked filters.
1705:                inputBuffer.addFilter(new ChunkedInputFilter());
1706:                outputBuffer.addFilter(new ChunkedOutputFilter());
1707:
1708:                // Create and add the void filters.
1709:                inputBuffer.addFilter(new VoidInputFilter());
1710:                outputBuffer.addFilter(new VoidOutputFilter());
1711:
1712:                // Create and add buffered input filter
1713:                inputBuffer.addFilter(new BufferedInputFilter());
1714:
1715:                // Create and add the chunked filters.
1716:                //inputBuffer.addFilter(new GzipInputFilter());
1717:                outputBuffer.addFilter(new GzipOutputFilter());
1718:
1719:            }
1720:
1721:            /**
1722:             * Add an input filter to the current request.
1723:             *
1724:             * @return false if the encoding was not found (which would mean it is
1725:             * unsupported)
1726:             */
1727:            protected boolean addInputFilter(InputFilter[] inputFilters,
1728:                    String encodingName) {
1729:                if (encodingName.equals("identity")) {
1730:                    // Skip
1731:                } else if (encodingName.equals("chunked")) {
1732:                    inputBuffer
1733:                            .addActiveFilter(inputFilters[Constants.CHUNKED_FILTER]);
1734:                    contentDelimitation = true;
1735:                } else {
1736:                    for (int i = 2; i < inputFilters.length; i++) {
1737:                        if (inputFilters[i].getEncodingName().toString()
1738:                                .equals(encodingName)) {
1739:                            inputBuffer.addActiveFilter(inputFilters[i]);
1740:                            return true;
1741:                        }
1742:                    }
1743:                    return false;
1744:                }
1745:                return true;
1746:            }
1747:
1748:            /**
1749:             * Specialized utility method: find a sequence of lower case bytes inside
1750:             * a ByteChunk.
1751:             */
1752:            protected int findBytes(ByteChunk bc, byte[] b) {
1753:
1754:                byte first = b[0];
1755:                byte[] buff = bc.getBuffer();
1756:                int start = bc.getStart();
1757:                int end = bc.getEnd();
1758:
1759:                // Look for first char
1760:                int srcEnd = b.length;
1761:
1762:                for (int i = start; i <= (end - srcEnd); i++) {
1763:                    if (Ascii.toLower(buff[i]) != first)
1764:                        continue;
1765:                    // found first char, now look for a match
1766:                    int myPos = i + 1;
1767:                    for (int srcPos = 1; srcPos < srcEnd;) {
1768:                        if (Ascii.toLower(buff[myPos++]) != b[srcPos++])
1769:                            break;
1770:                        if (srcPos == srcEnd)
1771:                            return i - start; // found it
1772:                    }
1773:                }
1774:                return -1;
1775:
1776:            }
1777:
1778:            /**
1779:             * Determine if we must drop the connection because of the HTTP status
1780:             * code.  Use the same list of codes as Apache/httpd.
1781:             */
1782:            protected boolean statusDropsConnection(int status) {
1783:                return status == 400 /* SC_BAD_REQUEST */|| status == 408 /* SC_REQUEST_TIMEOUT */
1784:                        || status == 411 /* SC_LENGTH_REQUIRED */
1785:                        || status == 413 /* SC_REQUEST_ENTITY_TOO_LARGE */
1786:                        || status == 414 /* SC_REQUEST_URI_TOO_LARGE */
1787:                        || status == 500 /* SC_INTERNAL_SERVER_ERROR */
1788:                        || status == 503 /* SC_SERVICE_UNAVAILABLE */
1789:                        || status == 501 /* SC_NOT_IMPLEMENTED */;
1790:            }
1791:
1792:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.