如何反序列化Java属性文件中给出的bean?
问题描述:
请考虑下面的一段典型的VMware配置文件(* .vmx)所在:如何反序列化Java属性文件中给出的bean?
memsize = "2048"
MemTrimRate = "-1"
mks.enable3d = "TRUE"
nvram = "Windows Server 2003 Standard Edition.nvram"
pciBridge0.pciSlotNumber = "17"
pciBridge0.present = "TRUE"
pciBridge4.functions = "8"
pciBridge4.pciSlotNumber = "18"
pciBridge4.present = "TRUE"
pciBridge4.virtualDev = "pcieRootPort"
pciBridge5.functions = "8"
pciBridge5.pciSlotNumber = "19"
pciBridge5.present = "TRUE"
pciBridge5.virtualDev = "pcieRootPort"
pciBridge6.functions = "8"
pciBridge6.pciSlotNumber = "20"
pciBridge6.present = "TRUE"
pciBridge6.virtualDev = "pcieRootPort"
pciBridge7.functions = "8"
pciBridge7.pciSlotNumber = "32"
pciBridge7.present = "TRUE"
pciBridge7.virtualDev = "pcieRootPort"
replay.filename = ""
replay.supported = "FALSE"
roamingVM.exitBehavior = "go"
通过观察这种配置,可以想见一个PciBridge
的java bean类具有以下特征:
class PciBridge
{
public int pciSlotNumber; // or public int getPciSlotNumber(){...} and public void setPciSlotNumber(int v){...}
public boolean present; // or get/is/set methods
public int functions; // or get/set methods
public String virtualDev; // or get/set methods
}
此外,负责读取VMX文件中的配置管理器可能会暴露出下面的方法:
public <T> List<T> getObjects(final String prop, Class<T> clazz);
然后给出上述配置,调用getObjects("pciBridge", PciBridge.class)
将返回配置中指定的所有PciBridge
对象的列表 - 在我们的例子中总共为5。
如何实现此功能?当然,我在几种不同的产品中看到了相同的模式,所以我认为应该有一些东西可以用来实现此功能。
任何想法?
谢谢。
编辑
更正 - 我并不认为VMWare的利用Java属性文件格式(双引号是多余的),但精神是一样的。此外,有适当的Java应用程序使用相同的模式。
答
我张贴我自己的解决方案。代码取决于http://commons.apache.org/beanutils/来反映bean,并且http://commons.apache.org/configuration/用于管理基于属性的配置(因为它使用$ {}语法支持属性引用)。
public static <T> Collection<T> getBeans(String prop, Class<T> clazz) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Pattern pattern = Pattern.compile("^" + prop.replace(".", "\\.") + "(\\d*)\\.(\\w+)$");
Map<String, T> beans = new TreeMap<String, T>();
@SuppressWarnings("rawtypes")
Map description = null;
T tmpBean = null;
Iterator<String> itKeys = m_propStore.getKeys();
while (itKeys.hasNext()) {
String key = itKeys.next();
Matcher matcher = pattern.matcher(key);
boolean matchFound = matcher.find();
if (matchFound) {
if (description == null) {
tmpBean = clazz.newInstance();
description = BeanUtils.describe(tmpBean);
}
String beanPropName = matcher.group(2);
if (description.containsKey(beanPropName)) {
String beanKey = matcher.group(1);
T bean = beans.get(beanKey);
if (bean == null) {
bean = tmpBean == null ? clazz.newInstance() : tmpBean;
tmpBean = null;
beans.put(beanKey, bean);
}
try {
BeanUtils.setProperty(bean, beanPropName, m_propStore.getString(key));
} catch (Exception e) {
m_logger.error(String.format("[SystemConfiguration]: failed to set the %s.%s bean property to the value of the %s configuration property - %s",
bean.getClass().getName(), beanPropName, key, e.getMessage()));
}
}
}
}
return beans.values();
}