CapacityFactory.java

/*
 *  IronJacamar, a Java EE Connector Architecture implementation
 *  Copyright 2016, Red Hat Inc, and individual contributors
 *  as indicated by the @author tags. See the copyright.txt file in the
 *  distribution for a full listing of individual contributors.
 *
 *  This is free software; you can redistribute it and/or modify it
 *  under the terms of the Eclipse Public License 1.0 as
 *  published by the Free Software Foundation.
 *
 *  This software is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse
 *  Public License for more details.
 *
 *  You should have received a copy of the Eclipse Public License
 *  along with this software; if not, write to the Free
 *  Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 *  02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.ironjacamar.core.connectionmanager.pool.capacity;

import org.ironjacamar.common.api.metadata.common.Extension;
import org.ironjacamar.core.CoreLogger;
import org.ironjacamar.core.api.connectionmanager.pool.CapacityDecrementer;
import org.ironjacamar.core.api.connectionmanager.pool.CapacityIncrementer;
import org.ironjacamar.core.spi.classloading.ClassLoaderPlugin;
import org.ironjacamar.core.util.Injection;

import java.util.Map;

import org.jboss.logging.Logger;

/**
 * The capacity factory
 *
 * @author <a href="mailto:jesper.pedersen@ironjacamar.org">Jesper Pedersen</a>
 */
public class CapacityFactory
{
   /** The logger */
   private static CoreLogger log = Logger.getMessageLogger(CoreLogger.class, CapacityFactory.class.getName());

   /**
    * Constructor
    */
   private CapacityFactory()
   {
   }

   /**
    * Create a capacity instance based on the metadata
    * @param metadata The metadata
    * @param classLoaderPlugin the ClassLoaderPlugin used to load incrementer/decrementer classes
    * @return The instance
    */
   public static org.ironjacamar.core.connectionmanager.pool.Capacity create(
         org.ironjacamar.common.api.metadata.common.Capacity metadata,
         ClassLoaderPlugin classLoaderPlugin)
   {
      if (metadata == null)
         return DefaultCapacity.INSTANCE;

      CapacityIncrementer incrementer = null;
      CapacityDecrementer decrementer = null;

      // Incrementer
      if (metadata.getIncrementer() != null && metadata.getIncrementer().getClassName() != null)
      {
         incrementer = loadIncrementer(metadata.getIncrementer(), classLoaderPlugin);

         if (incrementer != null)
         {
            injectProperties(metadata.getIncrementer().getConfigPropertiesMap(), incrementer);
         }
         else
         {
            log.invalidCapacityIncrementer(metadata.getIncrementer().getClassName());
         }
      }

      if (incrementer == null)
         incrementer = DefaultCapacity.DEFAULT_INCREMENTER;

      // Decrementer
      if (metadata.getDecrementer() != null && metadata.getDecrementer().getClassName() != null)
      {

         decrementer = loadDecrementer(metadata.getDecrementer(), classLoaderPlugin);

         if (decrementer != null)
         {
            injectProperties(metadata.getDecrementer().getConfigPropertiesMap(), decrementer);

         }
         else
         {
            // Explicit allow TimedOutDecrementer, MinPoolSizeDecrementer and SizeDecrementer for CRI based pools
            if (TimedOutDecrementer.class.getName().equals(metadata.getDecrementer().getClassName()) ||
                TimedOutFIFODecrementer.class.getName().equals(metadata.getDecrementer().getClassName()) ||
                MinPoolSizeDecrementer.class.getName().equals(metadata.getDecrementer().getClassName()) ||
                SizeDecrementer.class.getName().equals(metadata.getDecrementer().getClassName()))
            {
               decrementer = loadDecrementer(metadata.getDecrementer(), classLoaderPlugin);

               injectProperties(metadata.getDecrementer().getConfigPropertiesMap(), decrementer);
            }
            else
            {
               log.invalidCapacityDecrementer(metadata.getDecrementer().getClassName());
            }
         }
      }

      if (decrementer == null)
         decrementer = DefaultCapacity.DEFAULT_DECREMENTER;

      return new ExplicitCapacity(incrementer, decrementer);
   }


   private static void injectProperties(Map<String, String> properties, Object decrementer)
   {
      if (!properties.isEmpty())
      {
         Injection injector = new Injection();

         for (Map.Entry<String, String> property : properties.entrySet())
         {
            try
            {
               injector.inject(decrementer, property.getKey(), property.getValue());
            }
            catch (Throwable t)
            {
               log.invalidCapacityOption(property.getKey(),
                                         property.getValue(), decrementer.getClass().getName());
            }
         }
      }
   }

   /**
    * Load the incrementer
    * @param incrementer The incrementer metadata to load as class instance
    * @param classLoaderPlugin class loader plugin to use to load class
    * @return The incrementer
    */
   private static CapacityIncrementer loadIncrementer(Extension incrementer, ClassLoaderPlugin classLoaderPlugin)
   {
      Object result = loadExtension(incrementer, classLoaderPlugin);

      if (result != null && result instanceof CapacityIncrementer)
      {
         return (CapacityIncrementer)result;
      }

      log.debugf("%s wasn't a CapacityIncrementer", incrementer.getClassName());

      return null;
   }

   /**
    * Load the decrementer
    * @param decrementer The incrementer metadata to load as class instance
    * @param classLoaderPlugin class loader plugin to use to load class
    * @return The decrementer
    */
   private static CapacityDecrementer loadDecrementer(Extension decrementer, ClassLoaderPlugin classLoaderPlugin)
   {
      Object result = loadExtension(decrementer, classLoaderPlugin);

      if (result != null && result instanceof CapacityDecrementer)
      {
         return (CapacityDecrementer)result;
      }

      log.debugf("%s wasn't a CapacityDecrementer", decrementer.getClassName());

      return null;
   }

   /**
    * Load the class
    * @param extension The extension metadata to load as class instance
    * @param classLoaderPlugin class loader plugin to use to load class
    * @return The object
    */
   private static Object loadExtension(Extension extension, ClassLoaderPlugin classLoaderPlugin)
   {
      try
      {
         Class<?> c = classLoaderPlugin.loadClass(extension.getClassName(),
               extension.getModuleName(), extension.getModuleSlot());
         return c.newInstance();
      }
      catch (Throwable t)
      {
         log.tracef("Throwable while loading %s using own classloader: %s", extension.getClassName(), t.getMessage());
      }

      return null;
   }
}