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