1
24 package net.sf.jasperreports.engine.fill;
25
26 import java.util.concurrent.ExecutorService;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.ThreadFactory;
29 import java.util.concurrent.atomic.AtomicInteger;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33
34
35
38 public class ThreadPoolSubreportRunnerFactory implements JRSubreportRunnerFactory
39 {
40 private static final Log log = LogFactory.getLog(ThreadPoolSubreportRunnerFactory.class);
41
42 private static final String THREAD_POOL_KEY = "net.sf.jasperreports.engine.fill.JRThreadSubreportRunner.ThreadPool";
43
44 @Override
45 public JRSubreportRunner createSubreportRunner(JRFillSubreport fillSubreport, JRBaseFiller subreportFiller)
46 {
47 JRFillContext fillContext = subreportFiller.getFillContext();
48 ExecutorServiceDisposable executor = (ExecutorServiceDisposable) fillContext.getFillCache(THREAD_POOL_KEY);
49 if (executor == null)
50 {
51 ExecutorService threadExecutor = createThreadExecutor(fillContext);
52 executor = new ExecutorServiceDisposable(threadExecutor);
53 fillContext.setFillCache(THREAD_POOL_KEY, executor);
54 }
55
56 return new ThreadExecutorSubreportRunner(fillSubreport, subreportFiller,
57 executor.getExecutorService());
58 }
59
60 protected ExecutorService createThreadExecutor(JRFillContext fillContext)
61 {
62 SubreportsThreadFactory threadFactory = new SubreportsThreadFactory(fillContext);
63 ExecutorService threadExecutor = Executors.newCachedThreadPool(threadFactory);
64 if (log.isDebugEnabled())
65 {
66 log.debug("created subreports thread executor " + threadExecutor
67 + " for " + fillContext.getMasterFiller().getJasperReport().getName());
68 }
69 return threadExecutor;
70 }
71
72 protected static class ExecutorServiceDisposable implements JRFillContext.FillCacheDisposable
73 {
74 private final ExecutorService executorService;
75
76 public ExecutorServiceDisposable(ExecutorService executorService)
77 {
78 this.executorService = executorService;
79 }
80
81 public ExecutorService getExecutorService()
82 {
83 return executorService;
84 }
85
86 @Override
87 public void dispose()
88 {
89 if (log.isDebugEnabled())
90 {
91 log.debug("shutting down " + executorService);
92 }
93
94 executorService.shutdownNow();
95 }
96 }
97
98 protected static class SubreportsThreadFactory implements ThreadFactory
99 {
100 private final JRFillContext fillContext;
101 private final AtomicInteger threadCount;
102
103 public SubreportsThreadFactory(JRFillContext fillContext)
104 {
105 this.fillContext = fillContext;
106 this.threadCount = new AtomicInteger();
107 }
108
109 @Override
110 public Thread newThread(Runnable r)
111 {
112 String threadName = fillContext.getMasterFiller().getJasperReport().getName()
113 + " subreports #" + threadCount.incrementAndGet();
114 Thread thread = new Thread(r, threadName);
115 if (log.isDebugEnabled())
116 {
117 log.debug("created thread " + thread);
118 }
119 return thread;
120 }
121
122 }
123 }
124