如何反序列化java属性文件中给出的bean?

时间:2012-02-28 12:35:11

标签: java properties

请考虑以下典型的VMWare配置文件(* .vmx):

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应用程序使用相同的模式。

1 个答案:

答案 0 :(得分:1)

我发布了自己的解决方案。代码依赖于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();
}