tigase运行流程分析(十六)
加载配置文件,运行的时候选择的主类是XMPPServer
。打开XMPPServer
的main
函数入口,直接上源码进行分析:
/**
*
* @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\n" + "tigase.xml.level=INFO\n"
+ "handlers=java.util.logging.ConsoleHandler\n"
+ "java.util.logging.ConsoleHandler.level=ALL\n"
+ "java.util.logging.ConsoleHandler.formatter=tigase.util.LogFormatter\n";
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_name
是tigase.server.MessageRouter
,MessageRouterIfc
是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);
}
__EOF__
本文链接:https://www.cnblogs.com/veblen/p/14703915.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!