1   /*
2    * Copyright 2003 - 2013 The eFaps Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  package org.efaps.update.schema.program.jasperreport;
22  
23  import java.io.ByteArrayInputStream;
24  import java.io.ByteArrayOutputStream;
25  import java.io.IOException;
26  import java.util.List;
27  import java.util.Map;
28  
29  import net.sf.jasperreports.engine.DefaultJasperReportsContext;
30  import net.sf.jasperreports.engine.JRException;
31  import net.sf.jasperreports.engine.JRReport;
32  import net.sf.jasperreports.engine.JasperCompileManager;
33  import net.sf.jasperreports.engine.design.JRCompiler;
34  import net.sf.jasperreports.engine.design.JasperDesign;
35  
36  import org.efaps.admin.program.jasper.JasperUtil;
37  import org.efaps.ci.CIAdminProgram;
38  import org.efaps.ci.CIType;
39  import org.efaps.db.Checkin;
40  import org.efaps.db.Insert;
41  import org.efaps.db.Instance;
42  import org.efaps.db.Update;
43  import org.efaps.update.schema.program.jasperreport.JasperReportCompiler.OneJasperReport;
44  import org.efaps.update.schema.program.jasperreport.JasperReportImporter.FakeQueryExecuterFactory;
45  import org.efaps.update.schema.program.staticsource.AbstractStaticSourceCompiler;
46  import org.efaps.util.EFapsException;
47  
48  /**
49   * Class serves as the compiler for JasperReports.
50   *
51   * @author The eFaps Team
52   * @version $Id: JasperReportCompiler.java 3932 2011-03-31 20:40:50Z jan.moxter
53   *          $
54   */
55  public class JasperReportCompiler
56      extends AbstractStaticSourceCompiler<OneJasperReport>
57  {
58  
59      /**
60       * Stores the list of classpath needed to compile (if needed).
61       */
62      private final List<String> classPathElements;
63  
64      /**
65       * Constructor setting the classpath elements.
66       *
67       * @param _classPathElements elemnts for the classpath
68       */
69      public JasperReportCompiler(final List<String> _classPathElements)
70      {
71          this.classPathElements = _classPathElements;
72      }
73  
74      /**
75       * {@inheritDoc}
76       */
77      @Override
78      public void compile()
79          throws EFapsException
80      {
81          final List<OneJasperReport> sources = readSources();
82          compile(sources.toArray(new OneJasperReport[sources.size()]));
83      }
84  
85      /**
86       * @param _sources source to be compiled
87       * @throws EFapsException on error
88       */
89      public void compile(final OneJasperReport... _sources)
90          throws EFapsException
91      {
92          final Map<String, String> compiled = readCompiledSources();
93  
94          for (final OneJasperReport onesource : _sources) {
95  
96              if (AbstractStaticSourceCompiler.LOG.isInfoEnabled()) {
97                  AbstractStaticSourceCompiler.LOG.info("compiling " + onesource.getName());
98              }
99  
100             final Update update;
101             if (compiled.containsKey(onesource.getName())) {
102                 update = new Update(compiled.get(onesource.getName()));
103             } else {
104                 update = new Insert(getClassName4TypeCompiled());
105             }
106             update.add("Name", onesource.getName());
107             update.add("ProgramLink", "" + onesource.getInstance().getId());
108             update.executeWithoutAccessCheck();
109             final Instance instance = update.getInstance();
110             update.close();
111             compileJasperReport(onesource.getInstance(), instance);
112         }
113     }
114 
115     /**
116      * Method to compile one JasperReport.
117      *
118      * @param _instSource instance of the source
119      * @param _instCompiled instance of the compiled source
120      * @throws EFapsException on error
121      */
122     private void compileJasperReport(final Instance _instSource,
123                                      final Instance _instCompiled)
124         throws EFapsException
125     {
126         // make the classPath
127         final String sep = System.getProperty("os.name").startsWith("Windows") ? ";" : ":";
128         final StringBuilder classPath = new StringBuilder();
129         for (final String classPathElement : this.classPathElements) {
130             classPath.append(classPathElement).append(sep);
131         }
132         final DefaultJasperReportsContext reportContext = DefaultJasperReportsContext.getInstance();
133         reportContext.setProperty(JRCompiler.COMPILER_CLASSPATH, classPath.toString());
134         reportContext.setProperty("net.sf.jasperreports.compiler.groovy", JasperGroovyCompiler.class.getName());
135         reportContext.setProperty("net.sf.jasperreports.query.executer.factory.eFaps",
136                         FakeQueryExecuterFactory.class.getName());
137         try {
138             final JasperDesign jasperDesign = JasperUtil.getJasperDesign(_instSource);
139 
140             // the fault value for the language is no information but the used compiler needs a value,
141             // therefore it must be set explicitly
142             if (jasperDesign.getLanguage() == null) {
143                 jasperDesign.setLanguage(JRReport.LANGUAGE_JAVA);
144             }
145 
146             final ByteArrayOutputStream out = new ByteArrayOutputStream();
147             JasperCompileManager.compileReportToStream(jasperDesign, out);
148 
149             final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
150             final Checkin checkin = new Checkin(_instCompiled);
151             checkin.executeWithoutAccessCheck(jasperDesign.getName() + ".jasper", in, in.available());
152             out.close();
153             in.close();
154         } catch (final JRException e) {
155             throw new EFapsException(JasperReportCompiler.class, "JRException", e);
156         } catch (final IOException e) {
157             throw new EFapsException(JasperReportCompiler.class, "IOException", e);
158         }
159     }
160 
161     /**
162      * Not needed in this case. {@inheritDoc}
163      */
164     @Override
165     protected String getCompiledString(final Instance _instance)
166     {
167         return null;
168     }
169 
170     /**
171      * {@inheritDoc}
172      */
173     @Override
174     protected CIType getClassName4Type()
175     {
176         return CIAdminProgram.JasperReport;
177     }
178 
179     /**
180      * {@inheritDoc}
181      */
182     @Override
183     protected CIType getClassName4Type2Type()
184     {
185         return CIAdminProgram.JasperReport2JasperReport;
186     }
187 
188     /**
189      * {@inheritDoc}
190      */
191     @Override
192     protected CIType getClassName4TypeCompiled()
193     {
194         return CIAdminProgram.JasperReportCompiled;
195     }
196 
197     /**
198      * {@inheritDoc}
199      */
200     @Override
201     public OneJasperReport getNewSource(final String _name,
202                                        final Instance _instance)
203     {
204         return new OneJasperReport(_name, _instance);
205     }
206 
207     /**
208      */
209     public static class OneJasperReport
210         extends AbstractStaticSourceCompiler.AbstractSource
211     {
212         /**
213          * @param _name name
214          * @param _instance Instance
215          */
216         public OneJasperReport(final String _name,
217                                final Instance _instance)
218         {
219             super(_name, _instance);
220         }
221     }
222 }