示例#1
0
  @Override
  public void setAnySystemSettings(
      SystemSettings settings, boolean skipValidation, boolean ignoreReadOnly) {
    // first, we need to get the current settings so we'll know if we need to persist or merge the
    // new ones
    @SuppressWarnings("unchecked")
    List<SystemConfiguration> configs =
        entityManager.createNamedQuery(SystemConfiguration.QUERY_FIND_ALL).getResultList();

    Map<String, SystemConfiguration> existingConfigMap = new HashMap<String, SystemConfiguration>();

    for (SystemConfiguration config : configs) {
      existingConfigMap.put(config.getPropertyKey(), config);
    }

    boolean changed = false;

    SystemConfiguration lastUpdateTime =
        existingConfigMap.get(SystemSetting.LAST_SYSTEM_CONFIG_UPDATE_TIME.getInternalName());

    // verify each new setting and persist them to the database
    // note that if a new setting is the same as the old one, we do nothing - leave the old entity
    // as is
    for (Map.Entry<SystemSetting, String> e : settings.entrySet()) {
      SystemSetting prop = e.getKey();

      String value = e.getValue();

      if (!skipValidation) {
        verifyNewSystemConfigurationProperty(prop, value, settings);
      }

      SystemConfiguration existingConfig = existingConfigMap.get(prop.getInternalName());
      if (e.getKey() == SystemSetting.LAST_SYSTEM_CONFIG_UPDATE_TIME) {
        // we don't let the user persist their own last system config update time
        // in any manner
        lastUpdateTime = existingConfig;
      } else if (existingConfig == null) {
        value = transformSystemConfigurationPropertyToDb(prop, value, null);
        existingConfig = new SystemConfiguration(prop.getInternalName(), value);
        entityManager.persist(existingConfig);
        changed = true;
        existingConfigMap.put(existingConfig.getPropertyKey(), existingConfig);
      } else {
        // make sure we compare the new value with a database-agnostic value
        // it is important to compare in the database-agnostic format instead
        // of database specific because the conversion isn't reflective.
        // Some legacy code somewhere is (or just used to) store booleans as "0"s and "1"s
        // even though they are stored as strings and thus don't suffer from Oracle's
        // lack of support for boolean data type. If we encounter such values, we convert
        // them to "false"/"true" and store that value to database. This is a one way operation
        // and therefore we need to compare the database-agnostic (i.e. "true"/"false") and
        // not database specific.
        //
        // More importantly though, we store the password fields obfuscated, so we need to compare
        // apples with
        // apples here.
        String existingValue =
            transformSystemConfigurationPropertyFromDb(
                prop, existingConfig.getPropertyValue(), true);
        // we need to unmask the new value so that we can compare for changes. only after that can
        // we transform
        // it into the DB format.
        value = unmask(prop, value, existingValue);

        // also for oracle, treat null and empty string as the same.
        if ((isEmpty(existingValue) && !isEmpty(value))
            || (null != existingValue && !existingValue.equals(value))) {
          // SystemSetting#isReadOnly should be a superset of the "fReadOnly" field in the database
          // but let's just be super paranoid here...
          if ((prop.isReadOnly()
                  || (existingConfig.getFreadOnly() != null
                      && existingConfig.getFreadOnly().booleanValue()))
              && !(isStorageSetting(prop) || ignoreReadOnly)) {
            throw new IllegalArgumentException(
                "The setting ["
                    + prop.getInternalName()
                    + "] is read-only - you cannot change its current value! Current value is ["
                    + existingConfig.getPropertyValue()
                    + "] while the new value was ["
                    + value
                    + "].");
          }

          // transform to the database-specific format
          value = transformSystemConfigurationPropertyToDb(prop, value, existingValue);

          existingConfig.setPropertyValue(value);
          entityManager.merge(existingConfig);
          changed = true;
        }
      }
    }

    if (changed) {
      if (lastUpdateTime == null) {
        lastUpdateTime =
            new SystemConfiguration(
                SystemSetting.LAST_SYSTEM_CONFIG_UPDATE_TIME.getInternalName(),
                Long.toString(System.currentTimeMillis()));
        lastUpdateTime.setFreadOnly(SystemSetting.LAST_SYSTEM_CONFIG_UPDATE_TIME.isReadOnly());
        entityManager.persist(lastUpdateTime);
      } else {
        lastUpdateTime.setPropertyValue(Long.toString(System.currentTimeMillis()));

        entityManager.merge(lastUpdateTime);
      }

      existingConfigMap.put(
          SystemSetting.LAST_SYSTEM_CONFIG_UPDATE_TIME.getInternalName(), lastUpdateTime);

      fillCache(existingConfigMap.values());
    }
  }