Как десериализовать bean-компоненты, указанные в файле свойств Java? - PullRequest
2 голосов
/ 28 февраля 2012

Пожалуйста, рассмотрите следующий фрагмент типичного файла конфигурации 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"

Наблюдая эту конфигурацию, можно представить тип java-компонента PciBridge со следующей сигнатурой:

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 Ответ

1 голос
/ 06 марта 2012

Я публикую свое собственное решение.Код зависит от 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...