最近搭建kettle的源码调试环境整的焦头烂额。编译的zip包运行正常,可是用ide进行调试确实各种报错。
为了制止这些不停歇的恶心,我们来看看Spoon.java里面到底干了些什么,为什么有那么多的报错。
我们可以看到执行最大的作用是加载插件包和初始化环境。
下面是源码部分:
public static void main( String[] a ) throws KettleException {
boolean doConsoleRedirect = !Boolean.getBoolean( "Spoon.Console.Redirect.Disabled" );
// 首先来的是配置spoon的日志目录和日志文件
if ( doConsoleRedirect ) {
try {
Path parent = Paths.get( System.getProperty( "user.dir" ) + File.separator + "logs" );
Files.createDirectories( parent );
Files.deleteIfExists( Paths.get( parent.toString(), "spoon.log" ) );
Path path = Files.createFile( Paths.get( parent.toString(), "spoon.log" ) );
System.setProperty( "LOG_PATH", path.toString() );
final FileOutputStream fos = new FileOutputStream( path.toFile() );
System.setOut( new PrintStream( new TeeOutputStream( originalSystemOut, fos ) ) );
System.setErr( new PrintStream( new TeeOutputStream( originalSystemErr, fos ) ) );
KettleLogStore.OriginalSystemOut = System.out;
KettleLogStore.OriginalSystemErr = System.err;
} catch ( Throwable ignored ) {
// ignored
}
}
// 然后,在这里起了一个线程进行插件加载,初始化环境
ExecutorService executor = Executors.newCachedThreadPool();
Future<KettleException> pluginRegistryFuture = executor.submit( new Callable<KettleException>() {
@Override
public KettleException call() throws Exception {
// 注册ui插件类型
registerUIPluginObjectTypes();
KettleClientEnvironment.getInstance().setClient( KettleClientEnvironment.ClientType.SPOON );
try {
// 初始化环境变量
KettleEnvironment.init();
} catch ( KettleException e ) {
return e;
}
return null;
}
} );
try {
OsHelper.setAppName();
// Bootstrap Kettle
//
Display display;
if ( System.getProperties().containsKey( "SLEAK" ) ) {
DeviceData data = new DeviceData();
data.tracking = true;
display = new Display( data );
Sleak sleak = new Sleak();
Shell sleakShell = new Shell( display );
sleakShell.setText( "S-Leak" );
org.eclipse.swt.graphics.Point size = sleakShell.getSize();
sleakShell.setSize( size.x / 2, size.y / 2 );
sleak.create( sleakShell );
sleakShell.open();
} else {
display = new Display();
}
// Note: this needs to be done before the look and feel is set
OsHelper.initOsHandlers( display );
UIManager.setLookAndFeel( new MetalLookAndFeel() );
// The core plugin types don't know about UI classes. Add them in now
// before the PluginRegistry is inited.
splash = new Splash( display );
List<String> args = new ArrayList<>( Arrays.asList( a ) );
CommandLineOption[] commandLineOptions = getCommandLineArgs( args );
KettleException registryException = pluginRegistryFuture.get();
if ( registryException != null ) {
throw registryException;
}
PropsUI.init( display, Props.TYPE_PROPERTIES_SPOON );
KettleLogStore
.init( PropsUI.getInstance().getMaxNrLinesInLog(), PropsUI.getInstance().getMaxLogLineTimeoutMinutes() );
initLogging( commandLineOptions );
// remember...
staticSpoon = new Spoon();
staticSpoon.commandLineOptions = commandLineOptions;
// pull the startup perspective id from the command line options and hand it to Spoon
String pId;
StringBuilder perspectiveIdBuff = Spoon.getCommandLineOption( commandLineOptions, "perspective" ).getArgument();
pId = perspectiveIdBuff.toString();
if ( !Utils.isEmpty( pId ) ) {
Spoon.staticSpoon.startupPerspective = pId;
}
SpoonFactory.setSpoonInstance( staticSpoon );
staticSpoon.setDestroy( true );
GUIFactory.setThreadDialogs( new ThreadGuiResources() );
staticSpoon.setArguments( args.toArray( new String[ args.size() ] ) );
staticSpoon.start();
} catch ( Throwable t ) {
// avoid calls to Messages i18n method getString() in this block
// We do this to (hopefully) also catch Out of Memory Exceptions
//
t.printStackTrace();
if ( staticSpoon != null ) {
log.logError( "Fatal error : " + Const.NVL( t.toString(), Const.NVL( t.getMessage(), "Unknown error" ) ) );
log.logError( Const.getStackTracker( t ) );
}
}
// Kill all remaining things in this VM!
System.exit( 0 );
}
而且,我们瞅瞅pdi的执行脚本的实现,其实是设置一下变量,核心还是调用的spoon,如carte:
call Spoon.bat -main org.pentaho.di.www.Carte %*