Source Code Cross Referenced for AbstractHttpResponse.java in  » EJB-Server-resin-3.1.5 » resin » com » caucho » server » connection » 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 » EJB Server resin 3.1.5 » resin » com.caucho.server.connection 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003:         *
0004:         * This file is part of Resin(R) Open Source
0005:         *
0006:         * Each copy or derived work must preserve the copyright notice and this
0007:         * notice unmodified.
0008:         *
0009:         * Resin Open Source is free software; you can redistribute it and/or modify
0010:         * it under the terms of the GNU General Public License as published by
0011:         * the Free Software Foundation; either version 2 of the License, or
0012:         * (at your option) any later version.
0013:         *
0014:         * Resin Open Source is distributed in the hope that it will be useful,
0015:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017:         * of NON-INFRINGEMENT.  See the GNU General Public License for more
0018:         * details.
0019:         *
0020:         * You should have received a copy of the GNU General Public License
0021:         * along with Resin Open Source; if not, write to the
0022:         *
0023:         *   Free Software Foundation, Inc.
0024:         *   59 Temple Place, Suite 330
0025:         *   Boston, MA 02111-1307  USA
0026:         *
0027:         * @author Scott Ferguson
0028:         */
0029:
0030:        package com.caucho.server.connection;
0031:
0032:        import com.caucho.log.Log;
0033:        import com.caucho.server.cache.AbstractCacheEntry;
0034:        import com.caucho.server.cache.AbstractCacheFilterChain;
0035:        import com.caucho.server.dispatch.BadRequestException;
0036:        import com.caucho.server.dispatch.InvocationDecoder;
0037:        import com.caucho.server.session.CookieImpl;
0038:        import com.caucho.server.session.SessionImpl;
0039:        import com.caucho.server.session.SessionManager;
0040:        import com.caucho.server.util.CauchoSystem;
0041:        import com.caucho.server.webapp.ErrorPageManager;
0042:        import com.caucho.server.webapp.WebApp;
0043:        import com.caucho.util.Alarm;
0044:        import com.caucho.util.CaseInsensitiveIntMap;
0045:        import com.caucho.util.CharBuffer;
0046:        import com.caucho.util.HTTPUtil;
0047:        import com.caucho.util.L10N;
0048:        import com.caucho.util.QDate;
0049:        import com.caucho.vfs.ClientDisconnectException;
0050:        import com.caucho.vfs.FlushBuffer;
0051:        import com.caucho.vfs.TempBuffer;
0052:        import com.caucho.vfs.WriteStream;
0053:        import com.caucho.xml.XmlChar;
0054:
0055:        import javax.servlet.ServletOutputStream;
0056:        import javax.servlet.ServletResponse;
0057:        import javax.servlet.http.Cookie;
0058:        import javax.servlet.http.HttpServletResponse;
0059:        import javax.servlet.http.HttpSession;
0060:        import java.io.IOException;
0061:        import java.io.OutputStream;
0062:        import java.io.PrintWriter;
0063:        import java.io.Writer;
0064:        import java.util.ArrayList;
0065:        import java.util.HashMap;
0066:        import java.util.Locale;
0067:        import java.util.logging.Level;
0068:        import java.util.logging.Logger;
0069:
0070:        /**
0071:         * Encapsulates the servlet response, controlling response headers and the
0072:         * response stream.
0073:         */
0074:        abstract public class AbstractHttpResponse implements  CauchoResponse {
0075:            static final protected Logger log = Logger
0076:                    .getLogger(AbstractHttpResponse.class.getName());
0077:            static final L10N L = new L10N(AbstractHttpResponse.class);
0078:
0079:            static final HashMap<String, String> _errors;
0080:
0081:            protected static final CaseInsensitiveIntMap _headerCodes;
0082:            protected static final int HEADER_CACHE_CONTROL = 1;
0083:            protected static final int HEADER_CONTENT_TYPE = HEADER_CACHE_CONTROL + 1;
0084:            protected static final int HEADER_CONTENT_LENGTH = HEADER_CONTENT_TYPE + 1;
0085:            protected static final int HEADER_DATE = HEADER_CONTENT_LENGTH + 1;
0086:            protected static final int HEADER_SERVER = HEADER_DATE + 1;
0087:            protected static final int HEADER_CONNECTION = HEADER_SERVER + 1;
0088:
0089:            protected CauchoRequest _originalRequest;
0090:            protected CauchoRequest _request;
0091:
0092:            protected int _statusCode;
0093:            protected String _statusMessage;
0094:
0095:            protected String _contentType;
0096:            protected String _contentPrefix;
0097:            protected String _charEncoding;
0098:            protected boolean _hasCharEncoding;
0099:
0100:            protected final ArrayList<String> _headerKeys = new ArrayList<String>();
0101:            protected final ArrayList<String> _headerValues = new ArrayList<String>();
0102:
0103:            protected final ArrayList<String> _footerKeys = new ArrayList<String>();
0104:            protected final ArrayList<String> _footerValues = new ArrayList<String>();
0105:
0106:            protected final ArrayList<Cookie> _cookiesOut = new ArrayList<Cookie>();
0107:
0108:            private final AbstractResponseStream _originalResponseStream;
0109:
0110:            private final ServletOutputStreamImpl _responseOutputStream;
0111:            private final ResponseWriter _responsePrintWriter;
0112:
0113:            private AbstractResponseStream _responseStream;
0114:
0115:            // the raw output stream.
0116:            protected WriteStream _rawWrite;
0117:
0118:            // any stream that needs flusing before getting the writer.
0119:            private FlushBuffer _flushBuffer;
0120:
0121:            private boolean _isHeaderWritten;
0122:            private boolean _isChunked;
0123:            protected final QDate _calendar = new QDate(false);
0124:
0125:            protected final CharBuffer _cb = new CharBuffer();
0126:            protected final char[] _headerBuffer = new char[256];
0127:
0128:            private String _sessionId;
0129:            private boolean _hasSessionCookie;
0130:
0131:            private Locale _locale;
0132:            protected boolean _disableHeaders;
0133:            protected boolean _disableCaching;
0134:            protected long _contentLength;
0135:            protected boolean _isClosed;
0136:            protected boolean _hasSentLog;
0137:
0138:            protected boolean _hasWriter;
0139:            protected boolean _hasOutputStream;
0140:
0141:            private AbstractCacheFilterChain _cacheInvocation;
0142:
0143:            // the cache entry for a match/if-modified-since
0144:            private AbstractCacheEntry _matchCacheEntry;
0145:
0146:            // the new cache for a request getting filled
0147:            private AbstractCacheEntry _newCacheEntry;
0148:            private OutputStream _cacheStream;
0149:            private Writer _cacheWriter;
0150:
0151:            protected boolean _isNoCache;
0152:            private boolean _allowCache;
0153:            private boolean _isPrivateCache;
0154:            private boolean _hasCacheControl;
0155:
0156:            protected boolean _isTopCache;
0157:
0158:            protected boolean _forbidForward;
0159:            protected boolean _hasError;
0160:
0161:            private final TempBuffer _tempBuffer = TempBuffer.allocate();
0162:
0163:            protected AbstractHttpResponse() {
0164:                _originalResponseStream = createResponseStream();
0165:
0166:                _responseOutputStream = new ServletOutputStreamImpl();
0167:                _responsePrintWriter = new ResponseWriter();
0168:
0169:                _responseOutputStream.init(_originalResponseStream);
0170:                _responsePrintWriter.init(_originalResponseStream);
0171:            }
0172:
0173:            protected AbstractResponseStream createResponseStream() {
0174:                return new ResponseStream(this );
0175:            }
0176:
0177:            protected AbstractHttpResponse(CauchoRequest request) {
0178:                this ();
0179:
0180:                _request = request;
0181:                _originalRequest = request;
0182:
0183:                _responseOutputStream.init(_originalResponseStream);
0184:                _responsePrintWriter.init(_originalResponseStream);
0185:            }
0186:
0187:            /**
0188:             * If set true, client disconnect exceptions are no propagated to the
0189:             * server code.
0190:             */
0191:            public boolean isIgnoreClientDisconnect() {
0192:                if (!(_originalRequest instanceof  AbstractHttpRequest))
0193:                    return true;
0194:                else {
0195:                    return ((AbstractHttpRequest) _originalRequest)
0196:                            .isIgnoreClientDisconnect();
0197:                }
0198:            }
0199:
0200:            /**
0201:             * Return true for the top request.
0202:             */
0203:            public boolean isTop() {
0204:                if (!(_request instanceof  AbstractHttpRequest))
0205:                    return false;
0206:                else {
0207:                    return ((AbstractHttpRequest) _request).isTop();
0208:                }
0209:            }
0210:
0211:            /**
0212:             * Returns the next response.
0213:             */
0214:            public ServletResponse getResponse() {
0215:                return null;
0216:            }
0217:
0218:            /**
0219:             * Initialize the response for a new request.
0220:             *
0221:             * @param stream the underlying output stream.
0222:             */
0223:            public void init(WriteStream stream) {
0224:                _rawWrite = stream;
0225:                if (_originalResponseStream instanceof  ResponseStream)
0226:                    ((ResponseStream) _originalResponseStream).init(_rawWrite);
0227:            }
0228:
0229:            /**
0230:             * Initialize the response for a new request.
0231:             *
0232:             * @param request the matching request.
0233:             */
0234:            public void init(CauchoRequest request) {
0235:                _request = request;
0236:                _originalRequest = request;
0237:            }
0238:
0239:            /**
0240:             * Returns the corresponding request.
0241:             */
0242:            public CauchoRequest getRequest() {
0243:                return _request;
0244:            }
0245:
0246:            /**
0247:             * Sets the corresponding request.
0248:             */
0249:            public void setRequest(CauchoRequest req) {
0250:                _request = req;
0251:
0252:                if (_originalRequest == null)
0253:                    _originalRequest = req;
0254:            }
0255:
0256:            /**
0257:             * Returns the corresponding original
0258:             */
0259:            public CauchoRequest getOriginalRequest() {
0260:                return _originalRequest;
0261:            }
0262:
0263:            /**
0264:             * Closes the request.
0265:             */
0266:            public void close() throws IOException {
0267:                finish(true);
0268:                // getStream().flush();
0269:            }
0270:
0271:            /**
0272:             * Returns true for closed requests.
0273:             */
0274:            public boolean isClosed() {
0275:                return _isClosed;
0276:            }
0277:
0278:            /**
0279:             * Initializes the Response at the beginning of the request.
0280:             */
0281:            public void start() throws IOException {
0282:                _statusCode = 200;
0283:                _statusMessage = "OK";
0284:
0285:                _headerKeys.clear();
0286:                _headerValues.clear();
0287:
0288:                _footerKeys.clear();
0289:                _footerValues.clear();
0290:
0291:                _hasSessionCookie = false;
0292:                _cookiesOut.clear();
0293:
0294:                _isHeaderWritten = false;
0295:                _isChunked = false;
0296:                _charEncoding = null;
0297:                _hasCharEncoding = false;
0298:                _contentType = null;
0299:                _contentPrefix = null;
0300:                _locale = null;
0301:                if (_originalResponseStream instanceof  ResponseStream)
0302:                    ((ResponseStream) _originalResponseStream).init(_rawWrite);
0303:                _flushBuffer = null;
0304:
0305:                _contentLength = -1;
0306:                _disableHeaders = false;
0307:                _disableCaching = false;
0308:                _isClosed = false;
0309:                _hasSentLog = false;
0310:
0311:                _hasWriter = false;
0312:                _hasOutputStream = false;
0313:
0314:                _cacheInvocation = null;
0315:                _matchCacheEntry = null;
0316:                _newCacheEntry = null;
0317:                _cacheStream = null;
0318:                _cacheWriter = null;
0319:                _isPrivateCache = false;
0320:                _hasCacheControl = false;
0321:                _allowCache = true;
0322:                _isNoCache = false;
0323:                _isTopCache = false;
0324:
0325:                _sessionId = null;
0326:
0327:                _forbidForward = false;
0328:
0329:                _originalResponseStream.start();
0330:
0331:                _responseStream = _originalResponseStream;
0332:
0333:                _responseOutputStream.init(_responseStream);
0334:                _responsePrintWriter.init(_responseStream);
0335:            }
0336:
0337:            /**
0338:             * For a HEAD request, the response stream should write no data.
0339:             */
0340:            void setHead() {
0341:                _originalResponseStream.setHead();
0342:            }
0343:
0344:            /**
0345:             * For a HEAD request, the response stream should write no data.
0346:             */
0347:            protected final boolean isHead() {
0348:                return _originalResponseStream.isHead();
0349:            }
0350:
0351:            /**
0352:             * When set to true, RequestDispatcher.forward() is disallowed on
0353:             * this stream.
0354:             */
0355:            public void setForbidForward(boolean forbid) {
0356:                _forbidForward = forbid;
0357:            }
0358:
0359:            /**
0360:             * Returns true if RequestDispatcher.forward() is disallowed on
0361:             * this stream.
0362:             */
0363:            public boolean getForbidForward() {
0364:                return _forbidForward;
0365:            }
0366:
0367:            /**
0368:             * Set to true while processing an error.
0369:             */
0370:            public void setHasError(boolean hasError) {
0371:                _hasError = hasError;
0372:            }
0373:
0374:            /**
0375:             * Returns true if we're processing an error.
0376:             */
0377:            public boolean hasError() {
0378:                return _hasError;
0379:            }
0380:
0381:            /**
0382:             * Sets the cache entry so we can use it if the servlet returns
0383:             * not_modified response.
0384:             *
0385:             * @param entry the saved cache entry
0386:             */
0387:            public void setMatchCacheEntry(AbstractCacheEntry entry) {
0388:                _matchCacheEntry = entry;
0389:            }
0390:
0391:            /**
0392:             * Sets the cache invocation to indicate that the response might be
0393:             * cacheable.
0394:             */
0395:            public void setCacheInvocation(
0396:                    AbstractCacheFilterChain cacheInvocation) {
0397:                AbstractCacheFilterChain oldCache = _cacheInvocation;
0398:                _cacheInvocation = null;
0399:
0400:                AbstractCacheEntry oldEntry = _newCacheEntry;
0401:                _newCacheEntry = null;
0402:
0403:                if (oldEntry != null)
0404:                    oldCache.killCaching(oldEntry);
0405:
0406:                _cacheInvocation = cacheInvocation;
0407:            }
0408:
0409:            public void setTopCache(boolean isTopCache) {
0410:                _isTopCache = isTopCache;
0411:            }
0412:
0413:            public void setStatus(int code) {
0414:                setStatus(code, null);
0415:            }
0416:
0417:            public void setStatus(int code, String message) {
0418:                if (code < 0)
0419:                    code = 500;
0420:
0421:                if (message != null) {
0422:                } else if (code == SC_OK)
0423:                    message = "OK";
0424:
0425:                else if (code == SC_NOT_MODIFIED)
0426:                    message = "Not Modified";
0427:
0428:                else if (message == null) {
0429:                    message = (String) _errors.get(String.valueOf(code));
0430:
0431:                    if (message == null)
0432:                        message = L.l("Internal Server Error");
0433:                }
0434:
0435:                _statusCode = code;
0436:                _statusMessage = message;
0437:            }
0438:
0439:            public int getStatusCode() {
0440:                return _statusCode;
0441:            }
0442:
0443:            public void sendError(int code) throws IOException {
0444:                sendError(code, null);
0445:            }
0446:
0447:            /**
0448:             * Sends an HTTP error to the browser.
0449:             *
0450:             * @param code the HTTP error code
0451:             * @param value a string message
0452:             */
0453:            public void sendError(int code, String value) throws IOException {
0454:                if (code == SC_NOT_MODIFIED && _matchCacheEntry != null) {
0455:                    setStatus(code, value);
0456:                    if (handleNotModified(_isTopCache))
0457:                        return;
0458:                }
0459:
0460:                if (isCommitted())
0461:                    throw new IllegalStateException(
0462:                            L
0463:                                    .l("sendError() forbidden after buffer has been committed."));
0464:
0465:                //_currentWriter = null;
0466:                //setStream(_originalStream);
0467:                resetBuffer();
0468:
0469:                if (code != SC_NOT_MODIFIED)
0470:                    killCache();
0471:
0472:                /* XXX: if we've already got an error, won't this just mask it?
0473:                if (responseStream.isCommitted())
0474:                  throw new IllegalStateException("response can't sendError() after commit");
0475:                 */
0476:
0477:                WebApp app = getRequest().getWebApp();
0478:
0479:                ErrorPageManager errorManager = null;
0480:                if (app != null)
0481:                    errorManager = app.getErrorPageManager();
0482:
0483:                setStatus(code, value);
0484:                try {
0485:                    if (code == SC_NOT_MODIFIED || code == SC_NO_CONTENT) {
0486:                        finish();
0487:                        return;
0488:                    } else if (errorManager != null) {
0489:                        errorManager.sendError(getOriginalRequest(), this ,
0490:                                code, _statusMessage);
0491:                        // _request.killKeepalive();
0492:                        // close, but don't force a flush
0493:                        // XXX: finish(false);
0494:                        finish();
0495:                        return;
0496:                    }
0497:
0498:                    setContentType("text/html");
0499:                    ServletOutputStream s = getOutputStream();
0500:
0501:                    s.println("<html>");
0502:                    if (!isCommitted()) {
0503:                        s.print("<head><title>");
0504:                        s.print(code);
0505:                        s.print(" ");
0506:                        s.print(_statusMessage);
0507:                        s.println("</title></head>");
0508:                    }
0509:                    s.println("<body>");
0510:
0511:                    s.print("<h1>");
0512:                    s.print(code);
0513:                    s.print(" ");
0514:                    s.print(_statusMessage);
0515:                    s.println("</h1>");
0516:
0517:                    if (code == HttpServletResponse.SC_NOT_FOUND) {
0518:                        s.println(L
0519:                                .l("{0} was not found on this server.",
0520:                                        HTTPUtil.encodeString(getRequest()
0521:                                                .getPageURI())));
0522:                    } else if (code == HttpServletResponse.SC_SERVICE_UNAVAILABLE) {
0523:                        s
0524:                                .println(L
0525:                                        .l("The server is temporarily unavailable due to maintenance downtime or excessive load."));
0526:                    }
0527:
0528:                    String version = null;
0529:
0530:                    if (app == null) {
0531:                    } else if (app.getServer() != null
0532:                            && app.getServer().getServerHeader() != null) {
0533:                        version = app.getServer().getServerHeader();
0534:                    } else if (CauchoSystem.isTesting()) {
0535:                    } else
0536:                        version = com.caucho.Version.FULL_VERSION;
0537:
0538:                    if (version != null) {
0539:                        s.println("<p /><hr />");
0540:                        s.println("<small>");
0541:
0542:                        s.println(version);
0543:
0544:                        s.println("</small>");
0545:                    }
0546:
0547:                    s.println("</body></html>");
0548:                } catch (Exception e) {
0549:                    log.log(Level.FINE, e.toString(), e);
0550:                }
0551:
0552:                _request.killKeepalive();
0553:                // close, but don't force a flush
0554:                finish();
0555:            }
0556:
0557:            /**
0558:             * Sends a redirect to the browser.  If the URL is relative, it gets
0559:             * combined with the current url.
0560:             *
0561:             * @param url the possibly relative url to send to the browser
0562:             */
0563:            public void sendRedirect(String url) throws IOException {
0564:                if (url == null)
0565:                    throw new NullPointerException();
0566:
0567:                if (_originalResponseStream.isCommitted())
0568:                    throw new IllegalStateException(
0569:                            L
0570:                                    .l("Can't sendRedirect() after data has committed to the client."));
0571:
0572:                _responseStream.clearBuffer();
0573:                _originalResponseStream.clearBuffer();
0574:
0575:                _responseStream = _originalResponseStream;
0576:                resetBuffer();
0577:
0578:                setStatus(SC_MOVED_TEMPORARILY);
0579:                String path = getAbsolutePath(url);
0580:
0581:                CharBuffer cb = new CharBuffer();
0582:
0583:                for (int i = 0; i < path.length(); i++) {
0584:                    char ch = path.charAt(i);
0585:
0586:                    if (ch == '<')
0587:                        cb.append("%3c");
0588:                    else
0589:                        cb.append(ch);
0590:                }
0591:
0592:                path = cb.toString();
0593:
0594:                setHeader("Location", path);
0595:                setHeader("Content-Type", "text/html");
0596:
0597:                // The data is required for some WAP devices that can't handle an
0598:                // empty response.
0599:                ServletOutputStream out = getOutputStream();
0600:                out.println("The URL has moved <a href=\"" + path
0601:                        + "\">here</a>");
0602:                // closeConnection();
0603:
0604:                if (_request instanceof  AbstractHttpRequest) {
0605:                    AbstractHttpRequest request = (AbstractHttpRequest) _request;
0606:
0607:                    request.saveSession(); // #503
0608:                }
0609:
0610:                close();
0611:            }
0612:
0613:            /**
0614:             * Switch to raw socket mode.
0615:             */
0616:            public void switchToRaw() throws IOException {
0617:                throw new UnsupportedOperationException(L
0618:                        .l("raw mode is not supported in this configuration"));
0619:            }
0620:
0621:            /**
0622:             * Switch to raw socket mode.
0623:             */
0624:            public WriteStream getRawOutput() throws IOException {
0625:                throw new UnsupportedOperationException(L
0626:                        .l("raw mode is not supported in this configuration"));
0627:            }
0628:
0629:            /**
0630:             * Returns the absolute path for a given relative path.
0631:             *
0632:             * @param path the possibly relative url to send to the browser
0633:             */
0634:            private String getAbsolutePath(String path) {
0635:                int slash = path.indexOf('/');
0636:
0637:                int len = path.length();
0638:
0639:                for (int i = 0; i < len; i++) {
0640:                    char ch = path.charAt(i);
0641:
0642:                    if (ch == ':')
0643:                        return path;
0644:                    else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')
0645:                        continue;
0646:                    else
0647:                        break;
0648:                }
0649:
0650:                WebApp app = getRequest().getWebApp();
0651:
0652:                String hostPrefix = null;
0653:                String host = _request.getHeader("Host");
0654:                String serverName = app.getHostName();
0655:
0656:                if (serverName == null || serverName.equals(""))
0657:                    serverName = _request.getServerName();
0658:
0659:                int port = _request.getServerPort();
0660:
0661:                if (hostPrefix != null && !hostPrefix.equals("")) {
0662:                } else if (serverName.startsWith("http:")
0663:                        || serverName.startsWith("https:"))
0664:                    hostPrefix = serverName;
0665:                else if (host != null) {
0666:                    hostPrefix = _request.getScheme() + "://" + host;
0667:                } else {
0668:                    hostPrefix = _request.getScheme() + "://" + serverName;
0669:
0670:                    if (serverName.indexOf(':') < 0 && port != 0 && port != 80
0671:                            && port != 443)
0672:                        hostPrefix += ":" + port;
0673:                }
0674:
0675:                if (slash == 0)
0676:                    return hostPrefix + path;
0677:
0678:                String uri = _request.getRequestURI();
0679:                String queryString = null;
0680:
0681:                int p = path.indexOf('?');
0682:                if (p > 0) {
0683:                    queryString = path.substring(p + 1);
0684:                    path = path.substring(0, p);
0685:                }
0686:
0687:                p = uri.lastIndexOf('/');
0688:
0689:                if (p >= 0)
0690:                    path = uri.substring(0, p + 1) + path;
0691:
0692:                try {
0693:                    if (queryString != null)
0694:                        return hostPrefix
0695:                                + InvocationDecoder.normalizeUri(path) + '?'
0696:                                + queryString;
0697:                    else
0698:                        return hostPrefix
0699:                                + InvocationDecoder.normalizeUri(path);
0700:                } catch (IOException e) {
0701:                    throw new RuntimeException(e);
0702:                }
0703:            }
0704:
0705:            /**
0706:             * Returns true if the response already contains the named header.
0707:             *
0708:             * @param name name of the header to test.
0709:             */
0710:            public boolean containsHeader(String name) {
0711:                for (int i = 0; i < _headerKeys.size(); i++) {
0712:                    String oldKey = _headerKeys.get(i);
0713:
0714:                    if (oldKey.equalsIgnoreCase(name))
0715:                        return true;
0716:                }
0717:
0718:                if (name.equalsIgnoreCase("content-type"))
0719:                    return _contentType != null;
0720:
0721:                if (name.equalsIgnoreCase("content-length"))
0722:                    return _contentLength >= 0;
0723:
0724:                return false;
0725:            }
0726:
0727:            /**
0728:             * Returns the value of an already set output header.
0729:             *
0730:             * @param name name of the header to get.
0731:             */
0732:            public String getHeader(String name) {
0733:                for (int i = 0; i < _headerKeys.size(); i++) {
0734:                    String oldKey = (String) _headerKeys.get(i);
0735:
0736:                    if (oldKey.equalsIgnoreCase(name))
0737:                        return (String) _headerValues.get(i);
0738:                }
0739:
0740:                if (name.equalsIgnoreCase("content-type"))
0741:                    return _contentType;
0742:
0743:                if (name.equalsIgnoreCase("content-length"))
0744:                    return _contentLength >= 0 ? String.valueOf(_contentLength)
0745:                            : null;
0746:
0747:                return null;
0748:            }
0749:
0750:            /**
0751:             * Sets a header, replacing an already-existing header.
0752:             *
0753:             * @param key the header key to set.
0754:             * @param value the header value to set.
0755:             */
0756:            public void setHeader(String key, String value) {
0757:                if (_disableHeaders)
0758:                    return;
0759:                else if (value == null)
0760:                    throw new NullPointerException();
0761:
0762:                if (setSpecial(key, value))
0763:                    return;
0764:
0765:                int i = 0;
0766:                boolean hasHeader = false;
0767:
0768:                for (i = _headerKeys.size() - 1; i >= 0; i--) {
0769:                    String oldKey = _headerKeys.get(i);
0770:
0771:                    if (oldKey.equalsIgnoreCase(key)) {
0772:                        if (hasHeader) {
0773:                            _headerKeys.remove(i);
0774:                            _headerValues.remove(i);
0775:                        } else {
0776:                            hasHeader = true;
0777:
0778:                            _headerValues.set(i, value);
0779:                        }
0780:                    }
0781:                }
0782:
0783:                if (!hasHeader) {
0784:                    _headerKeys.add(key);
0785:                    _headerValues.add(value);
0786:                }
0787:            }
0788:
0789:            /**
0790:             * Adds a new header.  If an old header with that name exists,
0791:             * both headers are output.
0792:             *
0793:             * @param key the header key.
0794:             * @param value the header value.
0795:             */
0796:            public void addHeader(String key, String value) {
0797:                if (_disableHeaders)
0798:                    return;
0799:
0800:                if (setSpecial(key, value))
0801:                    return;
0802:
0803:                _headerKeys.add(key);
0804:                _headerValues.add(value);
0805:            }
0806:
0807:            /**
0808:             * Special processing for a special value.
0809:             */
0810:            protected boolean setSpecial(String key, String value) {
0811:                int length = key.length();
0812:                if (256 <= length)
0813:                    return false;
0814:
0815:                key.getChars(0, length, _headerBuffer, 0);
0816:
0817:                switch (_headerCodes.get(_headerBuffer, length)) {
0818:                case HEADER_CACHE_CONTROL:
0819:                    if (value.startsWith("max-age")) {
0820:                    } else if (value.equals("x-anonymous")) {
0821:                    } else
0822:                        _hasCacheControl = true;
0823:                    return false;
0824:
0825:                case HEADER_CONNECTION:
0826:                    if ("close".equalsIgnoreCase(value))
0827:                        _request.killKeepalive();
0828:                    return true;
0829:
0830:                case HEADER_CONTENT_TYPE:
0831:                    setContentType(value);
0832:                    return true;
0833:
0834:                case HEADER_CONTENT_LENGTH:
0835:                    _contentLength = Long.parseLong(value);
0836:                    return true;
0837:
0838:                case HEADER_DATE:
0839:                    return true;
0840:
0841:                case HEADER_SERVER:
0842:                    return false;
0843:
0844:                default:
0845:                    return false;
0846:                }
0847:            }
0848:
0849:            public void removeHeader(String key) {
0850:                if (_disableHeaders)
0851:                    return;
0852:
0853:                for (int i = _headerKeys.size() - 1; i >= 0; i--) {
0854:                    String oldKey = (String) _headerKeys.get(i);
0855:
0856:                    if (oldKey.equalsIgnoreCase(key)) {
0857:                        _headerKeys.remove(i);
0858:                        _headerValues.remove(i);
0859:                        return;
0860:                    }
0861:                }
0862:            }
0863:
0864:            /**
0865:             * Convenience for setting an integer header.  An old header with the
0866:             * same name will be replaced.
0867:             *
0868:             * @param name the header name.
0869:             * @param value an integer to be converted to a string for the header.
0870:             */
0871:            public void setIntHeader(String name, int value) {
0872:                _cb.clear();
0873:                _cb.append(value);
0874:                setHeader(name, _cb.toString());
0875:            }
0876:
0877:            /**
0878:             * Convenience for adding an integer header.  If an old header already
0879:             * exists, both will be sent to the browser.
0880:             *
0881:             * @param key the header name.
0882:             * @param value an integer to be converted to a string for the header.
0883:             */
0884:            public void addIntHeader(String key, int value) {
0885:                _cb.clear();
0886:                _cb.append(value);
0887:                addHeader(key, _cb.toString());
0888:            }
0889:
0890:            /**
0891:             * Convenience for setting a date header.  An old header with the
0892:             * same name will be replaced.
0893:             *
0894:             * @param name the header name.
0895:             * @param value an time in milliseconds to be converted to a date string.
0896:             */
0897:            public void setDateHeader(String name, long value) {
0898:                _calendar.setGMTTime(value);
0899:
0900:                setHeader(name, _calendar.printDate());
0901:            }
0902:
0903:            /**
0904:             * Convenience for adding a date header.  If an old header with the
0905:             * same name exists, both will be displayed.
0906:             *
0907:             * @param key the header name.
0908:             * @param value an time in milliseconds to be converted to a date string.
0909:             */
0910:            public void addDateHeader(String key, long value) {
0911:                _calendar.setGMTTime(value);
0912:
0913:                addHeader(key, _calendar.printDate());
0914:            }
0915:
0916:            /**
0917:             * Sets the content length of the result.  In general, Resin will handle
0918:             * the content length, but for things like long downloads adding the
0919:             * length will give a valuable hint to the browser.
0920:             *
0921:             * @param length the length of the content.
0922:             */
0923:            public void setContentLength(int length) {
0924:                _contentLength = length;
0925:            }
0926:
0927:            /**
0928:             * Returns the value of the content-length header.
0929:             */
0930:            public long getContentLengthHeader() {
0931:                return _contentLength;
0932:            }
0933:
0934:            /**
0935:             * Sets the browser content type.  If the value contains a charset,
0936:             * the output encoding will be changed to match.
0937:             *
0938:             * <p>For example, to set the output encoding to use UTF-8 instead of
0939:             * the default ISO-8859-1 (Latin-1), use the following:
0940:             * <code><pre>
0941:             * setContentType("text/html; charset=UTF-8");
0942:             * </pre></code>
0943:             */
0944:            public void setContentType(String value) {
0945:                if (isCommitted())
0946:                    return;
0947:
0948:                if (_disableHeaders || value == null) {
0949:                    _contentType = null;
0950:                    return;
0951:                } else if (value == "text/html" || value.equals("text/html")) {
0952:                    _contentType = "text/html";
0953:                    return;
0954:                }
0955:
0956:                _contentType = value;
0957:
0958:                int length = value.length();
0959:                int i;
0960:                int ch;
0961:
0962:                for (i = 0; i < length && value.charAt(i) != ';'
0963:                        && !Character.isWhitespace(value.charAt(i)); i++) {
0964:                }
0965:
0966:                if (i < length)
0967:                    _contentPrefix = _contentType.substring(0, i);
0968:                else
0969:                    _contentPrefix = _contentType;
0970:
0971:                while ((i = value.indexOf(';', i)) > 0) {
0972:                    int semicolon = i;
0973:                    for (i++; i < length
0974:                            && XmlChar.isWhitespace(value.charAt(i)); i++) {
0975:                    }
0976:
0977:                    int j;
0978:                    for (j = i + 1; j < length
0979:                            && !XmlChar.isWhitespace((ch = value.charAt(j)))
0980:                            && ch != '='; j++) {
0981:                    }
0982:
0983:                    if (length <= j)
0984:                        break;
0985:                    else if ((ch = value.charAt(i)) != 'c' && ch != 'C') {
0986:                    } else if (value.substring(i, j)
0987:                            .equalsIgnoreCase("charset")) {
0988:                        for (; j < length
0989:                                && XmlChar.isWhitespace(value.charAt(j)); j++) {
0990:                        }
0991:
0992:                        if (length <= j || value.charAt(j) != '=')
0993:                            continue;
0994:
0995:                        for (j++; j < length
0996:                                && XmlChar.isWhitespace(value.charAt(j)); j++) {
0997:                        }
0998:
0999:                        String encoding;
1000:
1001:                        if (j < length && value.charAt(j) == '"') {
1002:                            int k = ++j;
1003:
1004:                            for (; j < length && value.charAt(j) != '"'; j++) {
1005:                            }
1006:
1007:                            encoding = value.substring(k, j);
1008:                        } else {
1009:                            int k = j;
1010:                            for (k = j; j < length
1011:                                    && !XmlChar.isWhitespace(ch = value
1012:                                            .charAt(j)) && ch != ';'; j++) {
1013:                            }
1014:
1015:                            encoding = value.substring(k, j);
1016:                        }
1017:
1018:                        int tail = value.indexOf(';', semicolon + 1);
1019:
1020:                        StringBuilder sb = new StringBuilder();
1021:                        sb.append(value, 0, semicolon);
1022:                        if (tail > 0)
1023:                            sb.append(value, tail, value.length());
1024:
1025:                        _contentType = sb.toString();
1026:
1027:                        if (!_hasWriter) {
1028:                            _hasCharEncoding = true;
1029:                            _charEncoding = encoding;
1030:                        }
1031:                        break;
1032:                    } else
1033:                        i = j;
1034:                }
1035:
1036:                // XXX: conflict with servlet exception throwing order?
1037:                try {
1038:                    _responseStream.setEncoding(_charEncoding);
1039:                } catch (Exception e) {
1040:                    log.log(Level.WARNING, e.toString(), e);
1041:                }
1042:            }
1043:
1044:            /**
1045:             * Gets the content type.
1046:             */
1047:            public String getContentType() {
1048:                if (_contentType == null)
1049:                    return null;
1050:
1051:                String charEncoding = getCharacterEncoding();
1052:
1053:                if (charEncoding != null)
1054:                    return _contentType + "; charset=" + charEncoding;
1055:                else
1056:                    return _contentType;
1057:            }
1058:
1059:            /**
1060:             * Gets the character encoding.
1061:             */
1062:            public String getCharacterEncoding() {
1063:                if (_charEncoding != null)
1064:                    return _charEncoding;
1065:
1066:                WebApp app = _request.getWebApp();
1067:
1068:                String encoding = null;
1069:
1070:                if (app != null)
1071:                    encoding = app.getCharacterEncoding();
1072:
1073:                if (encoding != null)
1074:                    return encoding;
1075:                else
1076:                    return "iso-8859-1";
1077:            }
1078:
1079:            /**
1080:             * Sets the character encoding.
1081:             */
1082:            public void setCharacterEncoding(String encoding) {
1083:                if (isCommitted())
1084:                    return;
1085:                if (_hasWriter)
1086:                    return;
1087:
1088:                _hasCharEncoding = true;
1089:                if (encoding == null || encoding.equals("ISO-8859-1")
1090:                        || encoding.equals("")) {
1091:                    encoding = null;
1092:                    _charEncoding = "iso-8859-1";
1093:                } else
1094:                    _charEncoding = encoding;
1095:
1096:                try {
1097:                    _responseStream.setEncoding(encoding);
1098:                } catch (Exception e) {
1099:                    log.log(Level.WARNING, e.toString(), e);
1100:                }
1101:            }
1102:
1103:            String getRealCharacterEncoding() {
1104:                return _charEncoding;
1105:            }
1106:
1107:            /**
1108:             * Adds a cookie to the response.
1109:             *
1110:             * @param cookie the response cookie
1111:             */
1112:            public void addCookie(Cookie cookie) {
1113:                _request.setHasCookie();
1114:
1115:                if (_disableHeaders)
1116:                    return;
1117:
1118:                if (cookie == null)
1119:                    return;
1120:
1121:                _cookiesOut.add(cookie);
1122:            }
1123:
1124:            public Cookie getCookie(String name) {
1125:                if (_cookiesOut == null)
1126:                    return null;
1127:
1128:                for (int i = _cookiesOut.size() - 1; i >= 0; i--) {
1129:                    Cookie cookie = (Cookie) _cookiesOut.get(i);
1130:
1131:                    if (cookie.getName().equals(name))
1132:                        return cookie;
1133:                }
1134:
1135:                return null;
1136:            }
1137:
1138:            public ArrayList getCookies() {
1139:                return _cookiesOut;
1140:            }
1141:
1142:            public void setSessionId(String id) {
1143:                _sessionId = id;
1144:
1145:                // XXX: server/1315 vs server/0506 vs server/170k
1146:                // could also set the nocache=JSESSIONID
1147:                setPrivateOrResinCache(true);
1148:            }
1149:
1150:            /**
1151:             * Sets a footer, replacing an already-existing footer
1152:             *
1153:             * @param key the header key to set.
1154:             * @param value the header value to set.
1155:             */
1156:            public void setFooter(String key, String value) {
1157:                if (_disableHeaders)
1158:                    return;
1159:                else if (value == null)
1160:                    throw new NullPointerException();
1161:
1162:                int i = 0;
1163:                boolean hasFooter = false;
1164:
1165:                for (i = _footerKeys.size() - 1; i >= 0; i--) {
1166:                    String oldKey = _footerKeys.get(i);
1167:
1168:                    if (oldKey.equalsIgnoreCase(key)) {
1169:                        if (hasFooter) {
1170:                            _footerKeys.remove(i);
1171:                            _footerValues.remove(i);
1172:                        } else {
1173:                            hasFooter = true;
1174:
1175:                            _footerValues.set(i, value);
1176:                        }
1177:                    }
1178:                }
1179:
1180:                if (!hasFooter) {
1181:                    _footerKeys.add(key);
1182:                    _footerValues.add(value);
1183:                }
1184:            }
1185:
1186:            /**
1187:             * Adds a new footer.  If an old footer with that name exists,
1188:             * both footers are output.
1189:             *
1190:             * @param key the footer key.
1191:             * @param value the footer value.
1192:             */
1193:            public void addFooter(String key, String value) {
1194:                if (_disableHeaders)
1195:                    return;
1196:
1197:                if (setSpecial(key, value))
1198:                    return;
1199:
1200:                _footerKeys.add(key);
1201:                _footerValues.add(value);
1202:            }
1203:
1204:            /**
1205:             * Sets the ResponseStream
1206:             */
1207:            public void setResponseStream(AbstractResponseStream responseStream) {
1208:                _responseStream = responseStream;
1209:
1210:                _responseOutputStream.init(responseStream);
1211:                _responsePrintWriter.init(responseStream);
1212:            }
1213:
1214:            /**
1215:             * Gets the response stream.
1216:             */
1217:            public AbstractResponseStream getResponseStream() {
1218:                return _responseStream;
1219:            }
1220:
1221:            /**
1222:             * Gets the response stream.
1223:             */
1224:            public AbstractResponseStream getOriginalStream() {
1225:                return _originalResponseStream;
1226:            }
1227:
1228:            /**
1229:             * Returns true for a Caucho response stream.
1230:             */
1231:            public boolean isCauchoResponseStream() {
1232:                return _responseStream.isCauchoResponseStream();
1233:            }
1234:
1235:            /**
1236:             * Returns the ServletOutputStream for the response.
1237:             */
1238:            public ServletOutputStream getOutputStream() throws IOException {
1239:                /*
1240:                if (_hasWriter)
1241:                  throw new IllegalStateException(L.l("getOutputStream() can't be called after getWriter()."));
1242:                 */
1243:
1244:                _hasOutputStream = true;
1245:
1246:                /*
1247:                // server/10a2
1248:                if (! _hasWriter) {
1249:                  // jsp/0510 vs jsp/1b00
1250:                  // _responseStream.setOutputStreamOnly(true);
1251:                }
1252:                 */
1253:
1254:                return _responseOutputStream;
1255:            }
1256:
1257:            /**
1258:             * Sets the flush buffer
1259:             */
1260:            public void setFlushBuffer(FlushBuffer flushBuffer) {
1261:                _flushBuffer = flushBuffer;
1262:            }
1263:
1264:            /**
1265:             * Gets the flush buffer
1266:             */
1267:            public FlushBuffer getFlushBuffer() {
1268:                return _flushBuffer;
1269:            }
1270:
1271:            /**
1272:             * Returns a PrintWriter for the response.
1273:             */
1274:            public PrintWriter getWriter() throws IOException {
1275:                /*
1276:                if (_hasOutputStream)
1277:                  throw new IllegalStateException(L.l("getWriter() can't be called after getOutputStream()."));
1278:                 */
1279:
1280:                if (!_hasWriter) {
1281:                    _hasWriter = true;
1282:
1283:                    if (_charEncoding != null)
1284:                        _responseStream.setEncoding(_charEncoding);
1285:                }
1286:
1287:                return _responsePrintWriter;
1288:            }
1289:
1290:            /**
1291:             * Returns the parent writer.
1292:             */
1293:            public PrintWriter getNextWriter() {
1294:                return null;
1295:            }
1296:
1297:            /**
1298:             * Encode the URL with the session jd.
1299:             *
1300:             * @param string the url to be encoded
1301:             *
1302:             * @return the encoded url
1303:             */
1304:            public String encodeURL(String string) {
1305:                CauchoRequest request = getRequest();
1306:
1307:                WebApp app = request.getWebApp();
1308:
1309:                if (app == null)
1310:                    return string;
1311:
1312:                if (request.isRequestedSessionIdFromCookie())
1313:                    return string;
1314:
1315:                HttpSession session = request.getSession(false);
1316:                if (session == null)
1317:                    return string;
1318:
1319:                SessionManager sessionManager = app.getSessionManager();
1320:                if (!sessionManager.enableSessionUrls())
1321:                    return string;
1322:
1323:                CharBuffer cb = _cb;
1324:                cb.clear();
1325:
1326:                String altPrefix = sessionManager.getAlternateSessionPrefix();
1327:
1328:                if (altPrefix == null) {
1329:                    // standard url rewriting
1330:                    int p = string.indexOf('?');
1331:
1332:                    if (p == 0) {
1333:                        cb.append(string);
1334:                    } else if (p > 0) {
1335:                        cb.append(string, 0, p);
1336:                        cb.append(sessionManager.getSessionPrefix());
1337:                        cb.append(session.getId());
1338:                        cb.append(string, p, string.length() - p);
1339:                    } else if ((p = string.indexOf('#')) >= 0) {
1340:                        cb.append(string, 0, p);
1341:                        cb.append(sessionManager.getSessionPrefix());
1342:                        cb.append(session.getId());
1343:                        cb.append(string, p, string.length() - p);
1344:                    } else {
1345:                        cb.append(string);
1346:                        cb.append(sessionManager.getSessionPrefix());
1347:                        cb.append(session.getId());
1348:                    }
1349:                } else {
1350:                    int p = string.indexOf("://");
1351:
1352:                    if (p < 0) {
1353:                        cb.append(altPrefix);
1354:                        cb.append(session.getId());
1355:
1356:                        if (!string.startsWith("/")) {
1357:                            cb.append(_request.getContextPath());
1358:                            cb.append('/');
1359:                        }
1360:                        cb.append(string);
1361:                    } else {
1362:                        int q = string.indexOf('/', p + 3);
1363:
1364:                        if (q < 0) {
1365:                            cb.append(string);
1366:                            cb.append(altPrefix);
1367:                            cb.append(session.getId());
1368:                        } else {
1369:                            cb.append(string.substring(0, q));
1370:                            cb.append(altPrefix);
1371:                            cb.append(session.getId());
1372:                            cb.append(string.substring(q));
1373:                        }
1374:                    }
1375:                }
1376:
1377:                return cb.toString();
1378:            }
1379:
1380:            public String encodeRedirectURL(String string) {
1381:                return encodeURL(string);
1382:            }
1383:
1384:            /**
1385:             * @deprecated
1386:             */
1387:            public String encodeRedirectUrl(String string) {
1388:                return encodeRedirectURL(string);
1389:            }
1390:
1391:            /**
1392:             * @deprecated
1393:             */
1394:            public String encodeUrl(String string) {
1395:                return encodeURL(string);
1396:            }
1397:
1398:            /*
1399:             * jsdk 2.2
1400:             */
1401:
1402:            public void setBufferSize(int size) {
1403:                _responseStream.setBufferSize(size);
1404:            }
1405:
1406:            public int getBufferSize() {
1407:                return _responseStream.getBufferSize();
1408:            }
1409:
1410:            public void flushBuffer() throws IOException {
1411:                // server/10sn
1412:                _responseStream.flush();
1413:            }
1414:
1415:            public void flushHeader() throws IOException {
1416:                _responseStream.flushBuffer();
1417:            }
1418:
1419:            public void setDisableAutoFlush(boolean disable) {
1420:                // XXX: _responseStream.setDisableAutoFlush(disable);
1421:            }
1422:
1423:            /**
1424:             * Returns true if some data has been sent to the browser.
1425:             */
1426:            public boolean isCommitted() {
1427:                return _originalResponseStream.isCommitted();
1428:            }
1429:
1430:            public void reset() {
1431:                reset(false);
1432:            }
1433:
1434:            public void resetBuffer() {
1435:                _responseStream.clearBuffer();
1436:                /*
1437:                if (_currentWriter instanceof JspPrintWriter)
1438:                  ((JspPrintWriter) _currentWriter).clear();
1439:                 */
1440:            }
1441:
1442:            /**
1443:             * Clears the response for a forward()
1444:             *
1445:             * @param force if not true and the response stream has committed,
1446:             *   throw the IllegalStateException.
1447:             */
1448:            void reset(boolean force) {
1449:                if (!force && _originalResponseStream.isCommitted())
1450:                    throw new IllegalStateException(L
1451:                            .l("response cannot be reset() after committed"));
1452:
1453:                _responseStream.clearBuffer();
1454:                /*
1455:                if (_currentWriter instanceof JspPrintWriter)
1456:                  ((JspPrintWriter) _currentWriter).clear();
1457:                 */
1458:                _statusCode = 200;
1459:                _statusMessage = "OK";
1460:
1461:                _headerKeys.clear();
1462:                _headerValues.clear();
1463:
1464:                // cookiesOut.clear();
1465:
1466:                _contentLength = -1;
1467:                //_isNoCache = false;
1468:                //_isPrivateCache = false;
1469:
1470:                _charEncoding = null;
1471:                _locale = null;
1472:
1473:                _hasOutputStream = false;
1474:                _hasWriter = false;
1475:                try {
1476:                    _responseStream.setLocale(null);
1477:                    _responseStream.setEncoding(null);
1478:                } catch (Exception e) {
1479:                }
1480:            }
1481:
1482:            // XXX: hack to deal with forwarding
1483:            public void clearBuffer() {
1484:                _responseStream.clearBuffer();
1485:            }
1486:
1487:            public void setLocale(Locale locale) {
1488:                _locale = locale;
1489:
1490:                if (!_hasCharEncoding && !isCommitted()) {
1491:                    _charEncoding = getRequest().getWebApp().getLocaleEncoding(
1492:                            locale);
1493:
1494:                    try {
1495:                        if (_charEncoding != null) {
1496:                            // _originalStream.setEncoding(_charEncoding);
1497:                            _responseStream.setEncoding(_charEncoding);
1498:                        }
1499:                    } catch (IOException e) {
1500:                    }
1501:                }
1502:
1503:                CharBuffer cb = _cb;
1504:                cb.clear();
1505:                cb.append(locale.getLanguage());
1506:                if (locale.getCountry() != null
1507:                        && !"".equals(locale.getCountry())) {
1508:                    cb.append("-");
1509:                    cb.append(locale.getCountry());
1510:                    if (locale.getVariant() != null
1511:                            && !"".equals(locale.getVariant())) {
1512:                        cb.append("-");
1513:                        cb.append(locale.getVariant());
1514:                    }
1515:                }
1516:
1517:                setHeader("Content-Language", cb.toString());
1518:            }
1519:
1520:            public Locale getLocale() {
1521:                if (_locale != null)
1522:                    return _locale;
1523:                else
1524:                    return Locale.getDefault();
1525:            }
1526:
1527:            // needed to support JSP
1528:
1529:            public int getRemaining() {
1530:                return _responseStream.getRemaining();
1531:            }
1532:
1533:            /**
1534:             * Returns the number of bytes sent to the output.
1535:             */
1536:            public int getContentLength() {
1537:                return _originalResponseStream.getContentLength();
1538:            }
1539:
1540:            public boolean disableHeaders(boolean disable) {
1541:                boolean old = _disableHeaders;
1542:                _disableHeaders = disable;
1543:                return old;
1544:            }
1545:
1546:            public boolean disableCaching(boolean disable) {
1547:                boolean old = _disableCaching;
1548:                _disableCaching = disable;
1549:                return old;
1550:            }
1551:
1552:            /**
1553:             * Returns true if the headers have been written.
1554:             */
1555:            final public boolean isHeaderWritten() {
1556:                return _isHeaderWritten;
1557:            }
1558:
1559:            /**
1560:             * Returns true if the headers have been written.
1561:             */
1562:            final public void setHeaderWritten(boolean isWritten) {
1563:                _isHeaderWritten = isWritten;
1564:            }
1565:
1566:            /**
1567:             * Writes the continue
1568:             */
1569:            final void writeContinue() throws IOException {
1570:                if (!_isHeaderWritten) {
1571:                    writeContinueInt(_rawWrite);
1572:                    _rawWrite.flush();
1573:                }
1574:            }
1575:
1576:            /**
1577:             * Writes the continue
1578:             */
1579:            protected void writeContinueInt(WriteStream os) throws IOException {
1580:            }
1581:
1582:            /**
1583:             * Writes the headers to the stream.  Called prior to the first flush
1584:             * of data.
1585:             *
1586:             * @param os browser stream.
1587:             * @param length length of the response if known, or -1 is unknown.
1588:             * @return true if the content is chunked.
1589:             */
1590:            protected boolean writeHeaders(WriteStream os, int length)
1591:                    throws IOException {
1592:                if (_isHeaderWritten)
1593:                    return _isChunked;
1594:
1595:                // server/1373 for getBufferSize()
1596:                boolean canCache = startCaching(true);
1597:                _isHeaderWritten = true;
1598:
1599:                if (_request.getMethod().equals("HEAD")) {
1600:                    _originalResponseStream.setHead();
1601:                }
1602:
1603:                WebApp webApp = _request.getWebApp();
1604:
1605:                int majorCode = _statusCode / 100;
1606:
1607:                if (webApp != null) {
1608:                    if (majorCode == 5)
1609:                        webApp.addStatus500();
1610:                }
1611:
1612:                HttpSession session = _originalRequest.getMemorySession();
1613:                if (session instanceof  SessionImpl)
1614:                    ((SessionImpl) session).saveBeforeHeaders();
1615:
1616:                if (_sessionId != null && !_hasSessionCookie) {
1617:                    _hasSessionCookie = true;
1618:
1619:                    SessionManager manager = webApp.getSessionManager();
1620:
1621:                    String cookieName;
1622:
1623:                    if (_request.isSecure())
1624:                        cookieName = manager.getSSLCookieName();
1625:                    else
1626:                        cookieName = manager.getCookieName();
1627:
1628:                    CookieImpl cookie = new CookieImpl(cookieName, _sessionId);
1629:                    cookie.setVersion(manager.getCookieVersion());
1630:                    String domain = manager.getCookieDomain();
1631:                    if (domain != null)
1632:                        cookie.setDomain(domain);
1633:                    long maxAge = manager.getCookieMaxAge();
1634:                    if (maxAge > 0)
1635:                        cookie.setMaxAge((int) (maxAge / 1000));
1636:                    cookie.setPath("/");
1637:
1638:                    cookie.setPort(manager.getCookiePort());
1639:                    if (manager.getCookieSecure()) {
1640:                        cookie.setSecure(_request.isSecure());
1641:                        /*
1642:                        else if (manager.getCookiePort() == null)
1643:                          cookie.setPort(String.valueOf(_request.getServerPort()));
1644:                         */
1645:                    }
1646:
1647:                    addCookie(cookie);
1648:                }
1649:
1650:                _isChunked = writeHeadersInt(os, length);
1651:
1652:                return _isChunked;
1653:            }
1654:
1655:            /**
1656:             * Called to start caching.
1657:             */
1658:            protected boolean startCaching(boolean isByte) {
1659:                if (_isHeaderWritten)
1660:                    return false;
1661:                _isHeaderWritten = true;
1662:
1663:                if (_statusCode == SC_OK && !_disableCaching) // && getBufferSize() > 0)
1664:                    return startCaching(_headerKeys, _headerValues,
1665:                            _contentType, _charEncoding, isByte);
1666:                else
1667:                    return false;
1668:            }
1669:
1670:            /**
1671:             * Tests to see if the response is cacheable.
1672:             *
1673:             * @param keys the header keys of the response
1674:             * @param values the header values of the response
1675:             * @param contentType the contentType of the response
1676:             * @param charEncoding the character encoding of the response
1677:             *
1678:             * @return true if caching has started
1679:             */
1680:            boolean startCaching(ArrayList<String> keys,
1681:                    ArrayList<String> values, String contentType,
1682:                    String charEncoding, boolean isByte) {
1683:                if (_cacheInvocation == null)
1684:                    return false;
1685:                /*
1686:                  // jsp/17ah
1687:                else if (_responseStream != _originalResponseStream) {
1688:                  return false;
1689:                }
1690:                 */
1691:                else if (!isCauchoResponseStream()) {
1692:                    return false;
1693:                } else if (!(_originalRequest instanceof  CauchoRequest)) {
1694:                    return false;
1695:                } else if (!_allowCache) {
1696:                    return false;
1697:                } else {
1698:                    CauchoRequest request = (CauchoRequest) _originalRequest;
1699:
1700:                    _newCacheEntry = _cacheInvocation.startCaching(request,
1701:                            this , keys, values, contentType, charEncoding,
1702:                            _contentLength);
1703:
1704:                    if (_newCacheEntry == null) {
1705:                        return false;
1706:                    } else if (isByte) {
1707:                        _cacheStream = _newCacheEntry.openOutputStream();
1708:
1709:                        if (_cacheStream != null)
1710:                            _originalResponseStream
1711:                                    .setByteCacheStream(_cacheStream);
1712:
1713:                        return _cacheStream != null;
1714:                    } else {
1715:                        _cacheWriter = _newCacheEntry.openWriter();
1716:
1717:                        if (_cacheWriter != null)
1718:                            _originalResponseStream
1719:                                    .setCharCacheStream(_cacheWriter);
1720:
1721:                        return _cacheWriter != null;
1722:                    }
1723:                }
1724:            }
1725:
1726:            /**
1727:             * Handle a SC_NOT_MODIFIED response.  If we've got a cache, fill the
1728:             * results from the cache.
1729:             *
1730:             * @param isTop if true, this is the top-level request.
1731:             *
1732:             * @return true if we filled from the cache
1733:             */
1734:            private boolean handleNotModified(boolean isTop) throws IOException {
1735:                if (_statusCode != SC_NOT_MODIFIED) {
1736:                    return false;
1737:                } else if (_matchCacheEntry != null) {
1738:                    if (_originalResponseStream.isCommitted())
1739:                        return false;
1740:
1741:                    // need to unclose because the not modified might be detected only
1742:                    // when flushing the data
1743:                    _originalResponseStream.clearClosed();
1744:                    _isClosed = false;
1745:
1746:                    /* XXX: complications with filters */
1747:                    if (_cacheInvocation != null
1748:                            && _cacheInvocation.fillFromCache(
1749:                                    (CauchoRequest) _originalRequest, this ,
1750:                                    _matchCacheEntry, isTop)) {
1751:                        _matchCacheEntry.updateExpiresDate();
1752:                        _cacheInvocation = null;
1753:                        _matchCacheEntry = null;
1754:
1755:                        finish(); // Don't force a flush to avoid extra TCP packet
1756:
1757:                        return true;
1758:                    }
1759:                }
1760:                // server/13dh
1761:                else if (_cacheInvocation != null) {
1762:                    CauchoRequest req = (CauchoRequest) _originalRequest;
1763:                    WebApp app = req.getWebApp();
1764:
1765:                    long maxAge = app.getMaxAge(req.getRequestURI());
1766:
1767:                    if (maxAge > 0 && !containsHeader("Expires")) {
1768:                        setDateHeader("Expires", maxAge
1769:                                + Alarm.getCurrentTime());
1770:                    }
1771:                }
1772:
1773:                return false;
1774:            }
1775:
1776:            abstract protected boolean writeHeadersInt(WriteStream os,
1777:                    int length) throws IOException;
1778:
1779:            /**
1780:             * Sets true if the cache is only for the browser, but not
1781:             * Resin's cache or proxies.
1782:             *
1783:             * <p>Since proxy caching also caches headers, cached pages with
1784:             * session ids can't be cached in the browser.
1785:             *
1786:             * XXX: but doesn't this just mean that Resin shouldn't
1787:             * send the session information back if the page is cached?
1788:             * Because a second request where everything is identical
1789:             * would see the same response except for the cookies.
1790:             */
1791:            public void setPrivateCache(boolean isPrivate) {
1792:                // XXX: let the webApp override this?
1793:                _isPrivateCache = isPrivate;
1794:
1795:                // server/12dm
1796:                _allowCache = false;
1797:            }
1798:
1799:            /**
1800:             * Sets true if the cache is only for the browser and 
1801:             * Resin's cache but not proxies.
1802:             */
1803:            public void setPrivateOrResinCache(boolean isPrivate) {
1804:                // XXX: let the webApp override this?
1805:
1806:                _isPrivateCache = isPrivate;
1807:            }
1808:
1809:            /**
1810:             * Returns the value of the private cache.
1811:             */
1812:            public boolean getPrivateCache() {
1813:                return _isPrivateCache;
1814:            }
1815:
1816:            /**
1817:             * Returns true if the response should contain a Cache-Control: private
1818:             */
1819:            protected boolean isPrivateCache() {
1820:                return !_hasCacheControl && _isPrivateCache;
1821:            }
1822:
1823:            /**
1824:             * Set if the page is non-cacheable.
1825:             */
1826:            public void setNoCache(boolean isNoCache) {
1827:                _isNoCache = isNoCache;
1828:            }
1829:
1830:            /**
1831:             * Returns true if the page is non-cacheable
1832:             */
1833:            public boolean isNoCache() {
1834:                return _isNoCache;
1835:            }
1836:
1837:            /**
1838:             * Set if the page is non-cacheable.
1839:             */
1840:            public void killCache() {
1841:                _allowCache = false;
1842:
1843:                // server/1b15
1844:                // setNoCache(true);
1845:            }
1846:
1847:            /**
1848:             * Fills the response for a cookie
1849:             *
1850:             * @param cb result buffer to contain the generated string
1851:             * @param cookie the cookie
1852:             * @param date the current date
1853:             * @param version the cookies version
1854:             */
1855:            public boolean fillCookie(CharBuffer cb, Cookie cookie, long date,
1856:                    int version, boolean isCookie2) {
1857:                // How to deal with quoted values?  Old browsers can't deal with
1858:                // the quotes.
1859:
1860:                cb.clear();
1861:                cb.append(cookie.getName());
1862:                if (isCookie2) {
1863:                    cb.append("=\"");
1864:                    cb.append(cookie.getValue());
1865:                    cb.append("\"");
1866:                } else {
1867:                    cb.append("=");
1868:                    cb.append(cookie.getValue());
1869:                }
1870:
1871:                String domain = cookie.getDomain();
1872:                if (domain != null && !domain.equals("")) {
1873:                    if (isCookie2) {
1874:                        cb.append("; Domain=");
1875:
1876:                        cb.append('"');
1877:                        cb.append(domain);
1878:                        cb.append('"');
1879:                    } else {
1880:                        cb.append("; domain=");
1881:                        cb.append(domain);
1882:                    }
1883:                }
1884:
1885:                String path = cookie.getPath();
1886:                if (path != null && !path.equals("")) {
1887:                    if (isCookie2) {
1888:                        cb.append("; Path=");
1889:
1890:                        cb.append('"');
1891:                        cb.append(path);
1892:                        cb.append('"');
1893:                    } else {
1894:                        // Caps from TCK test
1895:                        if (version > 0)
1896:                            cb.append("; Path=");
1897:                        else
1898:                            cb.append("; path=");
1899:                        cb.append(path);
1900:                    }
1901:                }
1902:
1903:                if (cookie.getSecure()) {
1904:                    if (version > 0)
1905:                        cb.append("; Secure");
1906:                    else
1907:                        cb.append("; secure");
1908:                }
1909:
1910:                int maxAge = cookie.getMaxAge();
1911:                if (version > 0) {
1912:                    if (maxAge >= 0) {
1913:                        cb.append("; Max-Age=");
1914:                        cb.append(maxAge);
1915:                    }
1916:
1917:                    cb.append("; Version=");
1918:                    cb.append(version);
1919:
1920:                    if (cookie.getComment() != null) {
1921:                        cb.append("; Comment=\"");
1922:                        cb.append(cookie.getComment());
1923:                        cb.append("\"");
1924:                    }
1925:
1926:                    if (cookie instanceof  CookieImpl) {
1927:                        CookieImpl extCookie = (CookieImpl) cookie;
1928:                        String port = extCookie.getPort();
1929:
1930:                        if (port != null && isCookie2) {
1931:                            cb.append("; Port=\"");
1932:                            cb.append(port);
1933:                            cb.append("\"");
1934:                        }
1935:                    }
1936:                }
1937:
1938:                if (isCookie2) {
1939:                } else if (maxAge == 0) {
1940:                    cb.append("; expires=Thu, 01-Dec-1994 16:00:00 GMT");
1941:                } else if (maxAge >= 0) {
1942:                    _calendar.setGMTTime(date + 1000L * (long) maxAge);
1943:                    cb.append("; expires=");
1944:                    cb.append(_calendar.format("%a, %d-%b-%Y %H:%M:%S GMT"));
1945:                }
1946:
1947:                WebApp app = _request.getWebApp();
1948:                if (app.getCookieHttpOnly()) {
1949:                    cb.append("; HttpOnly");
1950:                }
1951:
1952:                return true;
1953:            }
1954:
1955:            protected ConnectionController getController() {
1956:                if (_originalRequest instanceof  AbstractHttpRequest) {
1957:                    AbstractHttpRequest request = (AbstractHttpRequest) _originalRequest;
1958:                    Connection conn = request.getConnection();
1959:                    return conn.getController();
1960:                } else
1961:                    return null;
1962:            }
1963:
1964:            /**
1965:             * Complete the request.  Flushes the streams, completes caching
1966:             * and writes the appropriate logs.
1967:             */
1968:            public void finish() throws IOException {
1969:                finish(false);
1970:            }
1971:
1972:            /**
1973:             * Complete the request.  Flushes the streams, completes caching
1974:             * and writes the appropriate logs.
1975:             *
1976:             * @param isClose true if the response should be flushed.
1977:             */
1978:            private void finish(boolean isClose) throws IOException {
1979:                if (_isClosed)
1980:                    return;
1981:
1982:                ConnectionController controller = null;
1983:
1984:                try {
1985:                    if (_originalRequest instanceof  AbstractHttpRequest) {
1986:                        AbstractHttpRequest request = (AbstractHttpRequest) _originalRequest;
1987:
1988:                        Connection conn = request.getConnection();
1989:                        controller = conn.getController();
1990:
1991:                        try {
1992:                            request.skip();
1993:                        } catch (BadRequestException e) {
1994:                            log.warning(e.toString());
1995:                            log.log(Level.FINE, e.toString(), e);
1996:                        } catch (Exception e) {
1997:                            log.log(Level.WARNING, e.toString(), e);
1998:                        }
1999:                    }
2000:
2001:                    if (_statusCode == SC_NOT_MODIFIED) {
2002:                        handleNotModified(_isTopCache);
2003:                    }
2004:
2005:                    if (controller != null && !controller.isClosed())
2006:                        isClose = false;
2007:
2008:                    // include() files finish too, but shouldn't force a flush, hence
2009:                    // flush is false
2010:                    // Never send flush?
2011:                    if (isClose)
2012:                        _responseStream.close();
2013:                    else if (_responseStream != _originalResponseStream)
2014:                        _responseStream.finish();
2015:                    else if (controller == null)
2016:                        _responseStream.finish();
2017:                    else
2018:                        _responseStream.flush();
2019:
2020:                    if (_responseStream != _originalResponseStream) {
2021:                        if (isClose)
2022:                            _originalResponseStream.close();
2023:                        else if (controller == null)
2024:                            _originalResponseStream.finish();
2025:                    }
2026:
2027:                    if (controller == null)
2028:                        _isClosed = true;
2029:
2030:                    if (_rawWrite == null) {
2031:                    }
2032:                    // server/0550
2033:                    // else if (isClose)
2034:                    // _rawWrite.close();
2035:                    else
2036:                        _rawWrite.flushBuffer();
2037:
2038:                    if (_cacheInvocation == null) {
2039:                    } else if (_newCacheEntry != null) {
2040:                        OutputStream cacheStream = _cacheStream;
2041:                        _cacheStream = null;
2042:
2043:                        Writer cacheWriter = _cacheWriter;
2044:                        _cacheWriter = null;
2045:
2046:                        if (cacheStream != null)
2047:                            cacheStream.close();
2048:
2049:                        if (cacheWriter != null)
2050:                            cacheWriter.close();
2051:
2052:                        if (_statusCode == 200 && _allowCache) {
2053:                            AbstractCacheFilterChain cache = _cacheInvocation;
2054:                            _cacheInvocation = null;
2055:
2056:                            AbstractCacheEntry cacheEntry = _newCacheEntry;
2057:                            _newCacheEntry = null;
2058:
2059:                            cache.finishCaching(cacheEntry);
2060:                        }
2061:                    }
2062:                } catch (ClientDisconnectException e) {
2063:                    _request.killKeepalive();
2064:
2065:                    if (isIgnoreClientDisconnect())
2066:                        log.fine(e.toString());
2067:                    else
2068:                        throw e;
2069:                } catch (IOException e) {
2070:                    _request.killKeepalive();
2071:
2072:                    throw e;
2073:                } finally {
2074:                    if (controller == null)
2075:                        _isClosed = true;
2076:
2077:                    AbstractCacheFilterChain cache = _cacheInvocation;
2078:                    _cacheInvocation = null;
2079:
2080:                    AbstractCacheEntry cacheEntry = _newCacheEntry;
2081:                    _newCacheEntry = null;
2082:
2083:                    _cacheStream = null;
2084:                    _cacheWriter = null;
2085:
2086:                    if (cacheEntry != null)
2087:                        cache.killCaching(cacheEntry);
2088:                }
2089:            }
2090:
2091:            public void killCaching() {
2092:                AbstractCacheFilterChain cache = _cacheInvocation;
2093:                _cacheInvocation = null;
2094:
2095:                AbstractCacheEntry cacheEntry = _newCacheEntry;
2096:                _newCacheEntry = null;
2097:
2098:                if (cacheEntry != null)
2099:                    cache.killCaching(cacheEntry);
2100:            }
2101:
2102:            TempBuffer getBuffer() {
2103:                return _tempBuffer;
2104:            }
2105:
2106:            protected final QDate getCalendar() {
2107:                return _calendar;
2108:            }
2109:
2110:            protected void free() {
2111:                _request = null;
2112:                _originalRequest = null;
2113:                _cacheInvocation = null;
2114:                _newCacheEntry = null;
2115:                _matchCacheEntry = null;
2116:                _cacheStream = null;
2117:                _cacheWriter = null;
2118:            }
2119:
2120:            static {
2121:                _errors = new HashMap<String, String>();
2122:                _errors.put("100", "Continue");
2123:                _errors.put("101", "Switching Protocols");
2124:                _errors.put("200", "OK");
2125:                _errors.put("201", "Created");
2126:                _errors.put("202", "Accepted");
2127:                _errors.put("203", "Non-Authoritative Information");
2128:                _errors.put("204", "No Content");
2129:                _errors.put("205", "Reset Content");
2130:                _errors.put("206", "Partial Content");
2131:                _errors.put("300", "Multiple Choices");
2132:                _errors.put("301", "Moved Permanently");
2133:                _errors.put("302", "Found");
2134:                _errors.put("303", "See Other");
2135:                _errors.put("304", "Not Modified");
2136:                _errors.put("305", "Use Proxy");
2137:                _errors.put("307", "Temporary Redirect");
2138:                _errors.put("400", "Bad Request");
2139:                _errors.put("401", "Unauthorized");
2140:                _errors.put("402", "Payment Required");
2141:                _errors.put("403", "Forbidden");
2142:                _errors.put("404", "Not Found");
2143:                _errors.put("405", "Method Not Allowed");
2144:                _errors.put("406", "Not Acceptable");
2145:                _errors.put("407", "Proxy Authentication Required");
2146:                _errors.put("408", "Request Timeout");
2147:                _errors.put("409", "Conflict");
2148:                _errors.put("410", "Gone");
2149:                _errors.put("411", "Length Required");
2150:                _errors.put("412", "Precondition Failed");
2151:                _errors.put("413", "Request Entity Too Large");
2152:                _errors.put("414", "Request-URI Too Long");
2153:                _errors.put("415", "Unsupported Media Type");
2154:                _errors.put("416", "Requested Range Not Satisfiable");
2155:                _errors.put("417", "Expectation Failed");
2156:                _errors.put("500", "Internal Server Error");
2157:                _errors.put("501", "Not Implemented");
2158:                _errors.put("502", "Bad Gateway");
2159:                _errors.put("503", "Service Temporarily Unavailable");
2160:                _errors.put("504", "Gateway Timeout");
2161:                _errors.put("505", "Http Version Not Supported");
2162:
2163:                _headerCodes = new CaseInsensitiveIntMap();
2164:                _headerCodes.put("cache-control", HEADER_CACHE_CONTROL);
2165:                _headerCodes.put("connection", HEADER_CONNECTION);
2166:                _headerCodes.put("content-type", HEADER_CONTENT_TYPE);
2167:                _headerCodes.put("content-length", HEADER_CONTENT_LENGTH);
2168:                _headerCodes.put("date", HEADER_DATE);
2169:                _headerCodes.put("server", HEADER_SERVER);
2170:            }
2171:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.