Job视图界面创建及执行机制
读取*.kbj文件创建Job视图
Spoon.java
private void loadLastUsedFile(
LastUsedFile lastUsedFile, String repositoryName, boolean trackIt, boolean isStartup ) throws KettleException {
if ( lastUsedFile.isTransformation() ) {
openFile( lastUsedFile.getFilename(), variables, rep != null );
}
if ( lastUsedFile.isJob() ) {
openFile( lastUsedFile.getFilename(), variables, false );
}
}
public void openFile( String filename, VariableSpace variableSpace, boolean importfile ) {
// otherwise try by looking at the root node if we were able to parse file
// as XML
if ( listener == null && root != null ) {
for ( FileListener li : fileListeners ) {
if ( li.acceptsXml( root.getNodeName() ) ) {
listener = li;
break;
}
}
}
loaded = listener.open( root, filename, importfile );
}
FileListener.java
public interface FileListener {
public boolean open( Node transNode, String fname, boolean importfile ) throws KettleMissingPluginsException;
public boolean save( EngineMetaInterface meta, String fname, boolean isExport );
public void syncMetaName( EngineMetaInterface meta, String name );
public boolean accepts( String fileName );
public boolean acceptsXml( String nodeName );
public String[] getSupportedExtensions();
public String[] getFileTypeDisplayNames( Locale locale );
public String getRootNodeName();
}
打开*.kjb流程
Spoon.java中的openFile
JobFileListener.java中
public boolean open( Node jobNode, String fname, String connection, boolean importfile ) {
JobMeta jobMeta = new JobMeta();
jobMeta.loadXML( jobNode, fname, spoon.getRepository(), spoon.getMetaStore(), false, spoon );
spoon.delegates.jobs.addJobGraph( jobMeta );
}
JobMeta.java loadXML 解析 *.kjb文件文件
public void loadXML( Node jobnode, String fname, Repository rep, IMetaStore metaStore,
boolean ignoreRepositorySharedObjects, OverwritePrompter prompter ) throws KettleXMLException {
/*
* read the job entries...
*/
Node entriesnode = XMLHandler.getSubNode( jobnode, "entries" );
int tr = XMLHandler.countNodes( entriesnode, "entry" );
for ( int i = 0; i < tr; i++ ) {
Node entrynode = XMLHandler.getSubNodeByNr( entriesnode, "entry", i );
// System.out.println("Reading entry:\n"+entrynode);
......
JobEntryCopy je = new JobEntryCopy( entrynode, databases, slaveServers, rep, metaStore );
// Add the JobEntryCopy...
addJobEntry( je );
}
Node hopsnode = XMLHandler.getSubNode( jobnode, "hops" );
int ho = XMLHandler.countNodes( hopsnode, "hop" );
for ( int i = 0; i < ho; i++ ) {
Node hopnode = XMLHandler.getSubNodeByNr( hopsnode, "hop", i );
JobHopMeta hi = new JobHopMeta( hopnode, this );
jobhops.add( hi );
}
}
JobEntryCopy.java类构造函数
public JobEntryCopy( Node entrynode, List<DatabaseMeta> databases, List<SlaveServer> slaveServers, Repository rep,
IMetaStore metaStore ) throws KettleXMLException {
String stype = XMLHandler.getTagValue( entrynode, "type" );
PluginRegistry registry = PluginRegistry.getInstance();
PluginInterface jobPlugin = registry.findPluginWithId( JobEntryPluginType.class, stype, true );
if ( jobPlugin == null ) {
String name = XMLHandler.getTagValue( entrynode, "name" );
entry = new MissingEntry( name, stype );
} else {
entry = registry.loadClass( jobPlugin, JobEntryInterface.class );//得到不同的Entry,比如JobEntryTrans、JobEntryEval、JobEntrySpecial
// Get an empty JobEntry of the appropriate class...、
if ( entry != null ) {
if ( jobPlugin != null ) {
entry.setPluginId( jobPlugin.getIds()[0] );
}
entry.setMetaStore( metaStore ); // inject metastore
entry.loadXML( entrynode, databases, slaveServers, rep, metaStore );
}
}
JobEntryInterface.java
public interface JobEntryInterface {
Result execute( Result prev_result, int nr ) throws KettleException;
void setParentJob( Job job );
Job getParentJob();
String getName();
void setName( String name );
String getPluginId();
void setPluginId( String pluginId );
String getDescription();
void setDescription( String description );
void loadXML( Node entrynode, List<DatabaseMeta> databases, List<SlaveServer> slaveServers,
Repository rep, IMetaStore metaStore ) throws KettleXMLException;
String getXML();
boolean isStart();
boolean isDummy();
boolean evaluates();
boolean isUnconditional();
boolean isEvaluation();
boolean isTransformation();
boolean isJob();
boolean isShell();
boolean isMail();
boolean isSpecial();
String getFilename();
}
JobEntryTrans.java //实现*.kjb中
*
public class JobEntryTrans extends JobEntryBase implements Cloneable, JobEntryInterface, HasRepositoryDirectories,
JobEntryRunConfigurableInterface {
@Override
public void loadXML( Node entrynode, List<DatabaseMeta> databases, List<SlaveServer> slaveServers,
Repository rep, IMetaStore metaStore ) throws KettleXMLException {
try {
super.loadXML( entrynode, databases, slaveServers );
String method = XMLHandler.getTagValue( entrynode, "specification_method" );
specificationMethod = ObjectLocationSpecificationMethod.getSpecificationMethodByCode( method );
String transId = XMLHandler.getTagValue( entrynode, "trans_object_id" );
transObjectId = Utils.isEmpty( transId ) ? null : new StringObjectId( transId );
filename = XMLHandler.getTagValue( entrynode, "filename" );
transname = XMLHandler.getTagValue( entrynode, "transname" );
......
}
}
JobEntryEval.java //实现*.kjb中
public class JobEntryEval extends JobEntryBase implements Cloneable, JobEntryInterface {
public void loadXML( Node entrynode, List<DatabaseMeta> databases, List<SlaveServer> slaveServers,
Repository rep, IMetaStore metaStore ) throws KettleXMLException {
try {
super.loadXML( entrynode, databases, slaveServers );
script = XMLHandler.getTagValue( entrynode, "script" );
} catch ( Exception e ) {
throw new KettleXMLException( BaseMessages.getString( PKG, "JobEntryEval.UnableToLoadFromXml" ), e );
}
}
}
Job视图界面创建
拖动插件到Job 视图区流程
类型为DragAndDropContainer.TYPE_BASE_JOB_ENTRY
TransGraph.java
public void drop( DropTargetEvent event ) {
// no data to copy, indicate failure in event.detail
if ( event.data == null ) {
event.detail = DND.DROP_NONE;
return;
}
switch ( container.getType() ) {
case DragAndDropContainer.TYPE_BASE_JOB_ENTRY: // Create a new Job Entry on the canvas
JobEntryCopy jge = spoon.newJobEntry( jobMeta, entry, false );
if ( jge != null )
{
redraw();
}
break;
}
}
双击插件到视图区流程
Spoon.java
private void doubleClickedInTree( Tree tree, boolean shift ) {
if ( selection instanceof PluginInterface ) {
PluginInterface plugin = (PluginInterface) selection;
if ( plugin.getPluginType().equals( StepPluginType.class ) ) {
TransGraph transGraph = getActiveTransGraph();
if ( transGraph != null ) {
transGraph.addStepToChain( plugin, shift );
}
}
if ( plugin.getPluginType().equals( JobEntryPluginType.class ) ) {
JobGraph jobGraph = getActiveJobGraph();
if ( jobGraph != null ) {
jobGraph.addJobEntryToChain( object.getItemText(), shift );
}
}
}
}
JobGraph.java
public void addJobEntryToChain( String typeDesc, boolean shift ) {
JobMeta jobMeta = spoon.getActiveJob();
if ( jobMeta == null ) {
return;
}
JobEntryCopy newEntry = spoon.newJobEntry( jobMeta, typeDesc, false );
if ( newEntry == null ) {
return;
}
if ( lastChained != null ) {
spoon.newJobHop( jobMeta, lastChained, newEntry );
}
}
Spoon.java
public JobEntryCopy newJobEntry( JobMeta jobMeta, String type_desc, boolean openit ) {
PluginRegistry registry = PluginRegistry.getInstance();
PluginInterface jobPlugin;
jobPlugin = PluginRegistry.getInstance().findPluginWithName( JobEntryPluginType.class, type_desc ); // Generate the appropriate class...
JobEntryInterface jei = (JobEntryInterface) registry.loadClass( jobPlugin );
jei.setPluginId( jobPlugin.getIds()[0] );
jei.setName( entry_name );
jobMeta.addJobEntry( jge );
}
Job执行
界面触发
JobGraph.java
private void addToolBar() {
ToolItem runItem = new ToolItem( swtToolbar, SWT.DROP_DOWN, 0 );
runItem.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent e ) {
if ( e.detail == SWT.DROP_DOWN ) {
Menu menu = new Menu( shell, SWT.POP_UP );
MenuItem item1 = new MenuItem( menu, SWT.PUSH );
item1.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent e1 ) {
runJob();
}
} );
MenuItem item2 = new MenuItem( menu, SWT.PUSH );
item2.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent e2 ) {
runOptionsJob();
}
} );
} else {
runJob();
}
}
} );
}
Job的Run机制
JobGraph.java
public void runJob() {
spoon.runFile();
}
Spoon.java
public void runFile() {
executeFile( true, false, false, false, false, null, false, false );
}
Spoon.java
public void executeFile( boolean local, boolean remote, boolean cluster, boolean preview, boolean debug,
Date replayDate, boolean safe, boolean show ) {
TransMeta transMeta = getActiveTransformation();
if ( transMeta != null ) {
executeTransformation( transMeta, local, remote, cluster, preview, debug, replayDate,
safe,transExecutionConfiguration.getLogLevel() );
}
JobMeta jobMeta = getActiveJob();
if ( jobMeta != null ) {
executeJob( jobMeta, local, remote, replayDate, safe, null, 0 );
}
}
Spoon.java
public void executeJob( JobMeta jobMeta, boolean local, boolean remote, Date replayDate, boolean safe,
delegates.jobs.executeJob( jobMeta, local, remote, replayDate, safe, startCopyName, startCopyNr );
}
SpoonJobDelegate.java
public class SpoonJobDelegate extends SpoonDelegate {
public void executeJob( JobMeta jobMeta, boolean local, boolean remote, Date replayDate, boolean safe,
String startCopyName, int startCopyNr ) throws KettleException {
//前面会弹出对话框,确认后才能后续操作
if ( executionConfiguration.isExecutingLocally() ) {
jobGraph.startJob( executionConfiguration );
} else if ( executionConfiguration.isExecutingRemotely() ) {}
}
JobGraph.java
public synchronized void startJob( JobExecutionConfiguration executionConfiguration ) throws KettleException {
if ( spoon.rep != null ) {
runJobMeta = spoon.rep.loadJob( jobMeta.getName(), jobMeta.getRepositoryDirectory(), null, null );
} else {
runJobMeta = new JobMeta( null, jobMeta.getFilename(), null, jobMeta.getMetaStore(), null );//解析*.kjb的xml文件
}
job = new Job( spoon.rep, runJobMeta, spoonLoggingObject );
job.getJobMeta().activateParameters();
job.start();
// Link to the new jobTracker!
jobGridDelegate.jobTracker = job.getJobTracker();
}
JobGraph.java
public void addAllTabs() {
transHistoryDelegate.addTransHistory();
transLogDelegate.addTransLog();
transGridDelegate.addTransGrid();
transPerfDelegate.addTransPerf();
transMetricsDelegate.addTransMetrics();
transPreviewDelegate.addTransPreview();
}
//注意Job继承自Thread
Job.java
public class Job extends Thread implements VariableSpace, NamedParams, HasLogChannelInterface, LoggingObjectInterface,
ExecutorInterface, ExtensionDataInterface {
}
TransGraph.java
private void checkStartThreads() {
if ( initialized && !running && trans != null ) {
startThreads();
}
}
private synchronized void startThreads() {
trans.startThreads();
}
Trans.java
public void startThreads() throws KettleException {
switch ( transMeta.getTransformationType() ) {
case Normal:
// Now start all the threads...
for ( int i = 0; i < steps.size(); i++ ) {
final StepMetaDataCombi combi = steps.get( i );
RunThread runThread = new RunThread( combi );
Thread thread = new Thread( runThread );
thread.setName( getName() + " - " + combi.stepname );
} );
thread.start();
}
break;
case SerialSingleThreaded:
break;
case SingleThreaded:
break;
default:
break;
}
}
RunThread.java中的run方法
public class RunThread implements Runnable {
public RunThread( StepMetaDataCombi combi ) {
this.step = combi.step;
this.meta = combi.meta;
this.data = combi.data;
this.log = step.getLogChannel();
}
public void run() {
step.setRunning( true );
// Wait
while ( step.processRow( meta, data ) ) {
if ( step.isStopped() ) {
break;
}
}
}
}
public void capturePreviewData( final Trans trans, List<StepMeta> stepMetas ) {
final TransMeta transMeta = trans.getTransMeta();
for ( final StepMeta stepMeta : stepMetas ) {
try {
StepInterface step = trans.findRunThread( stepMeta.getName() );
if ( step != null ) {
switch ( previewMode ) {
case LAST:
step.addRowListener( new RowAdapter() {
@Override
public void rowWrittenEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
try {
rowsData.add( new RowMetaAndData( rowMeta, rowMeta.cloneRow( row ) ) );
if ( rowsData.size() > PropsUI.getInstance().getDefaultPreviewSize() ) {
rowsData.remove( 0 );
}
} catch ( Exception e ) {
throw new KettleStepException( "Unable to clone row for metadata : " + rowMeta, e );
}
}
} );
break;
default:
step.addRowListener( new RowAdapter() {
@Override
public void rowWrittenEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
if ( rowsData.size() < PropsUI.getInstance().getDefaultPreviewSize() ) {
try {
rowsData.add( new RowMetaAndData( rowMeta, rowMeta.cloneRow( row ) ) );
} catch ( Exception e ) {
throw new KettleStepException( "Unable to clone row for metadata : " + rowMeta, e );
}
}
}
} );
break;
}
}
} catch ( Exception e ) {
loggingText.append( Const.getStackTracker( e ) );
}
}
} );
}
Transform的Debug机制
Transform的Previewer机制
浙公网安备 33010602011771号