content: package ro.isdc.wro.manager.factory;
  
  
  import static org.apache.commons.lang3.Validate.notNull;
  
  import java.util.Properties;
  
  import org.apache.commons.lang3.StringUtils;
  
  import ro.isdc.wro.WroRuntimeException;
  import ro.isdc.wro.config.jmx.ConfigConstants;
  import ro.isdc.wro.config.jmx.WroConfiguration;
  import ro.isdc.wro.config.support.PropertiesFactory;
  import ro.isdc.wro.manager.WroManager;
  import ro.isdc.wro.util.ObjectFactory;
  
  
  /**
   * Load the WroManagerFactory configured in {@link WroConfiguration} or loads a default one if none is configured.
   *
   * @author Alex Objelean
   * @created 7 May 2012
   * @since 1.4.6
   */
  public class DefaultWroManagerFactory
      implements WroManagerFactory {
    private final WroManagerFactory factory;
  
    /**
     * A factory method which uses {@link WroConfiguration} to get the configured wroManager className.
     *
     * @param configuration
     *          {@link WroConfiguration} to get the {@link ConfigConstants#managerFactoryClassName} from.
     */
    public static DefaultWroManagerFactory create(final WroConfiguration configuration) {
      return create(new ObjectFactory<WroConfiguration>() {
        public WroConfiguration create() {
          return configuration;
        }
      });
    }
  
    public static DefaultWroManagerFactory create(final ObjectFactory<WroConfiguration> configurationFactory) {
      notNull(configurationFactory);
      final Properties properties = configurationFactory instanceof PropertiesFactory ? ((PropertiesFactory) configurationFactory).createProperties()
          : new Properties();
      final String wroManagerClassName = configurationFactory.create().getWroManagerClassName();
      if (wroManagerClassName != null) {
        properties.setProperty(ConfigConstants.managerFactoryClassName.name(), wroManagerClassName);
      }
      return new DefaultWroManagerFactory(properties);
    }
  
    /**
     * Responsible for creating an instance of {@link WroManagerFactory} whose className is configured in provided
     * {@link Properties}. If managerFactoryClassName is missing, a default one is created.
     *
     * @param properties
     *          {@link Properties} from where the managerFactoryClassName will be read in order to load an instance of
     *          {@link WroManagerFactory}.
     */
    public DefaultWroManagerFactory(final Properties properties) {
      notNull(properties);
      factory = initFactory(properties);
    }
  
    /**
     * Initialized inner factory based on provided configuration.
     */
    private WroManagerFactory initFactory(final Properties properties) {
      final String wroManagerClassName = properties.getProperty(ConfigConstants.managerFactoryClassName.name());
      if (StringUtils.isEmpty(wroManagerClassName)) {
        // If no context param was specified we return the default factory
        return newManagerFactory();
      } else {
        // Try to find the specified factory class
        Class<?> factoryClass = null;
        try {
          factoryClass = Thread.currentThread().getContextClassLoader().loadClass(wroManagerClassName);
          // Instantiate the factory
          final WroManagerFactory factory = (WroManagerFactory)factoryClass.newInstance();
          // inject properties if required
          if (factory instanceof ConfigurableWroManagerFactory) {
            ((ConfigurableWroManagerFactory) factory).addConfigProperties(properties);
          }
          return factory;
        } catch (final Exception e) {
          throw new WroRuntimeException("Exception while loading WroManagerFactory class:" + wroManagerClassName, e);
        }
      }
    }
  
    /**
     * @return the default {@link WroManagerFactory} to be used when {@link WroConfiguration} doesn't specify any factory.
     */
    protected WroManagerFactory newManagerFactory() {
      return new BaseWroManagerFactory();
    }
  
    /**
     * {@inheritDoc}
     */
    public void onCachePeriodChanged(final long value) {
      factory.onCachePeriodChanged(value);
    }
  
    /**
     * {@inheritDoc}
     */
    public void onModelPeriodChanged(final long value) {
      factory.onModelPeriodChanged(value);
    }
  
    /**
     * {@inheritDoc}
     */
    public WroManager create() {
      return factory.create();
    }
  
    /**
     * {@inheritDoc}
     */
    public void destroy() {
      factory.destroy();
    }
  
    /**
     * @VisibleForTesting
     * @return the inner factory.
     */
    public final WroManagerFactory getFactory() {
      return factory;
    }
  
    @Override
    public String toString() {
      return factory.toString();
    }
  }
  