openmeetings-install分析(十二)——Admin类询问阶段processInstall分析(5)

2021SC@SDUSC


在上篇文章中,我们分析了performImport方法中使用Simple框架序列化Java Bean对象的部分,在本篇文章中我们将对performImport方法中剩下的代码进行分析。

performImport

本篇文章要分析的performImport代码
    // BackupImport.java
	public void performImport(InputStream is) throws Exception {
		...
        // 上面的代码已经分析过,就省略
		BackupVersion ver = getVersion(simpleSerializer, f);
		importConfigs(f);
        ...
	}
BackupVersion
    // BackupImport.java
	private static BackupVersion getVersion(Serializer ser, File f) throws Exception {
		List<BackupVersion> list = readList(ser, f, "version.xml", "version", BackupVersion.class, null, true);
		// 判断list是否为空,若空,则新建一个BackupVersion对象,否则,取列表的第一个元素作为返回值
		return list.isEmpty() ? new BackupVersion() : list.get(0);
	}

    // 来看一下getVersion中的readList方法,该方法也在该类中
	private static <T> List<T> readList(Serializer ser, File baseDir, String fileName, String listNodeName, Class<T> clazz, BiConsumer<InputNode, T> consumer, boolean notThow) throws Exception {
		List<T> list = new ArrayList<>();
		// 读取version.xml文件
		File xml = new File(baseDir, fileName);
		if (!xml.exists()) {
			final String msg = fileName + " missing";
			if (notThow) {
				log.debug(msg);
				return list;
			} else {
				throw new BackupException(msg);
			}
		}
		// 根据读取的xml文件创建2个输入流
		try (InputStream rootIs1 = new FileInputStream(xml); InputStream rootIs2 = new FileInputStream(xml)) {
		    /* InputNode、NodeBuilder来自simple框架 */
		    /* 
		      NodeBuilder对象用于为给定的源或目标创建输入节点或输出节点。
		      如果读取XML文档需要InputNode,那么必须提供读取器来读取其中的内容。
		    */
		    /* 
		      InputNode对象表示元素中元素的迭代器。
		      这允许输入节点对象成为元素及其子元素的自包含迭代器。
		      从输入节点对象中获取的每一个子节点本身就是一个输入节点,可以用来探索其子元素,而不会对其外部元素产生任何影响。
		    */
			InputNode root1 = NodeBuilder.read(rootIs1);
			InputNode root2 = NodeBuilder.read(rootIs2); // for various hacks
			// getNext():返回该元素的子元素
			InputNode listNode1 = root1.getNext();
			InputNode listNode2 = root2.getNext(); // for various hacks
			if (listNodeName.equals(listNode1.getName())) {
				InputNode item1 = listNode1.getNext();
				while (item1 != null) {
				    /* 
				    
				      <T> T read(Class<? extends T> type,Reader source,boolean strict) throws Exception
				      
				      这个read方法将从提供的源读取XML文档的内容,并将其转换为指定类型的对象。
				      
				      如果XML源不能反序列化,或者在构建对象图时出现问题,则会引发异常。
				      返回反序列化的实例。
				      
				      参数:
				      type:这是要从XML反序列化的类类型
				      source:提供xml文档的源
				      strict:决定是否在严格模式下读取
				      
				      在这里即表示不在严格模式下将version.xml文档反序列化为BackupVersion类对象
				    */
					T o = ser.read(clazz, item1, false);;
					if (consumer != null) {
						consumer.accept(listNode2, o);
					}
					// 把反序列后的对象放入列表中
					list.add(o);
					// 遍历下一个子元素
					item1 = listNode1.getNext();
				}
			}
		}
		// 最终会得到一个version.xml文档反序列化后的BackupVersion对象列表
		return list;
	}
importConfigs
    // BackupImport.java
    private void importConfigs(File f) throws Exception {
		Registry registry = new Registry();
		Strategy strategy = new RegistryStrategy(registry);
		RegistryMatcher matcher = new RegistryMatcher();
		Serializer serializer = new Persister(strategy, matcher);

		matcher.bind(Long.class, LongTransform.class);
		registry.bind(Date.class, DateConverter.class);
		registry.bind(User.class, new UserConverter(userDao, userMap));

        // Configuration类来自openmeetings-db包,不属于我的分析范围,在这里就不展开分析了
		List<Configuration> list = readList(serializer, f, "configs.xml", "configs", Configuration.class, null, true);
		// 以上内容和我们之前在performImport方法中分析过的代码很像,在这里是对configs.xml文件进行反序列化,得到一个包含Configuration对象的列表
		for (Configuration c : list) {
			if (c.getKey() == null || c.isDeleted()) {
				continue;
			}
			String newKey = outdatedConfigKeys.get(c.getKey());
			if (newKey != null) {
				c.setKey(newKey);
			}
			Configuration.Type type = configTypes.get(c.getKey());
			if (type != null) {
				c.setType(type);
				if (Configuration.Type.bool == type) {
					c.setValue(String.valueOf("1".equals(c.getValue()) || "yes".equals(c.getValue()) || "true".equals(c.getValue())));
				}
			}
			// 根据key值检索配置
			Configuration cfg = cfgDao.forceGet(c.getKey());
			if (cfg != null && !cfg.isDeleted()) {
				log.warn("Non deleted configuration with same key is found! old value: {}, new value: {}", cfg.getValue(), c.getValue());
			}
			c.setId(cfg == null ? null : cfg.getId());
			if (c.getUser() != null && c.getUser().getId() == null) {
				c.setUser(null);
			}
			if (CONFIG_CRYPT.equals(c.getKey())) {
				try {
					Class<?> clazz = Class.forName(c.getValue());
					// getDeclaredConstructor返回一个构造函数对象
					// newInstance使用此构造函数创建和初始化构造函数所声明类的新实例。
					clazz.getDeclaredConstructor().newInstance();
				} catch (Exception e) {
					log.warn("Not existing Crypt class found {}, replacing with SCryptImplementation", c.getValue());
					c.setValue(SCryptImplementation.class.getCanonicalName());
				}
			}
			// 更新数据库
			cfgDao.update(c, null);
		}
	}
总结

在本篇文章中,分析了2行代码:

		BackupVersion ver = getVersion(simpleSerializer, f);
		importConfigs(f);

分析这部分代码时,也分析到了涉及的getVersion、readList方法。在readList方法和importConfigs方法中都涉及到了上篇文章分析的simple框架,理解需要一定的时间。performImport方法后面还有很多的import方法,其作用应该和importConfigs大同小异,都是引入相关的配置、资源等等。performImport方法中的内容比较多,也涉及到很多其他的方法,逐一分析耗时较长,还需以后慢慢理解、慢慢钻研。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值