/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2008 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.deployment.ejb;

import org.objectweb.util.monolog.api.BasicLevel;
import org.ow2.jonas.deployment.common.DeploymentDescException;
import org.ow2.jonas.deployment.common.xml.JLinkedList;
import org.ow2.jonas.deployment.ejb.xml.AssemblyDescriptor;
import org.ow2.jonas.deployment.ejb.xml.JonasSession;
import org.ow2.jonas.deployment.ejb.xml.Session;

/**
 * Base class to hold meta-information related to a session bean.
 *
 * @author Christophe Ney [cney@batisseurs.com] : Initial developer
 * @author Helene Joanin : unsetting transaction attribute set to a default value.
 */
public abstract class SessionDesc extends BeanDesc {

    protected int transactionType;
    int sessionTimeout = 0;
    boolean monitoringEnabled = false;
    int warningThreshold = 0;
    boolean  monitoringSettingsDefinedInDD = false;

    /**
     * constructor: called when the DeploymentDescriptor is read. Currently,
     * called by both GenIC and createContainer.
     */
    public SessionDesc(final ClassLoader classLoader, final Session ses,
            final AssemblyDescriptor asd, final JonasSession jSes, final JLinkedList jMDRList,
            final String filename) throws DeploymentDescException {

        super(classLoader, ses, jSes, asd, jMDRList, filename);

        // session timeout
        if (jSes.getSessionTimeout() != null) {
            String tstr = jSes.getSessionTimeout();
            Integer tval = new Integer(tstr);
            sessionTimeout = tval.intValue();
        }

        //monitoring-enabled
        if (jSes.getMonitoringEnabled()!=null) {
            monitoringSettingsDefinedInDD = true;
            if (jSes.getMonitoringEnabled().equalsIgnoreCase("True")) {
                monitoringEnabled = true;
            } else if (jSes.getMonitoringEnabled().equalsIgnoreCase("False")) {
                monitoringEnabled = false;
            } else {
                throw new DeploymentDescException("Invalid monitoringEnabled value for bean " + this.ejbName);
            }
        }

        //warning-threshold
        if (jSes.getWarningThreshold() != null) {
            monitoringSettingsDefinedInDD = true;
            String tstr = jSes.getWarningThreshold();
            Integer tval = new Integer(tstr);
            warningThreshold = tval.intValue();
        }

        // min-pool-size
        if (jSes.getMinPoolSize() != null) {
            String tstr = jSes.getMinPoolSize();
            Integer tval = new Integer(tstr);
            poolMin = tval.intValue();
        }

        // max-cache-size
        if (jSes.getMaxCacheSize() != null) {
            String tstr = jSes.getMaxCacheSize();
            Integer tval = new Integer(tstr);
            cacheMax = tval.intValue();
        }

        // bean or container managed transaction
        if ("Bean".equals(ses.getTransactionType())) {
            transactionType = BEAN_TRANSACTION_TYPE;
        } else if ("Container".equals(ses.getTransactionType())) {
            transactionType = CONTAINER_TRANSACTION_TYPE;
        } else {
            throw new DeploymentDescException(
                    "Invalid transaction-type content for ejb-name " + ejbName);
        }
    }

    /**
     * check that trans-attribute is valid for bean
     */
    @Override
    protected void checkTxAttribute(final MethodDesc md)
            throws DeploymentDescException {
        java.lang.reflect.Method m = md.getMethod();
        if (getTransactionType() == CONTAINER_TRANSACTION_TYPE) {
            // tx-attribute must be set for methods of remote interface
            // excluding the methods of the javax.ejb.EJBObject interface
            if ((md.getTxAttribute() == MethodDesc.TX_NOT_SET)
                    && javax.ejb.EJBObject.class.isAssignableFrom(m
                            .getDeclaringClass())
                    && !javax.ejb.EJBObject.class.equals(m.getDeclaringClass())) {
                // trace a warning and set the tx-attribute with the default
                // value
                logger.log(BasicLevel.WARN,
                        "trans-attribute missing for method " + m.toString()
                                + " in session bean " + getEjbName()
                                + " (set to the default value "
                                + MethodDesc.TX_STR_DEFAULT_VALUE + ")");
                md.setTxAttribute(MethodDesc.TX_STR_DEFAULT_VALUE);
            }
            // tx-attribute must not be set for methods of home interface
            if ((md.getTxAttribute() != MethodDesc.TX_NOT_SET)
                    && javax.ejb.EJBHome.class.isAssignableFrom(m
                            .getDeclaringClass())
                    && ((md.getTxAttributeStatus() == MethodDesc.APPLY_TO_CLASS)
                            || (md.getTxAttributeStatus() == MethodDesc.APPLY_TO_CLASS_METHOD_NAME) || (md
                            .getTxAttributeStatus() == MethodDesc.APPLY_TO_CLASS_METHOD))) {
                logger.log(BasicLevel.WARN,
                        "trans-attribute must not be specified for home interface's method "
                                + m.toString() + " in session bean "
                                + getEjbName());
            }
        } else {
            if (md.getTxAttribute() != MethodDesc.TX_NOT_SET) {
                throw new DeploymentDescException(md.getTxAttributeName()
                        + " is not a valid trans-attribute for method "
                        + m.toString() + " in session bean " + getEjbName());
            }
        }
    }

    /**
     * Get session transaction management type. <BR>
     *
     * @return transaction type value within
     *         BEAN_TRANSACTION_TYPE,CONTAINER_TRANSACTION_TYPE
     */
    public int getTransactionType() {
        return transactionType;
    }

    /**
     * Returns true if bean managed transaction. (used by JOnAS Server)
     */
    public boolean isBeanManagedTransaction() {
        return (transactionType == BEAN_TRANSACTION_TYPE);
    }

    /**
     * Get the session timeout value
     */
    public int getSessionTimeout() {
        return sessionTimeout;
    }

    /**
     * Check that the bean descriptor is valid
     *
     * @exception DeploymentDescException
     *                thrown for non-valid bean
     */
    @Override
    public void check() throws DeploymentDescException {
        super.check();
        // for BEAN_TRANSACTION_TYPE transactions ejbClass should not implement
        // javax.ejb.SessionSynchronization
        if ((getTransactionType() == BEAN_TRANSACTION_TYPE)
                && (javax.ejb.SessionSynchronization.class
                        .isAssignableFrom(ejbClass))) {
            throw new DeploymentDescException(
                    ejbClass.getName()
                            + " should NOT manage transactions and implement javax.ejb.SessionSynchronization");
        }
    }

    /**
     * String representation of the object for test purpose
     *
     * @return String representation of this object
     */
    @Override
    public String toString() {
        StringBuffer ret = new StringBuffer();
        ret.append(super.toString());
        ret.append("\ngetTransactionType()" + TRANS[getTransactionType()]);
        ret.append("\nsessionTimeout = " + sessionTimeout);
        return ret.toString();
    }

    public boolean isMonitoringSettingsDefinedInDD() {
        return monitoringSettingsDefinedInDD;
    }

    public void setWarningThreshold(final int warningThreshold) {
        this.warningThreshold = warningThreshold;
    }

    public boolean isMonitoringEnabled() {
        return monitoringEnabled;
    }

    public int getWarningThreshold() {
        return warningThreshold;
    }

}

