/**
   * Initialize the PersistenceManagerFactory for the given location.
   *
   * @throws IllegalArgumentException in case of illegal property values
   * @throws IOException if the properties could not be loaded from the given location
   * @throws JDOException in case of JDO initialization errors
   */
  public void afterPropertiesSet() throws IllegalArgumentException, IOException, JDOException {
    if (this.persistenceManagerFactoryName != null) {
      if (this.configLocation != null || !this.jdoPropertyMap.isEmpty()) {
        throw new IllegalStateException(
            "'configLocation'/'jdoProperties' not supported in "
                + "combination with 'persistenceManagerFactoryName' - specify one or the other, not both");
      }
      if (logger.isInfoEnabled()) {
        logger.info(
            "Building new JDO PersistenceManagerFactory for name '"
                + this.persistenceManagerFactoryName
                + "'");
      }
      this.persistenceManagerFactory =
          newPersistenceManagerFactory(this.persistenceManagerFactoryName);
    } else {
      Map<String, Object> mergedProps = new HashMap<String, Object>();
      if (this.configLocation != null) {
        if (logger.isInfoEnabled()) {
          logger.info("Loading JDO config from [" + this.configLocation + "]");
        }
        CollectionUtils.mergePropertiesIntoMap(
            PropertiesLoaderUtils.loadProperties(this.configLocation), mergedProps);
      }
      mergedProps.putAll(this.jdoPropertyMap);
      logger.info("Building new JDO PersistenceManagerFactory");
      this.persistenceManagerFactory = newPersistenceManagerFactory(mergedProps);
    }

    // Build default JdoDialect if none explicitly specified.
    if (this.jdoDialect == null) {
      this.jdoDialect =
          new DefaultJdoDialect(this.persistenceManagerFactory.getConnectionFactory());
    }
  }
  /**
   * Load and/or apply Quartz properties to the given SchedulerFactory.
   *
   * @param schedulerFactory the SchedulerFactory to initialize
   */
  private void initSchedulerFactory(SchedulerFactory schedulerFactory)
      throws SchedulerException, IOException {

    if (!(schedulerFactory instanceof StdSchedulerFactory)) {
      if (this.configLocation != null
          || this.quartzProperties != null
          || this.taskExecutor != null
          || this.dataSource != null) {
        throw new IllegalArgumentException(
            "StdSchedulerFactory required for applying Quartz properties: " + schedulerFactory);
      }
      // Otherwise assume that no initialization is necessary...
      return;
    }

    Properties mergedProps = new Properties();

    if (this.resourceLoader != null) {
      mergedProps.setProperty(
          StdSchedulerFactory.PROP_SCHED_CLASS_LOAD_HELPER_CLASS,
          ResourceLoaderClassLoadHelper.class.getName());
    }

    if (this.taskExecutor != null) {
      mergedProps.setProperty(
          StdSchedulerFactory.PROP_THREAD_POOL_CLASS, LocalTaskExecutorThreadPool.class.getName());
    } else {
      // Set necessary default properties here, as Quartz will not apply
      // its default configuration when explicitly given properties.
      mergedProps.setProperty(
          StdSchedulerFactory.PROP_THREAD_POOL_CLASS, SimpleThreadPool.class.getName());
      mergedProps.setProperty(PROP_THREAD_COUNT, Integer.toString(DEFAULT_THREAD_COUNT));
    }

    if (this.configLocation != null) {
      if (logger.isInfoEnabled()) {
        logger.info("Loading Quartz config from [" + this.configLocation + "]");
      }
      PropertiesLoaderUtils.fillProperties(mergedProps, this.configLocation);
    }

    CollectionUtils.mergePropertiesIntoMap(this.quartzProperties, mergedProps);

    if (this.dataSource != null) {
      mergedProps.put(
          StdSchedulerFactory.PROP_JOB_STORE_CLASS, LocalDataSourceJobStore.class.getName());
    }

    // Make sure to set the scheduler name as configured in the Spring configuration.
    if (this.schedulerName != null) {
      mergedProps.put(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME, this.schedulerName);
    }

    ((StdSchedulerFactory) schedulerFactory).initialize(mergedProps);
  }
  /**
   * Prepare the VelocityEngine instance and return it.
   *
   * @return the VelocityEngine instance
   * @throws IOException if the config file wasn't found
   * @throws VelocityException on Velocity initialization failure
   */
  public VelocityEngine createVelocityEngine() throws IOException, VelocityException {
    VelocityEngine velocityEngine = newVelocityEngine();
    Map<String, Object> props = new HashMap<String, Object>();

    // Load config file if set.
    if (this.configLocation != null) {
      if (logger.isInfoEnabled()) {
        logger.info("Loading Velocity config from [" + this.configLocation + "]");
      }
      CollectionUtils.mergePropertiesIntoMap(
          PropertiesLoaderUtils.loadProperties(this.configLocation), props);
    }

    // Merge local properties if set.
    if (!this.velocityProperties.isEmpty()) {
      props.putAll(this.velocityProperties);
    }

    // Set a resource loader path, if required.
    if (this.resourceLoaderPath != null) {
      initVelocityResourceLoader(velocityEngine, this.resourceLoaderPath);
    }

    // Log via Commons Logging?
    if (this.overrideLogging) {
      velocityEngine.setProperty(
          RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, new CommonsLoggingLogSystem());
    }

    // Apply properties to VelocityEngine.
    for (Map.Entry<String, Object> entry : props.entrySet()) {
      velocityEngine.setProperty(entry.getKey(), entry.getValue());
    }

    postProcessVelocityEngine(velocityEngine);

    try {
      // Perform actual initialization.
      velocityEngine.init();
    } catch (IOException ex) {
      throw ex;
    } catch (VelocityException ex) {
      throw ex;
    } catch (RuntimeException ex) {
      throw ex;
    } catch (Exception ex) {
      logger.error("Why does VelocityEngine throw a generic checked exception, after all?", ex);
      throw new VelocityException(ex.toString());
    }

    return velocityEngine;
  }
  @Test
  public void testMergePropertiesIntoMap() {
    Properties defaults = new Properties();
    defaults.setProperty("prop1", "value1");
    Properties props = new Properties(defaults);
    props.setProperty("prop2", "value2");
    props.put("prop3", new Integer(3));

    Map<String, String> map = new HashMap<>();
    map.put("prop4", "value4");

    CollectionUtils.mergePropertiesIntoMap(props, map);
    assertEquals("value1", map.get("prop1"));
    assertEquals("value2", map.get("prop2"));
    assertEquals(new Integer(3), map.get("prop3"));
    assertEquals("value4", map.get("prop4"));
  }
  /**
   * Return a merged Properties instance containing both the loaded properties and properties set on
   * this FactoryBean.
   */
  protected Properties mergeProperties() throws IOException {
    Properties result = new Properties();

    if (this.localOverride) {
      // Load properties from file upfront, to let local properties override.
      loadProperties(result);
    }

    if (this.localProperties != null) {
      for (int i = 0; i < this.localProperties.length; i++) {
        CollectionUtils.mergePropertiesIntoMap(this.localProperties[i], result);
      }
    }

    if (!this.localOverride) {
      // Load properties from file afterwards, to let those properties override.
      loadProperties(result);
    }

    return result;
  }
 /**
  * Set JDO properties, such as"javax.jdo.PersistenceManagerFactoryClass".
  *
  * <p>Can be used to override values in a JDO properties config file, or to specify all necessary
  * properties locally.
  *
  * <p>Can be populated with a String "value" (parsed via PropertiesEditor) or a "props" element in
  * XML bean definitions.
  */
 public void setJdoProperties(Properties jdoProperties) {
   CollectionUtils.mergePropertiesIntoMap(jdoProperties, this.jdoPropertyMap);
 }
 /**
  * Set Velocity properties, like "file.resource.loader.path". Can be used to override values in a
  * Velocity config file, or to specify all necessary properties locally.
  *
  * <p>Note that the Velocity resource loader path also be set to any Spring resource location via
  * the "resourceLoaderPath" property. Setting it here is just necessary when using a
  * non-file-based resource loader.
  *
  * @see #setVelocityPropertiesMap
  * @see #setConfigLocation
  * @see #setResourceLoaderPath
  */
 public void setVelocityProperties(Properties velocityProperties) {
   CollectionUtils.mergePropertiesIntoMap(velocityProperties, this.velocityProperties);
 }
 /**
  * Set static attributes for this view from a <code>java.util.Properties</code> object.
  *
  * <p>"Static" attributes are fixed attributes that are specified in the View instance
  * configuration. "Dynamic" attributes, on the other hand, are values passed in as part of the
  * model.
  *
  * <p>This is the most convenient way to set static attributes. Note that static attributes can be
  * overridden by dynamic attributes, if a value with the same name is included in the model.
  *
  * <p>Can be populated with a String "value" (parsed via PropertiesEditor) or a "props" element in
  * XML bean definitions.
  *
  * @see org.springframework.beans.propertyeditors.PropertiesEditor
  */
 public void setAttributes(Properties attributes) {
   CollectionUtils.mergePropertiesIntoMap(attributes, this.staticAttributes);
 }
 /**
  * Specify bean validation properties to be passed to the validation provider.
  *
  * <p>Can be populated with a String "value" (parsed via PropertiesEditor) or a "props" element in
  * XML bean definitions.
  *
  * @see javax.validation.Configuration#addProperty(String, String)
  */
 public void setValidationProperties(Properties jpaProperties) {
   CollectionUtils.mergePropertiesIntoMap(jpaProperties, this.validationPropertyMap);
 }