Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

There

...

are

...

four

...

ways

...

of

...

creating

...

a

...

BI

...

Component:

...

create

...

a

...

BI

...

Component

...

from

...

scratch,

...

convert

...

an

...

existing

...

class

...

into

...

a

...

BI

...

Component,

...

create

...

a

...

subclass

...

of

...

ComponentBase

...

(org.pentaho.plugin.ComponentBase),

...

or

...

create

...

a

...

subclass

...

of

...

SimpleComponent

...

(org.pentaho.plugin.core.SimpleComponent).

...

To

...

become

...

a

...

BI

...

Component,

...

a

...

Java

...

object

...

must

...

implement

...

the

...

org.pentaho.core.component.IComponent

...

interface.

...

The

...

IComponent

...

interface

...

extends

...

two

...

other

...

interfaces:

...

org.pentaho.core.audit.IAuditable

...

and

...

org.pentaho.util.logging.ILogger.

...

Pentaho

...

provides

...

classes

...

that

...

implement

...

these

...

interfaces.

...

The

...

hierarchy

...

of

...

the

...

Pentaho

...

classes

...

looks

...

like

...

this:

...


org.pentaho.core.system.PentahoBase

...

(implements

...

ILogger

...

and

...

Serializable)

...


    -->

...

org.pentaho.core.system.PentahoMessenger

...


        -->

...

org.pentaho.plugin.ComponentBase

...

(implements

...

IComponent

...

and

...

IAuditable)

...


            -->

...

org.pentaho.plugin.core.SimpleComponent

...


                -->

...

other

...

Pentaho-provided

...

BI

...

Components

...

You

...

can

...

create

...

your

...

BI

...

Components

...

in

...

whatever

...

package

...

you

...

like

...

whether

...

they

...

are

...

subclasses

...

of

...

Pentaho

...

classes

...

or

...

not.

...

There

...

are

...

no

...

required

...

methods

...

that

...

will

...

be

...

inaccessible

...

if

...

you

...

use

...

a

...

non-Pentaho

...

package.

...

Extend SimpleComponent

This is the easiest way to create a new component and the recommended place to start.

  1. Create a new Java class that is a subclass of (extends) org.pentaho.plugin.core.SimpleComponent.

...

  1. Implement

...

  1. an

...

  1. executeAction()

...

  1. method

...

  1. and

...

  1. a

...

  1. getLogger()

...

  1. method.

...

  1. See

...

  1. 'Component

...

  1. Methods'

...

  1. below

...

  1. for

...

  1. a

...

  1. description

...

  1. of

...

  1. these

...

  1. methods.

...

Extend ComponentBase

If your component needs to validate its inputs and/or

...

system

...

settings

...

or

...

needs

...

to

...

perform

...

any

...

initialization

...

and/or

...

cleanup,

...

you

...

should

...

extend

...

org.pentaho.plugin.ComponentBase.

...

  1. Create

...

  1. a

...

  1. new

...

  1. Java

...

  1. class

...

  1. that

...

  1. is

...

  1. a

...

  1. subclass

...

  1. of

...

  1. (extends)

...

  1. org.pentaho.plugin.ComponentBase.

...

  1. Add

...

  1. code

...

  1. to

...

  1. the

...

  1. init(),

...

  1. validateSystemSettings(),

...

  1. validateAction(),

...

  1. executeAction(),

...

  1. done(),

...

  1. and

...

  1. getLogger()

...

  1. methods

...

  1. as

...

  1. appropriate.

...

  1. See

...

  1. 'Component

...

  1. Methods'

...

  1. below

...

  1. for

...

  1. a

...

  1. description

...

  1. of

...

  1. these

...

  1. methods.

...

Convert

...

a

...

Java

...

Object

...

into

...

a

...

BI

...

Component

...

If

...

you

...

have

...

an

...

existing

...

object

...

that

...

you

...

wish

...

to

...

convert

...

into

...

a

...

BI

...

Component

...

there

...

are

...

two

...

options.

...


Create

...

a

...

new

...

object

...

that

...

subclasses

...

your

...

existing

...

object

...

and

...

implements

...

the

...

required

...

interfaces

...


Change

...

your

...

object

...

to

...

implement

...

the

...

required

...

interfaces

...

Which

...

of

...

these

...

options

...

is

...

the

...

best

...

for

...

your

...

particular

...

object

...

will

...

depend

...

on

...

your

...

specific

...

circumstances;

...

but,

...

we

...

recommend

...

creating

...

a

...

subclass

...

if

...

only

...

to

...

keep

...

your

...

source

...

file

...

size

...

manageable.

...

If

...

you

...

do

...

need

...

to

...

use

...

this

...

approach

...

most

...

of

...

the

...

code

...

you

...

need

...

to

...

create

...

your

...

new

...

class

...

can

...

be

...

found

...

in

...

these

...

classes:

...

org.pentaho.core.system.PentahoBase,

...

org.pentaho.core.system.PentahoMessenger,

...

and

...

org.pentaho.plugin.ComponentBase.

...

To

...

make

...

this

...

process

...

easier

...

we

...

have

...

created

...

a

...

class,

...

org.pentaho.plugin.ComponentSubclassExample,

...

that

...

contains

...

the

...

code

...

you

...

need.

...

To

...

convert

...

a

...

Java

...

class

...

to

...

a

...

BI

...

Component:

...

  1. Copy

...

  1. the

...

  1. imports,

...

  1. member

...

  1. variables,

...

  1. and

...

  1. methods

...

  1. from

...

  1. org.pentaho.plugin.ComponentSubclassExample

...

  1. into

...

  1. your

...

  1. Java

...

  1. class.

...

  1. Add

...

  1. code

...

  1. to

...

  1. the

...

  1. init(),

...

  1. validateSystemSettings(),

...

  1. validateAction(),

...

  1. executeAction(),

...

  1. done(),

...

  1. and

...

  1. getLogger()

...

  1. methods

...

  1. as

...

  1. appropriate.

...

  1. See

...

  1. 'Component

...

  1. Methods'

...

  1. below

...

  1. for

...

  1. a

...

  1. description

...

  1. of

...

  1. these

...

  1. methods.

...

Components from Scratch

In order to create a component from scratch a new class that implements the interface org.pentaho.core.component.IComponent

...

must

...

be

...

created.

...

To

...

implement

...

all

...

three

...

interfaces

...

requires

...

about

...

30

...

methods

...

to

...

be

...

implemented.

...

It

...

is

...

not

...

recommended

...

to

...

use

...

this

...

option

...

and

...

there

...

should

...

be

...

no

...

need

...

to

...

do

...

this

...

given

...

the

...

options

...

above.

...

Component Methods

If using one of the three recommended methods for creating new components, the methods below are the BI Component methods that need to be customized to provide your needed functionality. The methods are listed in the order that they are typically called during normal processing. Depending on the option used to create your component, not all of these methods are required. See above sections for more details.

getLogger()

This method creates a Log object that will be use to log messages from your component. It has to be created by your component (instead of a superclass) so that the log correctly records the class name of your object.

This method is implemented with a single line.

Code Block
public Log getLogger() {
       return LogFactory.getLog(this.class);
}


h3. 

validateSystemSettings()

...

This

...

method

...

allows

...

your

...

component

...

to

...

verify

...

that

...

any

...

its

...

required

...

system

...

settings

...

it

...

needs

...

in

...

order

...

to

...

operate

...

are

...

set

...

correctly.

...

For

...

examples,

...

the

...

Kettle

...

component

...

(org.pentaho.plugin.kettle.KettleComponent)

...

checks

...

it

...

system

...

settings

...

to

...

see

...

if

...

it

...

is

...

configured

...

for

...

a

...

file-based

...

or

...

RBDMS-based

...

repository,

...

and

...

the

...

email

...

component

...

(org.pentaho.plugin.email.EmailComponent)

...

uses

...

its

...

system

...

settings

...

to

...

connect

...

to

...

your

...

email

...

server.

...

System-wide

...

settings

...

for

...

components

...

should

...

be

...

stored

...

in

...

XML

...

documents

...

in

...

the

...

'system'

...

folder

...

in

...

the

...

Pentaho

...

solution

...

root

...

folder.

...

System

...

settings

...

are

...

ones

...

that

...

will

...

be

...

the

...

same

...

for

...

every

...

instance

...

of

...

your

...

component

...

and

...

that

...

won't

...

change

...

while

...

the

...

server

...

or

...

application

...

is

...

running

...

(unless

...

manually

...

changed

...

by

...

an

...

administrator).

...

In

...

the

...

system

...

folder

...

you

...

will

...

see

...

subdirectories

...

such

...

as

...

'kettle',

...

'quartz',

...

and

...

'smtp-email'.

...

If

...

your

...

component

...

needs

...

system

...

settings

...

you

...

can

...

create

...

a

...

directory

...

to

...

store

...

your

...

settings

...

in

...

and

...

place

...

an

...

XML

...

file

...

in

...

the

...

directory.

...

The

...

XML

...

file

...

can

...

be

...

named

...

anything

...

that

...

you

...

like.

...

Within

...

the

...

XML

...

document

...

you

...

can

...

arrange

...

the

...

settings

...

in

...

any

...

format

...

that

...

you

...

like.

...

The

...

settings

...

file

...

for

...

the

...

email

...

component

...

provides

...

a

...

good

...

example

...

of

...

a

...

settings

...

file.

...

Within

...

the

...

root

...

solution

...

folder

...

the

...

path

...

to

...

the

...

email

...

settings

...

file

...

is

...

'system/smtp-email/email_config.xml'.

...

Code Block
xml
xml
<email-smtp>

&nbsp;&nbsp;   <\!-\- The values within <properties> are passed directly to the JavaMail API.
&nbsp;&nbsp;   For a list of valid properties see&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
   http://java.sun.com/products/javamail/javadocs/index.html \-->
&nbsp;&nbsp;
   <properties>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\!-\
      <!-- This is the address of your SMTP email server for sending email. e.g.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; smtp.pentaho.org \-->
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.
           smtp.pentaho.org -->
      <mail.smtp.host></mail.smtp.host>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\!-\

      <!-- This is the port of your SMTP email server. Usually this is 25.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
           For GMail this is 587 \-->&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <mail.smtp.port>25</mail.smtp.port>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\!-\

      <!-- The transport for accessing the email server. Usually this is smtp.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
           For GMail this is smtps \-->
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <mail.transport.protocol>smtp</mail.transport.protocol>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\!-\

      <!-- Usually this is 'false'. For GMail it is 'true' \-->
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <mail.smtp.starttls.enable>false</mail.smtp.starttls.enable>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\!-\

      <!-- Set to true if the email server requires the sender to authenticate \-->
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <mail.smtp.auth>true</mail.smtp.auth>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\!-\

      <!-- This is true if the email server requires an SSL connection.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
           Usually 'false'. For GMail this is 'true' \-->
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <mail.smtp.ssl>false</mail.smtp.ssl>

     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\!-\- Output debug information from the JavaMail API \-->
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <mail.debug>false</mail.debug>
&nbsp;&nbsp;
   </properties>

&nbsp;&nbsp;   <\!-\- This is the default 'from' address that emails from the Pentaho BI Suite
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Suite
        will appear to come from e.g. joe.pentaho@pentaho.org \-->
&nbsp;&nbsp;
   <mail.from.default>joe.pentaho@pentaho.org</mail.from.default>

&nbsp;&nbsp;   <\!-\- This is the user id used to connect to the email server for sending email
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        It is only required if email-authenticate is set to true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        This is never sent or shown to anyone \-->
&nbsp;&nbsp;
   <mail.userid></mail.userid>
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
   <\!-\- This is the password used to connect to the email server for sending email
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        It is only required if email-authenticate is set to true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;authenticate is set to true
        This is never sent or shown to anyone \-->
&nbsp;&nbsp;
   <mail.password></mail.password>

</email-smtp>
&nbsp;

The

...

email

...

component

...

accesses

...

these

...

settings

...

by

...

calling

...

PentahoSystem.getSystemSetting().

...

For

...

example:

...

String

...

mailhost

...

=

...

PentahoSystem.getSystemSetting("smtp-email/email_config.xml",

...

"mail.smtp.host",

...

null);

...

The

...

getSystemSetting()

...

method

...

finds

...

an

...

entry

...

in

...

a

...

system

...

setting

...

file

...

and

...

returns

...

it

...

to

...

the

...

component.

...

The

...

component

...

does

...

not

...

need

...

to

...

know

...

where

...

the

...

system

...

settings

...

files

...

are

...

located.

...

See

...

the

...

'Utility'

...

section

...

below

...

for

...

more

...

information

...

on

...

the

...

method

...

PentahoSystem.getSystemSetting().

...

validateAction()

...

This

...

method

...

is

...

called

...

to

...

give

...

your

...

component

...

the

...

chance

...

to

...

verify

...

that

...

it

...

has

...

the

...

inputs

...

and

...

resources

...

that

...

it

...

needs

...

to

...

complete

...

successfully.

...

If

...

you

...

return

...

'false'

...

from

...

this

...

method

...

execution

...

of

...

the

...

action

...

sequence

...

will

...

terminate.

...

This

...

method

...

should

...

only

...

be

...

used

...

to

...

check

...

that

...

the

...

inputs

...

are

...

available

...

it

...

should

...

not

...

check

...

the

...

values

...

of

...

inputs

...

because

...

they

...

are

...

not

...

guaranteed

...

to

...

be

...

available

...

at

...

this

...

point

...

during

...

execution.

...

If

...

your

...

component

...

needs

...

resources

...

such

...

as

...

a

...

template

...

file

...

referred

...

to

...

in

...

the

...

action

...

sequence

...

as

...

"new-employee-greeting",

...

you

...

can

...

check

...

that

...

the

...

resource

...

is

...

available

...

by

...

calling

...

isDefinedResource("new-employee-greeting").

...

If

...

your

...

component

...

needs

...

an

...

input

...

called

...

'employee-id',

...

you

...

can

...

check

...

that

...

it

...

has

...

been

...

defined

...

in

...

the

...

action

...

sequence

...

by

...

calling

...

isDefinedInput("employee-id").

...

If

...

your

...

component

...

needs

...

an

...

output

...

called

...

"employee-greeting-email-text",

...

you

...

can

...

check

...

that

...

it

...

has

...

been

...

defined

...

in

...

the

...

action

...

sequence

...

by

...

calling

...

isDefinedOutput("employee-greeting-email-text").

...

Your

...

validateAction()

...

method

...

would

...

now

...

look

...

like

...

this

Code Block

public boolean validateAction() {
&nbsp;&nbsp;&nbsp;
    if (\!isDefinedResource("new-employee-greeting")) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        error( "A template called 'new-employee-greeting' has not been defined" );
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        return false;
&nbsp;&nbsp;&nbsp;
    }
&nbsp;&nbsp;&nbsp;
    if (\!isDefinedInput("employee-id")) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
        error( "An employee id is needed" );
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        return false;
&nbsp;&nbsp;&nbsp;
    }
&nbsp;&nbsp;&nbsp;
    if (\!isDefinedOutput("employee-greeting-email-text") ) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
        error("An output called 'employee-greeting-email-text' has not been defined" );
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        return false;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;
    }
    return true;
}

Notice

...

that

...

we

...

are

...

only

...

checking

...

to

...

see

...

if

...

the

...

input

...

has

...

been

...

defined

...

and

...

we

...

are

...

not

...

trying

...

to

...

get

...

the

...

input

...

value.

...

The

...

validateAction()

...

of

...

the

...

EmailComponent

...

looks

...

like

...

this:

Code Block

public boolean validateAction() {
&nbsp;&nbsp;&nbsp;
    // make sure that we can get a 'to' email address
&nbsp;&nbsp;&nbsp;
    if (\!isDefinedInput("to")) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        error(Messages.getErrorString("Email.ERROR_0001_TO_NOT_DEFINED",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getActionName()));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
              getActionName()));
        return false;
&nbsp;&nbsp;&nbsp;    }
&nbsp;&nbsp;&nbsp;
    // make sure that we can get a subject for the email
&nbsp;&nbsp;&nbsp;
    if (\!isDefinedInput("subject")) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        error(Messages.getErrorString("Email.ERROR_0002_SUBJECT_NOT_DEFINED",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
              getActionName()));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        return false;
&nbsp;&nbsp;&nbsp;    }
&nbsp;&nbsp;&nbsp;
    // make sure that we have either a plain text or html message for the email
&nbsp;&nbsp;&nbsp;
    if (\!isDefinedInput("message-plain") && \!isDefinedInput("message-html")) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        error(Messages.getErrorString("Email.ERROR_0003_BODY_NOT_DEFINED",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;",
              getActionName()));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        return false;
&nbsp;&nbsp;&nbsp;    }
&nbsp;&nbsp;&nbsp;
    return true;
}

Notice

...

that

...

this

...

method

...

does

...

not

...

check

...

for

...

the

...

optional

...

parameters

...

such

...

as

...

'cc',

...

'bcc',

...

or

...

email

...

attachments

...

but

...

only

...

checks

...

for

...

the

...

minimum

...

parameters

...

that

...

are

...

required

...

for

...

the

...

component

...

to

...

execute

...

successfully.

...

You

...

do

...

not

...

have

...

to

...

call

...

for

...

each

...

individual

...

resource,

...

input,

...

or

...

output.

...

If

...

you

...

prefer,

...

you

...

can

...

work

...

with

...

java.util.Set

...

objects

...

that

...

contain

...

the

...

names

...

of

...

the

...

available

...

items.

...

These

...

sets

...

can

...

be

...

obtained

...

by

...

calling

...

getResourceNames(),

...

getInputNames(),

...

and

...

getOutputNames().

...

For

...

example

Code Block

Set inputNames = getInputNames();
if( \!inputNames.contains( "param1" ) && \!inputNames.contains( "param2" ) ) {
&nbsp;&nbsp;&nbsp;    error( "I need both param1 and param2" );
&nbsp;&nbsp;&nbsp;
    return false;
}


h3. 

init()

...

This

...

method

...

is

...

called

...

to

...

allow

...

the

...

component

...

to

...

perform

...

any

...

initialization

...

operations

...

that

...

are

...

required

...

before

...

the

...

executeAction()

...

is

...

called.

...

executeAction()

...

This

...

method

...

is

...

called

...

to

...

cause

...

the

...

component

...

to

...

perform

...

its

...

function.

...

Within

...

this

...

method

...

you

...

can

...

call

...

other

...

internal

...

API

...

methods

...

to

...

get

...

the

...

values

...

of

...

inputs,

...

to

...

get

...

resources,

...

to

...

ask

...

users

...

for

...

parameters,

...

and

...

to

...

get

...

output

...

streams.

...

Typically,

...

during

...

the

...

execute

...

method

...

a

...

component

...

will:

...

  1. Gather

...

  1. input

...

  1. values.

...

  1. These

...

  1. might

...

  1. be

...

  1. parameters

...

  1. or

...

  1. component

...

  1. settings.

...

  1. If

...

  1. the

...

  1. input

...

  1. values

...

  1. are

...

  1. not

...

  1. complete,

...

  1. the

...

  1. component

...

  1. can

...

  1. stop

...

  1. executing

...

  1. or

...

  1. prompt

...

  1. the

...

  1. user

...

  1. for

...

  1. additional

...

  1. information.

...

  1. Gather

...

  1. resources.

...

  1. These

...

  1. might

...

  1. be

...

  1. templates

...

  1. or

...

  1. definition

...

  1. files.

...

  1. Get

...

  1. an

...

  1. output

...

  1. pipe

...

  1. of

...

  1. some

...

  1. kind

...

  1. (e.g.

...

  1. an

...

  1. output

...

  1. stream).

...

  1. Create

...

  1. output

...

  1. contents.

...

  1. Return

...

  1. the

...

  1. status

...

  1. of

...

  1. the

...

  1. execution.

...

See

...

'Internal

...

API'

...

below

...

for

...

descriptions

...

of

...

the

...

methods

...

available

...

for

...

the

...

component

...

to

...

use.

...

We

...

will

...

use

...

the

...

executeAction()

...

of

...

the

...

PrintComponent

...

(org.pentaho.plugin.print.PrintComponent)

...

as

...

an

...

example

...

(minor

...

modifications

...

have

...

been

...

made

...

for

...

clarity).

...

Code Block
protected boolean executeAction() {
&nbsp;&nbsp;&nbsp;
    String printFileName = null;
&nbsp;&nbsp;&nbsp;
    IActionResource printFileResource = null;

&nbsp;&nbsp;&nbsp;    // see if we are printing a file
&nbsp;&nbsp;&nbsp;
    if (isDefinedInput("print-file")) {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

        // get the name of the file to print
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        printFileName = getInputStringValue("print-file");
&nbsp;&nbsp;&nbsp;    } 

  &nbsp;&nbsp;&nbsp;  InputStream inStream = null;
&nbsp;&nbsp;&nbsp;    // Get the name of the printer to use
&nbsp;&nbsp;&nbsp;    if (isDefinedInput("printer-name")) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        printerName = getInputStringValue("printer-name");
&nbsp;&nbsp;&nbsp;
    }
&nbsp;&nbsp;&nbsp;
    // try to find the requested printer
&nbsp;&nbsp;&nbsp;
    PrintService printer = getPrinterInternal(printerName);
&nbsp;&nbsp;&nbsp;
    if (printer == null) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        // the requested printer is not available
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        if (\!feedbackAllowed()) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            // we are not allowed to prompt the user for a printer, we have to fail&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                
            error( "The requested printer "+printerName+" is not available" );
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is not available" );
            return false;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        }
        // prompt the user for an available printer
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        // get a list of available print services
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintService\[\
        PrintService[] services = PrinterJob.lookupPrintServices();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrinterJob.lookupPrintServices();
        ArrayList values = new ArrayList();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        // add each print service to our list of printers
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        for (int i = 0; i < services.length; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            String value = services\[i\].getName();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; services[i].getName();
            values.add(value);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        }
        // create a parameter for the user to select from
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        createFeedbackParameter("printer-name",&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;     
            "select a printer", "", null, values, null, "select");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            return null;
        }
        promptNeeded();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        return true;
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;
    }

    // Get the number of copies
&nbsp;&nbsp;&nbsp;
    int copies = 1;
&nbsp;&nbsp;&nbsp;    if (isDefinedInput("copies")) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        copies = Integer.valueOf(getInputStringValue("copies")).intValue();
&nbsp;&nbsp;&nbsp;    }

&nbsp;&nbsp;&nbsp;    // Check for a valid printFileName or printFile Resource
&nbsp;&nbsp;&nbsp;
    if (printFileName \!= null) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        try {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            inStream = new FileInputStream(printFileName);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        } catch (FileNotFoundException fnfe) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            error(fnfe.toString(), fnfe);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            return false;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        }
        // Set the input source for sending to the driver.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        InputSource source = new InputSource(inStream);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        try {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            Driver driver = new Driver(source, null);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            PrinterJob pj = PrinterJob.getPrinterJob();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pj.setPrintService(printer);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getPrinterJob();
            pj.setPrintService(printer);
            PrintRenderer renderer = new PrintRenderer(pj, copies);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            driver.setRenderer(renderer);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            driver.run();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        } catch (Exception ex) {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;
	     error( "Could not print the document", ex);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            return false;
        }
        return true;
&nbsp;&nbsp;&nbsp; }   h3.}

done()

...

This

...

method

...

is

...

called

...

to

...

give

...

the

...

component

...

the

...

opportunity

...

to

...

perform

...

any

...

cleanup

...

operations

...

that

...

are

...

necessary.