Source Code Cross Referenced for RequestCache.java in  » Ajax » Laszlo-4.0.10 » org » openlaszlo » cache » 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 » Ajax » Laszlo 4.0.10 » org.openlaszlo.cache 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /******************************************************************************
002:         * RequestCache.java
003:         * ****************************************************************************/package org.openlaszlo.cache;
004:
005:        import javax.servlet.http.*;
006:        import java.io.InputStream;
007:        import java.io.IOException;
008:        import java.io.File;
009:        import java.io.Serializable;
010:        import java.io.OutputStream;
011:        import java.util.Properties;
012:        import java.net.MalformedURLException;
013:        import org.openlaszlo.data.*;
014:        import org.openlaszlo.utils.LZHttpUtils;
015:        import org.openlaszlo.utils.FileUtils;
016:        import org.apache.log4j.*;
017:
018:        /**
019:         * A class for maintaining a disk-backed cache of HTTP requests.
020:         *
021:         * The main entry point is the <code>getAsSWF</code> method.
022:         * Given a specific HTTP request and response, the item returns
023:         * an InputStream for a possibly-converted SWF that represents
024:         * the item requested.  This method may return NULL, indicating
025:         * that a special HTTP status code has been stuck in the response.
026:         *
027:         * @author <a href="mailto:bloch@laszlosystems.com">Eric Bloch</a>
028:         */
029:        public abstract class RequestCache extends Cache {
030:
031:            /** logger */
032:            private static Logger mLogger = Logger.getLogger(Cache.class);
033:
034:            /** converter */
035:            protected Converter mConverter;
036:
037:            /**
038:             * Creates a new <code>RequestCache</code> instance.
039:             *
040:             * @param name
041:             * @param cacheDirectory a <code>File</code> naming a directory
042:             * where cache files should be kept
043:             * @param converter
044:             * @param props
045:             */
046:            public RequestCache(String name, File cacheDirectory,
047:                    Converter converter, Properties props) throws IOException {
048:
049:                super (name, cacheDirectory, props);
050:                mConverter = converter;
051:            }
052:
053:            /**
054:             * @return a serializable cache key for the given request
055:             */
056:            public Serializable getKey(HttpServletRequest req)
057:                    throws MalformedURLException {
058:
059:                // This is a nice, easy to read key
060:                String enc = mConverter.chooseEncoding(req);
061:                if (enc == null)
062:                    enc = "";
063:                StringBuffer key = new StringBuffer();
064:                key.append(DataSource.getURL(req));
065:                // note: space not allowed in URLS so it's good to 
066:                // use here as a separator to distinguish encoded keys
067:                key.append(" ");
068:                key.append(enc);
069:                return key.toString();
070:            }
071:
072:            /**
073:             * Using the given datasource from the incoming request,
074:             * get the data if it's out of data from the cache, convert it
075:             * to SWF, and write it out to the given response.
076:             * 
077:             * @param app absolute path name to app
078:             * @param req servlet request that triggered the get
079:             * @param res servlet response to fill out
080:             * @param dataSource source of data
081:             * @throws IOException if there's an IOException while creating
082:             * the response
083:             * @throws DataSourceException if there's an error getting the data
084:             * @throws ConversionException if there's an error convering the data
085:             */
086:            public void getAsSWF(String app, HttpServletRequest req,
087:                    HttpServletResponse res, DataSource dataSource)
088:                    throws IOException, DataSourceException,
089:                    ConversionException {
090:
091:                // Skip the cache if it's 0 size
092:                if (getMaxMemSize() == 0 && getMaxDiskSize() == 0) {
093:                    dataSource.getAsSWF(app, req, res, mConverter);
094:                    return;
095:                }
096:
097:                StringBuffer kb = new StringBuffer();
098:                kb.append(dataSource.name());
099:                kb.append(" ");
100:                String rk = getKey(req).toString();
101:                kb.append(rk);
102:                String key = kb.toString();
103:                String enc = mConverter.chooseEncoding(req);
104:
105:                mLogger.info("requesting '" + rk + "'");
106:                if (enc != null) {
107:                    mLogger.debug("encoding " + enc);
108:                }
109:
110:                Item item = null;
111:                InputStream input = null;
112:                OutputStream output = null;
113:                try {
114:                    item = findItem(key, enc, /* lock it and leave active */
115:                            true);
116:
117:                    // Get an input stream for a SWF version of this item;
118:                    try {
119:                        input = getItemStreamAsSWF(item, app, req, res,
120:                                dataSource);
121:                    } finally {
122:                        // Unlock it while we send out the response 
123:                        // FIXME: [2003-08-27 bloch] there is a slight race here since the source 
124:                        // of the stream could be removed before we are finished; this would
125:                        // be rare since we're MRU now.
126:                        item.unlock();
127:                    }
128:
129:                    // Send out the response
130:                    if (input != null) {
131:                        try {
132:                            output = res.getOutputStream();
133:                            long n = FileUtils.sendToStream(input, output);
134:                            mLogger.info(n + " bytes sent");
135:                        } catch (FileUtils.StreamWritingException e) {
136:                            mLogger
137:                                    .warn("StreamWritingException while responding: "
138:                                            + e.getMessage());
139:                        }
140:                    } else {
141:                        mLogger.info("Cache responding with NOT_MODIFIED");
142:                    }
143:                } finally {
144:                    FileUtils.close(output);
145:                    FileUtils.close(input);
146:
147:                    // If there's an item, unlock it and update the cache
148:                    if (item != null) {
149:                        updateCacheAndDeactivateItem(item);
150:                    }
151:                }
152:            }
153:
154:            /**
155:             * @return true if the request is cacheable.
156:             *
157:             * If response headers are to be sentback, then the request is 
158:             * not cacheable on the server.
159:             *
160:             * If req headers are sent, then the request is not cacheable
161:             * on the server.
162:             *
163:             * If the cache parameter is present and set to true, 
164:             * the request is cacheable.  Otherwise it's not.
165:             */
166:            public boolean isCacheable(HttpServletRequest req) {
167:                String hds = req.getParameter("sendheaders");
168:                if (hds != null) {
169:                    if (hds.equals("true")) {
170:                        return false;
171:                    }
172:                }
173:                hds = req.getParameter("headers");
174:                if (hds != null) {
175:                    return false;
176:                }
177:                String c = req.getParameter("cache");
178:                if (c == null)
179:                    return false;
180:                return c.equals("true");
181:            }
182:
183:            /**
184:             * Return the converter for this cache
185:             */
186:            public Converter getConverter() {
187:                return mConverter;
188:            }
189:
190:            /**
191:             * Get the item if it's been updated since the given time.  Item
192:             * must be locked when you call this.
193:             * @return null if the url hasn't been modified since the given time
194:             * or an input stream that can be used to read the item's content
195:             * as SWF.
196:             */
197:            InputStream getItemStreamAsSWF(Item item, String app,
198:                    HttpServletRequest req, HttpServletResponse res,
199:                    DataSource dataSource) throws IOException,
200:                    DataSourceException, ConversionException {
201:
202:                long ifModifiedSince = -1;
203:                long lastModified = -1;
204:
205:                CachedInfo info = item.getInfo();
206:                String enc = info.getEncoding();
207:
208:                String hdr = req.getHeader(LZHttpUtils.IF_MODIFIED_SINCE);
209:                if (hdr != null) {
210:                    mLogger.debug("req last modified time: " + hdr);
211:                    lastModified = LZHttpUtils.getDate(hdr);
212:                }
213:
214:                boolean doClientCache = DataSource.isClientCacheable(req);
215:
216:                // FIXME[2003-05-21 bloch]:  Max and I worked through the 
217:                // logic in this comment below and it seemed correct
218:                // but as I paste it in here it's missing an else clause...
219:                //
220:                // If (there is an entry in the cache)
221:                //     If there's no timestamp in the request 
222:                //        Use the timestamp from the cache.
223:                //     else 
224:                //        If request time is <= cache time
225:                //            use cache time
226:                // else (no entry in the cache)
227:                //        use -1
228:                //
229:                // Max prefers the following code to implement but I'm leaving the extant code
230:                // because it's too close to release for me to be making changes
231:                // like that.  Here's the code Max, liked:
232:                //
233:                // if (info.getLastModified() != -1) {
234:                //     if (ifModifiedSince == -1) {
235:                //         ifModifiedSince = info.getLastModified();
236:                //     } else {
237:                //         if (ifModifiedSince <= info.getLastModified()) {
238:                //             ifModifiedSince = info.getLastModified();
239:                //         }
240:                //     }
241:                // } else {
242:                //     ifModifiedSince = -1;
243:                // }
244:                //
245:                //
246:                // The code below has existed for a while and actually implements the logic above
247:                // in a slightly convoluted way because of the special dual meaning of -1; it means no 
248:                // last modified time at all when coming from data or the cache and it 
249:                // means get fresh data when making a data request (as the 3rd parameter to 
250:                // the getData() method below.
251:
252:                if (info.getLastModified() > lastModified
253:                        || info.getLastModified() == -1) {
254:                    ifModifiedSince = info.getLastModified();
255:                    mLogger.debug("using cached last modified time: "
256:                            + ifModifiedSince);
257:                } else {
258:                    ifModifiedSince = lastModified;
259:                    mLogger.debug("using req last modified time: "
260:                            + ifModifiedSince);
261:                }
262:
263:                Data data = null;
264:
265:                try {
266:
267:                    try {
268:                        data = dataSource.getData(app, req, res,
269:                                ifModifiedSince);
270:                    } catch (DataSourceException e) {
271:                        // When we get an error from the back end,
272:                        // we must nuke the item from the cache.
273:                        item.markDirty();
274:                        throw e;
275:                    } catch (IOException e) {
276:                        item.markDirty();
277:                        throw e;
278:                    } catch (RuntimeException e) {
279:                        item.markDirty();
280:                        throw e;
281:                    }
282:
283:                    if (data.notModified()) {
284:
285:                        mLogger.debug("Remote response: NOT_MODIFIED");
286:                        if (lastModified >= info.getLastModified()
287:                                && doClientCache) {
288:                            res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
289:                            return null;
290:                        }
291:
292:                        if (item.validForData(data)) {
293:
294:                            if (enc != null) {
295:                                res
296:                                        .setHeader(
297:                                                LZHttpUtils.CONTENT_ENCODING,
298:                                                enc);
299:                            }
300:                            if (doClientCache) {
301:                                long l = info.getLastModified();
302:                                if (l != -1) {
303:                                    res.setDateHeader(
304:                                            LZHttpUtils.LAST_MODIFIED, l);
305:                                }
306:                            } else {
307:                                LZHttpUtils.noStore(res);
308:                            }
309:                            res.setContentLength((int) info.getSize());
310:                            return item.getStream();
311:                        }
312:                    }
313:
314:                    mLogger.debug("path name: " + item.getPathName());
315:
316:                    // We know the cached item is dirty
317:                    item.markDirty();
318:
319:                    // Mark the info with the new last modified time
320:                    info.setLastModified(data.lastModified());
321:
322:                    // Convert the data to SWF
323:                    InputStream input = mConverter.convertToSWF(data, req, res);
324:                    // TODO: [2003-09-22 bloch] add content length when
325:                    // converter api provides this info; input.available() is not reliable
326:                    // TODO: [2003-09-22 bloch] could handle case when conversion is a no-op from swf,
327:                    // without the above
328:
329:                    // Update the item with the data
330:                    try {
331:                        item.update(input);
332:                        item.updateInfo();
333:                        item.markClean();
334:                    } finally {
335:                        FileUtils.close(input);
336:                    }
337:
338:                    // FIXME: [2003-03-13 bloch] hope that no one
339:                    // removes the file before we're done with this
340:                    // input stream.  This would happen only
341:                    // when the cache is full and small; a rare
342:                    // case in production.  
343:
344:                    InputStream str = item.getStream();
345:
346:                    if (enc != null) {
347:                        res.setHeader(LZHttpUtils.CONTENT_ENCODING, enc);
348:                    }
349:
350:                    if (doClientCache) {
351:                        long l = info.getLastModified();
352:                        if (l != -1) {
353:                            res.setDateHeader(LZHttpUtils.LAST_MODIFIED, l);
354:                        }
355:
356:                    } else {
357:                        LZHttpUtils.noStore(res);
358:                    }
359:
360:                    res.setContentLength((int) info.getSize());
361:
362:                    return str;
363:
364:                } finally {
365:                    if (data != null) {
366:                        data.release();
367:                    }
368:                }
369:            }
370:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.