1 /*
2  * JasperReports - Free Java Reporting Library.
3  * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
4  * http://www.jaspersoft.com
5  *
6  * Unless you have purchased a commercial license agreement from Jaspersoft,
7  * the following license terms apply:
8  *
9  * This program is part of JasperReports.
10  *
11  * JasperReports is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * JasperReports is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with JasperReports. If not, see <http://www.gnu.org/licenses/>.
23  */

24 package net.sf.jasperreports.engine;
25
26 import java.io.File;
27 import java.io.InputStream;
28 import java.io.OutputStream;
29 import java.lang.reflect.Constructor;
30 import java.lang.reflect.InvocationTargetException;
31 import java.util.Collection;
32
33 import net.sf.jasperreports.crosstabs.JRCrosstab;
34 import net.sf.jasperreports.engine.design.JRCompiler;
35 import net.sf.jasperreports.engine.design.JRJavacCompiler;
36 import net.sf.jasperreports.engine.design.JRJdk13Compiler;
37 import net.sf.jasperreports.engine.design.JRJdtCompiler;
38 import net.sf.jasperreports.engine.design.JRValidationFault;
39 import net.sf.jasperreports.engine.design.JRVerifier;
40 import net.sf.jasperreports.engine.design.JasperDesign;
41 import net.sf.jasperreports.engine.fill.JREvaluator;
42 import net.sf.jasperreports.engine.fill.JasperReportsContextAware;
43 import net.sf.jasperreports.engine.util.JRClassLoader;
44 import net.sf.jasperreports.engine.util.JRLoader;
45 import net.sf.jasperreports.engine.util.JRSaver;
46 import net.sf.jasperreports.engine.xml.JRXmlLoader;
47 import net.sf.jasperreports.engine.xml.JRXmlWriter;
48
49
50 /**
51  * Facade class for compiling report designs into the ready-to-fill form
52  * and for getting the XML representation of report design objects for
53  * storage or network transfer.
54  * <p>
55  * This class exposes all the library's report compilation functionality. It has
56  * various methods that allow the users to compile JRXML report templates found in files
57  * on disk or that come from input streams. It also lets people compile in-memory report
58  * templates by directly passing a
59  * {@link net.sf.jasperreports.engine.design.JasperDesign} object and receiving the
60  * corresponding {@link net.sf.jasperreports.engine.JasperReport} object.
61  * </p><p>
62  * Other utility methods include report template verification and JRXML report template
63  * generation for in-memory constructed
64  * {@link net.sf.jasperreports.engine.design.JasperDesign} class instances. These
65  * instances are especially useful in GUI tools that simplify report design work.
66  * </p><p>
67  * The facade class relies on the report template language to determine an appropriate report compiler.
68  * The report compilation facade first reads a configuration property called
69  * {@link net.sf.jasperreports.engine.design.JRCompiler#COMPILER_PREFIX net.sf.jasperreports.compiler.&lt;language&gt;} to determine whether a compiler
70  * implementation has been configured for the specific report language. If such a property
71  * is found, its value is used as compiler implementation class name and the facade
72  * instantiates a compiler object and delegates the report compilation to it. By default,
73  * JasperReports includes configuration properties that map the Groovy and JavaScript 
74  * report compilers to the <code>groovy</code> and <code>javascript</code> 
75  * report languages, respectively.
76  * </p><p>
77  * If the report uses Java as language and no specific compiler has been set for this
78  * language, the report compilation facade employs a built-in fall back mechanism that
79  * picks the best Java-based report compiler available in the environment in which the
80  * report compilation process takes place.
81  * </p><p>
82  * The facade first reads the
83  * configuration property called {@link net.sf.jasperreports.engine.design.JRCompiler#COMPILER_CLASS net.sf.jasperreports.compiler.class} to allow
84  * users to override its built-in compiler-detection logic by providing the name of the report
85  * compiler implementation to use directly.
86  * </p><p>
87  * If the property is not provided, the facade first tries to see if the JDT compiler from the 
88  * Eclipse Foundation is available in the application's classpath. If it is, the
89  * {@link net.sf.jasperreports.engine.design.JRJdtCompiler} implementation is used.
90  * </p><p>
91  * If the JDT compiler is not available, the compilation facade then tries to locate the JDK
92  * 1.3-compatible Java compiler from Sun Microsystems. This is normally found in the
93  * <code>tools.jar</code> file that comes with the JDK installation.
94  * </p><p>
95  * If all these fail, the last thing the fall back mechanism does is to try to launch the
96  * <code>javac.exe</code> program from the command line in order to compile the temporarily
97  * generated Java source file on the fly.
98  * </p>
99  * <h3>Configuration Properties to Customize Report Compilation</h3>
100  * JasperReports offers various mechanisms for letting users
101  * customize its behavior. One of these mechanisms is a complete set of configuration
102  * properties. The following list contains all the configuration properties that customize
103  * report compilation.
104  * <dl>
105  * <dt>{@link net.sf.jasperreports.engine.design.JRCompiler#COMPILER_PREFIX net.sf.jasperreports.compiler.&lt;language&gt;}<dt>
106  * <dd>Such properties are used for indicating the name of the class that implements the
107  * {@link net.sf.jasperreports.engine.design.JRCompiler} interface to be instantiated by 
108  * the engine for a specific report language
109  * when the default compilation is used through this facade class. The
110  * value for such a configuration property can be the name of one of the built-in
111  * implementations of this interface shipped with the library as listed previously, or the
112  * name of a custom-made implementing class.
113  * <br/>
114  * One can configure report compilers for custom report languages and override the default
115  * compiler mappings by setting JasperReports properties of the form
116  * {@link net.sf.jasperreports.engine.design.JRCompiler#COMPILER_PREFIX net.sf.jasperreports.compiler.&lt;language&gt;} to the desired compiler
117  * implementation class names. In particular, the mechanism that automatically chooses a
118  * Java report compiler can be superseded by explicitly setting the
119  * <code>net.sf.jasperreports.compiler.java</code> property to the name of one of the built-in
120  * Java compiler classes or of a custom compiler implementation class.
121  * <br/>
122  * Note that the classes implementing the {@link net.sf.jasperreports.engine.design.JRCompiler} 
123  * interface can also be used directly in
124  * the programs without having to call them through this facade class.</dd>
125  * <dt>{@link net.sf.jasperreports.engine.xml.JRReportSaxParserFactory#COMPILER_XML_VALIDATION net.sf.jasperreports.compiler.xml.validation}<dt>
126  * <dd>The XML validation, which is on by default, can be turned off by setting this
127  * configuration property to
128  * false. When turned off, the XML parser no longer validates the supplied JRXML
129  * against its associated XSD. This might prove useful in some environments, although it is
130  * not recommended.</dd>
131  * <dt>{@link net.sf.jasperreports.engine.design.JRCompiler#COMPILER_CLASSPATH net.sf.jasperreports.compiler.classpath}<dt>
132  * <dd>This property
133  * supplies the classpath. JDK-based compilers require that the classpath be
134  * supplied as a parameter. They cannot use the current JVM classpath. The supplied
135  * classpath resolves class references inside the Java code they are compiling.
136  * <br/>
137  * This property is not used by the JDT-based report compiler, which simply uses the parent
138  * application's classpath during Java source file compilation.</dd>
139  * <dt>{@link net.sf.jasperreports.engine.design.JRCompiler#COMPILER_TEMP_DIR net.sf.jasperreports.compiler.temp.dir}<dt>
140  * <dd>The temporary location for the files generated on the fly is by default the current working
141  * directory. It can be changed by supplying a value to this
142  * configuration property. This is used by
143  * the JDT-based compiler only when it is requested that a copy of the on-the-fly generated
144  * Java class be kept for debugging purposes as specified by the next configuration
145  * property, because normally this report compiler does not work with files on disk.</dd>
146  * <dt>{@link net.sf.jasperreports.engine.design.JRCompiler#COMPILER_KEEP_JAVA_FILE net.sf.jasperreports.compiler.keep.java.file}<dt>
147  * <dd>Sometimes, for debugging purposes, it is useful to have the generated <code>*.java</code> file or
148  * generated script in order to fix compilation problems related to report expressions. By
149  * default, the engine deletes this file after report compilation, along with its corresponding
150  * <code>*.class</code> file. To keep it, however, set this configuration property to true.</dd>
151  * </dl>
152  * <h3>JDT Compiler-Specific Configuration Properties</h3>
153  * The JRJdtCompiler report compiler can use special JasperReports configuration
154  * properties to configure the underlying JDT Java compiler. This report compiler collects
155  * all the JasperReports configuration properties (the ones usually set in the
156  * jasperreports.properties file) that start with the <code>org.eclipse.jdt.core.</code> prefix
157  * and passes them to the JDT Java compiler when compiling the generated Java class to
158  * evaluate report expressions.
159  * <p>
160  * One of the uses of this mechanism is to instruct the JDT compiler to observe Java 1.5
161  * code compatibility. To do so, the following properties should be set:</p>
162  * <ul>
163  * <li><code>org.eclipse.jdt.core.compiler.source=1.5</code></li>
164  * <li><code>org.eclipse.jdt.core.compiler.compliance=1.5</code></li>
165  * <li><code>org.eclipse.jdt.core.compiler.codegen.TargetPlatform=1.5</code></li>
166  * </ul>
167  * @see net.sf.jasperreports.engine.JasperReport
168  * @see net.sf.jasperreports.engine.design.JasperDesign
169  * @see net.sf.jasperreports.engine.design.JRCompiler
170  * @see net.sf.jasperreports.engine.design.JRJdtCompiler
171  * @see net.sf.jasperreports.engine.design.JRVerifier
172  * @see net.sf.jasperreports.engine.xml.JRXmlLoader
173  * @see net.sf.jasperreports.engine.xml.JRXmlWriter
174  * @see net.sf.jasperreports.engine.util.JRLoader
175  * @see net.sf.jasperreports.engine.util.JRSaver
176  * @author Teodor Danciu (teodord@users.sourceforge.net)
177  */

178 public final class JasperCompileManager
179 {
180     public static final String EXCEPTION_MESSAGE_KEY_INSTANTIATE_REPORT_COMPILER_FAILURE = "engine.instantiate.report.compiler.failure";
181     public static final String EXCEPTION_MESSAGE_KEY_REPORT_COMPILER_CLASS_NOT_FOUND = "engine.report.compiler.class.not.found";
182     public static final String EXCEPTION_MESSAGE_KEY_REPORT_COMPILER_NOT_SET = "engine.report.compiler.not.set";
183     
184     private JasperReportsContext jasperReportsContext;
185
186
187     /**
188      *
189      */

190     private JasperCompileManager(JasperReportsContext jasperReportsContext)
191     {
192         this.jasperReportsContext = jasperReportsContext;
193     }
194     
195     
196     /**
197      *
198      */

199     private static JasperCompileManager getDefaultInstance()
200     {
201         return new JasperCompileManager(DefaultJasperReportsContext.getInstance());
202     }
203     
204     
205     /**
206      *
207      */

208     public static JasperCompileManager getInstance(JasperReportsContext jasperReportsContext)
209     {
210         return new JasperCompileManager(jasperReportsContext);
211     }
212     
213     
214     /**
215      * Compiles the XML report design file specified by the parameter.
216      * The result of this operation is another file that will contain the serialized  
217      * {@link net.sf.jasperreports.engine.JasperReport} object representing the compiled report design,
218      * having the same name as the report design as declared in the XML plus the <code>*.jasper</code> extension,
219      * located in the same directory as the XML source file.
220      * 
221      * @param sourceFileName XML source file name
222      * @return resulting file name containing a serialized {@link net.sf.jasperreports.engine.JasperReport} object 
223      */

224     public String compileToFile(String sourceFileName) throws JRException
225     {
226         File sourceFile = new File(sourceFileName);
227
228         JasperDesign jasperDesign = JRXmlLoader.load(sourceFileName);
229
230         File destFile = new File(sourceFile.getParent(), jasperDesign.getName() + ".jasper");
231         String destFileName = destFile.toString();
232
233         compileToFile(jasperDesign, destFileName);
234         
235         return destFileName;
236     }
237
238
239     /**
240      * Compiles the XML report design file received as the first parameter, placing the result 
241      * in the file specified by the second parameter.
242      * The resulting file will contain a serialized instance of a 
243      * {@link net.sf.jasperreports.engine.JasperReport} object representing 
244      * the compiled report design. 
245      * 
246      * @param sourceFileName XML source file name
247      * @param destFileName   file name to place the result into
248      */

249     public void compileToFile(
250         String sourceFileName,
251         String destFileName
252         ) throws JRException
253     {
254         JasperDesign jasperDesign = JRXmlLoader.load(sourceFileName);
255
256         compileToFile(jasperDesign, destFileName);
257     }
258
259
260     /**
261      * Compiles the report design object received as the first parameter, placing the result 
262      * in the file specified by the second parameter.
263      * The resulting file will contain a serialized instance of a 
264      * {@link net.sf.jasperreports.engine.JasperReport} object representing the compiled report design.
265      * 
266      * @param jasperDesign source report design object
267      * @param destFileName file name to place the compiled report design into
268      */

269     public void compileToFile(
270         JasperDesign jasperDesign,
271         String destFileName
272         ) throws JRException
273     {
274         JasperReport jasperReport = compile(jasperDesign);
275
276         JRSaver.saveObject(jasperReport, destFileName);
277     }
278
279
280     /**
281      * Compiles the XML report design file received as parameter, and returns 
282      * the compiled report design object.
283      *  
284      * @param sourceFileName XML source file name
285      * @return compiled report design object 
286      */

287     public  JasperReport compile(String sourceFileName) throws JRException
288     {
289         JasperDesign jasperDesign = JRXmlLoader.load(sourceFileName);
290
291         return compile(jasperDesign);
292     }
293
294
295     /**
296      * Compiles the XML representation of the report design read from the supplied input stream and
297      * writes the generated compiled report design object to the output stream specified 
298      * by the second parameter.
299      * 
300      * @param inputStream  XML source input stream
301      * @param outputStream output stream to write the compiled report design to
302      */

303     public void compileToStream(
304         InputStream inputStream,
305         OutputStream outputStream
306         ) throws JRException
307     {
308         JasperDesign jasperDesign = JRXmlLoader.load(inputStream);
309
310         compileToStream(jasperDesign, outputStream);
311     }
312
313
314     /**
315      * Compiles the report design object represented by the first parameter and
316      * writes the generated compiled report design object to the output stream specified 
317      * by the second parameter.
318      * 
319      * @param jasperDesign source report design object
320      * @param outputStream output stream to write the compiled report design to
321      */

322     public void compileToStream(
323         JasperDesign jasperDesign,
324         OutputStream outputStream
325         ) throws JRException
326     {
327         JasperReport jasperReport = compile(jasperDesign);
328
329         JRSaver.saveObject(jasperReport, outputStream);
330     }
331
332
333     /**
334      * Compiles the serialized report design object read from the supplied input stream and
335      * returns the generated compiled report design object.
336      * 
337      * @param inputStream XML source input stream
338      * @return compiled report design object 
339      */

340     public JasperReport compile(InputStream inputStream) throws JRException
341     {
342         JasperDesign jasperDesign = JRXmlLoader.load(inputStream);
343
344         return compile(jasperDesign);
345     }
346
347
348     /**
349      * Compiles the report design object received as parameter and
350      * returns the generated compiled report design object.
351      *
352      * @param jasperDesign source report design object
353      * @return compiled report design object 
354      * @see net.sf.jasperreports.engine.design.JRCompiler
355      */

356     public JasperReport compile(JasperDesign jasperDesign) throws JRException
357     {
358         return getCompiler(jasperDesign).compileReport(jasperDesign);
359     }
360
361
362     /**
363      * Verifies the validity and consistency of the report design object.
364      * Returns a collection of {@link JRValidationFault errors}, if problems are found in the report design.
365      *
366      * @param jasperDesign report design object to verify
367      * @return collection of {@link JRValidationFault JRValidationFault} if problems are found
368      * @see net.sf.jasperreports.engine.design.JRVerifier
369      */

370     public Collection<JRValidationFault> verify(JasperDesign jasperDesign)
371     {
372         return JRVerifier.verifyDesign(jasperDesign);
373     }
374
375
376     /**
377      * 
378      */

379     public JREvaluator getEvaluator(JasperReport jasperReport, JRDataset dataset) throws JRException
380     {
381         JRCompiler compiler = getCompiler(jasperReport);
382         JREvaluator evaluator = compiler.loadEvaluator(jasperReport, dataset);
383         initialize(evaluator);
384         return evaluator;
385     }
386
387
388     /**
389      * 
390      */

391     public JREvaluator getEvaluator(JasperReport jasperReport, JRCrosstab crosstab) throws JRException
392     {
393         JRCompiler compiler = getCompiler(jasperReport);
394         JREvaluator evaluator = compiler.loadEvaluator(jasperReport, crosstab);
395         initialize(evaluator);
396         return evaluator;
397     }
398
399
400     /**
401      * 
402      */

403     public JREvaluator getEvaluator(JasperReport jasperReport) throws JRException
404     {
405         return getEvaluator(jasperReport, jasperReport.getMainDataset());
406     }
407
408     protected void initialize(JREvaluator evaluator)
409     {
410         if (evaluator instanceof JasperReportsContextAware)
411         {
412             ((JasperReportsContextAware) evaluator).setJasperReportsContext(jasperReportsContext);
413         }
414     }
415
416     
417     /**
418      * Generates the XML representation of the report design loaded from the specified filename.
419      * The result of this operation is an "UTF-8" encoded XML file having the same name as 
420      * the report design, plus the <code>*.jasper.jrxml</code> extension, located in the same directory as 
421      * the source file.
422      * 
423      * @param sourceFileName source file name containing the report design object
424      * @return XML representation of the report design
425      */

426     public String writeToXmlFile(
427         String sourceFileName
428         ) throws JRException
429     {
430         File sourceFile = new File(sourceFileName);
431
432         /* We need the report name. */
433         JRReport report = (JRReport)JRLoader.loadObject(sourceFile);
434
435         File destFile = new File(sourceFile.getParent(), report.getName() + ".jasper.jrxml");
436         String destFileName = destFile.toString();
437         
438         writeToXmlFile(report, destFileName);
439         
440         return destFileName;
441     }
442
443
444     /**
445      * Generates the XML representation of the report design loaded from the first file parameter
446      * and place it in the file specified by the second parameter. The result is "UTF-8" encoded.
447      * 
448      * @param sourceFileName source file name containing the report design object
449      * @param destFileName   output file name to write the XML report design representation to
450      */

451     public void writeToXmlFile(
452         String sourceFileName, 
453         String destFileName
454         ) throws JRException
455     {
456         JRReport report = (JRReport)JRLoader.loadObjectFromFile(sourceFileName);
457
458         writeToXmlFile(report, destFileName);
459     }
460
461     
462     /**
463      * Generates the XML representation of the report design supplied as the first parameter
464      * and place it in the file specified by the second parameter. The result is "UTF-8" encoded.
465      *
466      * @param report       source report design object
467      * @param destFileName output file name to write the XML report design representation to
468      * @see net.sf.jasperreports.engine.xml.JRXmlWriter
469      */

470     public void writeToXmlFile(
471         JRReport report,
472         String destFileName
473         ) throws JRException
474     {
475         new JRXmlWriter(jasperReportsContext).write(
476             report,
477             destFileName,
478             "UTF-8"
479             );
480     }
481
482
483     /**
484      * Generates the XML representation of the serialized report design object read from the supplied 
485      * input stream abd writes it to the specified output stream, using the "UTF-8" encoding.
486      * 
487      * @param inputStream  source input stream to read the report design object from
488      * @param outputStream output stream to write the XML report design representation to
489      */

490     public void writeToXmlStream(
491         InputStream inputStream, 
492         OutputStream outputStream
493         ) throws JRException
494     {
495         JRReport report = (JRReport)JRLoader.loadObject(inputStream);
496
497         writeToXmlStream(report, outputStream);
498     }
499
500     
501     /**
502      * Generates the XML representation of the report design object supplied as parameter
503      * and writes it to the specified output stream, using the "UTF-8" encoding.
504      *
505      * @param report       source report design object
506      * @param outputStream output stream to write the XML report design representation to
507      * @see net.sf.jasperreports.engine.xml.JRXmlWriter
508      */

509     public void writeToXmlStream(
510         JRReport report, 
511         OutputStream outputStream
512         ) throws JRException
513     {
514         new JRXmlWriter(jasperReportsContext).write(
515             report, 
516             outputStream,
517             "UTF-8"
518             );
519     }
520
521
522     /**
523      * Generates the XML representation of the report design object supplied as parameter
524      * using the "UTF-8" enconding.
525      *
526      * @param report source report design object
527      * @return XML representation of the report design
528      * @see net.sf.jasperreports.engine.xml.JRXmlWriter
529      */

530     public String writeToXml(JRReport report)
531     {
532         return new JRXmlWriter(jasperReportsContext).write(report, "UTF-8");
533     }
534
535
536     
537     
538     /**
539      * @see #compileToFile(String)
540      */

541     public static String compileReportToFile(String sourceFileName) throws JRException
542     {
543         return getDefaultInstance().compileToFile(sourceFileName);
544     }
545
546
547     /**
548      * @see #compileToFile(String, String)
549      */

550     public static void compileReportToFile(
551         String sourceFileName,
552         String destFileName
553         ) throws JRException
554     {
555         getDefaultInstance().compileToFile(sourceFileName, destFileName);
556     }
557
558
559     /**
560      * @see #compileToFile(JasperDesign, String)
561      */

562     public static void compileReportToFile(
563         JasperDesign jasperDesign,
564         String destFileName
565         ) throws JRException
566     {
567         getDefaultInstance().compileToFile(jasperDesign, destFileName);
568     }
569
570
571     /**
572      * @see #compile(String)
573      */

574     public static JasperReport compileReport(String sourceFileName) throws JRException
575     {
576         return getDefaultInstance().compile(sourceFileName);
577     }
578
579
580     /**
581      * @see #compileToStream(InputStream, OutputStream)
582      */

583     public static void compileReportToStream(
584         InputStream inputStream,
585         OutputStream outputStream
586         ) throws JRException
587     {
588         getDefaultInstance().compileToStream(inputStream, outputStream);
589     }
590
591
592     /**
593      * @see #compileToStream(JasperDesign, OutputStream)
594      */

595     public static void compileReportToStream(
596         JasperDesign jasperDesign,
597         OutputStream outputStream
598         ) throws JRException
599     {
600         getDefaultInstance().compileToStream(jasperDesign, outputStream);
601     }
602
603
604     /**
605      * @see #compile(InputStream)
606      */

607     public static JasperReport compileReport(InputStream inputStream) throws JRException
608     {
609         return getDefaultInstance().compile(inputStream);
610     }
611
612
613     /**
614      * @see #compile(JasperDesign)
615      */

616     public static JasperReport compileReport(JasperDesign jasperDesign) throws JRException
617     {
618         return getDefaultInstance().compile(jasperDesign);
619     }
620
621
622     /**
623      * @see #verify(JasperDesign)
624      */

625     public static Collection<JRValidationFault> verifyDesign(JasperDesign jasperDesign)
626     {
627         return getDefaultInstance().verify(jasperDesign);
628     }
629
630
631     /**
632      * @see #getEvaluator(JasperReport, JRDataset)
633      */

634     public static JREvaluator loadEvaluator(JasperReport jasperReport, JRDataset dataset) throws JRException
635     {
636         return getDefaultInstance().getEvaluator(jasperReport, dataset);
637     }
638
639
640     /**
641      * @see #getEvaluator(JasperReport, JRCrosstab)
642      */

643     public static JREvaluator loadEvaluator(JasperReport jasperReport, JRCrosstab crosstab) throws JRException
644     {
645         return getDefaultInstance().getEvaluator(jasperReport, crosstab);
646     }
647
648
649     /**
650      * @see #getEvaluator(JasperReport)
651      */

652     public static JREvaluator loadEvaluator(JasperReport jasperReport) throws JRException
653     {
654         return getDefaultInstance().getEvaluator(jasperReport);
655     }
656
657     
658     /**
659      * @see #writeToXmlFile(String)
660      */

661     public static String writeReportToXmlFile(
662         String sourceFileName
663         ) throws JRException
664     {
665         return getDefaultInstance().writeToXmlFile(sourceFileName);
666     }
667
668
669     /**
670      * @see #writeToXmlFile(String, String)
671      */

672     public static void writeReportToXmlFile(
673         String sourceFileName, 
674         String destFileName
675         ) throws JRException
676     {
677         getDefaultInstance().writeToXmlFile(
678             sourceFileName, 
679             destFileName
680             );
681     }
682
683     
684     /**
685      * @see #writeToXmlFile(JRReport, String)
686      */

687     public static void writeReportToXmlFile(
688         JRReport report,
689         String destFileName
690         ) throws JRException
691     {
692         getDefaultInstance().writeToXmlFile(report, destFileName);
693     }
694
695
696     /**
697      * @see #writeToXmlStream(InputStream, OutputStream)
698      */

699     public static void writeReportToXmlStream(
700         InputStream inputStream, 
701         OutputStream outputStream
702         ) throws JRException
703     {
704         getDefaultInstance().writeToXmlStream(inputStream, outputStream);
705     }
706
707     
708     /**
709      * @see #writeToXmlStream(JRReport, OutputStream)
710      */

711     public static void writeReportToXmlStream(
712         JRReport report, 
713         OutputStream outputStream
714         ) throws JRException
715     {
716         getDefaultInstance().writeToXmlStream(report, outputStream);
717     }
718
719
720     /**
721      * @see #writeToXml(JRReport)
722      */

723     public static String writeReportToXml(JRReport report)
724     {
725         return getDefaultInstance().writeToXml(report);
726     }
727
728
729     /**
730      *
731      */

732     private JRCompiler getJavaCompiler()
733     {
734         JRCompiler compiler = null;
735
736         try 
737         {
738             JRClassLoader.loadClassForRealName("org.eclipse.jdt.internal.compiler.Compiler");
739             compiler = new JRJdtCompiler(jasperReportsContext);
740         }
741         catch (Exception e)
742         {
743         }
744
745         if (compiler == null)
746         {
747             try 
748             {
749                 JRClassLoader.loadClassForRealName("com.sun.tools.javac.Main");
750                 compiler = new JRJdk13Compiler(jasperReportsContext);
751             }
752             catch (Exception e)
753             {
754             }
755         }
756
757         if (compiler == null)
758         {
759             compiler = new JRJavacCompiler(jasperReportsContext);
760         }
761         
762         return compiler;
763     }
764
765
766     /**
767      *
768      */

769     private JRCompiler getCompiler(JasperReport jasperReport) throws JRException
770     {
771         JRCompiler compiler = null;
772         
773         String compilerClassName = jasperReport.getCompilerClass();
774
775         Class<? extends JRCompiler> compilerClass = null;
776         
777         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
778         if (classLoader != null)
779         {
780             try
781             {
782                 @SuppressWarnings("unchecked")
783                 Class<? extends JRCompiler> tmpCompilerClass = (Class<? extends JRCompiler>)classLoader.loadClass(compilerClassName);
784                 compilerClass = tmpCompilerClass;
785             }
786             catch(ClassNotFoundException e)
787             {
788             }
789         }
790         
791         if (compilerClass == null)
792         {
793             classLoader = JasperCompileManager.class.getClassLoader();
794             try
795             {
796                 if (classLoader == null)
797                 {
798                     @SuppressWarnings("unchecked")
799                     Class<? extends JRCompiler> tmpCompilerClass = (Class<? extends JRCompiler>)Class.forName(compilerClassName);
800                     compilerClass = tmpCompilerClass;
801                 }
802                 else
803                 {
804                     @SuppressWarnings("unchecked")
805                     Class<? extends JRCompiler> tmpCompilerClass = (Class<? extends JRCompiler>)classLoader.loadClass(compilerClassName);
806                     compilerClass = tmpCompilerClass;
807                 }
808             }
809             catch(ClassNotFoundException e)
810             {
811                 throw 
812                     new JRException(
813                         EXCEPTION_MESSAGE_KEY_REPORT_COMPILER_CLASS_NOT_FOUND,
814                         new Object[] {compilerClassName}, 
815                         e
816                         );
817             }
818         }
819
820
821         try
822         {
823             Constructor<? extends JRCompiler>  constructor = compilerClass.getConstructor(JasperReportsContext.class);//FIXMECONTEXT check all constructors like that
824             compiler = constructor.newInstance(jasperReportsContext);
825         }
826         catch (Exception e)
827         {
828             throw 
829                 new JRException(
830                     EXCEPTION_MESSAGE_KEY_INSTANTIATE_REPORT_COMPILER_FAILURE,
831                     new Object[] {compilerClassName}, 
832                     e);
833         }
834         return compiler;
835     }
836
837     
838
839
840     /**
841      *
842      */

843     private JRCompiler getCompiler(JasperDesign jasperDesign) throws JRException
844     {
845         JRCompiler compiler = null;
846
847         String compilerClassName = getCompilerClassProperty();
848         if (compilerClassName == null || compilerClassName.trim().length() == 0)
849         {
850             String language = jasperDesign.getLanguage();
851             compilerClassName = JRPropertiesUtil.getInstance(jasperReportsContext).getProperty(JRCompiler.COMPILER_PREFIX + language);
852             if (compilerClassName == null || compilerClassName.trim().length() == 0)
853             {
854                 if (JRReport.LANGUAGE_JAVA.equals(language))
855                 {
856                     return getJavaCompiler();
857                 }
858                 else
859                 {
860                     throw 
861                         new JRException(
862                             EXCEPTION_MESSAGE_KEY_REPORT_COMPILER_NOT_SET,
863                             new Object[]{language});
864                 }
865             }
866         }
867
868         try 
869         {
870             Class<?> clazz = JRClassLoader.loadClassForName(compilerClassName);
871             
872             Constructor<?> contextConstructor;
873             try
874             {
875                 contextConstructor = clazz.getConstructor(JasperReportsContext.class);
876             }
877             catch (NoSuchMethodException e)
878             {
879                 // no context constructor
880                 contextConstructor = null;
881             }
882             
883             if (contextConstructor == null)
884             {
885                 // assuming default constructor
886                 compiler = (JRCompiler) clazz.getDeclaredConstructor().newInstance();
887             }
888             else
889             {
890                 compiler = (JRCompiler) contextConstructor.newInstance(jasperReportsContext);
891             }
892         }
893         catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException 
894             | IllegalAccessException |  InstantiationException e)
895         {
896             throw new JRException(
897                     EXCEPTION_MESSAGE_KEY_INSTANTIATE_REPORT_COMPILER_FAILURE,
898                     new Object[] {compilerClassName}, 
899                     e);
900         }
901         
902         return compiler;
903     }
904
905     
906     /**
907      *
908      */

909     @SuppressWarnings("deprecation")
910     private String getCompilerClassProperty()
911     {
912         return JRPropertiesUtil.getInstance(jasperReportsContext).getProperty(JRCompiler.COMPILER_CLASS);
913     }
914 }
915