Source Code Cross Referenced for ChannelRenderer.java in  » Portal » uPortal_rel-2-6-1-GA » org » jasig » portal » 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 » Portal » uPortal_rel 2 6 1 GA » org.jasig.portal 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* Copyright 2001 The JA-SIG Collaborative.  All rights reserved.
002:         *  See license distributed with this file and
003:         *  available online at http://www.uportal.org/license.html
004:         */
005:
006:        package org.jasig.portal;
007:
008:        import java.io.PrintWriter;
009:        import java.io.StringWriter;
010:        import java.util.Map;
011:
012:        import javax.servlet.http.HttpServletRequest;
013:        import javax.servlet.http.HttpServletResponse;
014:
015:        import org.apache.commons.logging.Log;
016:        import org.apache.commons.logging.LogFactory;
017:        import org.jasig.portal.channels.support.IChannelTitle;
018:        import org.jasig.portal.channels.support.IDynamicChannelTitleRenderer;
019:        import org.jasig.portal.properties.PropertiesManager;
020:        import org.jasig.portal.servlet.AttributeScopingRequestWrapper;
021:        import org.jasig.portal.utils.SAX2BufferImpl;
022:        import org.jasig.portal.utils.SetCheckInSemaphore;
023:        import org.jasig.portal.utils.SoftHashMap;
024:        import org.jasig.portal.utils.threading.BaseTask;
025:        import org.xml.sax.ContentHandler;
026:        import org.xml.sax.SAXException;
027:
028:        import edu.emory.mathcs.backport.java.util.concurrent.CancellationException;
029:        import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
030:        import edu.emory.mathcs.backport.java.util.concurrent.Future;
031:        import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
032:        import edu.emory.mathcs.backport.java.util.concurrent.TimeoutException;
033:        import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
034:
035:        /**
036:         * This class takes care of initiating channel rendering thread,
037:         * monitoring it for timeouts, retreiving cache, and returning
038:         * rendering results and status.
039:         * @author Peter Kharchenko  {@link <a href="mailto:pkharchenko@interactivebusiness.com"">pkharchenko@interactivebusiness.com"</a>}
040:         * @version $Revision: 42516 $
041:         */
042:        public class ChannelRenderer implements  IChannelRenderer,
043:                IDynamicChannelTitleRenderer {
044:
045:            protected final Log log = LogFactory.getLog(getClass());
046:
047:            /**
048:             * Default value for CACHE_CHANNELS.
049:             * This value will be used when the corresponding property cannot be loaded.
050:             */
051:            private static final boolean DEFAULT_CACHE_CHANNELS = false;
052:
053:            public static final boolean CACHE_CHANNELS = PropertiesManager
054:                    .getPropertyAsBoolean(
055:                            "org.jasig.portal.ChannelRenderer.cache_channels",
056:                            DEFAULT_CACHE_CHANNELS);
057:
058:            public static final String[] renderingStatus = { "successful",
059:                    "failed", "timed out" };
060:
061:            protected IChannel channel;
062:            protected ChannelRuntimeData rd;
063:            protected Map channelCache;
064:            protected Map cacheTables;
065:            protected PortalControlStructures pcs;
066:
067:            protected boolean rendering;
068:            protected boolean donerendering;
069:
070:            protected Thread workerThread;
071:
072:            protected Worker worker;
073:            protected Future workTracker;
074:
075:            protected long startTime;
076:            protected long timeOut = java.lang.Long.MAX_VALUE;
077:
078:            protected boolean ccacheable;
079:
080:            protected static ExecutorService tp = null;
081:            protected static Map systemCache = null;
082:
083:            protected SetCheckInSemaphore groupSemaphore;
084:            protected Object groupRenderingKey;
085:
086:            /**
087:             * Default contstructor
088:             *
089:             * @param chan an <code>IChannel</code> value
090:             * @param runtimeData a <code>ChannelRuntimeData</code> value
091:             * @param threadPool a <code>ThreadPool</code> value
092:             */
093:            public ChannelRenderer(IChannel chan,
094:                    ChannelRuntimeData runtimeData,
095:                    PortalControlStructures pcs, ExecutorService threadPool) {
096:                this .channel = chan;
097:                this .rd = runtimeData;
098:                this .pcs = pcs;
099:                this .rendering = false;
100:                this .ccacheable = false;
101:                tp = threadPool;
102:
103:                if (systemCache == null) {
104:                    systemCache = ChannelManager.systemCache;
105:                }
106:
107:                this .groupSemaphore = null;
108:                this .groupRenderingKey = null;
109:            }
110:
111:            /**
112:             * Default contstructor
113:             *
114:             * @param chan an <code>IChannel</code> value
115:             * @param runtimeData a <code>ChannelRuntimeData</code> value
116:             * @param threadPool a <code>ThreadPool</code> value
117:             * @param groupSemaphore a <code>SetCheckInSemaphore</code> for the current rendering group
118:             * @param groupRenderingKey an <code>Object</code> to be used for check ins with the group semaphore
119:             */
120:            public ChannelRenderer(IChannel chan,
121:                    ChannelRuntimeData runtimeData,
122:                    PortalControlStructures pcs, ExecutorService threadPool,
123:                    SetCheckInSemaphore groupSemaphore, Object groupRenderingKey) {
124:                this (chan, runtimeData, pcs, threadPool);
125:                this .groupSemaphore = groupSemaphore;
126:                this .groupRenderingKey = groupRenderingKey;
127:            }
128:
129:            /**
130:             * Sets the channel on which ChannelRenderer is to operate.
131:             *
132:             * @param channel an <code>IChannel</code>
133:             */
134:            public void setChannel(IChannel channel) {
135:                if (log.isDebugEnabled())
136:                    log
137:                            .debug("ChannelRenderer::setChannel() : channel is being reset!");
138:                this .channel = channel;
139:                if (this .worker != null) {
140:                    this .worker.setChannel(channel);
141:                }
142:                // clear channel cache
143:                this .channelCache = null;
144:            }
145:
146:            /**
147:             * Obtains a content cache specific for this channel instance.
148:             *
149:             * @return a key->rendering map for this channel
150:             */
151:            // XXX is this thread safe?
152:            Map getChannelCache() {
153:                if (this .channelCache == null) {
154:                    if ((this .channelCache = (SoftHashMap) this .cacheTables
155:                            .get(this .channel)) == null) {
156:                        this .channelCache = new SoftHashMap(1);
157:                        this .cacheTables.put(this .channel, this .channelCache);
158:                    }
159:                }
160:                return this .channelCache;
161:            }
162:
163:            /**
164:             * Set the timeout value
165:             * @param value timeout in milliseconds
166:             */
167:            public void setTimeout(long value) {
168:                this .timeOut = value;
169:            }
170:
171:            public void setCacheTables(Map cacheTables) {
172:                this .cacheTables = cacheTables;
173:            }
174:
175:            /**
176:             * Informs IChannelRenderer that a character caching scheme
177:             * will be used for the current rendering.
178:             * @param setting a <code>boolean</code> value
179:             */
180:            public void setCharacterCacheable(boolean setting) {
181:                this .ccacheable = setting;
182:            }
183:
184:            /**
185:             * Start rendering of the channel in a new thread.
186:             * Note that rendered information will be accumulated in a
187:             * buffer until outputRendering() function is called.
188:             * startRendering() is a non-blocking function.
189:             */
190:            public void startRendering() {
191:                // start the rendering thread
192:
193:                //Pass the Request/Response for this thread into the worker so it can use them in the pool thread
194:                this .worker = new Worker(this .channel, this .rd, this .pcs
195:                        .getHttpServletRequest(), this .pcs
196:                        .getHttpServletResponse());
197:
198:                this .workTracker = tp.submit(this .worker); // XXX is execute okay?
199:                this .rendering = true;
200:                this .startTime = System.currentTimeMillis();
201:            }
202:
203:            public void startRendering(SetCheckInSemaphore groupSemaphore,
204:                    Object groupRenderingKey) {
205:                this .groupSemaphore = groupSemaphore;
206:                this .groupRenderingKey = groupRenderingKey;
207:                this .startRendering();
208:            }
209:
210:            /**
211:             * <p>Cancels the rendering job.
212:             **/
213:            public void cancelRendering() {
214:                if (null != this .workTracker) {
215:                    this .workTracker.cancel(true);
216:                }
217:            }
218:
219:            /**
220:             * Output channel rendering through a given ContentHandler.
221:             * Note: call of outputRendering() without prior call to startRendering() is equivalent to
222:             * sequential calling of startRendering() and then outputRendering().
223:             * outputRendering() is a blocking function. It will return only when the channel completes rendering
224:             * or fails to render by exceeding allowed rendering time.
225:             * @param out Document Handler that will receive information rendered by the channel.
226:             * @return error code. 0 - successful rendering; 1 - rendering failed; 2 - rendering timedOut;
227:             */
228:            public int outputRendering(ContentHandler out) throws Throwable {
229:                int renderingStatus = completeRendering();
230:                if (renderingStatus == RENDERING_SUCCESSFUL) {
231:                    SAX2BufferImpl buffer;
232:                    if ((buffer = this .worker.getBuffer()) != null) {
233:                        // unplug the buffer :)
234:                        try {
235:                            buffer.setAllHandlers(out);
236:                            buffer.outputBuffer();
237:                            return RENDERING_SUCCESSFUL;
238:                        } catch (SAXException e) {
239:                            // worst case scenario: partial content output :(
240:                            log
241:                                    .error("ChannelRenderer::outputRendering() : following SAX exception occured : "
242:                                            + e);
243:                            throw e;
244:                        }
245:                    } else {
246:                        log
247:                                .error("ChannelRenderer::outputRendering() : output buffer is null even though rendering was a success?! trying to rendering for ccaching ?");
248:                        throw new PortalException(
249:                                "unable to obtain rendering buffer");
250:                    }
251:                }
252:                return renderingStatus;
253:            }
254:
255:            /**
256:             * Requests renderer to complete rendering and return status.
257:             * This does exactly the same things as outputRendering except for the
258:             * actual stream output.
259:             *
260:             * @return an <code>int</code> return status value
261:             */
262:
263:            public int completeRendering() throws Throwable {
264:                if (!this .rendering) {
265:                    this .startRendering();
266:                }
267:                boolean abandoned = false;
268:                long timeOutTarget = this .startTime + this .timeOut;
269:
270:                // separate waits caused by rendering group
271:                if (this .groupSemaphore != null) {
272:                    while (!this .worker.isSetRuntimeDataComplete()
273:                            && System.currentTimeMillis() < timeOutTarget
274:                            && !this .workTracker.isDone()) {
275:                        long wait = timeOutTarget - System.currentTimeMillis();
276:                        if (wait <= 0) {
277:                            wait = 1;
278:                        }
279:                        try {
280:                            synchronized (this .groupSemaphore) {
281:                                this .groupSemaphore.wait(wait);
282:                            }
283:                        } catch (InterruptedException ie) {
284:                        }
285:                    }
286:                    if (!this .worker.isSetRuntimeDataComplete()
287:                            && !this .workTracker.isDone()) {
288:                        this .workTracker.cancel(true);
289:                        abandoned = true;
290:                        if (log.isDebugEnabled())
291:                            log
292:                                    .debug("ChannelRenderer::outputRendering() : killed. "
293:                                            + "(key="
294:                                            + this .groupRenderingKey.toString()
295:                                            + ")");
296:                    } else {
297:                        this .groupSemaphore.waitOn();
298:                    }
299:                    // reset timer for rendering
300:                    timeOutTarget = System.currentTimeMillis() + this .timeOut;
301:                }
302:
303:                if (!abandoned) {
304:                    try {
305:                        this .workTracker.get(this .timeOut,
306:                                TimeUnit.MILLISECONDS);
307:                    } catch (TimeoutException te) {
308:                        if (log.isDebugEnabled()) {
309:                            log.debug(
310:                                    "ChannelRenderer::outputRendering() : channel ["
311:                                            + this .channel + "] timed out", te);
312:                        }
313:                    } catch (CancellationException ce) {
314:
315:                        if (log.isDebugEnabled()) {
316:                            Throwable t = null;
317:                            try {
318:                                // in a try block to ensure further errors don't block reporting
319:                                // the CancellationException.
320:                                t = this .worker.getException();
321:                            } catch (Exception e) {
322:                                // ignore problem in getting the exception to report.
323:                            }
324:                            log
325:                                    .debug("ChannelRenderer::outputRendering() : channel ["
326:                                            + this .channel
327:                                            + "] threw an exception ["
328:                                            + t
329:                                            + "] and so its task was cancelled.");
330:                        }
331:
332:                    } catch (Exception e) {
333:                        // no matter what went wrong (CancellationException, a NullPointerException, etc.)
334:                        // the recovery code following this attempt to get the result from the workTracker Future
335:                        // should be allowed to run.
336:                        log
337:                                .error(
338:                                        "Unexpected exceptional condition trying to get the result from the workTracker Future rendering channel ["
339:                                                + this .channel + "].", e);
340:                    }
341:
342:                    if (!this .workTracker.isDone()) {
343:                        this .workTracker.cancel(true);
344:                        abandoned = true;
345:                        if (log.isDebugEnabled())
346:                            log
347:                                    .debug("ChannelRenderer::outputRendering() : killed.");
348:                    } else {
349:                        boolean successful = this .workTracker.isDone()
350:                                && !this .workTracker.isCancelled()
351:                                && this .worker.getException() == null;
352:                        abandoned = !successful;
353:                    }
354:
355:                }
356:
357:                if (!abandoned && this .worker.done()) {
358:                    if (this .worker.successful()
359:                            && (((this .worker.getBuffer()) != null) || (this .ccacheable && this .worker.cbuffer != null))) {
360:                        return RENDERING_SUCCESSFUL;
361:
362:                    } else {
363:                        // rendering was not successful
364:                        Throwable e;
365:                        if ((e = this .worker.getException()) != null)
366:                            throw new InternalPortalException(e);
367:                        // should never get there, unless thread.stop() has seriously messed things up for the worker thread.
368:                        return RENDERING_FAILED;
369:                    }
370:                } else {
371:                    Throwable e = null;
372:                    if (this .worker != null) {
373:                        e = this .worker.getException();
374:                    }
375:
376:                    if (e != null) {
377:                        throw new InternalPortalException(e);
378:                    } else {
379:                        // Assume rendering has timed out
380:                        return RENDERING_TIMED_OUT;
381:                    }
382:                }
383:            }
384:
385:            /**
386:             * Returns rendered buffer.
387:             * This method does not perform any status checks, so make sure to call completeRendering() prior to invoking this method.
388:             *
389:             * @return rendered buffer
390:             */
391:            public SAX2BufferImpl getBuffer() {
392:                return this .worker != null ? this .worker.getBuffer() : null;
393:            }
394:
395:            /**
396:             * Returns a character output of a channel rendering.
397:             */
398:            public String getCharacters() {
399:                if (this .worker != null) {
400:                    return this .worker.getCharacters();
401:                }
402:
403:                if (log.isDebugEnabled()) {
404:                    log
405:                            .debug("ChannelRenderer::getCharacters() : worker is null already !");
406:                }
407:
408:                return null;
409:            }
410:
411:            /**
412:             * Sets a character cache for the current rendering.
413:             */
414:            public void setCharacterCache(String chars) {
415:                if (this .worker != null) {
416:                    this .worker.setCharacterCache(chars);
417:                }
418:            }
419:
420:            /**
421:             * This method suppose to take care of the runaway rendering threads.
422:             * This method will be called from ChannelManager explictly.
423:             */
424:            protected void kill() {
425:                if (this .workTracker != null && !this .workTracker.isDone())
426:                    this .workTracker.cancel(true);
427:            }
428:
429:            public String toString() {
430:                StringBuffer sb = new StringBuffer();
431:
432:                sb.append("ChannelRenderer ");
433:                sb.append("channel = [").append(this .channel).append("] ");
434:                sb.append("rd = [").append(this .rd).append("] ");
435:                sb.append("rendering=").append(this .rendering).append(" ");
436:                sb.append("donerendering=").append(this .donerendering).append(
437:                        " ");
438:                sb.append("startTime=").append(this .startTime).append(" ");
439:                sb.append("timeOut=").append(this .timeOut).append(" ");
440:
441:                return sb.toString();
442:            }
443:
444:            public String getChannelTitle() {
445:
446:                if (log.isTraceEnabled()) {
447:                    log.trace("Getting channel title for ChannelRenderer "
448:                            + this );
449:                }
450:
451:                // default to null, which indicates the ChannelRenderer doesn't have
452:                // a dynamic channel title available.
453:                String channelTitle = null;
454:                try {
455:                    // block on channel rendering to allow channel opportunity to
456:                    // provide dynamic title.
457:                    int renderingStatus = completeRendering();
458:                    if (renderingStatus == RENDERING_SUCCESSFUL) {
459:                        channelTitle = this .worker.getChannelTitle();
460:                    }
461:                } catch (Throwable t) {
462:                    log.error(
463:                            "Channel rendering failed while getting title for channel renderer "
464:                                    + this , t);
465:                }
466:
467:                // will be null indicating no dynamic title unless successfully obtained title.
468:                return channelTitle;
469:
470:            }
471:
472:            protected class Worker extends BaseTask {
473:                private boolean successful;
474:                private boolean done;
475:                private boolean setRuntimeDataComplete;
476:                private IChannel channel;
477:                private ChannelRuntimeData rd;
478:                private SAX2BufferImpl buffer;
479:                private String cbuffer;
480:                private HttpServletRequest req;
481:                private HttpServletResponse res;
482:
483:                /**
484:                 * The dynamic title of the channel, if any.  Null otherwise.
485:                 */
486:                private String channelTitle = null;
487:
488:                //Pass the request/response into the worker, this will allow the objects
489:                //to be passed into the ThreadLocalized PortalControlStructures when execute()
490:                //is called by the worker thread.
491:                public Worker(IChannel ch, ChannelRuntimeData runtimeData,
492:                        HttpServletRequest req, HttpServletResponse res) {
493:                    this .channel = ch;
494:                    this .rd = runtimeData;
495:                    successful = false;
496:                    done = false;
497:                    setRuntimeDataComplete = false;
498:                    buffer = null;
499:                    cbuffer = null;
500:                    this .req = new AttributeScopingRequestWrapper(req);
501:                    this .res = res;
502:                }
503:
504:                public void setChannel(IChannel ch) {
505:                    this .channel = ch;
506:                }
507:
508:                public boolean isSetRuntimeDataComplete() {
509:                    return this .setRuntimeDataComplete;
510:                }
511:
512:                public void execute() throws Exception {
513:                    try {
514:                        if (pcs != null) {
515:                            //Set the request/response for this thread.
516:                            pcs.setHttpServletRequest(this .req);
517:                            pcs.setHttpServletResponse(this .res);
518:
519:                            if (channel instanceof  IPrivileged) {
520:                                ((IPrivileged) channel)
521:                                        .setPortalControlStructures(pcs);
522:                            }
523:                        }
524:
525:                        if (rd != null) {
526:                            channel.setRuntimeData(rd);
527:                        }
528:                        setRuntimeDataComplete = true;
529:
530:                        if (groupSemaphore != null) {
531:                            groupSemaphore.checkInAndWaitOn(groupRenderingKey);
532:                        }
533:
534:                        if (CACHE_CHANNELS) {
535:                            // try to obtain rendering from cache
536:                            if (channel instanceof  ICacheable) {
537:                                ChannelCacheKey key = ((ICacheable) channel)
538:                                        .generateKey();
539:                                if (key != null) {
540:                                    if (key.getKeyScope() == ChannelCacheKey.SYSTEM_KEY_SCOPE) {
541:                                        ChannelCacheEntry entry = (ChannelCacheEntry) systemCache
542:                                                .get(key.getKey());
543:                                        if (entry != null) {
544:                                            // found cached page
545:                                            // check page validity
546:                                            if (((ICacheable) channel)
547:                                                    .isCacheValid(entry.validity)
548:                                                    && (entry.buffer != null)) {
549:                                                // use it
550:                                                if (ccacheable
551:                                                        && (entry.buffer instanceof  String)) {
552:                                                    cbuffer = (String) entry.buffer;
553:                                                    if (log.isDebugEnabled()) {
554:                                                        log
555:                                                                .debug("ChannelRenderer.Worker::run() : retrieved system-wide cached character content based on a key \""
556:                                                                        + key
557:                                                                                .getKey()
558:                                                                        + "\"");
559:                                                    }
560:                                                } else if (entry.buffer instanceof  SAX2BufferImpl) {
561:                                                    buffer = (SAX2BufferImpl) entry.buffer;
562:                                                    if (log.isDebugEnabled()) {
563:                                                        log
564:                                                                .debug("ChannelRenderer.Worker::run() : retrieved system-wide cached content based on a key \""
565:                                                                        + key
566:                                                                                .getKey()
567:                                                                        + "\"");
568:                                                    }
569:                                                }
570:                                            } else {
571:                                                // remove it
572:                                                systemCache
573:                                                        .remove(key.getKey());
574:                                                if (log.isDebugEnabled()) {
575:                                                    log
576:                                                            .debug("ChannelRenderer.Worker::run() : removed system-wide unvalidated cache based on a key \""
577:                                                                    + key
578:                                                                            .getKey()
579:                                                                    + "\"");
580:                                                }
581:                                            }
582:                                        }
583:                                    } else {
584:                                        // by default we assume INSTANCE_KEY_SCOPE
585:                                        ChannelCacheEntry entry = (ChannelCacheEntry) getChannelCache()
586:                                                .get(key.getKey());
587:                                        if (entry != null) {
588:                                            // found cached page
589:                                            // check page validity
590:                                            if (((ICacheable) channel)
591:                                                    .isCacheValid(entry.validity)
592:                                                    && (entry.buffer != null)) {
593:                                                // use it
594:                                                if (ccacheable
595:                                                        && (entry.buffer instanceof  String)) {
596:                                                    cbuffer = (String) entry.buffer;
597:                                                    if (log.isDebugEnabled()) {
598:                                                        log
599:                                                                .debug("ChannelRenderer.Worker::run() : retrieved instance-cached character content based on a key \""
600:                                                                        + key
601:                                                                                .getKey()
602:                                                                        + "\"");
603:                                                    }
604:
605:                                                } else if (entry.buffer instanceof  SAX2BufferImpl) {
606:                                                    buffer = (SAX2BufferImpl) entry.buffer;
607:                                                    if (log.isDebugEnabled()) {
608:                                                        log
609:                                                                .debug("ChannelRenderer.Worker::run() : retrieved instance-cached content based on a key \""
610:                                                                        + key
611:                                                                                .getKey()
612:                                                                        + "\"");
613:                                                    }
614:                                                }
615:                                            } else {
616:                                                // remove it
617:                                                getChannelCache().remove(
618:                                                        key.getKey());
619:                                                if (log.isDebugEnabled()) {
620:                                                    log
621:                                                            .debug("ChannelRenderer.Worker::run() : removed unvalidated instance-cache based on a key \""
622:                                                                    + key
623:                                                                            .getKey()
624:                                                                    + "\"");
625:                                                }
626:                                            }
627:                                        }
628:                                    }
629:                                }
630:
631:                                // future work: here we should synchronize based on a particular cache key.
632:                                // Imagine a VERY popular cache entry timing out, then portal will attempt
633:                                // to re-render the page in many threads (serving many requests) simultaneously.
634:                                // If one was to synchronize on writing cache for a particular key, one thread
635:                                // would render and others would wait for it to complete.
636:
637:                                // check if need to render
638:                                if ((ccacheable && cbuffer == null && buffer == null)
639:                                        || ((!ccacheable) && buffer == null)) {
640:                                    if (ccacheable
641:                                            && channel instanceof  ICharacterChannel) {
642:                                        StringWriter sw = new StringWriter(100);
643:                                        PrintWriter pw = new PrintWriter(sw);
644:                                        ((ICharacterChannel) channel)
645:                                                .renderCharacters(pw);
646:                                        pw.flush();
647:                                        cbuffer = sw.toString();
648:                                        // save cache
649:                                        if (key != null) {
650:                                            if (key.getKeyScope() == ChannelCacheKey.SYSTEM_KEY_SCOPE) {
651:                                                systemCache
652:                                                        .put(
653:                                                                key.getKey(),
654:                                                                new ChannelCacheEntry(
655:                                                                        cbuffer,
656:                                                                        key
657:                                                                                .getKeyValidity()));
658:                                                if (log.isDebugEnabled()) {
659:                                                    log
660:                                                            .debug("ChannelRenderer.Worker::run() : recorded system character cache based on a key \""
661:                                                                    + key
662:                                                                            .getKey()
663:                                                                    + "\"");
664:                                                }
665:                                            } else {
666:                                                getChannelCache()
667:                                                        .put(
668:                                                                key.getKey(),
669:                                                                new ChannelCacheEntry(
670:                                                                        cbuffer,
671:                                                                        key
672:                                                                                .getKeyValidity()));
673:                                                if (log.isDebugEnabled()) {
674:                                                    log
675:                                                            .debug("ChannelRenderer.Worker::run() : recorded instance character cache based on a key \""
676:                                                                    + key
677:                                                                            .getKey()
678:                                                                    + "\"");
679:                                                }
680:                                            }
681:                                        }
682:                                    } else {
683:                                        // need to render again and cache the output
684:                                        buffer = new SAX2BufferImpl();
685:                                        buffer.startBuffering();
686:                                        channel.renderXML(buffer);
687:
688:                                        // save cache
689:                                        if (key != null) {
690:
691:                                            if (key.getKeyScope() == ChannelCacheKey.SYSTEM_KEY_SCOPE) {
692:                                                systemCache
693:                                                        .put(
694:                                                                key.getKey(),
695:                                                                new ChannelCacheEntry(
696:                                                                        buffer,
697:                                                                        key
698:                                                                                .getKeyValidity()));
699:                                                if (log.isDebugEnabled()) {
700:                                                    log
701:                                                            .debug("ChannelRenderer.Worker::run() : recorded system cache based on a key \""
702:                                                                    + key
703:                                                                            .getKey()
704:                                                                    + "\"");
705:                                                }
706:                                            } else {
707:                                                getChannelCache()
708:                                                        .put(
709:                                                                key.getKey(),
710:                                                                new ChannelCacheEntry(
711:                                                                        buffer,
712:                                                                        key
713:                                                                                .getKeyValidity()));
714:                                                if (log.isDebugEnabled()) {
715:                                                    log
716:                                                            .debug("ChannelRenderer.Worker::run() : recorded instance cache based on a key \""
717:                                                                    + key
718:                                                                            .getKey()
719:                                                                    + "\"");
720:                                                }
721:                                            }
722:                                        }
723:                                    }
724:                                }
725:                            } else {
726:                                if (ccacheable
727:                                        && channel instanceof  ICharacterChannel) {
728:                                    StringWriter sw = new StringWriter(100);
729:                                    PrintWriter pw = new PrintWriter(sw);
730:                                    ((ICharacterChannel) channel)
731:                                            .renderCharacters(pw);
732:                                    pw.flush();
733:                                    cbuffer = sw.toString();
734:                                } else {
735:                                    buffer = new SAX2BufferImpl();
736:                                    buffer.startBuffering();
737:                                    channel.renderXML(buffer);
738:                                }
739:                            }
740:                        } else {
741:                            // in the case when channel cache is not enabled
742:                            buffer = new SAX2BufferImpl();
743:                            buffer.startBuffering();
744:                            channel.renderXML(buffer);
745:                        }
746:                        successful = true;
747:                    } catch (Exception e) {
748:                        if (groupSemaphore != null) {
749:                            groupSemaphore.checkIn(groupRenderingKey);
750:                        }
751:                        this .setException(e);
752:                    } finally {
753:                        if (pcs != null) {
754:                            //Clear the request/response for this thread
755:                            pcs.setHttpServletRequest(null);
756:                            pcs.setHttpServletResponse(null);
757:                        }
758:                    }
759:
760:                    /*
761:                     * Get the channel's ChannelRuntimeProperties, and handle them.
762:                     */
763:                    processChannelRuntimeProperties();
764:
765:                    done = true;
766:                }
767:
768:                /**
769:                 * Query the channel for ChannelRuntimePRoperties and process those
770:                 * properties.
771:                 *
772:                 * Currently, only handles the optional {@link IChannelTitle} interface.
773:                 */
774:                private void processChannelRuntimeProperties() {
775:                    ChannelRuntimeProperties channelProps = this .channel
776:                            .getRuntimeProperties();
777:
778:                    if (channelProps != null) {
779:                        if (channelProps instanceof  IChannelTitle) {
780:
781:                            this .channelTitle = ((IChannelTitle) channelProps)
782:                                    .getChannelTitle();
783:                            if (log.isTraceEnabled()) {
784:                                log.trace("Read title " + this .channelTitle
785:                                        + ".");
786:                            }
787:                        } else {
788:                            if (log.isTraceEnabled()) {
789:                                log
790:                                        .trace("ChannelRuntimeProperties were non-null but did not implement ITitleable.");
791:                            }
792:                        }
793:                    } else {
794:                        if (log.isTraceEnabled()) {
795:                            log
796:                                    .trace("ChannelRuntimeProperties were null from channel "
797:                                            + channel);
798:                        }
799:                    }
800:                }
801:
802:                public boolean successful() {
803:                    return this .successful;
804:                }
805:
806:                public SAX2BufferImpl getBuffer() {
807:                    return this .buffer;
808:                }
809:
810:                /**
811:                 * Returns a character output of a channel rendering.
812:                 */
813:                public String getCharacters() {
814:                    if (ccacheable) {
815:                        return this .cbuffer;
816:                    } else {
817:                        log
818:                                .error("ChannelRenderer.Worker::getCharacters() : attempting to obtain character data while character caching is not enabled !");
819:                        return null;
820:                    }
821:                }
822:
823:                /**
824:                 * Sets a character cache for the current rendering.
825:                 */
826:                public void setCharacterCache(String chars) {
827:                    cbuffer = chars;
828:                    if (CACHE_CHANNELS) {
829:                        // try to obtain rendering from cache
830:                        if (channel instanceof  ICacheable) {
831:                            ChannelCacheKey key = ((ICacheable) channel)
832:                                    .generateKey();
833:                            if (key != null) {
834:                                if (log.isDebugEnabled()) {
835:                                    log
836:                                            .debug("ChannelRenderer::setCharacterCache() : called on a key \""
837:                                                    + key.getKey() + "\"");
838:                                }
839:                                ChannelCacheEntry entry = null;
840:                                if (key.getKeyScope() == ChannelCacheKey.SYSTEM_KEY_SCOPE) {
841:                                    entry = (ChannelCacheEntry) systemCache
842:                                            .get(key.getKey());
843:                                    if (entry == null) {
844:                                        if (log.isDebugEnabled()) {
845:                                            log
846:                                                    .debug("ChannelRenderer::setCharacterCache() : setting character cache buffer based on a system key \""
847:                                                            + key.getKey()
848:                                                            + "\"");
849:                                        }
850:                                        entry = new ChannelCacheEntry(chars,
851:                                                key.getKeyValidity());
852:                                    } else {
853:                                        entry.buffer = chars;
854:                                    }
855:                                    systemCache.put(key.getKey(), entry);
856:                                } else {
857:                                    // by default we assume INSTANCE_KEY_SCOPE
858:                                    entry = (ChannelCacheEntry) getChannelCache()
859:                                            .get(key.getKey());
860:                                    if (entry == null) {
861:                                        if (log.isDebugEnabled()) {
862:                                            log
863:                                                    .debug("ChannelRenderer::setCharacterCache() : no existing cache on a key \""
864:                                                            + key.getKey()
865:                                                            + "\"");
866:                                        }
867:                                        entry = new ChannelCacheEntry(chars,
868:                                                key.getKeyValidity());
869:                                    } else {
870:                                        entry.buffer = chars;
871:                                    }
872:                                    getChannelCache().put(key.getKey(), entry);
873:                                }
874:                            } else {
875:                                if (log.isDebugEnabled()) {
876:                                    log
877:                                            .debug("ChannelRenderer::setCharacterCache() : channel cache key is null.");
878:                                }
879:                            }
880:                        }
881:                    }
882:                }
883:
884:                public boolean done() {
885:                    return this .done;
886:                }
887:
888:                /**
889:                 * Get a Sring representing the dynamic channel title reported by the
890:                 * IChannel this ChannelRenderer rendered.  Returns null if the channel
891:                 * reported no such title or the channel isn't done rendering.
892:                 *
893:                 * @return dynamic channel title, or null if no title available.
894:                 */
895:                String getChannelTitle() {
896:
897:                    if (log.isTraceEnabled()) {
898:                        log.trace("Getting channel title (" + this .channelTitle
899:                                + "] for " + this );
900:                    }
901:
902:                    // currently, just provides no dynamic title if not done rendering
903:                    if (this.done) {
904:                        return this.channelTitle;
905:                    } else {
906:                        return null;
907:                    }
908:                }
909:            }
910:
911:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.