Source Code Cross Referenced for ResponseTrans.java in  » Web-Framework » helma » helma » framework » 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 » Web Framework » helma » helma.framework 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Helma License Notice
0003:         *
0004:         * The contents of this file are subject to the Helma License
0005:         * Version 2.0 (the "License"). You may not use this file except in
0006:         * compliance with the License. A copy of the License is available at
0007:         * http://adele.helma.org/download/helma/license.txt
0008:         *
0009:         * Copyright 1998-2003 Helma Software. All Rights Reserved.
0010:         *
0011:         * $RCSfile$
0012:         * $Author: hannes $
0013:         * $Revision: 8705 $
0014:         * $Date: 2007-12-11 17:32:22 +0100 (Die, 11 Dez 2007) $
0015:         */
0016:
0017:        package helma.framework;
0018:
0019:        import helma.framework.core.Skin;
0020:        import helma.framework.core.Application;
0021:        import helma.util.*;
0022:
0023:        import javax.servlet.http.HttpServletResponse;
0024:        import java.io.*;
0025:        import java.security.*;
0026:        import java.util.*;
0027:
0028:        import org.apache.xmlrpc.XmlRpcResponseProcessor;
0029:
0030:        /**
0031:         * A Transmitter for a response to the servlet client. Objects of this
0032:         * class are directly exposed to JavaScript as global property res.
0033:         */
0034:        public final class ResponseTrans extends Writer implements  Serializable {
0035:
0036:            static final long serialVersionUID = -8627370766119740844L;
0037:            static final int INITIAL_BUFFER_SIZE = 2048;
0038:
0039:            static final String newLine = System.getProperty("line.separator");
0040:
0041:            //  MIME content type of the response.
0042:            private String contentType = "text/html";
0043:
0044:            // Charset (encoding) to use for the response.
0045:            private String charset;
0046:
0047:            // Used to allow or disable client side caching
0048:            private boolean cacheable = true;
0049:
0050:            // HTTP response code, defaults to 200 (OK).
0051:            private int status = 200;
0052:
0053:            // HTTP authentication realm
0054:            private String realm;
0055:
0056:            // the actual response
0057:            private byte[] response = null;
0058:
0059:            // contains the redirect URL
0060:            private String redir = null;
0061:
0062:            // the forward (internal redirect) URL
0063:            private String forward = null;
0064:
0065:            // the last-modified date, if it should be set in the response
0066:            private long lastModified = -1;
0067:
0068:            // flag to signal that resource has not been modified
0069:            private boolean notModified = false;
0070:
0071:            // Entity Tag for this response, used for conditional GETs
0072:            private String etag = null;
0073:
0074:            // cookies
0075:            Map cookies;
0076:
0077:            // the buffer used to build the response
0078:            private transient StringBuffer buffer = null;
0079:
0080:            // an idle StringBuffer waiting to be reused
0081:            private transient StringBuffer cachedBuffer = null;
0082:
0083:            // these are used to implement the _as_string variants for Hop templates.
0084:            private transient Stack buffers;
0085:
0086:            // the path used to tell where to look for skins
0087:            private transient Object[] skinpath = null;
0088:
0089:            // hashmap for skin caching
0090:            private transient HashMap skincache;
0091:
0092:            // buffer for debug messages - will be automatically appended to response
0093:            private transient StringBuffer debugBuffer;
0094:
0095:            // field for generic message to be displayed
0096:            private transient String message;
0097:
0098:            // field for error message
0099:            private transient String error;
0100:
0101:            // the res.data map of form and cookie data
0102:            private transient Map values = new SystemMap();
0103:
0104:            // the res.handlers map of macro handlers
0105:            private transient Map handlers = new SystemMap();
0106:
0107:            // the res.meta map for meta response data
0108:            private transient Map meta = new SystemMap();
0109:
0110:            // the request trans for this response
0111:            private transient RequestTrans reqtrans;
0112:
0113:            // the message digest used to generate composed digests for ETag headers
0114:            private transient MessageDigest digest;
0115:
0116:            // the skin current or last rendered skin
0117:            private transient volatile Skin activeSkin;
0118:
0119:            // the application
0120:            Application app;
0121:
0122:            /**
0123:             * Creates a new ResponseTrans object.
0124:             *
0125:             * @param req the RequestTrans for this response
0126:             */
0127:            public ResponseTrans(Application app, RequestTrans req) {
0128:                this .app = app;
0129:                reqtrans = req;
0130:            }
0131:
0132:            /**
0133:             *  Get a value from the responses map by key.
0134:             */
0135:            public Object get(String name) {
0136:                try {
0137:                    return values.get(name);
0138:                } catch (Exception x) {
0139:                    return null;
0140:                }
0141:            }
0142:
0143:            /**
0144:             *  Get the data map for this response transmitter.
0145:             */
0146:            public Map getResponseData() {
0147:                return values;
0148:            }
0149:
0150:            /**
0151:             *  Get the macro handlers map for this response transmitter.
0152:             */
0153:            public Map getMacroHandlers() {
0154:                return handlers;
0155:            }
0156:
0157:            /**
0158:             *  Get the meta info map for this response transmitter.
0159:             */
0160:            public Map getMetaData() {
0161:                return meta;
0162:            }
0163:
0164:            /**
0165:             * Returns the ServletResponse instance for this ResponseTrans.
0166:             * Returns null for internal and XML-RPC requests.
0167:             */
0168:            public HttpServletResponse getServletResponse() {
0169:                return reqtrans.getServletResponse();
0170:            }
0171:
0172:            /**
0173:             * Reset the current response buffer.
0174:             */
0175:            public synchronized void resetBuffer() {
0176:                if (buffer != null) {
0177:                    buffer.setLength(0);
0178:                }
0179:            }
0180:
0181:            /**
0182:             * Reset the response object to its initial empty state.
0183:             */
0184:            public synchronized void reset() {
0185:                if (buffer != null) {
0186:                    buffer.setLength(0);
0187:                }
0188:
0189:                buffers = null;
0190:                response = null;
0191:                cacheable = true;
0192:                redir = forward = message = error = null;
0193:                etag = realm = charset = null;
0194:                contentType = "text/html";
0195:                values.clear();
0196:                handlers.clear();
0197:                meta.clear();
0198:                lastModified = -1;
0199:                notModified = false;
0200:                skinpath = null;
0201:                skincache = null;
0202:                cookies = null;
0203:
0204:                if (digest != null) {
0205:                    digest.reset();
0206:                }
0207:            }
0208:
0209:            /**
0210:             * This is called before a skin is rendered as string
0211:             * (renderSkinAsString) to redirect the output to a new
0212:             * string buffer.
0213:             * @param buf the StringBuffer to use, or null
0214:             * @return the new StringBuffer instance
0215:             */
0216:            public synchronized StringBuffer pushBuffer(StringBuffer buf) {
0217:                if (buffers == null) {
0218:                    buffers = new Stack();
0219:                }
0220:
0221:                if (buffer != null) {
0222:                    buffers.push(buffer);
0223:                }
0224:
0225:                if (buf != null) {
0226:                    buffer = buf;
0227:                } else if (cachedBuffer != null) {
0228:                    buffer = cachedBuffer;
0229:                    cachedBuffer = null;
0230:                } else {
0231:                    buffer = new StringBuffer(64);
0232:                }
0233:                return buffer;
0234:            }
0235:
0236:            /**
0237:             * Returns the content of the current string buffer and switches back to the previos one.
0238:             */
0239:            public synchronized String popString() {
0240:                StringBuffer buf = popBuffer();
0241:                String str = buf.toString();
0242:                // store stringbuffer for later reuse
0243:                buf.setLength(0);
0244:                cachedBuffer = buf;
0245:                return str;
0246:            }
0247:
0248:            public synchronized StringBuffer popBuffer() {
0249:                if (buffer == null) {
0250:                    throw new RuntimeException(
0251:                            "Can't pop string buffer: buffer is null");
0252:                } else if (buffers == null) {
0253:                    throw new RuntimeException(
0254:                            "Can't pop string buffer: buffer stack is empty");
0255:                }
0256:                // get local reference
0257:                StringBuffer buf = buffer;
0258:                // restore the previous buffer, which may be null
0259:                buffer = buffers.empty() ? null : (StringBuffer) buffers.pop();
0260:                return buf;
0261:            }
0262:
0263:            /**
0264:             *  Get the response buffer, creating it if it doesn't exist
0265:             */
0266:            public synchronized StringBuffer getBuffer() {
0267:                if (buffer == null) {
0268:                    buffer = new StringBuffer(INITIAL_BUFFER_SIZE);
0269:                }
0270:
0271:                return buffer;
0272:            }
0273:
0274:            /**
0275:             * Append a string to the response unchanged.
0276:             */
0277:            public synchronized void write(String str) {
0278:                if (str != null) {
0279:                    if (buffer == null) {
0280:                        buffer = new StringBuffer(Math.max(str.length() + 100,
0281:                                INITIAL_BUFFER_SIZE));
0282:                    }
0283:                    buffer.append(str);
0284:                }
0285:            }
0286:
0287:            /**
0288:             * Appends a objct to the response unchanged.
0289:             * The object is first converted to a string.
0290:             */
0291:            public void write(Object what) {
0292:                if (what != null) {
0293:                    write(what.toString());
0294:                }
0295:            }
0296:
0297:            /**
0298:             *  Appends a part from a char array to the response buffer.
0299:             *
0300:             * @param chars
0301:             * @param offset
0302:             * @param length
0303:             */
0304:            public synchronized void write(char[] chars, int offset, int length) {
0305:                if (buffer == null) {
0306:                    buffer = new StringBuffer(Math.max(length + 100,
0307:                            INITIAL_BUFFER_SIZE));
0308:                }
0309:                buffer.append(chars, offset, length);
0310:            }
0311:
0312:            /**
0313:             *  Appends a char array to the response buffer.
0314:             *
0315:             * @param chars
0316:             */
0317:            public void write(char chars[]) {
0318:                write(chars, 0, chars.length);
0319:            }
0320:
0321:            /**
0322:             * Appends a signle character to the response buffer.
0323:             * @param c
0324:             */
0325:            public synchronized void write(int c) {
0326:                if (buffer == null) {
0327:                    buffer = new StringBuffer(INITIAL_BUFFER_SIZE);
0328:                }
0329:                buffer.append((char) c);
0330:            }
0331:
0332:            /**
0333:             * Appends a part from a string to the response buffer.
0334:             * @param str
0335:             * @param offset
0336:             * @param length
0337:             */
0338:            public void write(String str, int offset, int length) {
0339:                char cbuf[] = new char[length];
0340:                str.getChars(offset, (offset + length), cbuf, 0);
0341:                write(cbuf, 0, length);
0342:            }
0343:
0344:            /**
0345:             * Write object to response buffer and append a platform dependent newline sequence.
0346:             */
0347:            public synchronized void writeln(Object what) {
0348:                if (what != null) {
0349:                    write(what.toString());
0350:                } else if (buffer == null) {
0351:                    // if what is null, buffer may still be uninitialized
0352:                    buffer = new StringBuffer(INITIAL_BUFFER_SIZE);
0353:                }
0354:                buffer.append(newLine);
0355:            }
0356:
0357:            /**
0358:             * Writes a platform dependent newline sequence to response buffer.
0359:             */
0360:            public synchronized void writeln() {
0361:                // buffer may still be uninitialized
0362:                if (buffer == null) {
0363:                    buffer = new StringBuffer(INITIAL_BUFFER_SIZE);
0364:                }
0365:                buffer.append(newLine);
0366:            }
0367:
0368:            /**
0369:             *  Insert string somewhere in the response buffer. Caller has to make sure
0370:             *  that buffer exists and its length is larger than offset. str may be null, in which
0371:             *  case nothing happens.
0372:             */
0373:            public void debug(Object message) {
0374:                if (debugBuffer == null) {
0375:                    debugBuffer = new StringBuffer();
0376:                }
0377:
0378:                String str = (message == null) ? "null" : message.toString();
0379:
0380:                debugBuffer
0381:                        .append("<div class=\"helma-debug-line\" style=\"background: yellow; ");
0382:                debugBuffer
0383:                        .append("color: black; border-top: 1px solid black;\">");
0384:                debugBuffer.append(str);
0385:                debugBuffer.append("</div>");
0386:            }
0387:
0388:            /**
0389:             * Replace special characters with entities, including <, > and ", thus allowing
0390:             * no HTML tags.
0391:             */
0392:            public synchronized void encode(Object what) {
0393:                if (what != null) {
0394:                    String str = what.toString();
0395:
0396:                    if (buffer == null) {
0397:                        buffer = new StringBuffer(Math.max(str.length() + 100,
0398:                                INITIAL_BUFFER_SIZE));
0399:                    }
0400:
0401:                    HtmlEncoder.encodeAll(str, buffer);
0402:                }
0403:            }
0404:
0405:            /**
0406:             * Replace special characters with entities but pass through HTML tags
0407:             */
0408:            public synchronized void format(Object what) {
0409:                if (what != null) {
0410:                    String str = what.toString();
0411:
0412:                    if (buffer == null) {
0413:                        buffer = new StringBuffer(Math.max(str.length() + 100,
0414:                                INITIAL_BUFFER_SIZE));
0415:                    }
0416:
0417:                    HtmlEncoder.encode(str, buffer);
0418:                }
0419:            }
0420:
0421:            /**
0422:             * Replace special characters with entities, including <, > and ", thus allowing
0423:             * no HTML tags.
0424:             */
0425:            public synchronized void encodeXml(Object what) {
0426:                if (what != null) {
0427:                    String str = what.toString();
0428:
0429:                    if (buffer == null) {
0430:                        buffer = new StringBuffer(Math.max(str.length() + 100,
0431:                                INITIAL_BUFFER_SIZE));
0432:                    }
0433:
0434:                    HtmlEncoder.encodeXml(str, buffer);
0435:                }
0436:            }
0437:
0438:            /**
0439:             * Encode HTML entities, but leave newlines alone. This is for the content of textarea forms.
0440:             */
0441:            public synchronized void encodeForm(Object what) {
0442:                if (what != null) {
0443:                    String str = what.toString();
0444:
0445:                    if (buffer == null) {
0446:                        buffer = new StringBuffer(Math.max(str.length() + 100,
0447:                                INITIAL_BUFFER_SIZE));
0448:                    }
0449:
0450:                    HtmlEncoder.encodeAll(str, buffer, false);
0451:                }
0452:            }
0453:
0454:            /**
0455:             *
0456:             *
0457:             * @param url ...
0458:             *
0459:             * @throws RedirectException ...
0460:             */
0461:            public void redirect(String url) throws RedirectException {
0462:                // remove newline chars to prevent response splitting attack
0463:                redir = url == null ? null : url.replaceAll("[\r\n]", "");
0464:                throw new RedirectException(redir);
0465:            }
0466:
0467:            /**
0468:             *
0469:             *
0470:             * @return ...
0471:             */
0472:            public String getRedirect() {
0473:                return redir;
0474:            }
0475:
0476:            /**
0477:             *
0478:             *
0479:             * @param url ...
0480:             *
0481:             * @throws RedirectException ...
0482:             */
0483:            public void forward(String url) throws RedirectException {
0484:                // remove newline chars to prevent response splitting attack
0485:                forward = url == null ? null : url.replaceAll("[\r\n]", "");
0486:                throw new RedirectException(forward);
0487:            }
0488:
0489:            /**
0490:             *
0491:             *
0492:             * @return ...
0493:             */
0494:            public String getForward() {
0495:                return forward;
0496:            }
0497:
0498:            /**
0499:             *  Allow to directly set the byte array for the response. Calling this more than once will
0500:             *  overwrite the previous output. We take a generic object as parameter to be able to
0501:             * generate a better error message, but it must be byte[].
0502:             */
0503:            public void writeBinary(byte[] what) {
0504:                response = what;
0505:            }
0506:
0507:            /**
0508:             * Proxy to HttpServletResponse.addHeader()
0509:             * @param name the header name
0510:             * @param value the header value
0511:             */
0512:            public void addHeader(String name, String value) {
0513:                HttpServletResponse res = getServletResponse();
0514:                if (res != null)
0515:                    res.addHeader(name, value);
0516:            }
0517:
0518:            /**
0519:             * Proxy to HttpServletResponse.addDateHeader()
0520:             * @param name the header name
0521:             * @param value the header value
0522:             */
0523:            public void addDateHeader(String name, Date value) {
0524:                HttpServletResponse res = getServletResponse();
0525:                if (res != null)
0526:                    res.addDateHeader(name, value.getTime());
0527:            }
0528:
0529:            /**
0530:             * Proxy to HttpServletResponse.setHeader()
0531:             * @param name the header name
0532:             * @param value the header value
0533:             */
0534:            public void setHeader(String name, String value) {
0535:                HttpServletResponse res = getServletResponse();
0536:                if (res != null)
0537:                    res.setHeader(name, value);
0538:            }
0539:
0540:            /**
0541:             * Proxy to HttpServletResponse.setDateHeader()
0542:             * @param name the header name
0543:             * @param value the header value
0544:             */
0545:            public void setDateHeader(String name, Date value) {
0546:                HttpServletResponse res = getServletResponse();
0547:                if (res != null)
0548:                    res.setDateHeader(name, value.getTime());
0549:            }
0550:
0551:            /**
0552:             * Write a vanilla error report. Callers should make sure the ResponeTrans is
0553:             * new or has been reset.
0554:             *
0555:             * @param appName the application name
0556:             * @param message the error message
0557:             */
0558:            public void reportError(String appName, String message) {
0559:                if (reqtrans.isXmlRpc()) {
0560:                    writeXmlRpcError(new RuntimeException(message));
0561:                } else {
0562:                    status = 500;
0563:                    if (!"true".equalsIgnoreCase(app
0564:                            .getProperty("suppressErrorPage"))) {
0565:                        write("<html><body><h3>");
0566:                        write("Error in application ");
0567:                        write(appName);
0568:                        write("</h3>");
0569:                        write(message);
0570:                        write("</body></html>");
0571:                    }
0572:                }
0573:            }
0574:
0575:            public void writeXmlRpcResponse(Object result) {
0576:                try {
0577:                    reset();
0578:                    contentType = "text/xml";
0579:                    if (charset == null) {
0580:                        charset = "UTF-8";
0581:                    }
0582:                    XmlRpcResponseProcessor xresproc = new XmlRpcResponseProcessor();
0583:                    writeBinary(xresproc.encodeResponse(result, charset));
0584:                } catch (Exception x) {
0585:                    writeXmlRpcError(x);
0586:                }
0587:            }
0588:
0589:            public void writeXmlRpcError(Exception x) {
0590:                contentType = "text/xml";
0591:                if (charset == null) {
0592:                    charset = "UTF-8";
0593:                }
0594:                XmlRpcResponseProcessor xresproc = new XmlRpcResponseProcessor();
0595:                writeBinary(xresproc.encodeException(x, charset));
0596:            }
0597:
0598:            public void flush() {
0599:                // does nothing!
0600:            }
0601:
0602:            /**
0603:             * This has to be called after writing to this response has finished and before it is shipped back to the
0604:             * web server. Transforms the string buffer into a byte array for transmission.
0605:             */
0606:            public void close() throws UnsupportedEncodingException {
0607:                close(null);
0608:            }
0609:
0610:            /**
0611:             * This has to be called after writing to this response has finished and before it is shipped back to the
0612:             * web server. Transforms the string buffer into a byte array for transmission.
0613:             */
0614:            public synchronized void close(String cset)
0615:                    throws UnsupportedEncodingException {
0616:                // if the response was already written and committed by the application
0617:                // there's no point in closing the response buffer
0618:                HttpServletResponse res = reqtrans.getServletResponse();
0619:                if (res != null && res.isCommitted()) {
0620:                    return;
0621:                }
0622:
0623:                // only use default charset if not explicitly set for this response.
0624:                if (charset == null) {
0625:                    charset = cset;
0626:                }
0627:
0628:                // if charset is not set, use western encoding
0629:                if (charset == null) {
0630:                    charset = "ISO-8859-1";
0631:                }
0632:
0633:                boolean encodingError = false;
0634:
0635:                // only close if the response hasn't been closed yet
0636:                if (response == null) {
0637:                    // if debug buffer exists, append it to main buffer
0638:                    if (contentType != null
0639:                            && contentType.startsWith("text/html")
0640:                            && debugBuffer != null) {
0641:                        debugBuffer.append("</div>");
0642:                        if (buffer == null) {
0643:                            buffer = debugBuffer;
0644:                        } else {
0645:                            buffer.append(debugBuffer);
0646:                        }
0647:                    }
0648:
0649:                    // get the buffer's bytes in the specified encoding
0650:                    if (buffer != null) {
0651:                        try {
0652:                            response = buffer.toString().getBytes(charset);
0653:                        } catch (UnsupportedEncodingException uee) {
0654:                            encodingError = true;
0655:                            response = buffer.toString().getBytes();
0656:                        }
0657:
0658:                        // make sure this is done only once, even with more requsts attached
0659:                        buffer = null;
0660:                    } else {
0661:                        response = new byte[0];
0662:                    }
0663:                }
0664:
0665:                boolean autoETags = "true".equals(app.getProperty("autoETags",
0666:                        "true"));
0667:                // if etag is not set, calc MD5 digest and check it, but only if
0668:                // not a redirect or error
0669:                if (autoETags && etag == null && lastModified == -1
0670:                        && status == 200 && redir == null) {
0671:                    try {
0672:                        digest = MessageDigest.getInstance("MD5");
0673:                        // if (contentType != null)
0674:                        //     digest.update (contentType.getBytes());
0675:                        byte[] b = digest.digest(response);
0676:                        etag = "\"" + new String(Base64.encode(b)) + "\"";
0677:                        // only set response to 304 not modified if no cookies were set
0678:                        if (reqtrans.hasETag(etag) && countCookies() == 0) {
0679:                            response = new byte[0];
0680:                            notModified = true;
0681:                        }
0682:                    } catch (Exception ignore) {
0683:                        // Etag creation failed for some reason. Ignore.
0684:                    }
0685:                }
0686:
0687:                notifyAll();
0688:
0689:                // if there was a problem with the encoding, let the app know
0690:                if (encodingError) {
0691:                    throw new UnsupportedEncodingException(charset);
0692:                }
0693:            }
0694:
0695:            /**
0696:             * If we just attached to evaluation we call this instead of close because only the primary thread
0697:             * is responsible for closing the result
0698:             */
0699:            public synchronized void waitForClose() {
0700:                try {
0701:                    if (response == null) {
0702:                        wait(10000L);
0703:                    }
0704:                } catch (InterruptedException ix) {
0705:                    // Ignore
0706:                }
0707:            }
0708:
0709:            /**
0710:             * Get the body content for this response as byte array, encoded using the
0711:             * response's charset.
0712:             *
0713:             * @return the response body
0714:             */
0715:            public byte[] getContent() {
0716:                return (response == null) ? new byte[0] : response;
0717:            }
0718:
0719:            /**
0720:             * Get the number of bytes of the response body.
0721:             *
0722:             * @return the length of the response body
0723:             */
0724:            public int getContentLength() {
0725:                if (response != null) {
0726:                    return response.length;
0727:                }
0728:
0729:                return 0;
0730:            }
0731:
0732:            /**
0733:             * Get the response's MIME content type
0734:             *
0735:             * @return the MIME type for this response
0736:             */
0737:            public String getContentType() {
0738:                if (charset != null) {
0739:                    return contentType + "; charset=" + charset;
0740:                }
0741:
0742:                return contentType;
0743:            }
0744:
0745:            /**
0746:             * Set the response's MIME content type
0747:             *
0748:             * @param contentType MIME type for this response
0749:             */
0750:            public void setContentType(String contentType) {
0751:                this .contentType = contentType;
0752:            }
0753:
0754:            /**
0755:             * Set the Last-Modified header for this response
0756:             *
0757:             * @param modified the Last-Modified header in milliseconds
0758:             */
0759:            public void setLastModified(long modified) {
0760:                // date headers don't do milliseconds, round to seconds
0761:                lastModified = (modified / 1000) * 1000;
0762:                if (reqtrans.getIfModifiedSince() == lastModified) {
0763:                    notModified = true;
0764:                    throw new RedirectException(null);
0765:                }
0766:            }
0767:
0768:            /**
0769:             * Get the value of the Last-Modified header for this response.
0770:             *
0771:             * @return the Last-Modified header in milliseconds
0772:             */
0773:            public long getLastModified() {
0774:                return lastModified;
0775:            }
0776:
0777:            /**
0778:             * Set the ETag header value for this response.
0779:             *
0780:             * @param value the ETag header value
0781:             */
0782:            public void setETag(String value) {
0783:                etag = (value == null) ? null : ("\"" + value + "\"");
0784:                if (etag != null && reqtrans.hasETag(etag)) {
0785:                    notModified = true;
0786:                    throw new RedirectException(null);
0787:                }
0788:            }
0789:
0790:            /**
0791:             * Get the ETag header value for this response.
0792:             *
0793:             * @return the ETag header value
0794:             */
0795:            public String getETag() {
0796:                return etag;
0797:            }
0798:
0799:            /**
0800:             * Check if this response should generate a Not-Modified response.
0801:             *
0802:             * @return true if the the response wasn't modified since the client last saw it.
0803:             */
0804:            public boolean getNotModified() {
0805:                return notModified;
0806:            }
0807:
0808:            /**
0809:             * Add a dependency to this response.
0810:             *
0811:             * @param what an item this response's output depends on.
0812:             */
0813:            public void dependsOn(Object what) {
0814:                if (digest == null) {
0815:                    try {
0816:                        digest = MessageDigest.getInstance("MD5");
0817:                    } catch (NoSuchAlgorithmException nsa) {
0818:                        // MD5 should always be available
0819:                    }
0820:                }
0821:
0822:                if (what == null) {
0823:                    digest.update(new byte[0]);
0824:                } else if (what instanceof  Date) {
0825:                    digest.update(MD5Encoder.toBytes(((Date) what).getTime()));
0826:                } else if (what instanceof  byte[]) {
0827:                    digest.update((byte[]) what);
0828:                } else {
0829:                    String str = what.toString();
0830:
0831:                    if (str != null) {
0832:                        digest.update(str.getBytes());
0833:                    } else {
0834:                        digest.update(new byte[0]);
0835:                    }
0836:                }
0837:            }
0838:
0839:            /**
0840:             * Digest all dependencies to a checksum to see if the response has changed.
0841:             */
0842:            public void digestDependencies() {
0843:                if (digest == null) {
0844:                    return;
0845:                }
0846:
0847:                // add the application checksum as dependency to make ETag
0848:                // generation sensitive to changes in the app
0849:                byte[] b = digest.digest(MD5Encoder.toBytes(app.getChecksum()));
0850:
0851:                setETag(new String(Base64.encode(b)));
0852:            }
0853:
0854:            /**
0855:             * Set the path in which to look for skins. This may contain file locations and
0856:             * HopObjects.
0857:             *
0858:             * @param arr the skin path
0859:             */
0860:            public void setSkinpath(Object[] arr) {
0861:                this .skinpath = arr;
0862:                skincache = null;
0863:            }
0864:
0865:            /**
0866:             * Get the path in which to look for skins. This may contain file locations and
0867:             * HopObjects.
0868:             *
0869:             * @return the skin path
0870:             */
0871:            public Object[] getSkinpath() {
0872:                if (skinpath == null) {
0873:                    skinpath = new Object[0];
0874:                }
0875:
0876:                return skinpath;
0877:            }
0878:
0879:            /**
0880:             * Look up a cached skin.
0881:             *
0882:             * @param id the skin key
0883:             * @return the skin, or null if no skin is cached for the given key
0884:             */
0885:            public Skin getCachedSkin(Object id) {
0886:                if (skincache == null) {
0887:                    return null;
0888:                }
0889:
0890:                return (Skin) skincache.get(id);
0891:            }
0892:
0893:            /**
0894:             * Cache a skin for the length of this response.
0895:             *
0896:             * @param id the skin key
0897:             * @param skin the skin to cache
0898:             */
0899:            public void cacheSkin(Object id, Skin skin) {
0900:                if (skincache == null) {
0901:                    skincache = new HashMap();
0902:                }
0903:
0904:                skincache.put(id, skin);
0905:            }
0906:
0907:            /**
0908:             * Set the skin currently being rendered, returning the previously active skin.
0909:             * @param skin the new active skin
0910:             * @return the previously active skin
0911:             */
0912:            public Skin switchActiveSkin(Skin skin) {
0913:                Skin previousSkin = activeSkin;
0914:                activeSkin = skin;
0915:                return previousSkin;
0916:            }
0917:
0918:            /**
0919:             * Return the skin currently being rendered, or none.
0920:             * @return the currently active skin
0921:             */
0922:            public Skin getActiveSkin() {
0923:                return activeSkin;
0924:            }
0925:
0926:            /**
0927:             * Set a cookie.
0928:             *
0929:             * @param key the cookie key
0930:             * @param value the cookie value
0931:             * @param days the cookie's lifespan in days
0932:             * @param path the URL path to apply the cookie to
0933:             * @param domain the domain to apply the cookie to
0934:             */
0935:            public void setCookie(String key, String value, int days,
0936:                    String path, String domain) {
0937:                CookieTrans c = null;
0938:
0939:                if (cookies == null) {
0940:                    cookies = new HashMap();
0941:                } else {
0942:                    c = (CookieTrans) cookies.get(key);
0943:                }
0944:
0945:                // remove newline chars to prevent response splitting attack
0946:                if (value != null) {
0947:                    value = value.replaceAll("[\r\n]", "");
0948:                }
0949:
0950:                if (c == null) {
0951:                    c = new CookieTrans(key, value);
0952:                    cookies.put(key, c);
0953:                } else {
0954:                    c.setValue(value);
0955:                }
0956:
0957:                c.setDays(days);
0958:                c.setPath(path);
0959:                c.setDomain(domain);
0960:            }
0961:
0962:            /**
0963:             * Reset all previously set cookies.
0964:             */
0965:            public void resetCookies() {
0966:                if (cookies != null) {
0967:                    cookies.clear();
0968:                }
0969:            }
0970:
0971:            /**
0972:             * Get the number of cookies set in this response.
0973:             *
0974:             * @return the number of cookies
0975:             */
0976:            public int countCookies() {
0977:                if (cookies != null) {
0978:                    return cookies.size();
0979:                }
0980:
0981:                return 0;
0982:            }
0983:
0984:            /**
0985:             * Get the cookies set in this response.
0986:             *
0987:             * @return the cookies
0988:             */
0989:            public CookieTrans[] getCookies() {
0990:                if (cookies == null) {
0991:                    return new CookieTrans[0];
0992:                }
0993:
0994:                CookieTrans[] c = new CookieTrans[cookies.size()];
0995:                cookies.values().toArray(c);
0996:                return c;
0997:            }
0998:
0999:            /**
1000:             * Get the message to display to the user, if any.
1001:             * @return the message
1002:             */
1003:            public String getMessage() {
1004:                return message;
1005:            }
1006:
1007:            /**
1008:             * Set a message to display to the user.
1009:             * @param message the message
1010:             */
1011:            public void setMessage(String message) {
1012:                this .message = message;
1013:            }
1014:
1015:            /**
1016:             * Get the error message to display to the user, if any.
1017:             * @return the error message
1018:             */
1019:            public String getError() {
1020:                return error;
1021:            }
1022:
1023:            /**
1024:             * Set a message to display to the user.
1025:             * @param error the error message
1026:             */
1027:            public void setError(String error) {
1028:                this .error = error;
1029:            }
1030:
1031:            /**
1032:             * Get debug messages to append to the response, if any.
1033:             * @return the response's debug buffer
1034:             */
1035:            public StringBuffer getDebugBuffer() {
1036:                return debugBuffer;
1037:            }
1038:
1039:            /**
1040:             * Set debug messages to append to the response.
1041:             * @param debugBuffer the response's debug buffer
1042:             */
1043:            public void setDebugBuffer(StringBuffer debugBuffer) {
1044:                this .debugBuffer = debugBuffer;
1045:            }
1046:
1047:            /**
1048:             * Get the charset/encoding for this response
1049:             * @return the charset name
1050:             */
1051:            public String getCharset() {
1052:                return charset;
1053:            }
1054:
1055:            /**
1056:             * Set the charset/encoding for this response
1057:             * @param charset the charset name
1058:             */
1059:            public void setCharset(String charset) {
1060:                this .charset = charset;
1061:            }
1062:
1063:            /**
1064:             * Returns true if this response may be cached by the client
1065:             * @return true if the response may be cached
1066:             */
1067:            public boolean isCacheable() {
1068:                return cacheable;
1069:            }
1070:
1071:            /**
1072:             * Set the cacheability of this response
1073:             * @param cache true if the response may be cached
1074:             */
1075:            public void setCacheable(boolean cache) {
1076:                this .cacheable = cache;
1077:            }
1078:
1079:            /**
1080:             * Get the HTTP response status code
1081:             * @return the HTTP response code
1082:             */
1083:            public int getStatus() {
1084:                return status;
1085:            }
1086:
1087:            /**
1088:             * Set the HTTP response status code
1089:             * @param status the HTTP response code
1090:             */
1091:            public void setStatus(int status) {
1092:                this .status = status;
1093:            }
1094:
1095:            /**
1096:             * Get the HTTP authentication realm
1097:             * @return the name of the authentication realm
1098:             */
1099:            public String getRealm() {
1100:                return realm;
1101:            }
1102:
1103:            /**
1104:             * Set the HTTP authentication realm
1105:             * @param realm the name of the authentication realm
1106:             */
1107:            public void setRealm(String realm) {
1108:                this.realm = realm;
1109:            }
1110:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.