    static public void main(String[] args) throws Throwable
    {
        Log4jConfiguration.configure( "log4j_datadock.xml" );
        log.trace( "DatadockMain main called" );
        ConsoleAppender startupAppender = new ConsoleAppender(new SimpleLayout());
        boolean terminateOnZeroSubmitted = false;
        boolean ESHarvesterCleanup = false;
        try
        {
            harvestType = HarvestType.getHarvestType( System.getProperty( "harvester" ) );
        }
        catch( NullPointerException npe )
        {
            harvestType = defaultHarvestType;
        }
        if ( harvestType == null )
        {
            harvestType = defaultHarvestType;
            log.debug( String.format( "getting harvestertype: %s form property", harvestType  ) );
        }        
        for( String a : args )
        {
            log.warn( String.format( "argument: '%s'", a ) );
            if ( a.equals( "--shutDownOnJobsDone" ) )
            {
                terminateOnZeroSubmitted = true;
            }
            else
            {
                log.warn( String.format( "Unknown argument '%s', ignoring it", a ) );
            }
        }
        try
        {
            if ( System.getProperty( "esharvester_cleanup" ) != null )
            {
                ESHarvesterCleanup = true;
            }
        }
        catch( NullPointerException npe)
        {
            log.info( "Test 1: catch" );
            ESHarvesterCleanup = false;
        }
        if ( ESHarvesterCleanup )
        {
            log.info( " ESHARVESTER CLEANUP! " );
        }
        try
        {
            init();
            log.removeAppender( "RootConsoleAppender" );
            log.addAppender( startupAppender );
            log.info( "Starting the datadock" );
            log.trace( "initializing resources" );
            IDBConnection dbConnection = new PostgresqlDBConnection();
            IProcessqueue processqueue = new Processqueue( dbConnection );
            IObjectRepository repository = new FedoraObjectRepository();
            pluginResolver = new PluginResolver(); 
            OracleDataSource ods;
            log.trace( "Starting datadockPool" );
            LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>( queueSize );
            ThreadPoolExecutor threadpool = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS , queue );
            threadpool.purge();
            log.trace( "Starting harvester" );
            switch( harvestType )
            {
                case ESHarvest:
                    log.trace( "selecting ES" );
                    String dataBaseName = DataBaseConfig.getOracleDataBaseName();
                    String oracleCacheName = DataBaseConfig.getOracleCacheName();
                    String oracleUrl = DataBaseConfig.getOracleUrl();
                    String oracleUser = DataBaseConfig.getOracleUserID();
                    String oraclePassWd = DataBaseConfig.getOraclePassWd();
                    String minLimit = DataBaseConfig.getOracleMinLimit();
                    String maxLimit = DataBaseConfig.getOracleMaxLimit();
                    String initialLimit = DataBaseConfig.getOracleInitialLimit();
                    String connectionWaitTimeout = DataBaseConfig.getOracleConnectionWaitTimeout();
                    log.info( String.format( "DB Url : %s ", oracleUrl ) );
                    log.info( String.format( "DB User: %s ", oracleUser ) );
                    try
                    {
                        ods = new OracleDataSource();
                        ods.setURL( oracleUrl );
                        ods.setUser( oracleUser );
                        ods.setPassword( oraclePassWd );
                        ods.setConnectionCachingEnabled( true ); 
                        ods.setConnectionCacheName( oracleCacheName );
                        Properties cacheProperties = new Properties();
                        cacheProperties.setProperty( "MinLimit", minLimit );
                        cacheProperties.setProperty( "MaxLimit", maxLimit );
                        cacheProperties.setProperty( "InitialLimit", initialLimit );
                        cacheProperties.setProperty( "ConnectionWaitTimeout", connectionWaitTimeout );
                        cacheProperties.setProperty( "ValidateConnection", "true" );
                        ods.setConnectionCacheProperties( cacheProperties );
                    }
                    catch( SQLException sqle )
                    {
                        String errorMsg = new String( "An SQL error occured during the setup of the OracleDataSource" );
                        log.fatal( errorMsg, sqle );
                        throw sqle;
                    }
                    OracleDBPooledConnection connectionPool = new OracleDBPooledConnection( oracleCacheName, ods );
                    harvester = new ESHarvest( connectionPool, dataBaseName );                    
                    if ( ESHarvesterCleanup )
                    {
                        ESHarvest esharvester = (ESHarvest)harvester;
                        try
                        {
                            esharvester.changeRecordstatusFromInProgressToQueued();
                        }
                        catch( HarvesterIOException hioe )
                        {
                            String errorMsg = new String( "An exception occured while performing 'changeRecordstatusFromInProgressToQueued'." );
                            log.fatal( errorMsg, hioe );
                            throw hioe;
                        }
                    }
                    break;
                case FileHarvest:
                    log.trace( "selecting FileHarvest" );
                    harvester = new FileHarvest();
                    break;
                case FileHarvestLight:
                    log.trace( "selecting FileHarvestLight" );
                    harvester = new FileHarvestLight();
                    break;
                default:
                    log.warn( "no harvester explicitly selected, running with FileHarvest" );
                    harvester = new FileHarvest();
            }
            datadockPool = new DatadockPool( threadpool, processqueue, repository, harvester, pluginResolver );
            log.trace( "Starting the manager" );
            datadockManager = new DatadockManager( datadockPool, harvester );
            log.info( "Daemonizing" );
            daemonize();
            addDaemonShutdownHook();
        }
        catch ( Exception e )
        {
            System.out.println( "Startup failed." + e );
            log.fatal( "Startup failed.", e);
            throw e;
        }
        finally
        {
            log.removeAppender( startupAppender );
        }
        long mainTimer = System.currentTimeMillis();
        int mainJobsSubmitted = 0;
        while( ! isShutdownRequested() )
        {
            try
            {
                log.trace( "DatadockMain calling datadockManager update" );
                long timer = System.currentTimeMillis();
                int jobsSubmited = datadockManager.update();
                timer = System.currentTimeMillis() - timer;
                mainJobsSubmitted += jobsSubmited;
                if ( jobsSubmited > 0 )
                {
                    log.info(String.format( "%1$d Jobs submittet in %2$d ms - %3$f jobs/s", jobsSubmited, timer, jobsSubmited/ (timer / 1000.0 ) ) );
                }
                else
                {
                    log.info( String.format( "%1$d Jobs submittet in %2$d ms - ", jobsSubmited, timer ) );
                    if ( terminateOnZeroSubmitted )
                    {
                        DatadockMain.shutdown();
                    }
                    else
                    {
                        Thread.currentThread();
                        Thread.sleep( pollTime );
                    }
                }
            }
            catch( HarvesterIOException hioe )
            {
                String fatal =  String.format( "A fatal error occured in the communication with the database, exiting." );
                log.fatal( fatal, hioe );
                DatadockMain.shutdown();
            }           
            catch( InterruptedException ie )
            {
                log.error( "InterruptedException caught in mainloop: "  + ie, ie);
                log.error( "  " + ie.getMessage(), ie );
            }
            catch( RuntimeException re )
            {
                log.error( "RuntimeException caught in mainloop: " + re, re);
                log.error( "  " + re.getCause().getMessage(), re);
                throw re;
            }
            catch( Exception e )
            {
                log.error( "Exception caught in mainloop: " + e.toString(), e );
            }
        }
        mainTimer = System.currentTimeMillis() - mainTimer;
        if ( mainJobsSubmitted > 0 )
        {
            log.info(String.format("Total: %1$d Jobs submittet in %2$d ms - %3$f jobs/s", mainJobsSubmitted, mainTimer, mainJobsSubmitted/ (mainTimer / 1000.0)));
        }
        else
        {
            log.info(String.format("Total: %1$d Jobs submittet in %2$d ms - ", mainJobsSubmitted, mainTimer));
        }
    }

    static public void main(String[] args) throws Throwable
    {
        Log4jConfiguration.configure( "log4j_datadock.xml" );
        log.trace( "DatadockMain main called" );
        ConsoleAppender startupAppender = new ConsoleAppender(new SimpleLayout());
        boolean terminateOnZeroSubmitted = false;
        boolean ESHarvesterCleanup = false;
        try
        {
            harvestType = HarvestType.getHarvestType( System.getProperty( "harvester" ) );
        }
        catch( NullPointerException npe )
        {
            harvestType = defaultHarvestType;
        }
        if ( harvestType == null )
        {
            harvestType = defaultHarvestType;
            log.debug( String.format( "getting harvestertype: %s form property", harvestType  ) );
        }        
        for( String a : args )
        {
            log.warn( String.format( "argument: '%s'", a ) );
            if ( a.equals( "--shutDownOnJobsDone" ) )
            {
                terminateOnZeroSubmitted = true;
            }
            else
            {
                log.warn( String.format( "Unknown argument '%s', ignoring it", a ) );
            }
        }
        try
        {
            if ( System.getProperty( "esharvester_cleanup" ) != null )
            {
                ESHarvesterCleanup = true;
            }
        }
        catch( NullPointerException npe)
        {
            log.info( "Test 1: catch" );
            ESHarvesterCleanup = false;
        }
        if ( ESHarvesterCleanup )
        {
            log.info( " ESHARVESTER CLEANUP! " );
        }
        try
        {
            init();
            log.removeAppender( "RootConsoleAppender" );
            log.addAppender( startupAppender );
            log.info( "Starting the datadock" );
            log.trace( "initializing resources" );
            IDBConnection dbConnection = new PostgresqlDBConnection();
            IProcessqueue processqueue = new Processqueue( dbConnection );
            IObjectRepository repository = new FedoraObjectRepository();
            pluginResolver = new PluginResolver(); 
            OracleDataSource ods;
            log.trace( "Starting datadockPool" );
            LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>( queueSize );
            ThreadPoolExecutor threadpool = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS , queue );
            threadpool.purge();
            log.trace( "Starting harvester" );
            switch( harvestType )
            {
                case ESHarvest:
                    log.trace( "selecting ES" );
                    String dataBaseName = DataBaseConfig.getOracleDataBaseName();
                    String oracleCacheName = DataBaseConfig.getOracleCacheName();
                    String oracleUrl = DataBaseConfig.getOracleUrl();
                    String oracleUser = DataBaseConfig.getOracleUserID();
                    String oraclePassWd = DataBaseConfig.getOraclePassWd();
                    String minLimit = DataBaseConfig.getOracleMinLimit();
                    String maxLimit = DataBaseConfig.getOracleMaxLimit();
                    String initialLimit = DataBaseConfig.getOracleInitialLimit();
                    String connectionWaitTimeout = DataBaseConfig.getOracleConnectionWaitTimeout();
                    log.info( String.format( "DB Url : %s ", oracleUrl ) );
                    log.info( String.format( "DB User: %s ", oracleUser ) );
                    try
                    {
                        ods = new OracleDataSource();
                        ods.setURL( oracleUrl );
                        ods.setUser( oracleUser );
                        ods.setPassword( oraclePassWd );
                        ods.setConnectionCachingEnabled( true ); 
                        ods.setConnectionCacheName( oracleCacheName );
                        Properties cacheProperties = new Properties();
                        cacheProperties.setProperty( "MinLimit", minLimit );
                        cacheProperties.setProperty( "MaxLimit", maxLimit );
                        cacheProperties.setProperty( "InitialLimit", initialLimit );
                        cacheProperties.setProperty( "ConnectionWaitTimeout", connectionWaitTimeout );
                        cacheProperties.setProperty( "ValidateConnection", "true" );
                        ods.setConnectionCacheProperties( cacheProperties );
                    }
                    catch( SQLException sqle )
                    {
                        String errorMsg = new String( "An SQL error occured during the setup of the OracleDataSource" );
                        log.fatal( errorMsg, sqle );
                        throw sqle;
                    }
                    OracleDBPooledConnection connectionPool = new OracleDBPooledConnection( oracleCacheName, ods );
                    harvester = new ESHarvest( connectionPool, dataBaseName );                    
                    if ( ESHarvesterCleanup )
                    {
                        ESHarvest esharvester = (ESHarvest)harvester;
                        try
                        {
                            esharvester.changeRecordstatusFromInProgressToQueued();
                        }
                        catch( HarvesterIOException hioe )
                        {
                            String errorMsg = new String( "An exception occured while performing 'changeRecordstatusFromInProgressToQueued'." );
                            log.fatal( errorMsg, hioe );
                            throw hioe;
                        }
                    }
                    break;
                case FileHarvest:
                    log.trace( "selecting FileHarvest" );
                    harvester = new FileHarvest();
                    break;
                case FileHarvestLight:
                    log.trace( "selecting FileHarvestLight" );
                    harvester = new FileHarvestLight();
                    break;
                default:
                    log.warn( "no harvester explicitly selected, running with FileHarvest" );
                    harvester = new FileHarvest();
            }
            datadockPool = new DatadockPool( threadpool, processqueue, repository, harvester, pluginResolver );
            log.trace( "Starting the manager" );
            datadockManager = new DatadockManager( datadockPool, harvester );
            log.info( "Daemonizing" );
            daemonize();
            addDaemonShutdownHook();
        }
        catch ( Exception e )
        {
            System.out.println( "Startup failed." + e );
            log.fatal( "Startup failed.", e);
            throw e;
        }
        finally
        {
            log.removeAppender( startupAppender );
        }
        long mainTimer = System.currentTimeMillis();
        int mainJobsSubmitted = 0;
        while( ! isShutdownRequested() )
        {
            try
            {
                log.trace( "DatadockMain calling datadockManager update" );
                long timer = System.currentTimeMillis();
                int jobsSubmited = datadockManager.update();
                timer = System.currentTimeMillis() - timer;
                mainJobsSubmitted += jobsSubmited;
                if ( jobsSubmited > 0 )
                {
                    log.info(String.format( "%1$d Jobs submittet in %2$d ms - %3$f jobs/s", jobsSubmited, timer, jobsSubmited/ (timer / 1000.0 ) ) );
                }
                else
                {
                    log.info( String.format( "%1$d Jobs submittet in %2$d ms - ", jobsSubmited, timer ) );
                    if ( terminateOnZeroSubmitted )
                    {
                        DatadockMain.shutdown();
                    }
                    else
                    {
                        Thread.currentThread();
                        Thread.sleep( pollTime );
                    }
                }
            }
            catch( HarvesterIOException hioe )
            {
                String fatal =  String.format( "A fatal error occured in the communication with the database: %s", hioe.getMessage() );
                log.fatal( fatal, hioe );
                DatadockMain.shutdown();
            }           
            catch( InterruptedException ie )
            {
                log.error( String.format( "InterruptedException caught in mainloop: %s", ie.getMessage(), ie ) );
            }
            catch( RuntimeException re )
            {
                log.error( String.format( "RuntimeException caught in mainloop: %s", re.getMessage(), re ) );
            }
            catch( Exception e )
            {
                log.error( "Exception caught in mainloop: " + e.getMessage(), e );
            }
        }
        mainTimer = System.currentTimeMillis() - mainTimer;
        if ( mainJobsSubmitted > 0 )
        {
            log.info(String.format("Total: %1$d Jobs submittet in %2$d ms - %3$f jobs/s", mainJobsSubmitted, mainTimer, mainJobsSubmitted/ (mainTimer / 1000.0)));
        }
        else
        {
            log.info(String.format("Total: %1$d Jobs submittet in %2$d ms - ", mainJobsSubmitted, mainTimer));
        }
    }
