blob: d389813b8cf87dd5c0ff99ab2f700cc6487ba0e3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 Actuate Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Actuate Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.birt.report.engine.api;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
import org.eclipse.birt.core.archive.FileArchiveWriter;
import org.eclipse.birt.core.archive.IDocArchiveWriter;
import org.eclipse.birt.core.data.DataTypeUtil;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.framework.IPlatformContext;
import org.eclipse.birt.core.framework.PlatformFileContext;
/**
* Defines a standalone reporting application that uses
* <code>StandaloneReportEngine</code> class. This application allows running
* a report to output in one or multiple formats.
* <p>
* Report parameters are handled as command line parameters. Currently, only
* scalar parameters are handled.
*
* @version $Revision: 1.2 $ $Date: 2006/03/14 21:21:12 $
*/
public class ReportRunner
{
// The static logger
static protected Logger logger = Logger.getLogger( ReportRunner.class
.getName( ) );
/**
* the input paramters
*/
protected String[] args; // The command line arguments
/**
* the source input ,can be designName or reportArchive name
*/
protected String source; // Name of the design file
/**
* The target file name
*/
protected String targetFile = null;
/**
* execution mode, one of the Run, RunAndRender and Render. the default mode
* is RunAndRender
*/
protected String mode = "RunAndRender"; // the execution mode, one of the
/**
* the output locale, used in Run and RunAndRender modes.
*/
protected String locale = "en"; // Application running locale //$NON-NLS-1$
/**
* the output format, used in Render and RunAndRender.
*/
protected String format = "html"; // The output format, defaults to HTML
/**
* used to decorate the HTML output, used in Render and RunAndRender mode.
*/
protected String htmlType = "HTML"; // The type of html
/**
* the output encoding, used in html format in Render and RunAndRender
* modes.
*/
protected String encoding = "utf-8"; // the targe encoding
/**
* paramters used to execute the report, used in Run and RunAndRender modes.
*/
protected HashMap params = new HashMap( ); // the input params
/**
* output page number, used in Render mode.
*/
protected long pageNumber = -1;
/**
* engine used to execute the tasks.
*/
private ReportEngine engine;
/**
* Constructor of ReportRunner
*
* @param args -
* application arguments
*/
protected ReportRunner( String[] args )
{
this.args = (String[]) args.clone( );
EngineConfig config = new EngineConfig( );
IPlatformContext context = new PlatformFileContext( );
config.setEngineContext( context );
engine = new ReportEngine( config );
// JRE default level is INFO, which may reveal too much internal logging
// information.
engine.changeLogLevel( Level.WARNING );
}
/**
* Main function.
*
* @param args -
* application argumetns.
*/
public static void main( String[] args )
{
int result = new ReportRunner( args ).execute( );
System.exit( result );
}
/**
* Check if the arguments are valid. If yes, continue to execuate the
* report. If no, simply return.
*/
public int execute( )
{
if ( args.length == 0 )
{
printUsage( );
return 0;
}
try
{
// Process command line arguments
parseOptions( );
if ( "Run".equalsIgnoreCase( mode ) )
{
return runReport( );
}
else if ( "Render".equalsIgnoreCase( mode ) )
{
return renderReport( );
}
else
{
return runAndRenderReport( );
}
}
catch ( Exception ex )
{
logger.log( Level.SEVERE, "exception in parsing the paramters", ex );
return -1;
}
}
/**
* Execute the report design which includes: <br>
* 1. Read the input design and create the task. <br>
* 2. Set report render options (including format, locale, output file name
* etc). <br>
* 3. Run the task.
*/
protected int runAndRenderReport( )
{
try
{
// parse the source to get the report runnable
IReportRunnable runnable = engine.openReportDesign( source );
// validate the input paramter values
HashMap inputValues = evaluateParameterValues( runnable );
//
IRunAndRenderTask task = engine.createRunAndRenderTask( runnable );
task.setParameterValues( inputValues );
// set report render options
IRenderOption options;
if ( format.equalsIgnoreCase( "pdf" ) )
{
options = new FORenderOption( );
}
else if ( format.equalsIgnoreCase( "fo" ) )
{
options = new FORenderOption( );
}
else
{
options = new HTMLRenderOption( );
if ( "ReportletNoCSS".equals( htmlType ) )
( (HTMLRenderOption) options ).setEmbeddable( true );
}
options.setOutputFormat( format );
// setup the output file
options.setOutputFileName( targetFile );
// setup the output encoding
options.getOutputSetting( ).put( HTMLRenderOption.URL_ENCODING,
encoding );
// set the render options
task.setRenderOption( options );
// setup the application context
if ( format.equalsIgnoreCase( "html" ) )
{
HTMLRenderContext renderContext = new HTMLRenderContext( );
renderContext.setImageDirectory( "image" ); //$NON-NLS-1$
HashMap appContext = new HashMap( );
appContext.put( EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT,
renderContext );
task.setAppContext( appContext );
}
// setup the locale
task.setLocale( getLocale( locale ) );
task.run( );
return 0;
}
catch ( EngineException e )
{
logger.log( Level.SEVERE, e.getMessage( ), e );
return -1;
}
}
/**
* running the report to create the report document
*/
protected int runReport( )
{
try
{
// parse the source to get the report runnable
IReportRunnable runnable = engine.openReportDesign( source );
// create the report task
IRunTask task = engine.createRunTask( runnable );
// set the paramter values
HashMap inputValues = evaluateParameterValues( runnable );
task.setParameterValues( inputValues );
// set the application context
task.setAppContext( new HashMap( ) );
// open the output archive
IDocArchiveWriter archive = null;
try
{
archive = new FileArchiveWriter( targetFile );
}
catch ( IOException e )
{
logger.log( Level.SEVERE, "Can't open file: " + targetFile ); //$NON-NLS-1
return -1;
}
// run the task to create the report document
task.run( archive );
// close the task.
task.close( );
return 0;
}
catch ( org.eclipse.birt.report.engine.api.EngineException e )
{
logger.log( Level.SEVERE, e.getMessage( ), e );
return -1;
}
}
/**
* render the report.
*/
protected int renderReport( )
{
try
{
// use the archive to open the report document
IReportDocument document = engine.openReportDocument( source );
// create the render task
IRenderTask task = engine.createRenderTask( document );
// set report render options
IRenderOption options;
if ( format.equalsIgnoreCase( "pdf" ) )
{
options = new FORenderOption( );
}
else if ( format.equalsIgnoreCase( "fo" ) )
{
options = new FORenderOption( );
}
else
{
options = new HTMLRenderOption( );
if ( htmlType == "ReportletNoCSS" )
{
( (HTMLRenderOption) options ).setEmbeddable( true );
}
}
// set the output format
options.setOutputFormat( format );
// setup the output encoding
options.getOutputSetting( ).put( HTMLRenderOption.URL_ENCODING,
encoding );
// set the render options
task.setRenderOption( options );
// setup the application context
if ( format.equalsIgnoreCase( "html" ) )
{
HTMLRenderContext renderContext = new HTMLRenderContext( );
renderContext.setImageDirectory( "image" ); //$NON-NLS-1$
HashMap appContext = new HashMap( );
appContext.put( EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT,
renderContext );
task.setAppContext( appContext );
}
// setup the locale
task.setLocale( getLocale( locale ) );
// setup the output file
if ( pageNumber <= 0 )
{
int extPos = targetFile.lastIndexOf( '.' );
assert extPos != -1;
String pathName = targetFile.substring( 0, extPos );
String extName = targetFile.substring( extPos );
for ( long i = 1; i <= document.getPageCount( ); i++ )
{
String fileName = pathName + '_' + ( i ) + extName;
options.setOutputFileName( fileName );
task.render( i );
}
}
else
{
options.setOutputFileName( targetFile );
task.render( pageNumber );
}
task.close( );
return 0;
}
catch ( org.eclipse.birt.report.engine.api.EngineException e )
{
logger.log( Level.SEVERE, e.getMessage( ), e );
return -1;
}
}
/**
* print out the command line usage.
*
*/
protected void printUsage( )
{
System.out.println( "org.eclipse.birt.report.engine.impl.ReportRunner" ); //$NON-NLS-1$
System.out.println( "" ); //$NON-NLS-1$
System.out
.println( "--mode/-m [ run | render | runrender] the default is runrender" );
System.out.println( " for runrender mode:" );
System.out.println( "\t we should add it in the end<design file>" ); //$NON-NLS-1$
System.out.println( "\t --format/-f [ HTML | FO | PDF ]" ); //$NON-NLS-1$
System.out.println( "\t --output/-o <target file>" ); //$NON-NLS-1$
System.out.println( "\t --htmltype/-t < HTML | ReportletNoCSS >" ); //$NON-NLS-1$
System.out.println( "\t --locale /-l<locale>" ); //$NON-NLS-1$
System.out.println( "\t --parameter/-p <parameterName=parameterValue>" ); //$NON-NLS-1$
System.out.println( "\t --file/-F <parameter file>" ); //$NON-NLS-1$
System.out.println( "\t --encoding/-e <target encoding>" ); //$NON-NLS-1$
System.out.println( "\nLocale: default is english\n" ); //$NON-NLS-1$
System.out
.println( "\nparameters in command line will overide parameters in parameter file" ); //$NON-NLS-1$
System.out
.println( "\nparameter name can't include characters such as ' ', '=', ':' " ); //$NON-NLS-1$
System.out.println( "For RUN mode:" );
System.out.println( "\t we should add it in the end<design file>" ); //$NON-NLS-1$
System.out.println( "\t --output/-o <target file>" ); //$NON-NLS-1$
System.out.println( "\t --locale /-l<locale>" ); //$NON-NLS-1$
System.out.println( "\t --parameter/-p <parameterName=parameterValue>" ); //$NON-NLS-1$
System.out.println( "\t --file/-F <parameter file>" ); //$NON-NLS-1$
System.out.println( "\nLocale: default is english\n" ); //$NON-NLS-1$
System.out
.println( "\nparameters in command line will overide parameters in parameter file" ); //$NON-NLS-1$
System.out
.println( "\nparameter name can't include characters such as ' ', '=', ':' " ); //$NON-NLS-1$
System.out.println( "For RENDER mode:" );
System.out.println( "\t we should add it in the end<design file>" ); //$NON-NLS-1$
System.out.println( "\t --output/-o <target file>" ); //$NON-NLS-1$
System.out.println( "\\t --page/-p <pageNumber>" );
System.out.println( "\t --locale /-l<locale>" ); //$NON-NLS-1$
System.out.println( "\nLocale: default is english\n" ); //$NON-NLS-1$
}
/**
* Private function to convert a locale name string to a locale object
*
* @param locale -
* locale name string
* @return A locale object
*/
private Locale getLocale( String locale )
{
int index = locale.indexOf( '_' );
if ( index != -1 )
{
// e.g, zh_CN (language_country)
String language = locale.substring( 0, index );
String country = locale.substring( index + 1 );
return new Locale( language, country );
}
// e.g, en (language)
return new Locale( locale );
}
CommandLine results;
protected void parseRunOptions( ) throws Exception
{
if ( results.hasOption( 'o' ) )
{
targetFile = results.getOptionValue( 'o' );
}
parseParameterOptions( );
}
protected void parseRenderOptions( ) throws Exception
{
assert ( mode.equals( "Run" ) );
if ( results.hasOption( 'f' ) )
{
format = results.getOptionValue( 'f' );
}
if ( results.hasOption( 't' ) )
{
htmlType = results.getOptionValue( 't' );
}
if ( results.hasOption( 'o' ) )
{
targetFile = results.getOptionValue( 'o' );
}
if ( results.hasOption( 'l' ) )
{
locale = results.getOptionValue( 'l' );
}
if ( results.hasOption( 'e' ) )
{
encoding = results.getOptionValue( 'e' );
}
if ( results.hasOption( 'p' ) )
{
pageNumber = Long.parseLong( results.getOptionValue( 'p' ) );
}
parseParameterOptions( );
}
protected void parseRunAndRenderOptions( ) throws Exception
{
assert ( mode.equals( "RunAndRender" ) );
if ( results.hasOption( 'f' ) )
{
format = results.getOptionValue( 'f' );
}
if ( results.hasOption( 't' ) )
{
htmlType = results.getOptionValue( 't' );
}
if ( results.hasOption( 'o' ) )
{
targetFile = results.getOptionValue( 'o' );
}
if ( results.hasOption( 'l' ) )
{
locale = results.getOptionValue( 'l' );
}
if ( results.hasOption( 'e' ) )
{
encoding = results.getOptionValue( 'e' );
}
parseParameterOptions( );
}
/**
* parse the arguments.
*
* -html html-file-name -pdf pdf-file-name -fo fo-file-name -l locale-name
* -p page-number design-file-name
*
* @param args -
* arguments
*/
protected void parseOptions( )
{
source = args[args.length - 1];
args[args.length - 1] = ""; //$NON-NLS-1$
try
{
Options option = new Options( );// Collection of all the options
/*
* Add these basic argument into instance option
*/
option.addOption( "m", "mode", true, "RunAndRender" );
option.addOption( "o", "output", true, "" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
option.addOption( "f", "format", true, "html" ); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
option.addOption( "t", "type", true, "" ); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
option.addOption( "l", "locale", true, "" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
option.addOption( "e", "encoding", true, "" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
option.addOption( "p", "parameter", true, "" );
option.addOption( "p", "page", true, "" );
option.addOption( "F", "file", true, "parameter file" );
results = new BasicParser( ).parse( option, args, true );
if ( results.hasOption( 'm' ) )
{
mode = results.getOptionValue( 'm' );
}
if ( "Run".equalsIgnoreCase( mode ) )
{
parseRunOptions( );
}
else if ( "Render".equalsIgnoreCase( mode ) )
{
parseRenderOptions( );
}
else
{
parseRunAndRenderOptions( );
}
checkTargetFileName( );
}
catch ( Exception ex )
{
logger.log( Level.SEVERE, ex.getMessage( ), ex );
printUsage( );
}
}
/**
* read paramters from the param and add it into the params.
*
* @param param
* parameter string line. use '=' to separate the name and value.
* @param params
* maps contains all the paramter name and value.
*/
protected void readParamString( String param, HashMap params )
{
if ( param == null || param.length( ) < 2 )
{
return;
}
int index = param.indexOf( "=" );
if ( index < 1 )
{
return;
}
String name = param.substring( 0, index ).trim( );
String value = param.substring( index + 1 ).trim( );
if ( value.startsWith( "\"" ) && value.endsWith( "\"" )
&& value.length( ) > 2 )
{
value = value.substring( 1, value.length( ) - 1 );
}
params.put( name, value );
}
/**
* paraser the paramter command line inputs.
*
* @return the HashMap contains all the paramter name and values.
*/
protected void parseParameterOptions( )
{
if ( results.hasOption( 'F' ) )
{
String fileName = results.getOptionValue( 'F' );
readParamFile( fileName, params );
}
if ( results.hasOption( 'p' ) )
{
String[] stringParams = results.getOptionValues( 'p' );
if ( stringParams != null )
{
for ( int i = 0; i < stringParams.length; i++ )
{
readParamString( stringParams[i], params );
}
}
}
}
protected void readParamFile( String fileName, HashMap params )
{
File file = new File( fileName );
Properties ps = new Properties( );
try
{
ps.load( new FileInputStream( file ) );
}
catch ( FileNotFoundException e )
{
logger.log( Level.SEVERE,
"file: " + file.getAbsolutePath( ) + " not exists!" ); //$NON-NLS-1$
}
catch ( IOException e )
{
logger.log( Level.SEVERE,
"Can't open file: " + file.getAbsolutePath( ) ); //$NON-NLS-1
}
params.putAll( ps );
}
private HashMap evaluateParameterValues( IReportRunnable runnable )
{
HashMap inputValues = new HashMap( );
IGetParameterDefinitionTask task = engine
.createGetParameterDefinitionTask( runnable );
Collection paramDefns = task.getParameterDefns( false );
Iterator iter = paramDefns.iterator( );
while ( iter.hasNext( ) )
{
// now only support scalar parameter
IParameterDefnBase pBase = (IParameterDefnBase) iter.next( );
if ( pBase instanceof IScalarParameterDefn )
{
IScalarParameterDefn paramDefn = (IScalarParameterDefn) pBase;
String paramName = paramDefn.getName( );
String inputValue = (String) params.get( paramName );
int paramType = paramDefn.getDataType( );
try
{
Object paramValue = stringToObject( paramType, inputValue );
if ( paramValue != null )
{
inputValues.put( paramName, paramValue );
}
}
catch ( BirtException ex )
{
logger.log( Level.SEVERE, "the value of parameter "
+ paramName + " is invalid", ex );
}
}
}
return inputValues;
}
/**
* @param p
* the scalar parameter
* @param expr
* the default value expression
*/
protected Object stringToObject( int type, String value )
throws BirtException
{
if ( value == null )
{
return null;
}
switch ( type )
{
case IScalarParameterDefn.TYPE_BOOLEAN :
return DataTypeUtil.toBoolean( value );
case IScalarParameterDefn.TYPE_DATE_TIME :
return DataTypeUtil.toDate( value );
case IScalarParameterDefn.TYPE_DECIMAL :
return DataTypeUtil.toBigDecimal( value );
case IScalarParameterDefn.TYPE_FLOAT :
return DataTypeUtil.toDouble( value );
case IScalarParameterDefn.TYPE_STRING :
return DataTypeUtil.toString( value );
}
return null;
}
/**
* If -o (targetFile) is not specified, assume same directory as inputfile,
* and inputfile.*** as output file name (where *** is the output format.
*
* If -o specifies a directory, assume the file name is the same as
* inputfile.***.
*
* If -o specifies a file, it has a path part and a filename part. Take the
* path as the directory to store the file and other resources (for example
* image).
*/
protected void checkTargetFileName( )
{
String fileExt = "." + format;
if ( "Run".equalsIgnoreCase( mode ) )
{
fileExt = ".rptdocument";
}
File designFile = new File( new File( source ).getAbsolutePath( ) );
String designFileName = designFile.getName( );
int n = designFileName.lastIndexOf( '.' );
if ( n != -1 )
{
designFileName = designFileName.substring( 0, n );
}
if ( targetFile == null )
{
targetFile = designFile.getParent( ) + File.separatorChar
+ designFileName + fileExt;
}
else if ( !targetFile.toLowerCase( ).endsWith( fileExt ) )
{
targetFile = targetFile + File.separatorChar + designFileName
+ fileExt;
}
}
}