如何反序列化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(); 
}