OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 132 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 132 Rev 180
Line 37... Line 37...
37
import java.util.List;
37
import java.util.List;
38
import java.util.Map;
38
import java.util.Map;
39
import java.util.Map.Entry;
39
import java.util.Map.Entry;
40
import java.util.Stack;
40
import java.util.Stack;
41
import java.util.concurrent.Callable;
41
import java.util.concurrent.Callable;
42
import java.util.concurrent.ExecutionException;
-
 
43
import java.util.concurrent.FutureTask;
42
import java.util.concurrent.FutureTask;
-
 
43
import java.util.concurrent.TimeoutException;
44
 
44
 
45
import org.jdom.Element;
45
import org.jdom.Element;
46
import org.jdom.JDOMException;
46
import org.jdom.JDOMException;
47
import org.jdom.filter.Filter;
47
import org.jdom.filter.Filter;
48
 
48
 
-
 
49
import net.jcip.annotations.GuardedBy;
49
import ognl.Ognl;
50
import ognl.Ognl;
50
import ognl.OgnlException;
51
import ognl.OgnlException;
51
import ognl.OgnlRuntime;
52
import ognl.OgnlRuntime;
52
import ognl.PropertyAccessor;
53
import ognl.PropertyAccessor;
53
 
54
 
Line 85... Line 86...
85
    private C common;
86
    private C common;
86
    private XMLFormatVersion formatVersion;
87
    private XMLFormatVersion formatVersion;
87
    // Inheritable to allow generators to spawn threads
88
    // Inheritable to allow generators to spawn threads
88
    private final InheritableThreadLocal<ReportPart> currentParts;
89
    private final InheritableThreadLocal<ReportPart> currentParts;
89
    private final InheritableThreadLocal<DocumentGenerator> currentGenerator;
90
    private final InheritableThreadLocal<DocumentGenerator> currentGenerator;
-
 
91
    @GuardedBy("this")
90
    private Throwable interruptCause;
92
    private Throwable interruptCause;
91
    // tous les générateurs s'exécuter dans ce groupe
93
    // tous les générateurs s'exécuter dans ce groupe
-
 
94
    @GuardedBy("this")
92
    private final ThreadGroup thg;
95
    private List<Thread> thg;
93
    private final List<PropertyChangeListener> taskListeners;
96
    private final List<PropertyChangeListener> taskListeners;
94
    private final PropertyChangeListener taskListener;
97
    private final PropertyChangeListener taskListener;
95
    private Map<String, Object> commonData;
98
    private Map<String, Object> commonData;
96
 
99
 
97
    /**
100
    /**
Line 107... Line 110...
107
        this.commonData = null;
110
        this.commonData = null;
108
 
111
 
109
        this.currentParts = new InheritableThreadLocal<ReportPart>();
112
        this.currentParts = new InheritableThreadLocal<ReportPart>();
110
        this.currentGenerator = new InheritableThreadLocal<DocumentGenerator>();
113
        this.currentGenerator = new InheritableThreadLocal<DocumentGenerator>();
111
        this.interruptCause = null;
114
        this.interruptCause = null;
112
        this.thg = new ThreadGroup("Generateurs") {
-
 
113
            public void uncaughtException(Thread t, Throwable e) {
-
 
114
                ReportGeneration.this.interrupt(e);
-
 
115
            }
115
        this.thg = null;
116
        };
-
 
117
 
116
 
118
        this.taskListeners = new ArrayList<PropertyChangeListener>();
117
        this.taskListeners = new ArrayList<PropertyChangeListener>();
119
        this.taskListener = new PropertyChangeListener() {
118
        this.taskListener = new PropertyChangeListener() {
120
            public void propertyChange(PropertyChangeEvent evt) {
119
            public void propertyChange(PropertyChangeEvent evt) {
121
                for (final PropertyChangeListener l : ReportGeneration.this.taskListeners) {
120
                for (final PropertyChangeListener l : ReportGeneration.this.taskListeners) {
Line 196... Line 195...
196
     * @see #generate()
195
     * @see #generate()
197
     */
196
     */
198
    public final Map<String, ODSingleXMLDocument> generateMulti() throws Throwable {
197
    public final Map<String, ODSingleXMLDocument> generateMulti() throws Throwable {
199
        synchronized (this) {
198
        synchronized (this) {
200
            this.interruptCause = null;
199
            this.interruptCause = null;
-
 
200
            this.thg = new ArrayList<>();
201
        }
201
        }
202
 
202
 
203
        Map<String, ODSingleXMLDocument> f = null;
203
        Map<String, ODSingleXMLDocument> f = null;
204
        final FutureTask<Map<String, ODSingleXMLDocument>> future = new FutureTask<Map<String, ODSingleXMLDocument>>(new Callable<Map<String, ODSingleXMLDocument>>() {
204
        final FutureTask<Map<String, ODSingleXMLDocument>> future = new FutureTask<Map<String, ODSingleXMLDocument>>(new Callable<Map<String, ODSingleXMLDocument>>() {
205
            public Map<String, ODSingleXMLDocument> call() throws Exception {
205
            public Map<String, ODSingleXMLDocument> call() throws Exception {
206
                return createDocument();
206
                return createDocument();
207
            }
207
            }
208
        });
208
        });
-
 
209
        // Don't pass a ThreadGroup, since every thread created, including "cache timeout", JDBC
-
 
210
        // threads will be in it. But these threads must out-live this generation.
209
        final Thread thr = new Thread(this.thg, future);
211
        final Thread thr = new Thread(null, future);
-
 
212
        this.registerThread(thr);
210
        thr.start();
213
        thr.start();
211
        try {
214
        try {
212
            thr.join();
-
 
213
            f = future.get();
215
            f = future.get();
214
        } catch (Exception e) {
216
        } catch (Exception e) {
215
            if (isInterruptedExn(e) || (e instanceof ExecutionException && isInterruptedExn(e.getCause())))
-
 
216
                f = null;
217
            assert f == null;
217
            else
218
            // If one thread was interrupted (or failed), interrupt the others
218
                this.interrupt(e);
219
            this.interrupt(e);
-
 
220
        } finally {
-
 
221
            // Make sure all threads are stopped and don't prevent this from being garbage
-
 
222
            // collected.
-
 
223
            final List<Thread> toJoin;
-
 
224
            synchronized (this) {
-
 
225
                toJoin = this.thg;
-
 
226
                this.thg = null;
-
 
227
            }
-
 
228
            for (final Thread t : toJoin) {
-
 
229
                // If no exception occurred, then should already be finished but if there was one in
-
 
230
                // a thread, another thread might be stuck on some I/O for a while before it can
-
 
231
                // process the interrupt.
-
 
232
                t.join(4500);
-
 
233
                if (t.isAlive())
-
 
234
                    throw new TimeoutException("Thread still not terminated : " + t);
-
 
235
            }
219
        }
236
        }
220
 
237
 
221
        final Map<String, ODSingleXMLDocument> res;
238
        final Map<String, ODSingleXMLDocument> res;
222
        synchronized (this) {
239
        synchronized (this) {
223
            if (this.interruptCause != null && !isInterruptedExn(this.interruptCause)) {
240
            if (this.interruptCause != null && !isInterruptedExn(this.interruptCause)) {
Line 234... Line 251...
234
            }
251
            }
235
        }
252
        }
236
        return res;
253
        return res;
237
    }
254
    }
238
 
255
 
-
 
256
    public final synchronized void registerThread(final Thread thr) {
-
 
257
        this.thg.add(thr);
-
 
258
    }
-
 
259
 
239
    protected final void interrupt(Throwable cause) {
260
    protected final void interrupt(Throwable cause) {
240
        synchronized (this) {
261
        synchronized (this) {
241
            if (this.interruptCause == null) {
262
            if (this.interruptCause == null) {
242
                this.interruptCause = cause;
263
                this.interruptCause = cause;
-
 
264
                for (final Thread thr : this.thg) {
243
                this.thg.interrupt();
265
                    thr.interrupt();
-
 
266
                }
244
            }
267
            }
245
        }
268
        }
246
    }
269
    }
247
 
270
 
248
    private Map<String, ODSingleXMLDocument> createDocument() throws IOException, OgnlException, InterruptedException {
271
    private Map<String, ODSingleXMLDocument> createDocument() throws IOException, OgnlException, InterruptedException {
Line 274... Line 297...
274
            }
297
            }
275
            if (this.mustGenerate(part)) {
298
            if (this.mustGenerate(part)) {
276
                if (part instanceof ForkReportPart) {
299
                if (part instanceof ForkReportPart) {
277
                    GenThread thread = new GenThread(part.getName(), ((ForkReportPart) part).getChildren());
300
                    GenThread thread = new GenThread(part.getName(), ((ForkReportPart) part).getChildren());
278
                    forked.put(part.getName(), thread);
301
                    forked.put(part.getName(), thread);
-
 
302
                    this.registerThread(thread);
279
                    thread.start();
303
                    thread.start();
280
                } else if (part instanceof SubReportPart) {
304
                } else if (part instanceof SubReportPart) {
281
                    final SubReportPart subReportPart = (SubReportPart) part;
305
                    final SubReportPart subReportPart = (SubReportPart) part;
282
                    // the document for <sub>
306
                    // the document for <sub>
283
                    final ODSingleXMLDocument newDoc;
307
                    final ODSingleXMLDocument newDoc;