tigase运行流程分析(十六)

加载配置文件,运行的时候选择的主类是XMPPServer。打开XMPPServermain函数入口,直接上源码进行分析:

/**
     *
     * @param args 表示program argument
     */
    @SuppressWarnings("PMD")
    public static void main( final String[] args ) {
        // 开始运行
        System.out.println("开始执行");
        parseParams( args );
        System.out.println("开始加载组建");
        System.out.println( ( new ComponentInfo( XMLUtils.class ) ).toString() );
        System.out.println( ( new ComponentInfo( ClassUtil.class ) ).toString() );
        System.out.println( ( new ComponentInfo( XMPPServer.class ) ).toString() );
        start( args );
    }

首先看到的是parseParams( args );解析参数函数,判断args是否合法,进入函数:   

  /**
     * Method description
     * 传入init.property文件,全部使用这些文件,判断全部不会执行
     *     
     * @param args
     */
    @SuppressWarnings("PMD")
    public static void parseParams( final String[] args ) {
      // 判断args
        if ( ( args != null ) && ( args.length > 0 ) ){
            for ( int i = 0 ; i < args.length ; i++ ) {
                if ( args[i].equals( "-h" ) ){
                    System.out.print( help() );
                    System.exit( 0 );
                }

                if ( args[i].equals( "-v" ) ){
                    System.out.print( version() );
                    System.exit( 0 );
                }

                if ( args[i].equals( "-n" ) ){
                    if ( i + 1 == args.length ){
                        System.out.print( help() );
                        System.exit( 1 );
                    }
                    else {
                        serverName = args[++i];
                    }
                }

            }
        }
    }

咱们的args其实是这个

所以,没有一个是合法的。所以直接往下走。然后就是一大堆的输出:

     System.out.println("开始加载组建");
        System.out.println( ( new ComponentInfo( XMLUtils.class ) ).toString() );
        System.out.println( ( new ComponentInfo( ClassUtil.class ) ).toString() );
        System.out.println( ( new ComponentInfo( XMPPServer.class ) ).toString() );

并没有什么实际意义。再往下就是start( args );进入函数看看.

public static void start( String[] args ) {
        Thread.setDefaultUncaughtExceptionHandler( new ThreadExceptionHandler() );
        if ( !isOSGi() ){
            String initial_config
                         = "tigase.level=ALL
" + "tigase.xml.level=INFO
"
                             + "handlers=java.util.logging.ConsoleHandler
"
                             + "java.util.logging.ConsoleHandler.level=ALL
"
                             + "java.util.logging.ConsoleHandler.formatter=tigase.util.LogFormatter
";

            ConfiguratorAbstract.loadLogManagerConfig( initial_config );
        }

        try {
            // 解析init.properties
            String config_class_name = System.getProperty( CONFIGURATOR_PROP_KEY,DEF_CONFIGURATOR );
            // 根据拿到的ConfiguratorAbstract配置进行解析
            config = (ConfiguratorAbstract) Class.forName( config_class_name ).newInstance();
            config.init( args );
            config.setName( "basic-conf" );
            String mr_class_name = config.getMessageRouterClassName();
            System.out.println("mr_class_name的值为: "+mr_class_name);
            // tigase.server.MessageRouter,配置消息路由
            router = (MessageRouterIfc) Class.forName( mr_class_name ).newInstance();
            router.setName( serverName );
            router.setConfig( config );
            router.start();
        } catch ( ConfigurationException e ) {
            System.err.println( "" );
            System.err.println( "  --------------------------------------" );
            System.err.println( "  ERROR! Terminating the server process." );
            System.err.println( "  Invalid configuration data: " + e );
            System.err.println( "  Please fix the problem and start the server again." );
            System.exit( 1 );
        } catch ( Exception e ) {
            System.err.println( "" );
            System.err.println( "  --------------------------------------" );
            System.err.println( "  ERROR! Terminating the server process." );
            System.err.println( "  Problem initializing the server: " + e );
            System.err.println( "  Please fix the problem and start the server again." );
            e.printStackTrace();
            System.exit( 1 );
        }
    }

进入函数后,先判断isOSGi模式,默认就是false,并没有进行变动。然后通过系统初始化一个ConfiguratorAbstract,这是一个全局配置类,通过反射生成。通过传入args进行配置。

  /**
     * 初始化配置核心类
     * @throws ConfigurationException
     * @throws TigaseDBException
     */
    public void init(String[] args) throws ConfigurationException, TigaseDBException {
        parseArgs(args);

        String stringprep = (String) initProperties.get(STRINGPREP_PROCESSOR);
        if (stringprep != null) {
            BareJID.useStringprepProcessor(stringprep);
        }
        String cnf_class_name = System.getProperty(CONFIG_REPO_CLASS_PROP_KEY);
        if (cnf_class_name != null) {
            initProperties.put(CONFIG_REPO_CLASS_INIT_KEY, cnf_class_name);
        }
        cnf_class_name = (String) initProperties.get(CONFIG_REPO_CLASS_INIT_KEY);
        if (cnf_class_name != null) {
            System.out.println("cnf_class_name: "+cnf_class_name);
            try {
                configRepo = (ConfigRepositoryIfc) Class.forName(cnf_class_name).newInstance();
            } catch (Exception e) {
                log.log(Level.SEVERE, "Problem initializing configuration system: ", e);
                log.log(Level.SEVERE, "Please check settings, and rerun the server.");
                log.log(Level.SEVERE, "Server is stopping now.");
                System.err.println("Problem initializing configuration system: " + e);
                System.err.println("Please check settings, and rerun the server.");
                System.err.println("Server is stopping now.");
                System.exit(1);
            }
        }
        configRepo.addRepoChangeListener(this);
        configRepo.setDefHostname(getDefHostName().getDomain());
        try {
            // idea就是在这儿出问题
            configRepo.initRepository(null, (Map) initProperties);
        } catch (DBInitException ex) {
            throw new ConfigurationException(ex.getMessage(), ex);
        }

        for (String prop : initSettings) {
            ConfigItem item = configRepo.getItemInstance();
            item.initFromPropertyString(prop);
            configRepo.addItem(item);
        }

        Map<String, Object> repoInitProps = configRepo.getInitProperties();

        if (repoInitProps != null) {
            initProperties.putAll(repoInitProps);
        }
        String property_filenames = (String) initProperties.get(PROPERTY_FILENAME_PROP_KEY);
        if (property_filenames != null) {
            String[] prop_files = property_filenames.split(",");
            // 配置监视器
            initMonitoring((String) initProperties.get(MONITORING), new File(prop_files[0])
                    .getParent());
        }
    }

第一步进行配置文件参数读取工作

  
  /**
     * 解析 args,默认配置是/etc/init.properties
     * 将文件中的属性加入 initProperties map中
     * @param args
     */
    public void parseArgs(String[] args) {
        // 配置'--test'
        initProperties.put(GEN_TEST, Boolean.FALSE);
        // 配置'config-type'
        initProperties.put("config-type", GEN_CONFIG_DEF);
        // initProperties加入 --property-file=etc/init.properties
        if ((args != null) && (args.length > 0)) {
            for (int i = 0; i < args.length; i++) {
                String key = null;
                Object val = null;

                if (args[i].startsWith(GEN_CONFIG)) {
                    key = "config-type";
                    val = args[i];
                }
                if (args[i].startsWith(GEN_TEST)) {
                    key = args[i];
                    val = Boolean.TRUE;
                }
                if ((key == null) && args[i].startsWith("-") &&!args[i].startsWith(GEN_CONFIG)) {
                    key = args[i];
                    val = args[++i];
                }
                if ((key != null) && (val != null)) {
                    // Setting defaults: --property-file=etc/init.properties
                    initProperties.put(key, val);
                    log.log(Level.CONFIG, "Setting defaults: {0} = {1}", new Object[] { key,
                            val.toString() });
                }
            }
        }
        // init.properties
        String property_filenames = (String) initProperties.get(PROPERTY_FILENAME_PROP_KEY);
        if (property_filenames == null) {
            property_filenames = PROPERTY_FILENAME_PROP_DEF;
                log.log(Level.WARNING, "No property file not specified! Using default one {0}",
                        property_filenames);
        }

        // always true
        if (property_filenames != null) {
            String[] prop_files = property_filenames.split(",");
            if ( prop_files.length == 1 ){
                File f = new File( prop_files[0] );
                if ( !f.exists() ){
                    log.log( Level.WARNING, "Provided property file {0} does NOT EXISTS! Using default one {1}",
                                     new String[] { f.getAbsolutePath(), PROPERTY_FILENAME_PROP_DEF } );
                    prop_files[0] = PROPERTY_FILENAME_PROP_DEF;
                }
            }
            for (String property_filename : prop_files) {
                log.log(Level.CONFIG, "Loading initial properties from property file: {0}",
                        property_filename);
                try {
                    Properties defProps = new Properties();

                    defProps.load(new FileReader(property_filename));

                    Set<String> prop_keys = defProps.stringPropertyNames();

                    // 获取到配置文件并且进行遍历
                    for (String key : prop_keys) {
                        String value = defProps.getProperty(key).trim();
                        if (key.startsWith("-") || key.equals("config-type")) {
                            if (GEN_TEST.equalsIgnoreCase(key)) {
                                initProperties.put(key.trim().substring(2), DataTypes.parseBool(value));
                                initProperties.put(key.trim(), DataTypes.parseBool(value));
                            } else {
                                initProperties.put(key.trim(), value);
                            }
                            log.log(Level.CONFIG, "Added default config parameter: ({0}={1})",
                                    new Object[] { key,
                                    value });
                        } else {
                            initSettings.add(key + "=" + value);
                        }
                    }
                } catch (FileNotFoundException e) {
                    log.log(Level.WARNING, "Given property file was not found: {0}",
                            property_filename);
                } catch (IOException e) {
                    log.log(Level.WARNING, "Can not read property file: " + property_filename, e);
                }
            }
        }
        for (Map.Entry<String, Object> entry : initProperties.entrySet()) {
            if (entry.getKey().startsWith("--")) {
                System.setProperty(entry.getKey().substring(2), ((entry.getValue() == null)
                        ? null
                        : entry.getValue().toString()));

                // In cluster mode we switch DB cache off as this does not play well.
                if (CLUSTER_MODE.equals(entry.getKey())) {
                    if ("true".equalsIgnoreCase(entry.getValue().toString())) {
                        System.setProperty("tigase.cache", "false");
                    }
                }
            }
        }
    }

先将GEN_TEST加入到设置为false放入map中

  • GEN_TEST: false
  • config-type=--gen-config-def

然后对通过查询args中的值对key和val进行初始化。得到相应的值为

--property-file=etc/init.properties

往下走,拿到property_filenames,其实就是etc/init.properties。如果你没有设置默认的配置文件,其实加载的还是他。这一句就是:

    if (property_filenames == null) {
            property_filenames = PROPERTY_FILENAME_PROP_DEF;
                log.log(Level.WARNING, "No property file not specified! Using default one {0}",
                        property_filenames);
        }

然后我们看,直接对配置文件进行检查,判断是否设置有多个配置文件。这里我们没有多个配置文件。拿到文件之后,对文件进行遍历,将init.properties文件中的属性放入initProperties,initSettings文件中。配置完成后,启动各种应该启动的组建和插件。

启动服务

配置完成,启动插件和组件之后,就开始初始化消息路由:

	  
       String mr_class_name = config.getMessageRouterClassName();
            System.out.println("mr_class_name的值为: "+mr_class_name);
            // tigase.server.MessageRouter,配置消息路由
            router = (MessageRouterIfc) Class.forName( mr_class_name ).newInstance();
            router.setName( serverName );
            router.setConfig( config );
            router.start();      

mr_class_nametigase.server.MessageRouterMessageRouterIfc 是MessageRouter的代理。我们可以看看

router.setConfig( config );
router.start();

这两个方法。

router.setConfig( config );这个方法是通过全局配置来加载组件。

    
  @Override
    public void setConfig(ConfiguratorAbstract config) throws ConfigurationException {
        components.put(getName(), this);
        this.config = config;
        addRegistrator(config);
 }

router.start();方法是启动线程。这个是最重要的。来看看:

     
  /**
     * 线程启动
     */
    @Override
    public void start() {
        if (log.isLoggable(Level.FINER)) {
            log.log(Level.INFO, "{0}: starting queue management threads ...", getName());
        }
        startThreads();
    }

来贴一波启动线程的代码,下一篇博文就写启动现成的代码。

  
  /**
     * 重点
     */
    private void startThreads() {
        if (threadsQueue == null) {
            threadsQueue = new ArrayDeque<QueueListener>(8);
            for (int i = 0; i < in_queues_size; i++) {
                QueueListener in_thread = new QueueListener(in_queues.get(i), QueueType.IN_QUEUE);

                in_thread.setName("in_" + i + "-" + getName());
                in_thread.start();
                threadsQueue.add(in_thread);
            }
            for (int i = 0; i < out_queues_size; i++) {
                QueueListener out_thread = new QueueListener(out_queues.get(i), QueueType
                        .OUT_QUEUE);

                out_thread.setName("out_" + i + "-" + getName());
                out_thread.start();
                threadsQueue.add(out_thread);
            }
        }
        receiverScheduler = Executors.newScheduledThreadPool(schedulerThreads_size, threadFactory);
        receiverTasks     = new Timer(getName() + " tasks", true);
        receiverTasks.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                everySecond();
            }
        }, SECOND, SECOND);
        receiverTasks.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                everyMinute();
            }
        }, MINUTE, MINUTE);
        receiverTasks.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                everyHour();
            }
        }, HOUR, HOUR);
    }

 

学海无涯、何时是岸
原文地址:https://www.cnblogs.com/veblen/p/14703915.html