/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * Contact: jonas-team@objectweb.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.objectweb.jonas.container;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;

import org.objectweb.jonas.dbm.DataBaseServiceImpl;
import org.objectweb.jonas.mail.MailServiceImpl;
import org.objectweb.jonas.management.j2eemanagement.J2EEManagedObject;
import org.objectweb.jonas.resource.ResourceServiceImpl;
import org.objectweb.jonas.service.ServiceManager;
import org.objectweb.jonas_ejb.container.JFactory;
import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
import org.objectweb.jonas_ejb.deployment.api.EntityJdbcCmp1Desc;
import org.objectweb.jonas_ejb.deployment.api.EntityJdbcCmp2Desc;
import org.objectweb.jonas_lib.deployment.api.ResourceEnvRefDesc;
import org.objectweb.jonas_lib.deployment.api.ResourceRefDesc;

/**
 * This class implements the EJB type specified in JSR77
 * @author Adriana Danes
 *
 */
public class EJB extends J2EEManagedObject {
    /**
     * The Bean to manage
     */
    protected JFactory ejbToManage = null;
    protected BeanDesc desc = null;
    protected String fileName = null;

    public EJB(String objectName, JFactory ejbToManage) {
        super(objectName);
        this.ejbToManage = ejbToManage;
        this.fileName = ejbToManage.getContainer().getExternalFileName();
        this.desc = ejbToManage.getDeploymentDescriptor();
    }


    /**
     * @return String The Name of this JFactory
     */
    public String getName() {
        return desc.getEjbName();
    }

    /**
     * @return Ejb File Name
     */
    public String getFileName() {
        return fileName;
    }

    /**
     * Construct Hashtable containing for each ResourceRef jndi name
     * its corresponding the ResourceAdapter MBean OBJECT_NAME.
     * @return Hashtable table
     */
    public Hashtable getAllJdbcResourceAdapterName() {
        Hashtable result = new Hashtable();
        ArrayList jdbcResourceRefJndiNames = getAllJdbcResourceRefJndiNames();
        if (jdbcResourceRefJndiNames.isEmpty()) {
            // return empty result
            return result;
        }
        ServiceManager sm;
        try {
            sm = ServiceManager.getInstance();
        } catch (Exception e) {
            // Can't get the ServiceManger, return empty result
            return result;
        }
        ResourceServiceImpl resServ = null;
        try {
            resServ = (ResourceServiceImpl) sm.getRarService();
            // Resource Service activated
            // For each jndi name we look for a JDBC ResourceAdapater having this jndi name
            // This code can be improved by calling one the getJDBCResourceAdapaters()
            // outside the for loop. In this case, in order to get the 'jndiName' attribute's
            // the EJB object (this object) needs a reference ti the mbeanServer.
            for (Iterator it = jdbcResourceRefJndiNames.iterator(); it.hasNext();) {
                String jndiName = (String) it.next();
                String raON = resServ.getJDBCResourceAdapater(jndiName);
                if (raON != null) {
                    // found JDBC ResourceAdapater with the given jndi name
                    result.put(jndiName, raON);
                }
            }
        } catch (Exception e) {
            // Resource service not available or exception raised when
            // browsing RA MBeans
        }
        return result;
    }
    /**
     * Construct Hashtable containing for each ResourceRef jndi name
     * its corresponding the datasource name or empty String if no
     * corresponding datasource was found.
     * @return Hashtable table
     */
    public Hashtable getAllDataSourceName() {
        Hashtable result = new Hashtable();
        ArrayList jdbcResourceRefJndiNames = getAllJdbcResourceRefJndiNames();
        if (jdbcResourceRefJndiNames.isEmpty()) {
            // return empty result
            return result;
        }
        ServiceManager sm;
        try {
            sm = ServiceManager.getInstance();
        } catch (Exception e) {
            // Can't get the ServiceManger, return empty result
            return result;
        }
        DataBaseServiceImpl bdmServ = null;
        try {
            bdmServ = (DataBaseServiceImpl) sm.getDataBaseService();
            // Dbm Service activated
            for (Iterator it = jdbcResourceRefJndiNames.iterator(); it.hasNext();) {
                String jndiName = (String) it.next();
                String datasourceName = bdmServ.getDatasourceName(jndiName);
                if (datasourceName != null) {
                    result.put(jndiName, datasourceName);
                }
            }
        } catch (Exception e) {
        }
        return result;
    }

    private ArrayList getAllJdbcResourceRefJndiNames() {
        ArrayList jndiNames = new ArrayList();
        String jndiName = null;
        // find the resource refs
        ResourceRefDesc[] rrDesc = desc.getResourceRefDesc();
        for (int i = 0; i < rrDesc.length; i++) {
            if (rrDesc[i].isJdbc()) {
                // get the DD provided JNDI name
                jndiName = rrDesc[i].getJndiName();
                jndiNames.add(jndiName);
            }
        }

        // if the EJB is an entity with CMP, we have to find jndi name in the jdbc_mapping
        if (desc instanceof EntityJdbcCmp1Desc) {
            // in case of CMP1 :
            EntityJdbcCmp1Desc jdbcCmp1Desc = (EntityJdbcCmp1Desc) desc;
            jndiName = jdbcCmp1Desc.getDatasourceJndiName();
            jndiNames.add(jndiName);
        } else if (desc instanceof EntityJdbcCmp2Desc) {
            // in case of CMP2 :
            EntityJdbcCmp2Desc jdbcCmp2Desc = (EntityJdbcCmp2Desc) desc;
            jndiName = jdbcCmp2Desc.getDatasourceJndiName();
            jndiNames.add(jndiName);
        }
        return jndiNames;
    }

    /**
     * @return Set The Name set of the Connection Factories
     */
    public Set getAllJMSConnectionFactoryName(){
        Set result= new HashSet();
        ResourceRefDesc[] rrDesc = desc.getResourceRefDesc();
        for (int i = 0; i < rrDesc.length; i ++) {
            if ("javax.jms.TopicConnectionFactory".equals(rrDesc[i].getTypeName())
                    || "javax.jms.QueueConnectionFactory".equals(rrDesc[i].getTypeName())
                    || "javax.jms.ConnectionFactory".equals(rrDesc[i].getTypeName())) {
                result.add(rrDesc[i].getJndiName());
            }
        }
        return result;
    }

    /**
     * @return Hashtable which maps the JNDI names provided by the DD to the Session Mail factyory resources
     * known by the Mail Service
     */
    public Hashtable getAllMailFactorySName(){
        Hashtable result = new Hashtable();
        MailServiceImpl mailServ = null;
        try {
            // Modified for use with the gcj compiler
            ServiceManager sm = ServiceManager.getInstance();
            mailServ = (MailServiceImpl) sm.getMailService();
        } catch(Exception e) {
            // Mail Service not available, mailServ null
        }
        String jndiName = null; // name provided by the DD
        String factoryName = null; // resource name

        ResourceRefDesc[] rrDesc = desc.getResourceRefDesc();
        for (int i = 0; i < rrDesc.length; i ++) {
            if ("javax.mail.Session".equals(rrDesc[i].getTypeName())) {
                // The Bean uses a javax.mail.Session resource

                // get the DD provided JNDI name
                jndiName = rrDesc[i].getJndiName();

                // try to get the mail service
                if (mailServ != null) {
                    // get the resource factory name (maybe null if no resource factory registered under the jndiName)
                    factoryName = mailServ.getFactoryName(jndiName);
                    if (factoryName != null)
                        result.put(jndiName, factoryName);
                    else
                        result.put(jndiName, "");
                } else {
                    // Mail Service not available
                    result.put(jndiName, "");
                }
            }
        }
        return result;
    }

    /**
     * @return Hashtable which maps the JNDI names provided by the DD to the MimePartDataSource Mail factyory resources
     * known by the Mail Service
     */
    public Hashtable getAllMailFactoryMName() {
        Hashtable result = new Hashtable();
        MailServiceImpl mailServ = null;
        try {
            // Modified for use with the gcj compiler
            ServiceManager sm = ServiceManager.getInstance();
            mailServ = (MailServiceImpl) sm.getMailService();
        } catch(Exception e) {
            // Mail Service not available, mailServ null
        }
        String jndiName = null;
        String factoryName = null;

        ResourceRefDesc[] rrDesc = desc.getResourceRefDesc();
        for (int i = 0; i < rrDesc.length; i ++) {
            if ("javax.mail.internet.MimePartDataSource".equals(rrDesc[i].getTypeName())) {
                // the Bean uses a javax.mail.internet.MimePartDataSource resource

                // get the DD provided JNDI name
                jndiName = rrDesc[i].getJndiName();

                if (mailServ != null) {
                    // get the resource factory name (maybe bull if no resource factory registered under the jndiName)
                    factoryName = mailServ.getFactoryName(jndiName);
                    if (factoryName != null)
                        result.put(jndiName, factoryName);
                    else
                        result.put(jndiName, "");
                } else {
                    // Mail Service not available
                    result.put(jndiName, "");
                }
            }
        }
        return result;
    }

    /**
     * @return Set The Name set of the JMS Destinations
     */
    public Set getAllJMSDestinationName(){
        Set result= new HashSet();
        ResourceEnvRefDesc[] rrDesc = desc.getResourceEnvRefDesc();
        for (int i = 0; i < rrDesc.length; i ++) {
            if ((rrDesc[i].getType() == javax.jms.Topic.class )
                    ||(rrDesc[i].getType() == javax.jms.Queue.class )) {
                result.add(rrDesc[i].getJndiName());
            }
        }
        return result;
    }

    /**
     * @return Set The URL ressources used by the bean
     */
    public Set getAllURLs() {
        Set result= new HashSet();
        ResourceRefDesc[] rrDesc = desc.getResourceRefDesc();
        for (int i = 0; i < rrDesc.length; i ++) {
            if ("java.net.URL".equals(rrDesc[i].getTypeName())) {
                result.add(rrDesc[i].getJndiName());
            }
        }
        return result;
    }

    /**
     * @return The current instance pool size
     */
    public  int getPoolSize(){
        return ejbToManage.getPoolSize();
    }

    /**
     * @return min-pool-size value
     */
    public int getMinPoolSize() {
        return ejbToManage.getMinPoolSize();
    }

    /**
     * @return max-cache-size value
     */
    public int getMaxCacheSize() {
        return ejbToManage.getMaxCacheSize();
    }

    /**
     * @return  nb of instances (current cache size)
     */
    public int getCacheSize() {
        return ejbToManage.getCacheSize();
    }
    /**
     * Reduce number of instances
     */
    public void reduceCacheSize() {
        ejbToManage.reduceCache();
    }
    /**
     * @return String the  JFactory Class
     */
    public String getEjbClass(){
        return desc.getEjbClass().getName();
    }

    /**
     * @return String the displayName of the bean, or bean name if not defined.
     */
    public String getDisplayName() {
        return desc.getDisplayName() != null ? desc.getDisplayName() : desc.getEjbName();
    }

    /**
     * @return String the JNDI Name of the bean.
     */
    public String getJndiName() {
        return desc.getJndiName();
    }

    /**
     * @return String the HomeClass of the bean.
     */
    public String getHomeClass() {
        if (desc.getHomeClass() != null) {
            return desc.getHomeClass().getName();
        } else {
            return null;
        }
    }

    /**
     * @return String the RemoteClass of the bean.
     */
    public String getRemoteClass() {
        if (desc.getRemoteClass() != null) {
            return desc.getRemoteClass().getName();
        } else {
            return null;
        }
    }

    /**
     * @return String the LocalHomeClass of the bean.
     */
    public String getLocalHomeClass() {
        if (desc.getLocalHomeClass() != null) {
            return desc.getLocalHomeClass().getName();
        } else {
            return null;
        }
    }

    /**
     * @return String the LocalClass of the bean.
     */
    public String getLocalClass() {
        if (desc.getLocalClass() != null) {
            return desc.getLocalClass().getName();
        } else {
            return null;
        }
    }

}
