KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > pentaho > plugin > eclipsebirt > BIRTReportComponent


1 /*
2  * Copyright 2006 Pentaho Corporation. All rights reserved.
3  * This software was developed by Pentaho Corporation and is provided under the terms
4  * of the Mozilla Public License, Version 1.1, or any later version. You may not use
5  * this file except in compliance with the license. If you need a copy of the license,
6  * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
7  * BI Platform. The Initial Developer is Pentaho Corporation.
8  *
9  * Software distributed under the Mozilla Public License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
11  * the license for the specific language governing your rights and limitations.
12  *
13  * @created Jul 25, 2005
14  * @author James Dixon
15  */

16
17 package org.pentaho.plugin.eclipsebirt;
18
19 import java.io.InputStream JavaDoc;
20 import java.io.OutputStream JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.Locale JavaDoc;
26 import java.util.logging.Level JavaDoc;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.eclipse.birt.core.framework.Platform;
31 import org.eclipse.birt.report.engine.api.EngineConfig;
32 import org.eclipse.birt.report.engine.api.EngineConstants;
33 import org.eclipse.birt.report.engine.api.HTMLActionHandler;
34 import org.eclipse.birt.report.engine.api.HTMLEmitterConfig;
35 import org.eclipse.birt.report.engine.api.HTMLRenderContext;
36 import org.eclipse.birt.report.engine.api.HTMLRenderOption;
37 import org.eclipse.birt.report.engine.api.HTMLServerImageHandler;
38 import org.eclipse.birt.report.engine.api.IGetParameterDefinitionTask;
39 import org.eclipse.birt.report.engine.api.IParameterDefn;
40 import org.eclipse.birt.report.engine.api.IRenderOption;
41 import org.eclipse.birt.report.engine.api.IReportEngine;
42 import org.eclipse.birt.report.engine.api.IReportEngineFactory;
43 import org.eclipse.birt.report.engine.api.IReportRunnable;
44 import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
45 import org.eclipse.birt.report.engine.api.IScalarParameterDefn;
46 import org.eclipse.birt.report.engine.api.PDFRenderContext;
47 import org.eclipse.birt.report.engine.api.RenderOptionBase;
48 import org.eclipse.birt.report.engine.api.ReportParameterConverter;
49 import org.eclipse.birt.report.engine.api.impl.ParameterSelectionChoice;
50 import org.eclipse.birt.report.engine.api.impl.ScalarParameterDefn;
51 import org.pentaho.core.repository.IContentItem;
52 import org.pentaho.core.runtime.IActionParameter;
53 import org.pentaho.core.runtime.IRuntimeContext;
54 import org.pentaho.core.session.IPentahoSession;
55 import org.pentaho.core.solution.IOutputHandler;
56 import org.pentaho.core.system.PentahoSystem;
57 import org.pentaho.messages.Messages;
58 import org.pentaho.plugin.ComponentBase;
59 import org.pentaho.util.logging.ILogger;
60 import org.pentaho.util.logging.Logger;
61
62 /**
63  * @author James Dixon
64  *
65  * This component uses the BIRT report engine to generate PDF and HTML report
66  * output. It uses inputs provided by the runtime context and writes the output
67  * to the
68  *
69  */

70 public class BIRTReportComponent extends ComponentBase {
71     
72     protected static IReportEngine reportEngine = null;
73     
74     private static final long serialVersionUID = -6051215996386090147L;
75     
76     // these are defined inputs, outputs, and resources in the action definition
77
// files
78
private static final String JavaDoc OUTPUT_TYPE = "output-type"; //$NON-NLS-1$
79

80     private static final String JavaDoc REPORT_OUTPUT = "report-output"; //$NON-NLS-1$
81

82     private static final String JavaDoc REPORT_DEFINITION = "report-definition"; //$NON-NLS-1$
83

84     private static final int OUTPUT_TYPE_HTML = 0;
85     
86     private static final int OUTPUT_TYPE_PDF = 1;
87     
88     private static final ArrayList JavaDoc outputTypeStrings = new ArrayList JavaDoc();
89     
90     private String JavaDoc type;
91     
92     private int typeIdx = -1;
93     
94     private String JavaDoc mimeType;
95     
96     private String JavaDoc extension = ""; //$NON-NLS-1$
97

98     private IRenderOption renderOptions;
99     
100     static {
101         outputTypeStrings.add("html"); //$NON-NLS-1$
102
outputTypeStrings.add("pdf"); //$NON-NLS-1$
103
}
104     
105     public Log getLogger() {
106         return LogFactory.getLog(BIRTReportComponent.class);
107     }
108     
109     protected boolean validateSystemSettings() {
110         // This component does not have any system settings to validate
111
return true;
112     }
113     
114     /*
115      * This validates that the inputs, outputs, and resoruces that are available
116      * to us are correct. The actual values are not available at this point.
117      *
118      * @see org.pentaho.component.ComponentBase#validate()
119      */

120     protected boolean validateAction() {
121        
122         if ( reportEngine == null ) {
123             error(Messages.getErrorString("BIRTReportComponent.ERROR_0016_ENGINE_NOT_INITIALIZED") ); //$NON-NLS-1$
124
return false;
125         }
126         
127         // Check that we have an input called 'output-typ' that will specified
128
// 'html' or 'pdf' output
129
if (!isDefinedInput(OUTPUT_TYPE)) {
130             // We don't know what kind of output to produce, so return an error
131
error(Messages.getErrorString("BIRT.ERROR_0001_REPORT_TYPE_NOT_SPECIFIED")); //$NON-NLS-1$
132
return false;
133         }
134         
135         // Check that we have a resource called 'report-definition' tht should
136
// be the BIRT report definition file
137
if (!isDefinedInput(REPORT_DEFINITION) && !isDefinedResource(REPORT_DEFINITION)) {
138             // We don't have a report definition resource, so return an error
139
error(Messages.getErrorString("BIRT.ERROR_0002_REPORT_DEFINITION_NOT_SPECIFIED")); //$NON-NLS-1$
140
return false;
141         }
142         
143         // Looks like everything is ok so far
144
return true;
145     }
146     
147     /*
148      * perform any initialization required
149      *
150      * @see org.pentaho.component.ComponentBase#init()
151      */

152     public boolean init() {
153         // BIRT report engine is initialized by the BIRT System Listener so just return
154
return true;
155     }
156     
157     /*
158      * Execute the BIRT report using the input, resources and outputs defined.
159      * If we require parameters to be selected by the user, generate a form
160      * definition for the user
161      *
162      * @see org.pentaho.component.ComponentBase#execute()
163      */

164     protected boolean executeAction() {
165         
166         // IRuntimeContext context = getRuntimeContext();
167

168         // Get the real location of the report definition file
169
String JavaDoc reportDefinitionPath = getResource(REPORT_DEFINITION).getAddress();
170         InputStream JavaDoc reportDefinition = PentahoSystem.getSolutionRepository(getSession()).getResourceInputStream(getResource(REPORT_DEFINITION));
171         
172         // Get the type of the output
173
type = getInputStringValue(OUTPUT_TYPE);
174         typeIdx = outputTypeStrings.indexOf(type);
175         if (typeIdx < 0) {
176             error(Messages.getErrorString("BIRT.ERROR_0003_REPORT_TYPE_NOT_VALID", type)); //$NON-NLS-1$
177
return false;
178         }
179         
180         switch (typeIdx) {
181         case OUTPUT_TYPE_HTML: {
182             mimeType = "text/html"; //$NON-NLS-1$
183
extension = ".html"; //$NON-NLS-1$
184
renderOptions = new HTMLRenderOption();
185             break;
186         }
187         case OUTPUT_TYPE_PDF: {
188             mimeType = "application/pdf"; //$NON-NLS-1$
189
extension = ".pdf"; //$NON-NLS-1$
190
renderOptions = new HTMLRenderOption();
191             break;
192         }
193         default: {
194             error(Messages.getErrorString("BIRT.ERROR_0003_REPORT_TYPE_NOT_VALID", type)); //$NON-NLS-1$
195
return false;
196         }
197         }
198         
199         if (debug)
200             debug(Messages.getString("BIRT.DEBUG_EXECUTING_REPORT", reportDefinitionPath, type)); //$NON-NLS-1$
201

202         String JavaDoc baseUrl = PentahoSystem.getApplicationContext().getBaseUrl();
203         
204         boolean result = false;
205         try {
206
207             // TODO support caching or the ReportRunnable object
208
// Create an isntance of a runnable report using the report
209
// definition file provided
210
IReportRunnable design = reportEngine.openReportDesign(reportDefinition);
211             if (design == null) {
212                 return false;
213             }
214             
215             //getParameterDefns
216
IGetParameterDefinitionTask parameterDefinitionTask = reportEngine.createGetParameterDefinitionTask(design);
217             
218             // Set up the parameters for the report
219
HashMap JavaDoc parameterMap = new HashMap JavaDoc();
220             int parameterStatus = setupParameters(parameterDefinitionTask.getParameterDefns(false), parameterMap);
221             if (parameterStatus == IRuntimeContext.PARAMETERS_FAIL) {
222                 error(Messages.getErrorString("BIRT.ERROR_0005_INVALID_REPORT_PARAMETERS")); //$NON-NLS-1$
223
return false;
224             }
225             else if (parameterStatus == IRuntimeContext.PARAMETERS_UI_NEEDED) {
226                 return true;
227             }
228             parameterDefinitionTask.close();
229             
230             // Run task
231
IRunAndRenderTask runTask = reportEngine.createRunAndRenderTask(design);
232             IPentahoSession session = this.getSession();
233             runTask.setLocale(session.getLocale());
234                         
235             // Get the output stream that the content is going into
236
OutputStream JavaDoc outputStream = null;
237             if (isDefinedOutput(REPORT_OUTPUT)) {
238                 outputStream = getOutputStream(REPORT_OUTPUT, mimeType, extension);
239             }
240             else if (getOutputNames().size() == 1) {
241                 String JavaDoc outputName = (String JavaDoc) getOutputNames().iterator().next();
242                 IContentItem contentItem = getOutputContentItem(outputName);
243                 contentItem.setMimeType(mimeType);
244                 try {
245                     outputStream = contentItem.getOutputStream(getActionName());
246                 }
247                 catch (Exception JavaDoc e) {
248                 }
249             }
250             if (getOutputNames().size() == 0) {
251                 // There was no output in the action-sequence document, so make
252
// a default
253
// outputStream.
254
warn(Messages.getString("Base.WARN_NO_OUTPUT_STREAM")); //$NON-NLS-1$
255
outputStream = getDefaultOutputStream();
256                 if (outputStream != null) {
257                     setOutputMimeType(mimeType);
258                 }
259             }
260             
261             if (outputStream == null) {
262                 // We could not get an output stream for the content
263
error(Messages.getErrorString("BIRT.ERROR_0006_INVALID_OUTPUT_STREAM")); //$NON-NLS-1$
264
return false;
265             }
266             
267             // Execute the report
268
result = generateReport(parameterMap, outputStream, runTask, baseUrl);
269         }
270         catch (Throwable JavaDoc e) {
271             error(Messages.getErrorString("BIRT.ERROR_0007_REPORT_ERRORS_ENCOUNTERED", reportDefinitionPath), e); //$NON-NLS-1$
272
}
273         
274         return result;
275     }
276     
277     /*
278      * Create an instance of the EngineConfig class for the BIRT report engine.
279      */

280      /*
281      * Set up the report parameters
282      */

283     private int setupParameters(Collection JavaDoc params, HashMap JavaDoc reportParameterMap) {
284         try {
285             
286             boolean parameterUINeeded = false;
287             if (getOutputPreference() == IOutputHandler.OUTPUT_TYPE_PARAMETERS) {
288                 parameterUINeeded = true;
289             }
290             
291             // Process each parameter in turn
292
Iterator JavaDoc it = params.iterator();
293             while (it.hasNext()) {
294                 IParameterDefn param = (IParameterDefn) it.next();
295                 ScalarParameterDefn scalarParm = null;
296                 if (param instanceof ScalarParameterDefn) {
297                     scalarParm = (ScalarParameterDefn) param;
298                 }
299                 String JavaDoc paramName = param.getName();
300                 String JavaDoc defaultValue = ""; //$NON-NLS-1$
301
if (scalarParm != null) {
302                     defaultValue = scalarParm.getDefaultValue();
303                 }
304                 if (!isDefinedInput(paramName)) {
305                     // what do we do here?
306
continue;
307                 }
308                 String JavaDoc contextValue = getInputStringValue(paramName);
309                 
310                 // Get the value for the parameter from the current context
311
IActionParameter paramParameter = getInputParameter(paramName);
312                 // if(debug)
313
// debug(Messages.getString("BIRT.DEBUG_SETTING_PARAMETER",
314
// paramName, paramValue )); //$NON-NLS-1$
315

316                 // There is no parameter in the runtime or the parameter found
317
// has no value and no selections
318
if (paramParameter == null || ((!paramParameter.hasValue() || parameterUINeeded) && !paramParameter.hasSelections())) {
319                     
320                     if (paramParameter.getPromptStatus() == IActionParameter.PROMPT_PENDING) {
321                         parameterUINeeded = true;
322                         continue;
323                     } else {
324                         paramParameter = null;
325                     }
326                 }
327                 
328                 if (paramParameter == null) { // Still no parameter, use BIRTs
329
// default way
330
if ((scalarParm != null)) {
331                         if (parameterUIOk()) {
332                             // The parameter value was not provided, and we are
333
// allowed to create user interface forms
334
int controlType = scalarParm.getControlType();
335                             if ((controlType == IScalarParameterDefn.LIST_BOX)) {
336                                 ArrayList JavaDoc values = new ArrayList JavaDoc();
337                                 HashMap JavaDoc displayNames = new HashMap JavaDoc();
338                                 ArrayList JavaDoc birtValues = scalarParm.getSelectionList();
339                                 Iterator JavaDoc valueIterator = birtValues.iterator();
340                                 while (valueIterator.hasNext()) {
341                                     ParameterSelectionChoice selChoice = (ParameterSelectionChoice) valueIterator.next();
342                                     Object JavaDoc value = selChoice.getValue();
343                                     if (value != null) {
344                                         String JavaDoc label = selChoice.getLabel();
345                                         displayNames.put(value.toString(), (label != null) ? label : value);
346                                         values.add(value);
347                                     }
348                                 }
349                                 createFeedbackParameter(param.getName(), param.getDisplayName(), scalarParm.getHelpText(), defaultValue, values, displayNames, null);
350                             } else {
351                                 createFeedbackParameter(param.getName(), param.getDisplayName(), scalarParm.getHelpText(), defaultValue, true);
352                             }
353                             parameterUINeeded = true;
354                             continue;
355                         } else {
356                             return IRuntimeContext.PARAMETERS_FAIL;
357                         }
358                     } else if (defaultValue.length() == 0) {
359                         // If the length of the defaultValue is not zero, then:
360
// 1- It's a scalar parameter
361
// 2- There's a default value expression associated with
362
// the parameter.
363
// Therefore, let BIRT use that expression
364
// automatically.
365

366                         // The parameter was not provided and we are not allowed
367
// to create forms
368
error(Messages.getErrorString("BIRT.ERROR_0009_PARAMETER_NOT_PROVIDED", paramName)); //$NON-NLS-1$
369
return IRuntimeContext.PARAMETERS_FAIL;
370                     }
371                 }
372                 String JavaDoc paramValue = contextValue;
373                 if ((paramValue != null) && (!"".equals(paramValue))) { //$NON-NLS-1$
374
if (scalarParm != null) {
375                         String JavaDoc format = scalarParm.getDisplayFormat();
376                         ReportParameterConverter cfgConverter = new ReportParameterConverter(format, Locale.getDefault());
377                         Object JavaDoc configValueObj = cfgConverter.parse(paramValue, scalarParm.getDataType());
378                         reportParameterMap.put(paramName, configValueObj);
379                     } else {
380                         reportParameterMap.put(paramName, paramValue);
381                     }
382                 }
383             }
384             if (parameterUINeeded) {
385                 return IRuntimeContext.PARAMETERS_UI_NEEDED;
386             }
387             else if (getRuntimeContext().isPromptPending() ) {
388                     return IRuntimeContext.PARAMETERS_UI_NEEDED;
389             }
390             return IRuntimeContext.PARAMETERS_OK;
391         } catch (Throwable JavaDoc error) {
392             error(Messages.getErrorString("BIRT.ERROR_0005_INVALID_REPORT_PARAMETERS"), error); //$NON-NLS-1$
393
}
394         return IRuntimeContext.PARAMETERS_FAIL;
395     }
396     
397     private boolean parameterUIOk() {
398         /*
399          * See if we are allowed to generate a parameter selection user
400          * interface. If we are being called as part of a process, this will not
401          * be allowed.
402          */

403         
404         if( !feedbackAllowed() ) {
405             return false;
406         }
407         // We need input from the user, we have delivered an input form into the
408
// feeback stream
409
setFeedbackMimeType("text/html"); //$NON-NLS-1$
410
return true;
411     }
412     
413     
414     /*
415      * Generate the report output
416      */

417     private boolean generateReport(HashMap JavaDoc parameterMap, OutputStream JavaDoc outputStream, IRunAndRenderTask task, String JavaDoc baseUrl) {
418         
419         try {
420             HashMap JavaDoc appContextMap = new HashMap JavaDoc();
421             // Set the output options for the report
422
if (typeIdx == OUTPUT_TYPE_HTML) {
423                 HTMLRenderContext htmlContext = new HTMLRenderContext();
424                 htmlContext.setBaseImageURL(baseUrl + "getImage?image="); //$NON-NLS-1$
425
htmlContext.setImageDirectory(PentahoSystem.getApplicationContext().getSolutionPath("system/tmp")); //$NON-NLS-1$
426
htmlContext.setSupportedImageFormats("PNG;GIF;JPG;BMP"); //$NON-NLS-1$
427
appContextMap.put(EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT, htmlContext);
428             } else if (typeIdx == OUTPUT_TYPE_PDF){
429                 PDFRenderContext pdfContext = new PDFRenderContext();
430                 pdfContext.setBaseURL(baseUrl + "getImage?image="); //$NON-NLS-1$
431
pdfContext.setSupportedImageFormats("PNG;GIF;JPG;BMP"); //$NON-NLS-1$
432
appContextMap.put(EngineConstants.APPCONTEXT_PDF_RENDER_CONTEXT, pdfContext);
433             }
434             
435             task.setAppContext(appContextMap);
436             task.setRenderOption(renderOptions);
437             renderOptions.setOutputFormat(type);
438             
439             // Set the output stream for the content
440
renderOptions.setOutputStream(outputStream);
441             task.setParameterValues(parameterMap);
442             if (debug) {
443                 debug(task.toString());
444             }
445             task.run();
446             
447             outputStream.flush();
448             outputStream.close();
449             return true;
450         } catch (Exception JavaDoc e) {
451             e.printStackTrace();
452             error(Messages.getErrorString("BIRT.ERROR_0010_REPORT_COULD_NOT_BE_RUN", e.getMessage())); //$NON-NLS-1$
453
}
454         
455         return false;
456     }
457     
458     /*
459      * Perform any cleanup necessary
460      *
461      * @see org.pentaho.component.ComponentBase#done()
462      */

463     public void done() {
464         // we don't have anything to clean up to do
465
}
466
467     /* DM This should be removed when the JPivot/BIRT conflict is resolved
468      * Create an instance of the EngineConfig class for the BIRT report engine.
469      */

470     private IReportEngine createBIRTEngine() {
471
472         try {
473             // Get the global settings for the BIRT engine from our system settings
474
String JavaDoc birtHome = PentahoSystem.getApplicationContext().getSolutionPath("system/BIRT"); //$NON-NLS-1$
475
birtHome = birtHome.replaceAll("\\\\.\\\\", "\\\\"); //$NON-NLS-1$ //$NON-NLS-2$
476

477             if (PentahoSystem.debug)
478                 Logger.debug(BirtSystemListener.class.getName(), Messages.getString("BIRT.DEBUG_BIRT_HOME", birtHome)); //$NON-NLS-1$
479

480             // Create an appropriate Config object
481
EngineConfig config = new EngineConfig();
482             config.setEngineHome(birtHome); // Configuring where BIRT engine is installed
483

484             // Set the directory where the BIRT log files will go
485
String JavaDoc logDest = PentahoSystem.getApplicationContext().getFileOutputPath("system/logs/BIRT"); //$NON-NLS-1$
486

487             // Set the logging level
488
int loggingLevel = Logger.getLogLevel();
489             if (loggingLevel == ILogger.TRACE) {
490                 config.setLogConfig(logDest, Level.ALL);
491             } else if (loggingLevel == ILogger.DEBUG) {
492                 config.setLogConfig(logDest, Level.FINE);
493             } else if (loggingLevel == ILogger.INFO) {
494                 config.setLogConfig(logDest, Level.INFO);
495             } else if (loggingLevel == ILogger.WARN) {
496                 config.setLogConfig(logDest, Level.WARNING);
497             } else if (loggingLevel == ILogger.ERROR) {
498                 config.setLogConfig(logDest, Level.SEVERE);
499             } else if (loggingLevel == ILogger.FATAL) {
500                 config.setLogConfig(logDest, Level.SEVERE);
501             }
502
503             // Register new image handler
504
HTMLEmitterConfig emitterConfig = new HTMLEmitterConfig( );
505             emitterConfig.setActionHandler( new HTMLActionHandler( ) );
506             emitterConfig.setImageHandler( new HTMLServerImageHandler( ) );
507             config.getEmitterConfigs( ).put( RenderOptionBase.OUTPUT_FORMAT_HTML, emitterConfig );
508             
509             Platform.startup( config );
510
511             IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY );
512             IReportEngine engine = factory.createReportEngine( config );
513             return engine;
514         }
515         catch (Throwable JavaDoc error) {
516             error.printStackTrace();
517             Logger.error(BirtSystemListener.class.getName(), Messages.getErrorString("BIRT.ERROR_0008_INVALID_CONFIGURATION")); //$NON-NLS-1$
518
}
519         return null;
520     }
521     
522 }
523
Popular Tags