/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2007 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library 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 GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.resource.internal;

import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import javax.management.ObjectName;
import javax.naming.BinaryRefAddr;
import javax.naming.Context;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.resource.Referenceable;
import javax.resource.spi.ConnectionManager;
import javax.resource.spi.ManagedConnectionFactory;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.ResourceAdapterAssociation;

import org.apache.commons.modeler.Registry;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.ow2.jonas.deployment.ejb.ActivationConfigPropertyDesc;
import org.ow2.jonas.deployment.rar.ConfigPropertyDesc;
import org.ow2.jonas.deployment.rar.ConnectorDesc;
import org.ow2.jonas.deployment.rar.JdbcConnParamsDesc;
import org.ow2.jonas.deployment.rar.JonasConfigPropertyDesc;
import org.ow2.jonas.deployment.rar.JonasConnectorDesc;
import org.ow2.jonas.deployment.rar.PoolParamsDesc;
import org.ow2.jonas.jmx.JmxService;
import org.ow2.jonas.lib.management.javaee.J2eeObjectName;
import org.ow2.jonas.lib.naming.ComponentContext;
import org.ow2.jonas.lib.util.JNDIUtils;
import org.ow2.jonas.lib.util.Log;
import org.ow2.jonas.resource.internal.cm.ConnectionManagerImpl;
import org.ow2.jonas.resource.internal.cm.ConnectionManagerPoolParams;
import org.ow2.jonas.resource.internal.mbean.JCAConnectionFactory;
import org.ow2.jonas.resource.internal.mbean.JCAManagedConnectionFactory;
import org.ow2.jonas.resource.internal.mbean.JCAResource;
import org.ow2.jonas.resource.internal.naming.ResourceObjectFactory;
import org.ow2.jonas.tm.TransactionManager;

/**
 * ResourceUtility class
 * @author Eric Hardesty
 * Contributor(s):
 *
 */

public class ResourceUtility {

    /**
     * Main logger
     */
    private static Logger logger = null;
    /**
     * Config property setter logger
     */
    private static Logger setterLogger = null;
    /**
     * Management logger
     */
    private static Logger manageLogger = null;

    /**
     * Reference to a Registry object
     */
    private Registry oRegistry = null;

    /**
     * Reference to the jmx service
     */
    private JmxService jmx = null;

    // Properties for inits
    /**
     * JOnAS Connection Definition
     */
    public static final String JCD = "JCD";
    /**
     * JOnAS Activationspec
     */
    public static final String JAS = "JAS";
    /**
     * JOnAS Administrated Object
     */
    public static final String JAO = "JAO";

    /**
     * Default constructor
     *
     */
    public ResourceUtility() {
    }

    /**
     * Constructor
     *
     * @param log Logger main logger
     * @param sLog Logger setter logger
     * @param mLog Logger management logger
     */
    public ResourceUtility(final JmxService jmx,
                           final Logger log, final Logger sLog, final Logger mLog) {
        this.jmx = jmx;
        logger = log;
        setterLogger = sLog;
        manageLogger = mLog;
    }

    /**
     *
     * @param raCfg List
     * @param jRaCfg1 List
     * @param jRaCfg2 List
     * @return ConfigPropertyDesc array
     */
    public ConfigPropertyDesc [] buildConfigProperty(final List raCfg,
                                                     final List jRaCfg1,
                                                     final List jRaCfg2) {
        Vector cfVec = null;
        ConfigPropertyDesc[] configs = null;

        // Global config parameters for the Resource adapter
        if (raCfg != null) {
            for (Iterator i = raCfg.iterator(); i.hasNext();) {
                if (cfVec == null) {
                    cfVec = new Vector();
                }
                ConfigPropertyDesc cpd = (ConfigPropertyDesc) i.next();
                if (setterLogger.isLoggable(BasicLevel.DEBUG)) {
                    String name = cpd.getConfigPropertyName();
                    String val = cpd.getConfigPropertyValue();
                    setterLogger.log(BasicLevel.DEBUG, "Standard config: " + name + "=" + val);
                }
                cfVec.add(new ConfigPropertyDesc(cpd));
            }
        } else {  //Special case for configuring ActivationSpecs
            ActivationConfigPropertyDesc acp = null;
            ConfigPropertyDesc cp = null;
            if (jRaCfg1 != null) {
                for (Iterator i = jRaCfg1.iterator(); i.hasNext();) {
                    if (cfVec == null) {
                        cfVec = new Vector();
                    }
                    acp = (ActivationConfigPropertyDesc) i.next();
                    cp = new ConfigPropertyDesc();
                    cp.setConfigPropertyName(acp.getActivationConfigPropertyName());
                    cp.setConfigPropertyValue(acp.getActivationConfigPropertyValue());
                    cfVec.add(cp);
                }
            }

            if (cfVec == null) {
                if (jRaCfg2 != null) {
                    for (Iterator i = jRaCfg2.iterator(); i.hasNext();) {
                        if (cfVec == null) {
                            cfVec = new Vector();
                        }
                        acp = (ActivationConfigPropertyDesc) i.next();
                        cp = new ConfigPropertyDesc();
                        cp.setConfigPropertyName(acp.getActivationConfigPropertyName());
                        cp.setConfigPropertyValue(acp.getActivationConfigPropertyValue());
                        cfVec.add(cp);
                    }
                    if (cfVec != null) {
                        configs = new ConfigPropertyDesc[cfVec.size()];
                        cfVec.copyInto(configs);
                    }
                }
            } else {
                if (jRaCfg2 != null) {
                    boolean found = false;
                    for (Iterator i = jRaCfg2.iterator(); i.hasNext();) {
                        found = false;
                        acp = (ActivationConfigPropertyDesc) i.next();
                        String name = acp.getActivationConfigPropertyName();
                        String val = acp.getActivationConfigPropertyValue();
                        if (val != null && val.length() > 0) {
                            for (int j = 0; j < cfVec.size(); j++) {
                                cp = (ConfigPropertyDesc) cfVec.get(j);
                                if (name.equalsIgnoreCase(cp.getConfigPropertyName())) {
                                    cp.setConfigPropertyValue(val);
                                    cfVec.set(j, cp);
                                    found = true;
                                    break;
                                }
                            }
                            // This is the case where a new activation-config property is in
                            // the jonas specific dd
                            if (!found) {
                                cp = new ConfigPropertyDesc();
                                cp.setConfigPropertyName(name);
                                cp.setConfigPropertyValue(val);
                                cfVec.add(cp);
                            }
                        }
                    }
                }
                configs = new ConfigPropertyDesc[cfVec.size()];
                cfVec.copyInto(configs);
            }

            if (cfVec == null) {
                return null;
            }
            return configs;
        }

        if (cfVec == null) {
            return null;
        }

        configs = new ConfigPropertyDesc[cfVec.size()];
        cfVec.copyInto(configs);

        JonasConfigPropertyDesc jcpNext = null;
        if (jRaCfg2 != null) {
            for (Iterator i = jRaCfg2.iterator(); i.hasNext();) {
                jcpNext = (JonasConfigPropertyDesc) i.next();
                String name = jcpNext.getJonasConfigPropertyName();
                String val = jcpNext.getJonasConfigPropertyValue();
                if (val != null && val.length() > 0) {
                    for (int j = 0; j < configs.length; j++) {
                        if (name.equalsIgnoreCase(configs[j].getConfigPropertyName())) {
                            configs[j].setConfigPropertyValue(val);
                            break;
                        }
                    }
                }
            }
        }

        if (jRaCfg1 != null) {
            for (Iterator i = jRaCfg1.iterator(); i.hasNext();) {
                jcpNext = (JonasConfigPropertyDesc) i.next();
                String name = jcpNext.getJonasConfigPropertyName();
                String val = jcpNext.getJonasConfigPropertyValue();
                if (setterLogger.isLoggable(BasicLevel.DEBUG)) {
                    setterLogger.log(BasicLevel.DEBUG, "Jonas config: " + name + "=" + val);
                }
                if (val != null && val.length() > 0) {
                    for (int j = 0; j < configs.length; j++) {
                        if (name.equalsIgnoreCase(configs[j].getConfigPropertyName())) {
                            configs[j].setConfigPropertyValue(val);
                            break;
                        }
                    }
                }
            }
        }
        return configs;
    }

    /**
     *
     * @param inp String
     * @return boolean
     */
    private boolean checkLogEnabled(final String inp) {
        if (inp.equals("1") || inp.equalsIgnoreCase("on")
            || inp.equalsIgnoreCase("t") || inp.equalsIgnoreCase("true")
            || inp.equalsIgnoreCase("y") || inp.equalsIgnoreCase("yes")) {
            return true;
        }
         return false;
    }

    /**
     *
     * @param trans String
     * @param tm TransactionManager
     * @param logger Logger
     * @param poolLogger Logger
     * @return ConnectionManager
     * @throws Exception any exception
     */
    public ConnectionManager createConnectionManager(final String trans,
                                                     final TransactionManager tm,
                                                     final Logger logger,
                                                     final Logger poolLogger)
           throws Exception {

        ConnectionManagerImpl cm = new ConnectionManagerImpl(trans);

        Context c = new ComponentContext("");
        c.rebind(ConnectionManagerImpl.TRANSACTION_MANAGER, tm);

        // Set the MonologFactory into context of initialisation
        c.rebind(ConnectionManagerImpl.LOGGER, logger);
        c.rebind(ConnectionManagerImpl.POOL_LOGGER, poolLogger);

        // Initialize the ConnectionManager with the configured Context
        cm.init(c);
        return cm;
    }

    /**
     * Process the ManagedConnectionFactory object
     *
     * @param conn ConnectorDesc
     * @param jonasConn JonasConnectorDesc
     * @param curLoader ClassLoader
     * @param rarName String
     * @param mcfc String
     * @param jndiName String
     * @param logEnabled String
     * @param logTopic String
     * @param cfgRaJonas ConfigPropertyDesc array
     * @param resAdp ResourceAdapter
     * @param idOff int
     * @return Object
     * @throws Exception any exception
     */
    public Object processMCF(final ConnectorDesc conn, final JonasConnectorDesc jonasConn,
                              final ClassLoader curLoader, final String rarName, final String mcfc,
                              final String jndiName, final String logEnabled, final String logTopic,
                              final ConfigPropertyDesc [] cfgRaJonas, final ResourceAdapter resAdp,
                              final int idOff) throws Exception {

        if (mcfc == null) {
            logger.log(BasicLevel.ERROR, "ResourceService.createRA:"
                       + " managedconnectionfactoryclass property not found");
            throw new Exception("configuration file incorrect");
        }

        if (jndiName == null || jndiName.length() == 0) {
            logger.log(BasicLevel.ERROR, "ResourceService.createRA: jndi-name not set in jonas-ra.xml");
            throw new Exception("configuration file incorrect");
        }

        // Instantiate into the current loader
        Class mcfClass = curLoader.loadClass(mcfc);
        ManagedConnectionFactory mcf =
            (ManagedConnectionFactory) mcfClass.newInstance();

        if (resAdp != null) {
            try {
                ((ResourceAdapterAssociation) mcf).setResourceAdapter(resAdp);
            } catch (ClassCastException ce) {
                // Not able to associate ResourceAdapter to MCF
            } catch (Exception ex) {
                logger.log(BasicLevel.ERROR, "ResourceService: Error setting ResourceAdapter class to ManagedConnectionFactory ("
                           + mcfc + ") for " + jndiName);
                throw ex;
            }
        }

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "jndiName=" + jndiName);
        }

        // Check if logging desired and the value of the desired topic
        if (logEnabled != null) {
            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "log-enabled=" + logEnabled);
            }
            if (checkLogEnabled(logEnabled)) {
                if (logTopic != null && logTopic.length() > 0) {
                    if (logger.isLoggable(BasicLevel.DEBUG)) {
                        logger.log(BasicLevel.DEBUG, "log-topic=" + logTopic);
                    }
                    mcf.setLogWriter(Log.getLogWriter(logTopic));
                } else {
                    if (logger.isLoggable(BasicLevel.DEBUG)) {
                        logger.log(BasicLevel.DEBUG, "default log-topic=" + Log.JONAS_JCA_PREFIX);
                    }
                    mcf.setLogWriter(Log.getLogWriter(Log.JONAS_JCA_PREFIX));
                }
            }
        }

        processSetters(mcfClass, mcf, rarName, cfgRaJonas);

        PrintWriter pw = mcf.getLogWriter();
        if (pw != null) {
            //Create a date format
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
            String date = sdf.format(new Date());
            pw.println("MCF: output starting at " + date);
            pw.flush();
        }

        // Set hashCode for ManagedConnectionFactory
        try {
            mcf.hashCode();
        } catch (Exception ex) {
            String err = "Exception  in ManagedConnectionFactory.hashCode(): ";
            logger.log(BasicLevel.ERROR, err+ex);
        }


        return mcf;
    }


    /**
     *
     * @param cf Referenceable
     * @param jndiName String
     * @param rarName String
     * @param conn ConnectorDesc
     * @param jonasConn JonasConnectorDesc
     * @param factType String factory type
     * @param factOffset int factory offset
     * @param jcaResourceMBean JCAResource
     * @param jcaResourceName String
     * @param jDomain String of JOnAS domain name
     * @param jServer String of JOnAS server name
     * @param ictx Context
     * @param prop Properties
     * @throws Exception any Exception
     */
    public void registerMBean(final Referenceable cf, final String jndiName, final String rarName, final String rarFileName,
                              final ConnectorDesc conn, final JonasConnectorDesc jonasConn,
                              final String factType, final int factOffset,
                              final JCAResource jcaResourceMBean, final String jcaResourceName,
                              final String jDomain, final String jServer, final Context ictx, final Properties prop,
                              final String description, final ConnectionManagerImpl cm) throws Exception {

        try {
            Reference ref =
                new Reference(cf.getClass().getName(),
                              ResourceObjectFactory.class.getName(),
                              null);

            ref.add(new StringRefAddr(ResourceServiceConstants.JNDI_NAME, jndiName));
            ref.add(new StringRefAddr(ResourceServiceConstants.RAR_OBJNAME, rarName));
            ref.add(new StringRefAddr(ResourceServiceConstants.FACTORY_TYPE, factType));
            ref.add(new StringRefAddr(ResourceServiceConstants.FACTORY_OFFSET, "" + factOffset));
            //Put the connector objects
            byte[] bytes = JNDIUtils.getBytesFromObject(conn);
            if (bytes != null) {
                ref.add(new BinaryRefAddr(ResourceServiceConstants.RA_XML, bytes));
            }

            bytes = JNDIUtils.getBytesFromObject(jonasConn);
            if (bytes != null) {
                ref.add(new BinaryRefAddr(ResourceServiceConstants.JONAS_RA_XML, bytes));
            }

            cf.setReference(ref);
            ictx.rebind(jndiName, cf);

        } catch (Exception e) {
            logger.log(BasicLevel.ERROR, "ResourceService: Cannot register ResourceAdapter in naming with the name " + jndiName);
            logger.log(BasicLevel.ERROR, "ResourceService: Exception caught : " + e);
        }

        // check if jmx service reference is initialized before continuing
        if (jmx == null) {
            return;
        }
        // --------------------------
        // Register MBeans cf. JSR 77
        // --------------------------
        // Available ConnectionFactories and ManagedConnectionFactories
        // ------------------------------------------------------------
        // ConnectionFactory MBean
        // -----------------------
        String jcaConnectionFactoryName = jndiName;
        ObjectName onJCAConnectionFactory =
            J2eeObjectName.getJCAConnectionFactory(jDomain,
                    jcaResourceName,
                    jServer,
                    jcaConnectionFactoryName);
        JCAConnectionFactory jcaConnectionFactoryMBean = new JCAConnectionFactory(onJCAConnectionFactory.toString(), jndiName, rarFileName, prop, description, cm);
        jmx.registerModelMBean(jcaConnectionFactoryMBean, onJCAConnectionFactory);
        if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
            manageLogger.log(BasicLevel.DEBUG, "JCAConnectionFactory created");
        }

        // Update the list of connection factories in the JCAResource MBean with the JCAConnectionFactory
        // MBean's OBJECT_NAME
        jcaResourceMBean.setConnectionFactory(onJCAConnectionFactory.toString());

        // ManagedConnectionFactory MBean
        // ------------------------------
        String jcaManagedConnectionFactoryName = getJcaMcfName(jcaConnectionFactoryName);
        ObjectName onJCAManagedConnectionFactory =
            J2eeObjectName.getJCAManagedConnectionFactory(jDomain,
                    jServer,
                    jcaManagedConnectionFactoryName);
        JCAManagedConnectionFactory jcaManagedConnectionFactoryMBean =
            new JCAManagedConnectionFactory(onJCAManagedConnectionFactory.toString());
        jmx.registerModelMBean(jcaManagedConnectionFactoryMBean, onJCAManagedConnectionFactory);
        if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
            manageLogger.log(BasicLevel.DEBUG, "JCAManagedConnectionFactory created");
        }

        // Update the JCA ConnectionFactory with the JCA ManagedConnectionFactory
        jcaConnectionFactoryMBean.setManagedConnectionFactory(onJCAManagedConnectionFactory.toString());
        if (manageLogger.isLoggable(BasicLevel.DEBUG)) {
            manageLogger.log(BasicLevel.DEBUG, "JCAConnectionFactory updated");
        }
    }


    /**
     *
     * @param clsClass Class
     * @param clsObj Object
     * @param rarFileName String
     * @param cProp ConfigPropertyDesc array
     * @throws Exception any exception
     */
    public void processSetters(final Class clsClass, final Object clsObj, final String rarFileName,
                               final ConfigPropertyDesc [] cProp) throws Exception {

        int curParam = 0;
        while (cProp != null && curParam < cProp.length) {
            String fieldName = cProp[curParam].getConfigPropertyName();
            String methodName = "set" + fieldName.substring(0, 1).toUpperCase()
                                + fieldName.substring(1);
            String fieldType = cProp[curParam].getConfigPropertyType();
            Method[] m = clsClass.getMethods();

            int i = 0;
            while (i < m.length
                   && (!m[i].getName().equals(methodName)
                       || m[i].getParameterTypes().length != 1
                       || (fieldType != null
                           && !(m[i].getParameterTypes())[0].getName().equals(fieldType)))
                   ) {
                i++;
            }
            if (i < m.length) {
                Class [] paramtype = m[i].getParameterTypes();
                Object[] param = new Object[1];

                String curValue = cProp[curParam].getConfigPropertyValue();
                if (setterLogger.isLoggable(BasicLevel.DEBUG)) {
                    setterLogger.log(BasicLevel.DEBUG, "Processing Field Name: " + fieldName
                            + " Type: " + fieldType + " Value: " + curValue);
                }

                if (paramtype[0].equals(java.lang.Integer.TYPE)
                    || paramtype[0].equals(java.lang.Integer.class)) {
                    param[0]  = new Integer(curValue);

                } else if (paramtype[0].equals(java.lang.Boolean.TYPE)
                           || paramtype[0].equals(java.lang.Boolean.class)) {
                    param[0]  = new Boolean(curValue);

                } else if (paramtype[0].equals(java.lang.Double.TYPE)
                           || paramtype[0].equals(java.lang.Double.class)) {
                    param[0]  = new Double(curValue);

                } else if (paramtype[0].equals(java.lang.Byte.TYPE)
                           || paramtype[0].equals(java.lang.Byte.class)) {
                    param[0]  = new Byte(curValue);

                } else if (paramtype[0].equals(java.lang.Short.TYPE)
                           || paramtype[0].equals(java.lang.Short.class)) {
                    param[0]  = new Short(curValue);

                } else if (paramtype[0].equals(java.lang.Long.TYPE)
                           || paramtype[0].equals(java.lang.Long.class)) {
                    param[0]  = new Long(curValue);

                } else if (paramtype[0].equals(java.lang.Float.TYPE)
                           || paramtype[0].equals(java.lang.Float.class)) {
                    param[0]  = new Float(curValue);

                } else if (paramtype[0].equals(java.lang.Character.TYPE)
                           || paramtype[0].equals(java.lang.Character.class)) {
                    param[0]  = new Character(curValue.charAt(0));

                } else if (paramtype[0].equals(java.lang.String.class)) {
                    param[0]  = curValue;
                    if (setterLogger.isLoggable(BasicLevel.DEBUG)) {
                        setterLogger.log(BasicLevel.DEBUG, "Calling String method with " + curValue);
                    }

                } else {
                    logger.log(BasicLevel.ERROR, "Type unsupported for setter method:"
                                + methodName);
                    throw new Exception("incorrect type for setter method ");
                }
                // invocation of the corresponding setter method on
                // class object instance
                try {
                    m[i].invoke(clsObj, param);
                } catch (Exception e) {
                    if (logger.isLoggable(BasicLevel.DEBUG)) {
                        logger.log(BasicLevel.DEBUG, "method "
                                + methodName
                                + " not found for " + rarFileName + "check its configuration ");
                    }
                }
                curParam++;
            } else {
                logger.log(BasicLevel.ERROR, "Method not found in class '" + clsClass + "': " + methodName);
                throw new Exception("method name '" + methodName + "' not found in class '" + clsClass + "'");
            }
        }
    }

    /**
     * Set the PoolParams and the JdbcConnParams, if set.
     * @param pParams PoolParamsDesc
     * @param jConnParams JdbcConnParamsDesc
     * @param pool ConnectionManagerPoolParams
     * @return ConnectionManagerPoolParams
     * @throws Exception any exception
     */
    public ConnectionManagerPoolParams configurePoolParams (final PoolParamsDesc pParams,
                                                            final JdbcConnParamsDesc jConnParams,
                                                            final ConnectionManagerPoolParams pool)
               throws Exception {

        ConnectionManagerPoolParams cmpp = null;
        if (pool == null) {
            cmpp = new ConnectionManagerPoolParams();
        } else {
            cmpp = new ConnectionManagerPoolParams(pool);
        }
        String tmpPool = null;
        try {
            if (pParams != null) {
                if (pParams.getPoolInit() != null) {
                    tmpPool = pParams.getPoolInit();
                    if (tmpPool != null && tmpPool.length() > 0) {
                        cmpp.setPoolInit(Integer.parseInt(tmpPool));
                    }
                }
                if (pParams.getPoolMin() != null) {
                    tmpPool = pParams.getPoolMin();
                    if (tmpPool != null && tmpPool.length() > 0) {
                        cmpp.setPoolMin(Integer.parseInt(tmpPool));
                    }
                }
                if (pParams.getPoolMax() != null) {
                    tmpPool = pParams.getPoolMax();
                    if (tmpPool != null && tmpPool.length() > 0) {
                        cmpp.setPoolMax(Integer.parseInt(tmpPool));
                    }
                }
                if (pParams.getPoolMaxAge() != null) {
                    tmpPool = pParams.getPoolMaxAge();
                    if (tmpPool != null && tmpPool.length() > 0) {
                        cmpp.setPoolMaxAge(Long.parseLong(tmpPool));
                    }
                }
                if (pParams.getPoolMaxAgeMinutes() != null) {
                    tmpPool = pParams.getPoolMaxAgeMinutes();
                    if (tmpPool != null && tmpPool.length() > 0) {
                        cmpp.setPoolMaxAgeMinutes(Integer.parseInt(tmpPool));
                    }
                }
                if (pParams.getPoolMaxOpentime() != null) {
                    tmpPool = pParams.getPoolMaxOpentime();
                    if (tmpPool != null && tmpPool.length() > 0) {
                        cmpp.setPoolMaxOpentime(Integer.parseInt(tmpPool));
                    }
                }
                if (pParams.getPoolMaxWaiters() != null) {
                    tmpPool = pParams.getPoolMaxWaiters();
                    if (tmpPool != null && tmpPool.length() > 0) {
                        cmpp.setPoolMaxWaiters(Integer.parseInt(tmpPool));
                    }
                }
                if (pParams.getPoolMaxWaittime() != null) {
                    tmpPool = pParams.getPoolMaxWaittime();
                    if (tmpPool != null && tmpPool.length() > 0) {
                        cmpp.setPoolMaxWaittime(Integer.parseInt(tmpPool));
                    }
                }
                if (pParams.getPoolSamplingPeriod() != null) {
                    tmpPool = pParams.getPoolSamplingPeriod();
                    if (tmpPool != null && tmpPool.length() > 0) {
                        cmpp.setPoolSamplingPeriod(Integer.parseInt(tmpPool));
                    }
                }
                if (pParams.getPstmtMax() != null) {
                    tmpPool = pParams.getPstmtMax();
                    if (tmpPool != null && tmpPool.length() > 0) {
                        cmpp.setPstmtMax(Integer.parseInt(tmpPool));
                    }
                }
            }
           if (jConnParams != null) {
               if (jConnParams.isJdbcConnSetUp()) {
                   cmpp.setJdbcConnSetUp(true);
                   if (jConnParams.getJdbcCheckLevel() != null) {
                       tmpPool = jConnParams.getJdbcCheckLevel();
                       if (tmpPool != null && tmpPool.length() > 0) {
                           cmpp.setJdbcConnLevel(Integer.parseInt(tmpPool));
                       }
                   }
                   if (jConnParams.getJdbcTestStatement() != null) {
                       cmpp.setJdbcConnTestStmt(jConnParams.getJdbcTestStatement());
                   }
               }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.log(BasicLevel.ERROR, "Invalid Pool parameter from jonas-ra.xml:  Ensure that numeric values are used. " + tmpPool);
            throw new Exception("incorrect pool parameter ");
        }
        return cmpp;
    }

    /**
     * Return the parsed XML object relative to the section
     *
     * @param jonasConn JonasConnectorDesc object
     * @param id String id of the section
     * @param idOffset int offset within the section
     * @param oType String type of section
     * @return Object of parsed XML object
     * @throws Exception if the element is out of bound
     */
    public Object getJonasXML(final JonasConnectorDesc jonasConn,
                              final String id, final int idOffset, final String oType) throws Exception {
        try {
            Object obj = null;
            if (JCD.equals(oType)) {
                obj = jonasConn.getJonasConnectionDefinitionList().get(idOffset);
            } else if (JAS.equals(oType)) {
                obj = jonasConn.getJonasActivationspecList().get(idOffset);
            } else if (JAO.equals(oType)) {
                obj = jonasConn.getJonasAdminobjectList().get(idOffset);
            }
            return obj;
        } catch (IndexOutOfBoundsException e) {
            throw new Exception("Element " + oType + ", " + idOffset + " is not found in the jonas-ra.xml", e);
        }
    }

    /**
     * Return the JCA Managed Connection Factory name
     * @param jndiName String of jndi name
     * @return String of JCA Managed Connection Factory name
     */
    public String getJcaMcfName(final String jndiName) {
        return jndiName;
    }
}
