/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2017 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.pentaho.di.ui.spoon.delegates; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.MessageBox; import org.pentaho.di.core.Const; import org.pentaho.di.core.util.Utils; import org.pentaho.di.core.NotePadMeta; import org.pentaho.di.core.ObjectLocationSpecificationMethod; import org.pentaho.di.core.database.DatabaseMeta; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.exception.KettleStepException; import org.pentaho.di.core.extension.ExtensionPointHandler; import org.pentaho.di.core.extension.KettleExtensionPoint; import org.pentaho.di.core.gui.Point; import org.pentaho.di.core.logging.DefaultLogLevel; import org.pentaho.di.core.plugins.JobEntryPluginType; import org.pentaho.di.core.plugins.PluginInterface; import org.pentaho.di.core.plugins.PluginRegistry; import org.pentaho.di.core.plugins.StepPluginType; import org.pentaho.di.core.undo.TransAction; import org.pentaho.di.core.xml.XMLHandler; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.job.Job; import org.pentaho.di.job.JobExecutionConfiguration; import org.pentaho.di.job.JobHopMeta; import org.pentaho.di.job.JobMeta; import org.pentaho.di.job.entries.special.JobEntrySpecial; import org.pentaho.di.job.entries.sql.JobEntrySQL; import org.pentaho.di.job.entries.trans.JobEntryTrans; import org.pentaho.di.job.entry.JobEntryCopy; import org.pentaho.di.job.entry.JobEntryDialogInterface; import org.pentaho.di.job.entry.JobEntryInterface; import org.pentaho.di.repository.Repository; import org.pentaho.di.repository.RepositoryDirectoryInterface; import org.pentaho.di.trans.TransHopMeta; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.step.StepDialogInterface; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.di.trans.step.StepMetaInterface; import org.pentaho.di.trans.steps.tableinput.TableInputMeta; import org.pentaho.di.trans.steps.tableoutput.TableOutputMeta; import org.pentaho.di.ui.core.PropsUI; import org.pentaho.di.ui.core.dialog.ErrorDialog; import org.pentaho.di.ui.core.gui.GUIResource; import org.pentaho.di.ui.job.dialog.JobExecutionConfigurationDialog; import org.pentaho.di.ui.spoon.Spoon; import org.pentaho.di.ui.spoon.TabMapEntry; import org.pentaho.di.ui.spoon.TabMapEntry.ObjectType; import org.pentaho.di.ui.spoon.job.JobGraph; import org.pentaho.di.ui.spoon.wizards.RipDatabaseWizardPage1; import org.pentaho.di.ui.spoon.wizards.RipDatabaseWizardPage2; import org.pentaho.di.ui.spoon.wizards.RipDatabaseWizardPage3; import org.pentaho.xul.swt.tab.TabItem; import org.w3c.dom.Document; import org.w3c.dom.Node; public class SpoonJobDelegate extends SpoonDelegate { private static Class<?> PKG = Spoon.class; // for i18n purposes, needed by Translator2!! /** * This contains a map between the name of a transformation and the TransMeta object. If the transformation has no * name it will be mapped under a number [1], [2] etc. */ private List<JobMeta> jobMap; public SpoonJobDelegate( Spoon spoon ) { super( spoon ); jobMap = new ArrayList<JobMeta>(); } public JobEntryCopy newJobEntry( JobMeta jobMeta, String type_desc, boolean openit ) { PluginRegistry registry = PluginRegistry.getInstance(); PluginInterface jobPlugin = null; try { jobPlugin = PluginRegistry.getInstance().findPluginWithName( JobEntryPluginType.class, type_desc ); if ( jobPlugin == null ) { // Check if it's not START or DUMMY if ( JobMeta.STRING_SPECIAL_START.equals( type_desc ) || JobMeta.STRING_SPECIAL_DUMMY.equals( type_desc ) ) { jobPlugin = registry.findPluginWithId( JobEntryPluginType.class, JobMeta.STRING_SPECIAL ); } } if ( jobPlugin != null ) { // Determine name & number for this entry. String basename = type_desc; // See if the name is already used... // String entry_name = basename; int nr = 2; JobEntryCopy check = jobMeta.findJobEntry( entry_name, 0, true ); while ( check != null ) { entry_name = basename + " " + nr++; check = jobMeta.findJobEntry( entry_name, 0, true ); } // Generate the appropriate class... JobEntryInterface jei = (JobEntryInterface) registry.loadClass( jobPlugin ); jei.setPluginId( jobPlugin.getIds()[0] ); jei.setName( entry_name ); if ( jei.isSpecial() ) { if ( JobMeta.STRING_SPECIAL_START.equals( type_desc ) ) { // Check if start is already on the canvas... if ( jobMeta.findStart() != null ) { JobGraph.showOnlyStartOnceMessage( spoon.getShell() ); return null; } ( (JobEntrySpecial) jei ).setStart( true ); jei.setName( JobMeta.STRING_SPECIAL_START ); } if ( JobMeta.STRING_SPECIAL_DUMMY.equals( type_desc ) ) { ( (JobEntrySpecial) jei ).setDummy( true ); // jei.setName(JobMeta.STRING_SPECIAL_DUMMY); // Don't overwrite the name } } if ( openit ) { JobEntryDialogInterface d = getJobEntryDialog( jei, jobMeta ); if ( d != null && d.open() != null ) { JobEntryCopy jge = new JobEntryCopy(); jge.setEntry( jei ); jge.setLocation( 50, 50 ); jge.setNr( 0 ); jobMeta.addJobEntry( jge ); // Verify that the name is not already used in the job. // jobMeta.renameJobEntryIfNameCollides( jge ); spoon.addUndoNew( jobMeta, new JobEntryCopy[] { jge }, new int[] { jobMeta.indexOfJobEntry( jge ) } ); spoon.refreshGraph(); spoon.refreshTree(); return jge; } else { return null; } } else { JobEntryCopy jge = new JobEntryCopy(); jge.setEntry( jei ); jge.setLocation( 50, 50 ); jge.setNr( 0 ); jobMeta.addJobEntry( jge ); spoon.addUndoNew( jobMeta, new JobEntryCopy[] { jge }, new int[] { jobMeta.indexOfJobEntry( jge ) } ); spoon.refreshGraph(); spoon.refreshTree(); return jge; } } else { return null; } } catch ( Throwable e ) { new ErrorDialog( spoon.getShell(), BaseMessages.getString( PKG, "Spoon.ErrorDialog.UnexpectedErrorCreatingNewJobGraphEntry.Title" ), BaseMessages.getString( PKG, "Spoon.ErrorDialog.UnexpectedErrorCreatingNewJobGraphEntry.Message" ), new Exception( e ) ); return null; } } public JobEntryDialogInterface getJobEntryDialog( JobEntryInterface jobEntryInterface, JobMeta jobMeta ) { PluginRegistry registry = PluginRegistry.getInstance(); String dialogClassName = jobEntryInterface.getDialogClassName(); try { Class<?> dialogClass; Class<?>[] paramClasses = new Class<?>[] { spoon.getShell().getClass(), JobEntryInterface.class, Repository.class, JobMeta.class }; Object[] paramArgs = new Object[] { spoon.getShell(), jobEntryInterface, spoon.getRepository(), jobMeta }; Constructor<?> dialogConstructor; try { PluginInterface plugin = registry.getPlugin( JobEntryPluginType.class, jobEntryInterface ); dialogClass = PluginRegistry.getInstance().getClass( plugin, dialogClassName ); } catch ( Exception e ) { dialogClass = Class.forName( dialogClassName, true, jobEntryInterface.getClass().getClassLoader() ); } dialogConstructor = dialogClass.getConstructor( paramClasses ); JobEntryDialogInterface entryDialogInterface = (JobEntryDialogInterface) dialogConstructor.newInstance( paramArgs ); entryDialogInterface.setMetaStore( spoon.getMetaStore() ); return entryDialogInterface; } catch ( Throwable t ) { t.printStackTrace(); spoon.getLog().logError( spoon.toString(), "Could not create dialog for " + dialogClassName, t ); return null; } } public StepDialogInterface getStepEntryDialog( StepMetaInterface stepMeta, TransMeta transMeta, String stepName ) { String dialogClassName = stepMeta.getDialogClassName(); try { Class<?> dialogClass; Class<?>[] paramClasses = new Class<?>[] { spoon.getShell().getClass(), Object.class, TransMeta.class, String.class }; Object[] paramArgs = new Object[] { spoon.getShell(), stepMeta, transMeta, stepName }; Constructor<?> dialogConstructor; dialogClass = stepMeta.getClass().getClassLoader().loadClass( dialogClassName ); dialogConstructor = dialogClass.getConstructor( paramClasses ); return (StepDialogInterface) dialogConstructor.newInstance( paramArgs ); } catch ( Throwable t ) { spoon.getLog().logError( spoon.toString(), "Could not create dialog for " + dialogClassName, t ); } return null; } public void editJobEntry( JobMeta jobMeta, JobEntryCopy je ) { try { spoon.getLog().logBasic( spoon.toString(), BaseMessages.getString( PKG, "Spoon.Log.EditJobEntry", je.getName() ) ); JobEntryCopy before = (JobEntryCopy) je.clone_deep(); JobEntryInterface jei = je.getEntry(); if ( jei.isSpecial() ) { JobEntrySpecial special = (JobEntrySpecial) jei; if ( special.isDummy() ) { return; } } JobEntryDialogInterface d = getJobEntryDialog( jei, jobMeta ); if ( d != null ) { if ( d.open() != null ) { // First see if the name changed. // If so, we need to verify that the name is not already used in the job. // jobMeta.renameJobEntryIfNameCollides( je ); JobEntryCopy after = (JobEntryCopy) je.clone(); spoon.addUndoChange( jobMeta, new JobEntryCopy[] { before }, new JobEntryCopy[] { after }, new int[] { jobMeta .indexOfJobEntry( je ) } ); spoon.refreshGraph(); spoon.refreshTree(); } } else { MessageBox mb = new MessageBox( spoon.getShell(), SWT.OK | SWT.ICON_INFORMATION ); mb.setMessage( BaseMessages.getString( PKG, "Spoon.Dialog.JobEntryCanNotBeChanged.Message" ) ); mb.setText( BaseMessages.getString( PKG, "Spoon.Dialog.JobEntryCanNotBeChanged.Title" ) ); mb.open(); } } catch ( Exception e ) { if ( !spoon.getShell().isDisposed() ) { new ErrorDialog( spoon.getShell(), BaseMessages.getString( PKG, "Spoon.ErrorDialog.ErrorEditingJobEntry.Title" ), BaseMessages.getString( PKG, "Spoon.ErrorDialog.ErrorEditingJobEntry.Message" ), e ); } } } public void deleteJobEntryCopies( JobMeta job, JobEntryCopy[] jobEntries ) { // Hops belonging to the deleting jobEntries are placed in a single transaction and removed. List<JobHopMeta> jobHops = new ArrayList<JobHopMeta>(); int[] hopIndexes = new int[job.nrJobHops()]; int hopIndex = 0; for ( int i = job.nrJobHops() - 1; i >= 0; i-- ) { JobHopMeta hi = job.getJobHop( i ); for ( int j = 0; j < jobEntries.length && hopIndex < hopIndexes.length; j++ ) { if ( hi.getFromEntry().equals( jobEntries[j] ) || hi.getToEntry().equals( jobEntries[j] ) ) { int idx = job.indexOfJobHop( hi ); jobHops.add( (JobHopMeta) hi.clone() ); hopIndexes[hopIndex] = idx; job.removeJobHop( idx ); spoon.refreshTree(); hopIndex++; break; } } } if ( !jobHops.isEmpty() ) { JobHopMeta[] hops = jobHops.toArray( new JobHopMeta[jobHops.size()] ); spoon.addUndoDelete( job, hops, hopIndexes ); } // Deleting jobEntries are placed all in a single transaction and removed. int[] positions = new int[jobEntries.length]; for ( int i = 0; i < jobEntries.length; i++ ) { int pos = job.indexOfJobEntry( jobEntries[i] ); job.removeJobEntry( pos ); positions[i] = pos; } spoon.addUndoDelete( job, jobEntries, positions ); spoon.refreshTree(); spoon.refreshGraph(); } public void deleteJobEntryCopies( JobMeta jobMeta, JobEntryCopy jobEntry ) { for ( int i = jobMeta.nrJobHops() - 1; i >= 0; i-- ) { JobHopMeta hi = jobMeta.getJobHop( i ); if ( hi.getFromEntry().equals( jobEntry ) || hi.getToEntry().equals( jobEntry ) ) { int idx = jobMeta.indexOfJobHop( hi ); spoon.addUndoDelete( jobMeta, new JobHopMeta[] { (JobHopMeta) hi.clone() }, new int[] { idx } ); jobMeta.removeJobHop( idx ); spoon.refreshTree(); } } int pos = jobMeta.indexOfJobEntry( jobEntry ); jobMeta.removeJobEntry( pos ); spoon.addUndoDelete( jobMeta, new JobEntryCopy[] { jobEntry }, new int[] { pos } ); spoon.refreshTree(); spoon.refreshGraph(); } public void dupeJobEntry( JobMeta jobMeta, JobEntryCopy jobEntry ) { if ( jobEntry == null ) { return; } if ( jobEntry.isStart() ) { MessageBox mb = new MessageBox( spoon.getShell(), SWT.OK | SWT.ICON_INFORMATION ); mb.setMessage( BaseMessages.getString( PKG, "Spoon.Dialog.OnlyUseStartOnce.Message" ) ); mb.setText( BaseMessages.getString( PKG, "Spoon.Dialog.OnlyUseStartOnce.Title" ) ); mb.open(); return; } JobEntryCopy dupejge = (JobEntryCopy) jobEntry.clone(); dupejge.setNr( jobMeta.findUnusedNr( dupejge.getName() ) ); if ( dupejge.isDrawn() ) { Point p = jobEntry.getLocation(); dupejge.setLocation( p.x + 10, p.y + 10 ); } jobMeta.addJobEntry( dupejge ); spoon.refreshGraph(); spoon.refreshTree(); spoon.setShellText(); } public void copyJobEntries( JobMeta jobMeta, List<JobEntryCopy> jec ) { if ( jec == null || jec.size() == 0 ) { return; } String xml = XMLHandler.getXMLHeader(); xml += XMLHandler.openTag( Spoon.XML_TAG_JOB_JOB_ENTRIES ) + Const.CR; for ( int i = 0; i < jec.size(); i++ ) { xml += jec.get( i ).getXML(); } xml += " " + XMLHandler.closeTag( Spoon.XML_TAG_JOB_JOB_ENTRIES ) + Const.CR; spoon.toClipboard( xml ); } public void pasteXML( JobMeta jobMeta, String clipcontent, Point loc ) { try { Document doc = XMLHandler.loadXMLString( clipcontent ); // De-select all, re-select pasted steps... jobMeta.unselectAll(); Node entriesnode = XMLHandler.getSubNode( doc, Spoon.XML_TAG_JOB_JOB_ENTRIES ); int nr = XMLHandler.countNodes( entriesnode, "entry" ); spoon.getLog().logDebug( spoon.toString(), "I found " + nr + " job entries to paste on location: " + loc ); List<JobEntryCopy> entryList = new ArrayList<JobEntryCopy>( nr ); // Point min = new Point(loc.x, loc.y); Point min = new Point( 99999999, 99999999 ); for ( int i = 0; i < nr; i++ ) { Node entrynode = XMLHandler.getSubNodeByNr( entriesnode, "entry", i ); JobEntryCopy copy = new JobEntryCopy( entrynode, jobMeta.getDatabases(), jobMeta.getSlaveServers(), spoon.getRepository(), spoon .getMetaStore() ); if ( copy.isStart() && ( jobMeta.findStart() != null ) ) { JobGraph.showOnlyStartOnceMessage( spoon.getShell() ); continue; } String name = jobMeta.getAlternativeJobentryName( copy.getName() ); copy.setName( name ); if ( loc != null ) { Point p = copy.getLocation(); if ( min.x > p.x ) { min.x = p.x; } if ( min.y > p.y ) { min.y = p.y; } } entryList.add( copy ); } JobEntryCopy[] entries = entryList.toArray( new JobEntryCopy[] {} ); // What's the difference between loc and min? // This is the offset: Point offset = new Point( loc.x - min.x, loc.y - min.y ); // Undo/redo object positions... int[] position = new int[entries.length]; for ( int i = 0; i < entries.length; i++ ) { Point p = entries[i].getLocation(); String name = entries[i].getName(); entries[i].setLocation( p.x + offset.x, p.y + offset.y ); // Check the name, find alternative... entries[i].setName( jobMeta.getAlternativeJobentryName( name ) ); jobMeta.addJobEntry( entries[i] ); position[i] = jobMeta.indexOfJobEntry( entries[i] ); } // Save undo information too... spoon.addUndoNew( jobMeta, entries, position ); if ( jobMeta.hasChanged() ) { spoon.refreshTree(); spoon.refreshGraph(); } } catch ( KettleException e ) { new ErrorDialog( spoon.getShell(), BaseMessages.getString( PKG, "Spoon.ErrorDialog.ErrorPasingJobEntries.Title" ), BaseMessages.getString( PKG, "Spoon.ErrorDialog.ErrorPasingJobEntries.Message" ), e ); } } public void newJobHop( JobMeta jobMeta, JobEntryCopy fr, JobEntryCopy to ) { JobHopMeta hi = new JobHopMeta( fr, to ); jobMeta.addJobHop( hi ); spoon.addUndoNew( jobMeta, new JobHopMeta[] { hi }, new int[] { jobMeta.indexOfJobHop( hi ) } ); spoon.refreshGraph(); spoon.refreshTree(); } /** * Create a job that extracts tables & data from a database. * <p> * <p> * * 0) Select the database to rip * <p> * 1) Select the tables in the database to rip * <p> * 2) Select the database to dump to * <p> * 3) Select the repository directory in which it will end up * <p> * 4) Select a name for the new job * <p> * 5) Create an empty job with the selected name. * <p> * 6) Create 1 transformation for every selected table * <p> * 7) add every created transformation to the job & evaluate * <p> * */ public void ripDBWizard() { final List<DatabaseMeta> databases = spoon.getActiveDatabases(); if ( databases.size() == 0 ) { return; // Nothing to do here } final RipDatabaseWizardPage1 page1 = new RipDatabaseWizardPage1( "1", databases ); final RipDatabaseWizardPage2 page2 = new RipDatabaseWizardPage2( "2" ); final RipDatabaseWizardPage3 page3 = new RipDatabaseWizardPage3( "3", spoon.getRepository() ); Wizard wizard = new Wizard() { public boolean performFinish() { try { JobMeta jobMeta = ripDB( databases, page3.getJobname(), page3.getRepositoryDirectory(), page3.getDirectory(), page1 .getSourceDatabase(), page1.getTargetDatabase(), page2.getSelection() ); if ( jobMeta == null ) { return false; } if ( page3.getRepositoryDirectory() != null ) { spoon.saveToRepository( jobMeta, false ); } else { spoon.saveToFile( jobMeta ); } addJobGraph( jobMeta ); return true; } catch ( Exception e ) { new ErrorDialog( spoon.getShell(), "Error", "An unexpected error occurred!", e ); return false; } } /** * @see org.eclipse.jface.wizard.Wizard#canFinish() */ public boolean canFinish() { return page3.canFinish(); } }; wizard.addPage( page1 ); wizard.addPage( page2 ); wizard.addPage( page3 ); WizardDialog wd = new WizardDialog( spoon.getShell(), wizard ); WizardDialog.setDefaultImage( GUIResource.getInstance().getImageWizard() ); wd.setMinimumPageSize( 700, 400 ); wd.updateSize(); wd.open(); } public JobMeta ripDB( final List<DatabaseMeta> databases, final String jobname, final RepositoryDirectoryInterface repdir, final String directory, final DatabaseMeta sourceDbInfo, final DatabaseMeta targetDbInfo, final String[] tables ) { // // Create a new job... // final JobMeta jobMeta = new JobMeta(); jobMeta.setDatabases( databases ); jobMeta.setFilename( null ); jobMeta.setName( jobname ); if ( spoon.getRepository() != null ) { jobMeta.setRepositoryDirectory( repdir ); } else { jobMeta.setFilename( Const.createFilename( directory, jobname, "." + Const.STRING_JOB_DEFAULT_EXT ) ); } spoon.refreshTree(); spoon.refreshGraph(); final Point location = new Point( 50, 50 ); // The start entry... final JobEntryCopy start = JobMeta.createStartEntry(); start.setLocation( new Point( location.x, location.y ) ); start.setDrawn(); jobMeta.addJobEntry( start ); // final Thread parentThread = Thread.currentThread(); // Create a dialog with a progress indicator! IRunnableWithProgress op = new IRunnableWithProgress() { public void run( IProgressMonitor monitor ) throws InvocationTargetException, InterruptedException { try { // This is running in a new process: copy some KettleVariables // info // LocalVariables.getInstance().createKettleVariables(Thread.currentThread().getName(), // parentThread.getName(), true); monitor.beginTask( BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.BuildingNewJob" ), tables.length ); monitor.worked( 0 ); JobEntryCopy previous = start; // Loop over the table-names... for ( int i = 0; i < tables.length && !monitor.isCanceled(); i++ ) { monitor.setTaskName( BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.ProcessingTable" ) + tables[i] + "]..." ); // // Create the new transformation... // String transname = BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.Transname1" ) + sourceDbInfo + "].[" + tables[i] + BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.Transname2" ) + targetDbInfo + "]"; TransMeta transMeta = new TransMeta(); if ( repdir != null ) { transMeta.setRepositoryDirectory( repdir ); } else { transMeta.setFilename( Const.createFilename( directory, transname, "." + Const.STRING_TRANS_DEFAULT_EXT ) ); } // Add the source & target db transMeta.addDatabase( sourceDbInfo ); transMeta.addDatabase( targetDbInfo ); // // Add a note // String note = BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.Note1" ) + tables[i] + BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.Note2" ) + sourceDbInfo + "]" + Const.CR; note += BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.Note3" ) + tables[i] + BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.Note4" ) + targetDbInfo + "]"; NotePadMeta ni = new NotePadMeta( note, 150, 10, -1, -1 ); transMeta.addNote( ni ); // // Add the TableInputMeta step... // String fromstepname = BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.FromStep.Name" ) + tables[i] + "]"; TableInputMeta tii = new TableInputMeta(); tii.setDefault(); tii.setDatabaseMeta( sourceDbInfo ); tii.setSQL( "SELECT * FROM " + tables[i] ); // It's already quoted! String fromstepid = PluginRegistry.getInstance().getPluginId( StepPluginType.class, tii ); StepMeta fromstep = new StepMeta( fromstepid, fromstepname, tii ); fromstep.setLocation( 150, 100 ); fromstep.setDraw( true ); fromstep .setDescription( BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.FromStep.Description" ) + tables[i] + BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.FromStep.Description2" ) + sourceDbInfo + "]" ); transMeta.addStep( fromstep ); // // Add the TableOutputMeta step... // String tostepname = BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.ToStep.Name" ) + tables[i] + "]"; TableOutputMeta toi = new TableOutputMeta(); toi.setDatabaseMeta( targetDbInfo ); toi.setTableName( tables[i] ); toi.setCommitSize( 100 ); toi.setTruncateTable( true ); String tostepid = PluginRegistry.getInstance().getPluginId( StepPluginType.class, toi ); StepMeta tostep = new StepMeta( tostepid, tostepname, toi ); tostep.setLocation( 500, 100 ); tostep.setDraw( true ); tostep .setDescription( BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.ToStep.Description1" ) + tables[i] + BaseMessages.getString( PKG, "Spoon.RipDB.Monitor.ToStep.Description2" ) + targetDbInfo + "]" ); transMeta.addStep( tostep ); // // Add a hop between the two steps... // TransHopMeta hi = new TransHopMeta( fromstep, tostep ); transMeta.addTransHop( hi ); // // Now we generate the SQL needed to run for this // transformation. // // First set the limit to 1 to speed things up! String tmpSql = tii.getSQL(); tii.setSQL( tii.getSQL() + sourceDbInfo.getLimitClause( 1 ) ); String sql = ""; try { sql = transMeta.getSQLStatementsString(); } catch ( KettleStepException kse ) { throw new InvocationTargetException( kse, BaseMessages.getString( PKG, "Spoon.RipDB.Exception.ErrorGettingSQLFromTransformation" ) + transMeta + "] : " + kse.getMessage() ); } // remove the limit tii.setSQL( tmpSql ); // // Now, save the transformation... // boolean ok; if ( spoon.getRepository() != null ) { ok = spoon.saveToRepository( transMeta, false ); } else { ok = spoon.saveToFile( transMeta ); } if ( !ok ) { throw new InvocationTargetException( new Exception( BaseMessages.getString( PKG, "Spoon.RipDB.Exception.UnableToSaveTransformationToRepository" ) ), BaseMessages.getString( PKG, "Spoon.RipDB.Exception.UnableToSaveTransformationToRepository" ) ); } // We can now continue with the population of the job... // ////////////////////////////////////////////////////////////////////// location.x = 250; if ( i > 0 ) { location.y += 100; } // // We can continue defining the job. // // First the SQL, but only if needed! // If the table exists & has the correct format, nothing is // done // if ( !Utils.isEmpty( sql ) ) { String jesqlname = BaseMessages.getString( PKG, "Spoon.RipDB.JobEntrySQL.Name" ) + tables[i] + "]"; JobEntrySQL jesql = new JobEntrySQL( jesqlname ); jesql.setDatabase( targetDbInfo ); jesql.setSQL( sql ); jesql .setDescription( BaseMessages.getString( PKG, "Spoon.RipDB.JobEntrySQL.Description" ) + targetDbInfo + "].[" + tables[i] + "]" ); JobEntryCopy jecsql = new JobEntryCopy(); jecsql.setEntry( jesql ); jecsql.setLocation( new Point( location.x, location.y ) ); jecsql.setDrawn(); jobMeta.addJobEntry( jecsql ); // Add the hop too... JobHopMeta jhi = new JobHopMeta( previous, jecsql ); jobMeta.addJobHop( jhi ); previous = jecsql; } // // Add the jobentry for the transformation too... // String jetransname = BaseMessages.getString( PKG, "Spoon.RipDB.JobEntryTrans.Name" ) + tables[i] + "]"; JobEntryTrans jetrans = new JobEntryTrans( jetransname ); jetrans.setTransname( transMeta.getName() ); if ( spoon.getRepository() != null ) { jetrans.setSpecificationMethod( ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME ); jetrans.setDirectory( transMeta.getRepositoryDirectory().getPath() ); } else { jetrans.setSpecificationMethod( ObjectLocationSpecificationMethod.FILENAME ); jetrans.setFileName( Const.createFilename( "${" + Const.INTERNAL_VARIABLE_JOB_FILENAME_DIRECTORY + "}", transMeta.getName(), "." + Const.STRING_TRANS_DEFAULT_EXT ) ); } JobEntryCopy jectrans = new JobEntryCopy( jetrans ); jectrans .setDescription( BaseMessages.getString( PKG, "Spoon.RipDB.JobEntryTrans.Description1" ) + Const.CR + BaseMessages.getString( PKG, "Spoon.RipDB.JobEntryTrans.Description2" ) + sourceDbInfo + "].[" + tables[i] + "]" + Const.CR + BaseMessages.getString( PKG, "Spoon.RipDB.JobEntryTrans.Description3" ) + targetDbInfo + "].[" + tables[i] + "]" ); jectrans.setDrawn(); location.x += 400; jectrans.setLocation( new Point( location.x, location.y ) ); jobMeta.addJobEntry( jectrans ); // Add a hop between the last 2 job entries. JobHopMeta jhi2 = new JobHopMeta( previous, jectrans ); jobMeta.addJobHop( jhi2 ); previous = jectrans; monitor.worked( 1 ); } monitor.worked( 100 ); monitor.done(); } catch ( Exception e ) { new ErrorDialog( spoon.getShell(), "Error", "An unexpected error occurred!", e ); } } }; try { ProgressMonitorDialog pmd = new ProgressMonitorDialog( spoon.getShell() ); pmd.run( false, true, op ); } catch ( InvocationTargetException e ) { new ErrorDialog( spoon.getShell(), BaseMessages.getString( PKG, "Spoon.ErrorDialog.RipDB.ErrorRippingTheDatabase.Title" ), BaseMessages.getString( PKG, "Spoon.ErrorDialog.RipDB.ErrorRippingTheDatabase.Message" ), e ); return null; } catch ( InterruptedException e ) { new ErrorDialog( spoon.getShell(), BaseMessages.getString( PKG, "Spoon.ErrorDialog.RipDB.ErrorRippingTheDatabase.Title" ), BaseMessages.getString( PKG, "Spoon.ErrorDialog.RipDB.ErrorRippingTheDatabase.Message" ), e ); return null; } finally { spoon.refreshGraph(); spoon.refreshTree(); } return jobMeta; } public boolean isDefaultJobName( String name ) { if ( !name.startsWith( Spoon.STRING_JOB ) ) { return false; } // see if there are only digits behind the job... // This will detect: // "Job" // "Job " // "Job 1" // "Job 2" // ... for ( int i = Spoon.STRING_JOB.length() + 1; i < name.length(); i++ ) { if ( !Character.isDigit( name.charAt( i ) ) ) { return false; } } return true; } public JobGraph findJobGraphOfJob( JobMeta jobMeta ) { // Now loop over the entries in the tab-map for ( TabMapEntry mapEntry : spoon.delegates.tabs.getTabs() ) { if ( mapEntry.getObject() instanceof JobGraph ) { JobGraph jobGraph = (JobGraph) mapEntry.getObject(); if ( jobGraph.getMeta().equals( jobMeta ) ) { return jobGraph; } } } return null; } /** * Add a job to the job map * * @param jobMeta * the job to add to the map * @return true if the job was added */ public boolean addJob( JobMeta jobMeta ) { int index = jobMap.indexOf( jobMeta ); if ( index < 0 ) { jobMap.add( jobMeta ); return true; } else { /* * ShowMessageDialog dialog = new ShowMessageDialog(spoon.getShell(), SWT.OK | SWT.ICON_INFORMATION, * BaseMessages.getString(PKG, "Spoon.Dialog.JobAlreadyLoaded.Title"), "'" + jobMeta.toString() + "'" + Const.CR + * Const.CR + BaseMessages.getString(PKG, "Spoon.Dialog.JobAlreadyLoaded.Message")); dialog.setTimeOut(6); * dialog.open(); */ return false; } } /** * @param jobMeta * the transformation to close, make sure it's ok to dispose of it BEFORE you call this. */ public void closeJob( JobMeta jobMeta ) { // Close the associated tabs... // TabMapEntry entry = spoon.delegates.tabs.findTabMapEntry( jobMeta ); if ( entry != null ) { spoon.delegates.tabs.removeTab( entry ); } // Also remove it from the item from the jobMap // Otherwise it keeps showing up in the objects tree // int index = jobMap.indexOf( jobMeta ); if ( index >= 0 ) { jobMap.remove( index ); } spoon.refreshTree(); spoon.enableMenus(); } public void addJobGraph( JobMeta jobMeta ) { boolean added = addJob( jobMeta ); if ( added ) { // See if there already is a tab for this graph with the short default name. // If there is, set that one to show the location as well. // If not, simply add it without // If no, add it // If yes, select that tab // boolean showLocation = false; boolean addTab = true; String tabName = spoon.delegates.tabs.makeTabName( jobMeta, showLocation ); TabMapEntry tabEntry = spoon.delegates.tabs.findTabMapEntry( tabName, ObjectType.JOB_GRAPH ); if ( tabEntry != null ) { // We change the already loaded job to also show the location. // showLocation = true; tabEntry.setShowingLocation( true ); String newTabName = spoon.delegates.tabs.makeTabName( tabEntry.getObject().getMeta(), showLocation ); tabEntry.getTabItem().setText( newTabName ); // Try again, including the location of the object... // tabName = spoon.delegates.tabs.makeTabName( jobMeta, showLocation ); tabEntry = spoon.delegates.tabs.findTabMapEntry( tabName, ObjectType.JOB_GRAPH ); if ( tabEntry != null ) { // Already loaded, simply select the tab item in question... // addTab = false; } } if ( addTab ) { JobGraph jobGraph = new JobGraph( spoon.tabfolder.getSwtTabset(), spoon, jobMeta ); PropsUI props = PropsUI.getInstance(); TabItem tabItem = new TabItem( spoon.tabfolder, tabName, tabName, props.getSashWeights() ); String toolTipText = BaseMessages.getString( PKG, "Spoon.TabJob.Tooltip", spoon.delegates.tabs.makeTabName( jobMeta, showLocation ) ); if ( !Utils.isEmpty( jobMeta.getFilename() ) ) { toolTipText += Const.CR + Const.CR + jobMeta.getFilename(); } tabItem.setToolTipText( toolTipText ); tabItem.setImage( GUIResource.getInstance().getImageJobGraph() ); tabItem.setControl( jobGraph ); // OK, also see if we need to open a new history window. if ( jobMeta.getJobLogTable().getDatabaseMeta() != null && !Utils.isEmpty( jobMeta.getJobLogTable().getTableName() ) ) { jobGraph.addAllTabs(); jobGraph.extraViewTabFolder.setSelection( jobGraph.jobHistoryDelegate.getJobHistoryTab() ); } String versionLabel = jobMeta.getObjectRevision() == null ? null : jobMeta.getObjectRevision().getName(); tabEntry = new TabMapEntry( tabItem, jobMeta.getFilename(), jobMeta.getName(), jobMeta.getRepositoryDirectory(), versionLabel, jobGraph, ObjectType.JOB_GRAPH ); tabEntry.setShowingLocation( showLocation ); spoon.delegates.tabs.addTab( tabEntry ); } int idx = spoon.tabfolder.indexOf( tabEntry.getTabItem() ); // keep the focus on the graph spoon.tabfolder.setSelected( idx ); spoon.setUndoMenu( jobMeta ); spoon.enableMenus(); } else { TabMapEntry tabEntry = spoon.delegates.tabs.findTabMapEntry( jobMeta ); if ( tabEntry != null ) { int idx = spoon.tabfolder.indexOf( tabEntry.getTabItem() ); // keep the focus on the graph spoon.tabfolder.setSelected( idx ); // keep the focus on the graph spoon.tabfolder.setSelected( idx ); spoon.setUndoMenu( jobMeta ); spoon.enableMenus(); } } } /* * private void addJobLog(JobMeta jobMeta) { // See if there already is a tab for this log // If no, add it // If yes, * select that tab // String tabName = spoon.delegates.tabs.makeJobLogTabName(jobMeta); TabItem tabItem = * spoon.delegates.tabs.findTabItem(tabName, TabMapEntry.OBJECT_TYPE_JOB_LOG); if (tabItem == null) { JobLog jobLog = * new JobLog(spoon.tabfolder.getSwtTabset(), spoon, jobMeta); tabItem = new TabItem(spoon.tabfolder, tabName, * tabName); tabItem.setText(tabName); tabItem.setToolTipText(BaseMessages.getString(PKG, * "Spoon.Title.ExecLogJobView.Tooltip", spoon.delegates.tabs .makeJobGraphTabName(jobMeta))); * tabItem.setControl(jobLog); * * // If there is an associated history window, we want to keep that // one up-to-date as well. // JobHistory * jobHistory = findJobHistoryOfJob(jobMeta); TabItem historyItem = * spoon.delegates.tabs.findTabItem(spoon.delegates.tabs.makeJobHistoryTabName(jobMeta), * TabMapEntry.OBJECT_TYPE_JOB_HISTORY); * * if (jobHistory != null && historyItem != null) { JobHistoryRefresher jobHistoryRefresher = new * JobHistoryRefresher(historyItem, jobHistory); spoon.tabfolder.addListener(jobHistoryRefresher); // * jobLog.setJobHistoryRefresher(jobHistoryRefresher); } * * spoon.delegates.tabs.addTab(new TabMapEntry(tabItem, tabName, jobLog, TabMapEntry.OBJECT_TYPE_JOB_LOG)); } int idx * = spoon.tabfolder.indexOf(tabItem); spoon.tabfolder.setSelected(idx); } */ public List<JobMeta> getJobList() { return jobMap; } public JobMeta getJob( String name ) { TabMapEntry entry = spoon.delegates.tabs.findTabMapEntry( name, ObjectType.JOB_GRAPH ); if ( entry != null ) { return (JobMeta) entry.getObject().getManagedObject(); } // TODO: remove part below // for ( JobMeta jobMeta : jobMap ) { if ( name != null && name.equals( jobMeta.getName() ) ) { return jobMeta; } } return null; } public JobMeta[] getLoadedJobs() { return jobMap.toArray( new JobMeta[jobMap.size()] ); } public void removeJob( String key ) { jobMap.remove( key ); } public void redoJobAction( JobMeta jobMeta, TransAction transAction ) { switch ( transAction.getType() ) { // // NEW // case TransAction.TYPE_ACTION_NEW_JOB_ENTRY: // re-delete the entry at correct location: JobEntryCopy[] si = (JobEntryCopy[]) transAction.getCurrent(); int[] idx = transAction.getCurrentIndex(); for ( int i = 0; i < idx.length; i++ ) { jobMeta.addJobEntry( idx[i], si[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; case TransAction.TYPE_ACTION_NEW_NOTE: // re-insert the note at correct location: NotePadMeta[] ni = (NotePadMeta[]) transAction.getCurrent(); idx = transAction.getCurrentIndex(); for ( int i = 0; i < idx.length; i++ ) { jobMeta.addNote( idx[i], ni[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; case TransAction.TYPE_ACTION_NEW_JOB_HOP: // re-insert the hop at correct location: JobHopMeta[] hi = (JobHopMeta[]) transAction.getCurrent(); idx = transAction.getCurrentIndex(); for ( int i = 0; i < idx.length; i++ ) { jobMeta.addJobHop( idx[i], hi[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // // DELETE // case TransAction.TYPE_ACTION_DELETE_JOB_ENTRY: // re-remove the entry at correct location: idx = transAction.getCurrentIndex(); for ( int i = idx.length - 1; i >= 0; i-- ) { jobMeta.removeJobEntry( idx[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; case TransAction.TYPE_ACTION_DELETE_NOTE: // re-remove the note at correct location: idx = transAction.getCurrentIndex(); for ( int i = idx.length - 1; i >= 0; i-- ) { jobMeta.removeNote( idx[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; case TransAction.TYPE_ACTION_DELETE_JOB_HOP: // re-remove the hop at correct location: idx = transAction.getCurrentIndex(); for ( int i = idx.length - 1; i >= 0; i-- ) { jobMeta.removeJobHop( idx[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // // CHANGE // // We changed a step : undo this... case TransAction.TYPE_ACTION_CHANGE_JOB_ENTRY: // replace with "current" version. for ( int i = 0; i < transAction.getCurrent().length; i++ ) { JobEntryCopy copy = (JobEntryCopy) ( (JobEntryCopy) ( transAction.getCurrent()[i] ) ).clone_deep(); jobMeta.getJobEntry( transAction.getCurrentIndex()[i] ).replaceMeta( copy ); } spoon.refreshTree(); spoon.refreshGraph(); break; // We changed a note : undo this... case TransAction.TYPE_ACTION_CHANGE_NOTE: // Delete & re-insert ni = (NotePadMeta[]) transAction.getCurrent(); idx = transAction.getCurrentIndex(); for ( int i = 0; i < idx.length; i++ ) { jobMeta.removeNote( idx[i] ); jobMeta.addNote( idx[i], ni[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // We changed a hop : undo this... case TransAction.TYPE_ACTION_CHANGE_JOB_HOP: // Delete & re-insert hi = (JobHopMeta[]) transAction.getCurrent(); idx = transAction.getCurrentIndex(); for ( int i = 0; i < idx.length; i++ ) { jobMeta.removeJobHop( idx[i] ); jobMeta.addJobHop( idx[i], hi[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // // CHANGE POSITION // case TransAction.TYPE_ACTION_POSITION_JOB_ENTRY: // Find the location of the step: idx = transAction.getCurrentIndex(); Point[] p = transAction.getCurrentLocation(); for ( int i = 0; i < p.length; i++ ) { JobEntryCopy entry = jobMeta.getJobEntry( idx[i] ); entry.setLocation( p[i] ); } spoon.refreshGraph(); break; case TransAction.TYPE_ACTION_POSITION_NOTE: idx = transAction.getCurrentIndex(); Point[] curr = transAction.getCurrentLocation(); for ( int i = 0; i < idx.length; i++ ) { NotePadMeta npi = jobMeta.getNote( idx[i] ); npi.setLocation( curr[i] ); } spoon.refreshGraph(); break; default: break; } } public void undoJobAction( JobMeta jobMeta, TransAction transAction ) { switch ( transAction.getType() ) { // We created a new entry : undo this... case TransAction.TYPE_ACTION_NEW_JOB_ENTRY: // Delete the entry at correct location: int[] idx = transAction.getCurrentIndex(); for ( int i = idx.length - 1; i >= 0; i-- ) { jobMeta.removeJobEntry( idx[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // We created a new note : undo this... case TransAction.TYPE_ACTION_NEW_NOTE: // Delete the note at correct location: idx = transAction.getCurrentIndex(); for ( int i = idx.length - 1; i >= 0; i-- ) { jobMeta.removeNote( idx[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // We created a new hop : undo this... case TransAction.TYPE_ACTION_NEW_JOB_HOP: // Delete the hop at correct location: idx = transAction.getCurrentIndex(); for ( int i = idx.length - 1; i >= 0; i-- ) { jobMeta.removeJobHop( idx[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // // DELETE // // We delete an entry : undo this... case TransAction.TYPE_ACTION_DELETE_JOB_ENTRY: // un-Delete the entry at correct location: re-insert JobEntryCopy[] ce = (JobEntryCopy[]) transAction.getCurrent(); idx = transAction.getCurrentIndex(); for ( int i = 0; i < ce.length; i++ ) { jobMeta.addJobEntry( idx[i], ce[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // We delete new note : undo this... case TransAction.TYPE_ACTION_DELETE_NOTE: // re-insert the note at correct location: NotePadMeta[] ni = (NotePadMeta[]) transAction.getCurrent(); idx = transAction.getCurrentIndex(); for ( int i = 0; i < idx.length; i++ ) { jobMeta.addNote( idx[i], ni[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // We deleted a new hop : undo this... case TransAction.TYPE_ACTION_DELETE_JOB_HOP: // re-insert the hop at correct location: JobHopMeta[] hi = (JobHopMeta[]) transAction.getCurrent(); idx = transAction.getCurrentIndex(); for ( int i = 0; i < hi.length; i++ ) { jobMeta.addJobHop( idx[i], hi[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // // CHANGE // // We changed a job entry: undo this... case TransAction.TYPE_ACTION_CHANGE_JOB_ENTRY: // Delete the current job entry, insert previous version. for ( int i = 0; i < transAction.getPrevious().length; i++ ) { JobEntryCopy copy = (JobEntryCopy) ( (JobEntryCopy) transAction.getPrevious()[i] ).clone(); jobMeta.getJobEntry( transAction.getCurrentIndex()[i] ).replaceMeta( copy ); } spoon.refreshTree(); spoon.refreshGraph(); break; // We changed a note : undo this... case TransAction.TYPE_ACTION_CHANGE_NOTE: // Delete & re-insert NotePadMeta[] prev = (NotePadMeta[]) transAction.getPrevious(); idx = transAction.getCurrentIndex(); for ( int i = 0; i < idx.length; i++ ) { jobMeta.removeNote( idx[i] ); jobMeta.addNote( idx[i], prev[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // We changed a hop : undo this... case TransAction.TYPE_ACTION_CHANGE_JOB_HOP: // Delete & re-insert JobHopMeta[] prevHops = (JobHopMeta[]) transAction.getPrevious(); idx = transAction.getCurrentIndex(); for ( int i = 0; i < idx.length; i++ ) { jobMeta.removeJobHop( idx[i] ); jobMeta.addJobHop( idx[i], prevHops[i] ); } spoon.refreshTree(); spoon.refreshGraph(); break; // // POSITION // // The position of a step has changed: undo this... case TransAction.TYPE_ACTION_POSITION_JOB_ENTRY: // Find the location of the step: idx = transAction.getCurrentIndex(); Point[] p = transAction.getPreviousLocation(); for ( int i = 0; i < p.length; i++ ) { JobEntryCopy entry = jobMeta.getJobEntry( idx[i] ); entry.setLocation( p[i] ); } spoon.refreshGraph(); break; // The position of a note has changed: undo this... case TransAction.TYPE_ACTION_POSITION_NOTE: idx = transAction.getCurrentIndex(); Point[] prevLoc = transAction.getPreviousLocation(); for ( int i = 0; i < idx.length; i++ ) { NotePadMeta npi = jobMeta.getNote( idx[i] ); npi.setLocation( prevLoc[i] ); } spoon.refreshGraph(); break; default: break; } } public void executeJob( JobMeta jobMeta, boolean local, boolean remote, Date replayDate, boolean safe, String startCopyName, int startCopyNr ) throws KettleException { if ( jobMeta == null ) { return; } JobExecutionConfiguration executionConfiguration = spoon.getJobExecutionConfiguration(); // Remember the variables set previously // Object[] data = spoon.variables.getData(); String[] fields = spoon.variables.getRowMeta().getFieldNames(); Map<String, String> variableMap = new HashMap<String, String>(); for ( int idx = 0; idx < fields.length; idx++ ) { variableMap.put( fields[idx], data[idx].toString() ); } executionConfiguration.setVariables( variableMap ); executionConfiguration.getUsedVariables( jobMeta ); executionConfiguration.setReplayDate( replayDate ); executionConfiguration.setRepository( spoon.rep ); executionConfiguration.setSafeModeEnabled( safe ); executionConfiguration.setStartCopyName( startCopyName ); executionConfiguration.setStartCopyNr( startCopyNr ); executionConfiguration.getUsedArguments( jobMeta, spoon.getArguments(), spoon.getMetaStore() ); executionConfiguration.setLogLevel( DefaultLogLevel.getLogLevel() ); JobExecutionConfigurationDialog dialog = new JobExecutionConfigurationDialog( spoon.getShell(), executionConfiguration, jobMeta ); if ( !jobMeta.isShowDialog() ) { ExtensionPointHandler.callExtensionPoint( log, KettleExtensionPoint.SpoonJobMetaExecutionStart.id, jobMeta ); ExtensionPointHandler.callExtensionPoint( log, KettleExtensionPoint.SpoonJobExecutionConfiguration.id, executionConfiguration ); // addJobLog(jobMeta); JobGraph jobGraph = spoon.getActiveJobGraph(); // Set the variables that where specified... // for ( String varName : executionConfiguration.getVariables().keySet() ) { String varValue = executionConfiguration.getVariables().get( varName ); jobMeta.setVariable( varName, varValue ); } // Set and activate the parameters... // for ( String paramName : executionConfiguration.getParams().keySet() ) { String paramValue = executionConfiguration.getParams().get( paramName ); jobMeta.setParameterValue( paramName, paramValue ); } // Is this a local execution? // if ( executionConfiguration.isExecutingLocally() ) { jobGraph.startJob( executionConfiguration ); } else if ( executionConfiguration.isExecutingRemotely() ) { // Executing remotely // Check if jobMeta has changed jobGraph.handleJobMetaChanges( jobMeta ); // Activate the parameters, turn them into variables... // jobMeta.hasChanged() jobMeta.activateParameters(); if ( executionConfiguration.getRemoteServer() != null ) { Job.sendToSlaveServer( jobMeta, executionConfiguration, spoon.rep, spoon.metaStore ); spoon.delegates.slaves.addSpoonSlave( executionConfiguration.getRemoteServer() ); } else { MessageBox mb = new MessageBox( spoon.getShell(), SWT.OK | SWT.ICON_ERROR ); mb.setMessage( BaseMessages.getString( PKG, "Spoon.Dialog.NoRemoteServerSpecified.Message" ) ); mb.setText( BaseMessages.getString( PKG, "Spoon.Dialog.NoRemoteServerSpecified.Title" ) ); mb.open(); } } } else if ( dialog.open() ) { ExtensionPointHandler.callExtensionPoint( log, KettleExtensionPoint.SpoonJobMetaExecutionStart.id, jobMeta ); ExtensionPointHandler.callExtensionPoint( log, KettleExtensionPoint.SpoonJobExecutionConfiguration.id, executionConfiguration ); // addJobLog(jobMeta); JobGraph jobGraph = spoon.getActiveJobGraph(); // Set the variables that where specified... // for ( String varName : executionConfiguration.getVariables().keySet() ) { String varValue = executionConfiguration.getVariables().get( varName ); jobMeta.setVariable( varName, varValue ); } // Set and activate the parameters... // for ( String paramName : executionConfiguration.getParams().keySet() ) { String paramValue = executionConfiguration.getParams().get( paramName ); jobMeta.setParameterValue( paramName, paramValue ); } // Is this a local execution? // if ( executionConfiguration.isExecutingLocally() ) { jobGraph.startJob( executionConfiguration ); } else if ( executionConfiguration.isExecutingRemotely() ) { // Executing remotely // Check if jobMeta has changed jobGraph.handleJobMetaChanges( jobMeta ); // Activate the parameters, turn them into variables... // jobMeta.hasChanged() jobMeta.activateParameters(); if ( executionConfiguration.getRemoteServer() != null ) { Job.sendToSlaveServer( jobMeta, executionConfiguration, spoon.rep, spoon.metaStore ); spoon.delegates.slaves.addSpoonSlave( executionConfiguration.getRemoteServer() ); } else { MessageBox mb = new MessageBox( spoon.getShell(), SWT.OK | SWT.ICON_ERROR ); mb.setMessage( BaseMessages.getString( PKG, "Spoon.Dialog.NoRemoteServerSpecified.Message" ) ); mb.setText( BaseMessages.getString( PKG, "Spoon.Dialog.NoRemoteServerSpecified.Title" ) ); mb.open(); } } } } }