/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://glassfish.dev.java.net/public/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */

package com.sun.enterprise.connectors.system;

import com.sun.enterprise.deployment.ConnectorDescriptor;
import com.sun.enterprise.deployment.EjbMessageBeanDescriptor;
import com.sun.enterprise.deployment.runtime.BeanPoolDescriptor;
import com.sun.enterprise.deployment.EnvironmentProperty;

import com.sun.enterprise.connectors.*;
import com.sun.enterprise.connectors.inflow.*;
import com.sun.enterprise.connectors.util.JmsRaUtil; 
import com.sun.logging.LogDomains;
import com.sun.enterprise.config.ConfigBean;
import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.config.ConfigException;
import com.sun.enterprise.server.ApplicationServer;
import com.sun.enterprise.server.ResourcesUtil;

import com.sun.enterprise.server.ServerContext;
import com.sun.enterprise.config.serverbeans.ClusterHelper;
import com.sun.enterprise.config.serverbeans.JavaConfig;
import com.sun.enterprise.config.serverbeans.JdbcConnectionPool;
import com.sun.enterprise.config.serverbeans.JmsAvailability;
import com.sun.enterprise.config.serverbeans.Resources;
import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
import com.sun.enterprise.config.serverbeans.ConnectorResource;
import com.sun.enterprise.config.serverbeans.AdminObjectResource;
import com.sun.enterprise.config.serverbeans.ConnectorConnectionPool;
import com.sun.enterprise.config.serverbeans.ElementProperty;
import com.sun.enterprise.config.serverbeans.AvailabilityService;
import com.sun.enterprise.config.serverbeans.JmsService;
import com.sun.enterprise.config.serverbeans.JmsHost;
import com.sun.enterprise.config.serverbeans.AdminService;
import com.sun.enterprise.config.serverbeans.JmxConnector;
import com.sun.enterprise.config.serverbeans.ServerHelper;
import com.sun.enterprise.instance.ServerManager;
import com.sun.enterprise.jms.IASJmsUtil;
import com.sun.enterprise.jms.JmsProviderLifecycle;
import com.sun.enterprise.util.SystemPropertyConstants;
import com.sun.enterprise.util.i18n.StringManager;

import java.rmi.Naming;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.resource.spi.ManagedConnectionFactory;
import javax.resource.spi.ResourceAdapter;

/** 
 * Represents an active JMS resource adapter. This does 
 * additional configuration to ManagedConnectionFactory
 * and ResourceAdapter java beans.
 * 
 * XXX: For code management reasons, think about splitting this
 * to a preHawk and postHawk RA (with postHawk RA extending preHawk RA).  
 * 
 * @author Binod P.G, Sivakumar Thyagarajan
 */
public class ActiveJmsResourceAdapter extends ActiveInboundResourceAdapter {

    static Logger logger = LogDomains.getLogger(LogDomains.RSR_LOGGER);

    private final String SETTER = "setProperty";
    private static final String SEPARATOR = "#";    
    private static final String MQ_PASS_FILE_PREFIX = "asmq";
    private static final String MQ_PASS_FILE_KEY = "imq.imqcmd.password=";

    //RA Javabean properties.
    public static final String CONNECTION_URL = "ConnectionURL";
    private final String RECONNECTENABLED = "ReconnectEnabled";
    private final String RECONNECTINTERVAL = "ReconnectInterval";
    private final String RECONNECTATTEMPTS = "ReconnectAttempts";
    private static final String GROUPNAME = "GroupName";
    private static final String CLUSTERCONTAINER = "InClusteredContainer";
    
    //Lifecycle RA JavaBean properties
    public static final String BROKERTYPE="BrokerType";
    private static final String BROKERINSTANCENAME="BrokerInstanceName";
    private static final String BROKERBINDADDRESS="BrokerBindAddress";
    private static final String BROKERPORT="BrokerPort";
    private static final String BROKERARGS="BrokerArgs";
    private static final String BROKERHOMEDIR="BrokerHomeDir";
    private static final String BROKERVARDIR="BrokerVarDir";
    private static final String BROKERJAVADIR="BrokerJavaDir";
    private static final String BROKERSTARTTIMEOUT="BrokerStartTimeOut";
    private static final String ADMINUSERNAME="AdminUserName";
    private static final String ADMINPASSWORD="AdminPassword";
    private static final String ADMINPASSFILE="AdminPassFile";

    private static final String MASTERBROKER="MasterBroker";
    
    //JMX properties
    private static final String JMXSERVICEURL="JMXServiceURL";
    private static final String JMXSERVICEURLLIST="JMXServiceURLList";
    private static final String JMXCONNECTORENV="JMXConnectorEnv";
    private static final String USEJNDIRMISERVICEURL="useJNDIRMIServiceURL";
    private static final String RMIREGISTRYPORT="RmiRegistryPort";
    private static final String USEEXTERNALRMIREGISTRY="startRMIRegistry";
    private static final String SSLJMXCONNECTOR="SslJMXConnector";
    
    //Availability properties
    private static final String HAREQUIRED = "HARequired";
    private static final String CLUSTERID = "ClusterId";
    private static final String BROKERID = "BrokerId";
    private static final String PINGINTERVAL = "PingInterval";
    private static final String DBTYPE = "DBType";
    private static final String DBTYPE_HADB="hadb";
    private static final String BROKERENABLEHA = "BrokerEnableHA";
    
    private static final String DB_HADB_PROPS = "DBProps";
    //properties within DB_PROPS
    private static final String DB_HADB_USER = "hadb.user";
    private static final String DB_HADB_PASSWORD = "hadb.password";
    private static final String DB_HADB_DRIVERCLASS = "hadb.driverClass";
    private static final String DS_HADB_PROPS = "DSProps";
    //properties within DS_PROPS
    private static final String DS_HADB_SERVERLIST = "hadb.serverList";
    
    //Not used now.
    private final String CONTAINER = "InAppClientContainer";

    //Activation config properties of MQ resource adapter.
    public static String DESTINATION        = "Destination";
    public static String DESTINATION_TYPE   = "DestinationType";
    private static String SUBSCRIPTION_NAME  = "SubscriptionName";
    private static String CLIENT_ID          = "ClientID";
    public static String PHYSICAL_DESTINATION  = "Name";
    private static String MAXPOOLSIZE  = "EndpointPoolMaxSize";
    private static String MINPOOLSIZE  = "EndpointPoolSteadySize";
    private static String RESIZECOUNT  = "EndpointPoolResizeCount";
    private static String RESIZETIMEOUT  = "EndpointPoolResizeTimeout";
    private static String REDELIVERYCOUNT  = "EndpointExceptionRedeliveryAttempts";
    public static String ADDRESSLIST  = "AddressList";
    private static String ADRLIST_BEHAVIOUR  = "AddressListBehavior";
    private static String ADRLIST_ITERATIONS  = "AddressListIterations";
    private static final String MDBIDENTIFIER = "MdbName";

    //MCF properties
    private static final String MCFADDRESSLIST = "MessageServiceAddressList";

    private StringManager sm = 
        StringManager.getManager(ActiveJmsResourceAdapter.class);

    MQAddressList urlList = null;

    //Properties in domain.xml for HADB JDBC connection pool (for HA)
    private static final String DUSERNAME = "User";
    private static final String DPASSWORD = "Password";
    private static final String DSERVERLIST = "ServerList";
    private static final String HADB_CONNECTION_URL_PREFIX = "jdbc:sun:hadb:";
    
    //Lifecycle properties
    public static final String EMBEDDED="EMBEDDED";
    public static final String LOCAL="LOCAL";
    public static final String REMOTE="REMOTE";

    private final String DEFAULT_STORE_POOL_JNDI_NAME = "jdbc/hastore";

    // Both the properties below are hacks. These will be changed later on.
    private static String MQRmiPort = 
        System.getProperty("com.sun.enterprise.connectors.system.MQRmiPort");
    private static final String DASRMIPORT = "31099";

    private Properties dbProps = null;
    private Properties dsProps = null;
    private String brokerInstanceName = null;
        
    private File mqPassFile = null;
        
    /**
     * Constructor for an active Jms Adapter.
     * 
     * @param ra ResourceAdapter Javabean.
     * @param desc Deployment descriptor object
     * @param moduleName Name of the resource adapter.
     * @parm jcl Class Loader.
     * @throw ConnectorRuntimeException in case of an exception.
     */
    public ActiveJmsResourceAdapter(
            ResourceAdapter ra, ConnectorDescriptor desc, String moduleName, 
            ClassLoader jcl) throws ConnectorRuntimeException {
        super(ra,desc,moduleName,jcl);
        
        //Now that the RA has been started, delete the temp passfile
        if (mqPassFile != null) {
            mqPassFile.delete();
        }
    }

    /**
     * Loads RA configuration for MQ Resource adapter.
     * 
     * @throw ConnectorRuntimeException in case of an exception.
     */
    protected void loadRAConfiguration() throws ConnectorRuntimeException{
        if (ConnectorRuntime.getRuntime().getEnviron() 
                                       == ConnectorRuntime.SERVER) {
            // Check whether MQ has started up or not.
            try {
                if (!JmsProviderLifecycle.shouldUseMQRAForLifecycleControl()) {
                    JmsProviderLifecycle.checkProviderStartup();
                } else {
                	setLifecycleProperties();
                }
    	    } catch (Exception e) {
                ConnectorRuntimeException cre = new ConnectorRuntimeException
                                                        (e.getMessage());
    	        throw (ConnectorRuntimeException) cre.initCause(e);
    	    }
            
            setMdbContainerProperties();
            setJmsServiceProperties(null);
            setClusterRABeanProperties();
            setAvailabilityProperties();
        } else {
            setAppClientRABeanProperties();
        }
        super.loadRAConfiguration();
        postRAConfiguration();
    }

    /*
     * Set Availability related properties
     * If EE: If JMS availability true set availability properties
     * If shared hadb : get HADB CCP information and set accordingly
     * If not shared : read configured pool information and set.
     */
    private void setAvailabilityProperties() throws ConnectorRuntimeException {
        try {
            ConfigContext ctx = ApplicationServer.getServerContext().getConfigContext();
            AvailabilityService as = ServerBeansFactory.getConfigBean(ctx).getAvailabilityService();
            if (as == null) {
                logFine("Availability Service is null. Not setting HA attributes");
                return;
            }
            
            //Only if JMS availability is true
            if (isJMSAvailabilityOn(as)) {
                ConnectorDescriptor cd = getDescriptor();
                //Set HARequired as true - irrespective of whether it is REMOTE or
                //LOCAL
                EnvironmentProperty envProp1 = new EnvironmentProperty (
                                            HAREQUIRED , "true","HA Required", 
                                           "java.lang.String");
                setProperty(cd, envProp1);
                
                JmsService jmsService = ServerBeansFactory.getConfigBean(ctx).
                                                                getJmsService();
                if (isClustered()) {
                    if (jmsService.getType().equals(REMOTE)) {
                        //If REMOTE, the broker cluster instances already have 
                        //been configured with the right properties.
                        return;
                    } else {
                        //LOCAL/EMBEDDED instances in a cluster.
                        String clusterName = getMQClusterName();
                        EnvironmentProperty envProp2 = new EnvironmentProperty (
                                    CLUSTERID , clusterName,"Cluster Id", 
                                    "java.lang.String");
                        setProperty(cd, envProp2);
                        
                        if(brokerInstanceName == null) {
                            brokerInstanceName = getBrokerInstanceName(jmsService); 
                        }
                        EnvironmentProperty envProp3 = new EnvironmentProperty (
                                    BROKERID , brokerInstanceName,"Broker Id", 
                                    "java.lang.String");
                        setProperty(cd, envProp3);
                        
                        
                        EnvironmentProperty envProp4 = new EnvironmentProperty (
                                        DBTYPE , DBTYPE_HADB,"DBType", 
                                        "java.lang.String");
                        setProperty(cd, envProp4);

                        /*
                         * The broker has a property to control whether 
                         * it starts in HA mode or not and that's represented on 
                         * the RA by BrokerEnableHA.
                         * On the MQ Client connection side it is HARequired - 
                         * this does not control the broker, it just is a client 
                         * side requirement.
                         * So for AS EE, if BrokerType is LOCAL or EMBEDDED, 
                         * and AS HA is enabled for JMS then both these must be 
                         * set to true.
                         */
                        EnvironmentProperty envProp5 = new EnvironmentProperty (
                                        BROKERENABLEHA , "true",
                                        "BrokerEnableHA flag","java.lang.Boolean");
                        setProperty(cd, envProp5);
                        
                        //get pool name
                        String poolJNDIName = as.getJmsAvailability().getMqStorePoolName();
                        //If no MQ store pool name is specified, use default poolname
                        //XXX: default pool name is jdbc/hastore but asadmin
                        //configure-ha-cluster creates a resource called 
                        //"jdbc/<asclustername>-hastore" which needs to be used.
                        if (poolJNDIName == null || poolJNDIName =="" ) {
                            //get Web container's HA store's pool name
                            poolJNDIName = as.getWebContainerAvailability().
                                                getHttpSessionStorePoolName();
                            logFine("HTTP Session store pool jndi name " +
                                    "is " + poolJNDIName);
                        }
                        //XXX: request HADB team mq-store-pool name to be 
                        //populated as part of configure-ha-cluster

                        JdbcConnectionPool jdbcConPool = getJDBCConnectionPoolInfo(
                                                            poolJNDIName);
                        //DBProps: compute values from pool object
                        String userName = getPropertyFromPool(jdbcConPool, DUSERNAME);
                        logFine("HA username is " + userName);
                        
                        String password = getPropertyFromPool(jdbcConPool, DPASSWORD);
                        logFine("HA Password is " + password);
                        
                        String driverClass = jdbcConPool.getDatasourceClassname();
                        logFine("HA driverclass" + driverClass);
                        
                        dbProps = new Properties();
                        dbProps.setProperty(DB_HADB_USER, userName);
                        dbProps.setProperty(DB_HADB_PASSWORD, password);
                        dbProps.setProperty(DB_HADB_DRIVERCLASS, driverClass);
                        
                        //DSProps: compute values from pool object
                        String serverList = getPropertyFromPool(jdbcConPool, DSERVERLIST);
                        logFine("HADB server list is " + serverList);
                        dsProps = new Properties();

                        if (serverList != null) {
                            dsProps.setProperty(DS_HADB_SERVERLIST, serverList);
                        } else {
                            logger.warning("ajra.incorrect_hadb_server_list");
                        }
                        
                        //set all other properties in dsProps as well.
                        Properties p = getDSPropertiesFromThePool(jdbcConPool);
                        Iterator iterator = p.keySet().iterator();
                        while (iterator.hasNext()) {
                            String key = (String) iterator.next();
                            String val = (String)p.get(key);
                            dsProps.setProperty(key, val);
                        }
                    }
                } else {
                    //ignore. Not clustered.
                    logFine("Instance not clustered. Not setting HA " +
                    "attributes");
                }
            }
        } catch (ConfigException e) {
            ConnectorRuntimeException crex = new ConnectorRuntimeException(
                            e.getMessage());
            throw (ConnectorRuntimeException)crex.initCause(e);
        }
    }
    
    /*
     * Gets all the other [apart from serverlist] DataSource properties from 
     * the HADB JDBC connection pool.
     */
    private Properties getDSPropertiesFromThePool(JdbcConnectionPool jdbcConPool) {
        Properties p = new Properties();
        ElementProperty[] elemProp = jdbcConPool.getElementProperty();
        Set<String> excludeList = new HashSet<String>();
        excludeList.add(DUSERNAME);
        excludeList.add(DPASSWORD);
        excludeList.add(DSERVERLIST);
        
        for(ElementProperty e: elemProp) {
            String propName = e.getAttributeValue("name");
            if (!excludeList.contains(propName)) {
                p.setProperty(propName, e.getAttributeValue("value"));
            }
        }
        logFine("Additional DataSource properties from pool " 
                        + jdbcConPool.getName() + " are " + p);
        return p;
    }

    /**
     * Method to perform any post RA configuration action by derivative subclasses.
     * For example, this method is used by <code>ActiveJMSResourceAdapter</code>
     * to set unsupported javabean property types on its RA JavaBean runtime 
     * instance. 
     * @throws ConnectorRuntimeException
     */
    protected void postRAConfiguration() throws ConnectorRuntimeException {
        //Set all non-supported javabean property types in the JavaBean
        try {
            if (dbProps != null) {
                Method[] mthds = this.resourceadapter_.getClass().getMethods();
                for (int i = 0; i < mthds.length; i++) {
                    if(mthds[i].getName().equalsIgnoreCase("set" + DB_HADB_PROPS)) {
                        logFine("Setting property:" + DB_HADB_PROPS 
                                        + "=" + dbProps.toString());
                        mthds[i].invoke(this.resourceadapter_, 
                                        new Object[]{dbProps});
                    } else if(mthds[i].getName().equalsIgnoreCase("set" + DS_HADB_PROPS)) {
                        logFine("Setting property:" + DS_HADB_PROPS 
                                        + "=" + dsProps.toString());
                        mthds[i].invoke(this.resourceadapter_, new Object[]{dsProps});
                    }
                }
            }
        } catch (Exception e) {
            ConnectorRuntimeException crex = new ConnectorRuntimeException(
                            e.getMessage());
            throw (ConnectorRuntimeException)crex.initCause(e);
        }
    }
    
    private String getPropertyFromPool(JdbcConnectionPool jdbcConPool, 
                    String poolPropertyName) {
        String poolPropertyValue = null;
        if(jdbcConPool == null) {
            return null;
        }
        ElementProperty[] props = jdbcConPool.getElementProperty();
        for (int i = 0; i < props.length; i++) {
            String name = props[i].getAttributeValue("name");
            String value = props[i].getAttributeValue("value");
            if (name.equalsIgnoreCase(poolPropertyName)) {
            //if (name.equalsIgnoreCase("username")) {
                poolPropertyValue = value; 
            }
        }
        logFine("ActiveJMSResourceAdapter :: got property " + poolPropertyName 
                        + "="+ poolPropertyValue);
        return poolPropertyValue;
    }

    private JdbcConnectionPool getJDBCConnectionPoolInfo(String poolJndiName) 
                                                        throws ConfigException {
        return ResourcesUtil.getInstance().getJDBCPoolForResource(poolJndiName);    
    }

    private boolean isJMSAvailabilityOn(AvailabilityService as) {
        //need to check for global availability like EJB
        JmsAvailability ja = as.getJmsAvailability();
        boolean jmsAvailability = ja.isAvailabilityEnabled();
        logFine("JMS availability :: " + jmsAvailability);
        return jmsAvailability;
    }

    /**
     * Set MQ4.0 RA lifecycle properties 
     */
    private void setLifecycleProperties() throws 
                                      ConfigException, ConnectorRuntimeException {
        ConfigContext ctx = ApplicationServer.getServerContext().getConfigContext();
    

    	//If PE: 
        //EMBEDDED/LOCAL goto jms-service, get defaultjmshost info and set 
        //accordingly
        //if EE:
        //EMBEDDED/LOCAL get this instance and cluster name, search for a 
        //jms-host wth this this name in jms-service gets its proeprties 
        //and set
        //@siva As of now use default JMS host. As soon as changes for modifying EE
        //cluster to LOCAL is brought in, change this to use system properties
        //for EE to get port, host, adminusername, adminpassword.
        JmsService jmsService = ServerBeansFactory.getJmsServiceBean(ctx);
        String defaultJmsHost = jmsService.getDefaultJmsHost();
        logFine("Default JMS Host :: " + defaultJmsHost);
        
        JmsHost jmsHost = null;
        if (defaultJmsHost == null || defaultJmsHost.equals("")) {
            jmsHost = ServerBeansFactory.getJmsHostBean(ctx);
        } else {
            jmsHost = jmsService.getJmsHostByName(defaultJmsHost);
        }
        
        if (jmsHost != null && jmsHost.isEnabled()) {
            JavaConfig javaConfig = ServerBeansFactory.getJavaConfigBean(ctx);
            String java_home = javaConfig.getJavaHome();
            
            //Get broker type from JMS Service.
            String brokerType = jmsService.getType();
            String brokerPort = jmsHost.getPort();
            String adminUserName = jmsHost.getAdminUserName();
            String adminPassword = jmsHost.getAdminPassword();

            createMQVarDirectoryIfNecessary();
            String brokerVarDir = getMQVarDir(); 

            String tmpString = jmsService.getStartArgs();
            if (tmpString == null) {
                tmpString = "";
            }
            
            String brokerArgs = tmpString;
            

            //XXX: Extract the information from the optional properties.
            ElementProperty[] jmsProperties =
                jmsService.getElementProperty();
            
            String brokerHomeDir = getBrokerHomeDir();
            if (brokerInstanceName == null) {
                brokerInstanceName = getBrokerInstanceName(jmsService);
            }
            
            long brokerTimeOut = getBrokerTimeOut(jmsService);

            //Need to set the following properties
            //BrokerType, BrokerInstanceName, BrokerPort,
            //BrokerArgs, BrokerHomeDir, BrokerVarDir, BrokerStartTimeout
            //adminUserName, adminPassword
            ConnectorDescriptor cd = getDescriptor();
            EnvironmentProperty envProp1 = new EnvironmentProperty (
                    BROKERTYPE, brokerType, "Broker Type", "java.lang.String");
            setProperty(cd, envProp1);
            EnvironmentProperty envProp2 = new EnvironmentProperty (
                    BROKERINSTANCENAME, brokerInstanceName , 
                    "Broker Instance Name", "java.lang.String");
            setProperty(cd, envProp2);
            EnvironmentProperty envProp3 = new EnvironmentProperty (
                    BROKERPORT , brokerPort , 
                    "Broker Port", "java.lang.String");
            setProperty(cd, envProp3);
            EnvironmentProperty envProp4 = new EnvironmentProperty (
                    BROKERARGS , brokerArgs , 
                    "Broker Args", "java.lang.String");
            setProperty(cd, envProp4);
            EnvironmentProperty envProp5 = new EnvironmentProperty (
                    BROKERHOMEDIR , brokerHomeDir , 
                    "Broker Home Dir", "java.lang.String");
            setProperty(cd, envProp5);
            EnvironmentProperty envProp6 = new EnvironmentProperty (
                    BROKERJAVADIR , java_home , 
                    "Broker Java Dir", "java.lang.String");
                    setProperty(cd, envProp6);
            EnvironmentProperty envProp7 = new EnvironmentProperty (
                    BROKERVARDIR , brokerVarDir , 
                    "Broker Var Dir", "java.lang.String");
            setProperty(cd, envProp7);
            EnvironmentProperty envProp8 = new EnvironmentProperty (
                    BROKERSTARTTIMEOUT , "" + brokerTimeOut , 
                    "Broker Start Timeout", "java.lang.String");
            setProperty(cd, envProp8);
            EnvironmentProperty envProp9 = new EnvironmentProperty (
                    ADMINUSERNAME , adminUserName, 
                    "Broker admin username", "java.lang.String");
            setProperty(cd, envProp9);
            EnvironmentProperty envProp10 = new EnvironmentProperty (
                    ADMINPASSWORD , adminPassword , 
                    "Broker admin password", "java.lang.String");
            setProperty(cd, envProp10);
            
            //set adminpassfile
            if (!jmsService.getType().equals(REMOTE)) {
                //For LOCAL and EMBEDDED, we pass in the admin pass file path
                //containing the MQ admin password to enable authenticated 
                //startup of the broker.
                String adminPassFilePath = getAdminPassFilePath(adminPassword);
                if (adminPassFilePath != null) {
                    EnvironmentProperty envProp11 = new EnvironmentProperty (
                            ADMINPASSFILE , adminPassFilePath , 
                            "Broker admin password", "java.lang.String");
                    setProperty(cd, envProp11);
                }
            }
        }
        //Optional
        //BrokerBindAddress, RmiRegistryPort
    }
	
    private String getAdminPassFilePath(String adminPassword) {
        try {
            mqPassFile = File.createTempFile(MQ_PASS_FILE_PREFIX,null);
            BufferedWriter out = new BufferedWriter(new FileWriter(mqPassFile));
            out.write(MQ_PASS_FILE_KEY + adminPassword);
            out.newLine();
            out.flush();
            out.close();
            return mqPassFile.getCanonicalPath();
        } catch (IOException e) {
            logger.log(Level.WARNING, "IOException while creating MQ admin pass file" + e.getMessage());
        }
        return null;
    }

    private long getBrokerTimeOut(JmsService jmsService) {
        //@@remove
        long defaultTimeout = 30 * 1000; //30 seconds
        long timeout = defaultTimeout;
    
        String specifiedTimeOut = jmsService.getInitTimeoutInSeconds(); 
        if (specifiedTimeOut != null)
            timeout = Integer.parseInt(specifiedTimeOut) * 1000;
        return timeout;
    }

    public static String getBrokerInstanceName(JmsService js) 
                      throws ConfigException, ConnectorRuntimeException {
        String asInstance = ApplicationServer.getServerContext().getInstanceName();
        String domainName = null;
        if (isClustered()) {
            domainName = ClusterHelper.getClusterForInstance(
                            ApplicationServer.getServerContext().getConfigContext(), 
                            asInstance).getName();
        } else { 
            domainName = ServerManager.instance().getDomainName();
        }
        String s = IASJmsUtil.getBrokerInstanceName(domainName, asInstance, js);
        logFine("IASJMSUtil gave broker Instancename as " + s);
        String converted = convertStringToValidMQIdentifier(s);
        logFine("converted instance name " + converted);
        return converted;
    }

    private void createMQVarDirectoryIfNecessary(){
        String asInstanceRoot = ApplicationServer.getServerContext().
                                   getInstanceEnvironment().getInstancesRoot(); 
        String mqInstanceDir =  asInstanceRoot + java.io.File.separator 
    	                                          + IASJmsUtil.MQ_DIR_NAME;
    	 // If the directory doesnt exist, create it.
    	 // It is necessary for windows.
    	 java.io.File instanceDir = new java.io.File(mqInstanceDir);
    	 if (!(instanceDir.exists() && instanceDir.isDirectory())) {
    	     instanceDir.mkdirs();
    	 }
    }
    
    private String getMQVarDir(){
        String asInstanceRoot = ApplicationServer.getServerContext().
                                  getInstanceEnvironment().getInstancesRoot();
        String mqInstanceDir =  asInstanceRoot + java.io.File.separator
                                                 + IASJmsUtil.MQ_DIR_NAME;
        return mqInstanceDir;
    }
    
    private String getBrokerHomeDir() {
        // If the property was not specified, then look for the 
        // imqRoot as defined by the com.sun.aas.imqRoot property   
        String brokerHomeDir = java.lang.System.getProperty(SystemPropertyConstants.IMQ_BIN_PROPERTY);
        logFine("broker home dir from system property " + brokerHomeDir);
        
        // Finally if all else fails (though this should never happen)
        // look for IMQ relative to the installation directory
        //@todo reget brokerHomeDir
        if (brokerHomeDir == null) {
            String IMQ_INSTALL_SUBDIR = java.io.File.separator + 
                ".." + java.io.File.separator + ".." +
                java.io.File.separator + "imq" ;
                //java.io.File.separator + "bin"; hack until MQ RA changes
            //XXX: This doesn't work in clustered instances.
            brokerHomeDir = ApplicationServer.getServerContext().getInstallRoot() 
            					+ IMQ_INSTALL_SUBDIR;
        } else {
            //hack until MQ RA changes
            brokerHomeDir = brokerHomeDir + java.io.File.separator + ".." ; 
        }
        
        logFine("Broker Home Directory :: " + brokerHomeDir);
        logFine("broker home dir finally" + brokerHomeDir);
        return brokerHomeDir;
    	
    }
    
    ////@Siva: provide an API to read JMX information from RA and return it.
    //private 

    

    /**
     * Sets the SE/EE specific MQ-RA bean properties 
     * @throws ConnectorRuntimeException
     */
    private void setClusterRABeanProperties() throws ConnectorRuntimeException {
        ConnectorDescriptor cd = super.getDescriptor();
        try {
            if (isClustered()) {
                String val = getGroupName();
                EnvironmentProperty envProp = new EnvironmentProperty (
                    GROUPNAME, val, "Group Name", "java.lang.String");
                setProperty(cd, envProp);
                EnvironmentProperty envProp1 = new EnvironmentProperty (
                    CLUSTERCONTAINER, "true", "Cluster container flag", 
                    "java.lang.Boolean");
                setProperty(cd, envProp1);
                logFine("CLUSTERED instance - setting groupname as" + val);
            } else {
                logFine("Instance not Clustered and hence not setting " +
                        "groupname");
            }
        } catch (ConfigException e) {
            ConnectorRuntimeException crex = new ConnectorRuntimeException(e.getMessage());
            throw (ConnectorRuntimeException)crex.initCause(e);
        }
    }
    

    /**
     * Sets the SE/EE specific MQ-RA bean properties 
     * @throws ConnectorRuntimeException
     */
    private void setAppClientRABeanProperties() throws ConnectorRuntimeException {
        logFine("In Appclient container!!!");
        ConnectorDescriptor cd = super.getDescriptor();
        EnvironmentProperty envProp1 = new EnvironmentProperty (
                        BROKERTYPE, REMOTE, "Broker Type", "java.lang.String");
                setProperty(cd, envProp1);
        
        EnvironmentProperty envProp2 = new EnvironmentProperty (
            GROUPNAME, "", "Group Name", "java.lang.String");
        cd.removeConfigProperty(envProp2);
        EnvironmentProperty envProp3 = new EnvironmentProperty (
            CLUSTERCONTAINER, "false", "Cluster flag", "java.lang.Boolean");
        setProperty(cd, envProp3);
    }
    
    
    private static boolean isClustered() throws ConnectorRuntimeException {
        return JmsRaUtil.isClustered();
    }
    
    private String getGroupName() throws ConfigException{
        return getDomainName() + SEPARATOR + getClusterName();
    }
    
    private String getClusterName() throws ConfigException {
        return ClusterHelper.getClusterForInstance(
                        ApplicationServer.getServerContext().getConfigContext(), 
                        ApplicationServer.getServerContext().getInstanceName()).getName();
    }
    
    /*
     * Generates an Name for the MQ Cluster associated with the 
     * application server cluster.
     */ 
    private String getMQClusterName() throws ConfigException {
        return convertStringToValidMQIdentifier(getClusterName()) + "_MQCluster"; 
    }
    
    //All Names passed into MQ needs to be valid Java Identifiers
    //so as of now replacing all characters that are not valid
    //java identifier components with '_'
    private static String convertStringToValidMQIdentifier(String s) {
        if (s == null) return "";
        
        StringBuffer buf = new StringBuffer();
        for(int i = 0; i < s.length(); i++) {
            if(Character.isLetterOrDigit(s.charAt(i))){ 
                            //|| s.charAt(i) == '_'){
                buf.append(s.charAt(i));
            } 
        }
        return buf.toString();
    }
    
    private String getDomainName() throws ConfigException {
        ConfigContext ctxt = ApplicationServer.getServerContext().getConfigContext();
        //computing hashcode, since the application root string could
        //be potentially large
        /*
        String domainName = "" + ServerBeansFactory.getDomainBean(ctxt).
                            getApplicationRoot().hashCode();
        return domainName;
        */
        // FIX LATER
        return "";
    }

    /**
     * Recreates the ResourceAdapter using new values from JmsSerice.
     *
     * @param js JmsService element of the domain.xml
     * @throws ConnectorRuntimeException in case of any backend error.
     */
    public void reloadRA(JmsService js) throws ConnectorRuntimeException {
        setMdbContainerProperties();
        setJmsServiceProperties(js);
     
        super.loadRAConfiguration();
	rebindDescriptor();
    }

    /**
     * Adds the JmsHost to the MQAddressList of the resource adapter.
     * 
     * @param host JmsHost element in the domain.xml
     * @throws ConnectorRuntimeException in case of any backend error.
     */
    public void addJmsHost(JmsHost host) throws ConnectorRuntimeException {
        urlList.addMQUrl(host);
        setAddressList();
    }

    /**
     * Removes the JmsHost from the MQAddressList of the resource adapter.
     * 
     * @param host JmsHost element in the domain.xml
     * @throws ConnectorRuntimeException in case of any backend error.
     */
    public void deleteJmsHost(JmsHost host) throws ConnectorRuntimeException {
        urlList.removeMQUrl(host);
        setAddressList();
    }

    /**
     * Updates the JmsHost information in the MQAddressList of the resource adapter.
     * 
     * @param host JmsHost element in the domain.xml
     * @throws ConnectorRuntimeException in case of any backend error.
     */
    public void updateJmsHost(JmsHost host) throws ConnectorRuntimeException {
        urlList.updateMQUrl(host);
        setAddressList();
    }
    
    private void setMdbContainerProperties() throws ConnectorRuntimeException {
        JmsRaUtil raUtil = new JmsRaUtil(null);
				       
        ConnectorDescriptor cd = super.getDescriptor();
        raUtil.setMdbContainerProperties();

        String val = ""+MdbContainerProps.getReconnectEnabled();
        EnvironmentProperty envProp2 = new EnvironmentProperty (
            RECONNECTENABLED, val, val, "java.lang.Boolean");
        setProperty(cd, envProp2); 

        val = ""+MdbContainerProps.getReconnectDelay(); 
        EnvironmentProperty envProp3 = new EnvironmentProperty (
            RECONNECTINTERVAL, val, val, "java.lang.Integer");
        setProperty(cd, envProp3); 

        val = ""+MdbContainerProps.getReconnectMaxRetries(); 
        EnvironmentProperty envProp4 = new EnvironmentProperty (
            RECONNECTATTEMPTS, val, val, "java.lang.Integer");
        setProperty(cd, envProp4); 

	// The above properties will be set in ConnectorDescriptor and
	// will be bound in JNDI. This will be available to appclient
	// and standalone client.
    }

    private void setAddressList() throws ConnectorRuntimeException {
        //@Siva: Enhance setting AddressList. [Ignore this machines jms-host while 
        //constructing addresslist]
        try {
            ConfigContext ctx = ApplicationServer.getServerContext().getConfigContext();
            JmsService jmsService = ServerBeansFactory.getJmsServiceBean(ctx);
            setConnectionURL(jmsService, urlList);
        } catch (ConfigException e) {
            e.printStackTrace();
        }
        super.loadRAConfiguration();
    }

    //This is a MQ workaround. In PE, when the broker type is
    //EMBEDDED or LOCAL, do not set the addresslist, else
    //MQ RA assumes that there are two URLs and fails (EE limitation).
    private void setConnectionURL(JmsService jmsService, MQAddressList urlList) {
        ConnectorDescriptor cd = super.getDescriptor();
        String val = urlList.toString();
        if (val != null) {
            logger.info("JMS Service Connection URL is :" + val);
            EnvironmentProperty envProp1 = new EnvironmentProperty (
               CONNECTION_URL, val, val, "java.lang.String");
            setProperty(cd, envProp1); 
        }
    }

    private void setJmsServiceProperties(JmsService service) throws 
                                         ConnectorRuntimeException {
        JmsRaUtil jmsraUtil = new JmsRaUtil(service);
        
        urlList = jmsraUtil.getUrlList();

        ConnectorDescriptor cd = super.getDescriptor();
        setConnectionURL(service, urlList);

        String val = ""+jmsraUtil.getReconnectEnabled();
        EnvironmentProperty envProp2 = new EnvironmentProperty (
            RECONNECTENABLED, val, val, "java.lang.Boolean");
        setProperty(cd, envProp2); 

        //convert to milliseconds
        int newval = (new Integer(jmsraUtil.getReconnectInterval())).intValue() * 1000;
        val = "" + newval;  
        EnvironmentProperty envProp3 = new EnvironmentProperty (
            RECONNECTINTERVAL, val, val, "java.lang.Integer");
        setProperty(cd, envProp3); 

        val = ""+jmsraUtil.getReconnectAttempts(); 
        EnvironmentProperty envProp4 = new EnvironmentProperty (
            RECONNECTATTEMPTS, val, val, "java.lang.Integer");
        setProperty(cd, envProp4); 

        val = ""+jmsraUtil.getAddressListBehaviour(); 
        EnvironmentProperty envProp5 = new EnvironmentProperty (
            ADRLIST_BEHAVIOUR, val, val, "java.lang.String");
        setProperty(cd, envProp5); 

        val = ""+jmsraUtil.getAddressListIterations(); 
        EnvironmentProperty envProp6 = new EnvironmentProperty (
            ADRLIST_ITERATIONS, val, val, "java.lang.Integer");
        setProperty(cd, envProp6); 
        
        boolean useExternal = shouldUseExternalRmiRegistry();
        val = (new Boolean(useExternal)).toString();
        EnvironmentProperty envProp7 = new EnvironmentProperty (
            USEEXTERNALRMIREGISTRY, val, val, "java.lang.Boolean");
        setProperty(cd, envProp7); 

        //If MQ RA needs to use AS RMI Registry Port, then set
        //the RMI registry port, else MQ RA uses its default RMI
        //Registry port  [as of now 1099]
        if (!useExternal) {
            String configuredRmiRegistryPort = getRmiRegistryPort();
            val = configuredRmiRegistryPort;
            if (val != null) {
                EnvironmentProperty envProp8 = new EnvironmentProperty (
                    RMIREGISTRYPORT, val, val, "java.lang.Integer");
                setProperty(cd, envProp8);
            } else {
                logger.log(Level.WARNING, "Invalid RMI registry port");
            }
        }
    }

    /*
     * Checks if AS RMI registry is started and available for use.
     */
    private boolean shouldUseExternalRmiRegistry () {
        boolean useExternalRmiRegistry = ( !isASRmiRegistryPortAvailable() );
        //System.out.println("========== " + useExternalRmiRegistry);
        return useExternalRmiRegistry;
    }

    /**
     * Get the AS RMI registry port for MQ RA to use.
     */
    private String getRmiRegistryPort() {
        String val = null;
        if (MQRmiPort != null && !MQRmiPort.trim().equals("")){
            return MQRmiPort;
        } else {
            String configuredPort = null;
            try {
                configuredPort = getConfiguredRmiRegistryPort();
            } catch (ConfigException ex) {
                logger.log(Level.WARNING, ex.getMessage());
                logger.log(Level.FINE, "Exception while getting configured rmi " +
                                                 "registry port", ex);
            }
            if (configuredPort != null) {
                return configuredPort;
            } 
            
            //Finally if DAS and configured port doesn't work, return DAS'
            //RMI registry port as a fallback option.
            if (ResourcesUtil.isDAS()) {
                    return DASRMIPORT;
            }
        }
        return val;
    }
    
    private String getConfiguredRmiRegistryHost() throws ConfigException {
        return getJmxConnector().getAddress();
    }

    private String getConfiguredRmiRegistryPort() throws ConfigException {
        return getJmxConnector().getPort();
    }
    
    private JmxConnector getJmxConnector() throws ConfigException{
        AdminService as = ServerBeansFactory.getConfigBean(
                        ApplicationServer.getServerContext().getConfigContext()).getAdminService();
        return as.getJmxConnectorByName(as.getSystemJmxConnectorName());
    }
    
    private boolean isASRmiRegistryPortAvailable() {
        String name = null;
        try {
           //Attempt to connect to the RMI registry
            name = "rmi://"+getConfiguredRmiRegistryHost() + ":" + getConfiguredRmiRegistryPort();
            if (logger.isLoggable(Level.FINE)) {
                logger.fine("Attempting to list " + name);
            }
            String[] ss = Naming.list(name);
            if (logger.isLoggable(Level.FINE)) {
                logger.fine("List on " + name + " succeeded");
            }
            //return configured port only if RMI registry is available
            return true;
        } catch (Exception e) {
            logger.fine(e.getMessage() + " " + name);
            return false;
        }
    }
    
    private void setProperty(ConnectorDescriptor cd, EnvironmentProperty envProp){
        cd.removeConfigProperty(envProp);
        cd.addConfigProperty(envProp);
    }


    private void rebindDescriptor() throws ConnectorRuntimeException {
        try {
            String descriptorJNDIName = ConnectorAdminServiceUtils.getReservePrefixedJNDINameForDescriptor(super.getModuleName());
	    com.sun.enterprise.Switch.getSwitch().getNamingManager().
	    publishObject( descriptorJNDIName, super.getDescriptor(), true);
	} catch (javax.naming.NamingException ne) {
	    ConnectorRuntimeException cre = new ConnectorRuntimeException (ne.getMessage());
	    throw (ConnectorRuntimeException) cre.initCause(ne);
	}
    }


    /**
     * Creates ManagedConnection Factory instance. For any property that is 
     * for supporting AS7 imq properties, resource adapter has a set method
     * setProperty(String,String). All AS7 properties starts with "imq".
     * MQ Adapter supports this only for backward compatibility.
     * 
     * @param cpr <code>ConnectorConnectionPool</code> object
     * @parm loader Class Loader.
     * @throw ConnectorRuntimeException in case of an exception.
     */
    public ManagedConnectionFactory createManagedConnectionFactory
       	       (com.sun.enterprise.connectors.ConnectorConnectionPool cpr, 
                                                       ClassLoader loader) {
        ManagedConnectionFactory mcf = 
            super.createManagedConnectionFactory(cpr, loader);
        if ( mcf != null ) {
            Set s = cpr.getConnectorDescriptorInfo().getMCFConfigProperties();
            Iterator it = s.iterator();
            while (it.hasNext()) {
                EnvironmentProperty prop = (EnvironmentProperty) it.next();
                String propName = prop.getName();
           
                propName.substring(1);
                // If the property has started with imq, then it should go to
                // setProperty(String,String) method.
                if (propName.startsWith("imq") && prop.getValue() != "") {
                    try {
                        Method meth = mcf.getClass().getMethod
                        (SETTER, new  Class[] {java.lang.String.class, 
                                               java.lang.String.class});
                        meth.invoke(mcf, new Object[] {prop.getName(),
                                                        prop.getValueObject()});
                    } catch (NoSuchMethodException ex) {
                        logger.log(Level.WARNING, "no.such.method", 
                        new Object[] {SETTER, mcf.getClass().getName()});
                    } catch (Exception ex) {
                        logger.log(Level.SEVERE, "error.execute.method", 
                        new Object[] {SETTER, mcf.getClass().getName()});
                    }
	        }
            }
                
        }
        return mcf;
    }

    /**
     * This is the most appropriate time (??) to update the runtime
     * info of a 1.3 MDB into 1.4 MDB.  <p>
     *
     * Assumptions : <p>
     * 0. Assume it is a 1.3 MDB if no RA mid is specified.
     * 1. Use the default system JMS resource adapter. <p>
     * 2. The ActivationSpec of the default JMS RA will provide the
     *    setDestination, setDestinationType, setSubscriptionName methods.
     * 3. The jndi-name of the 1.3 MDB is the value for the Destination
     *    property for the ActivationSpec.
     * 4. The ActivationSpec provides setter methods for the properties
     *    defined in the CF that corresponds to the mdb-connection-factory
     *    JNDI name.
     *
     */
    public void updateMDBRuntimeInfo(EjbMessageBeanDescriptor descriptor_,
           BeanPoolDescriptor poolDescriptor) throws ConnectorRuntimeException{

        String jndiName = descriptor_.getJndiName();
        
        //handling of MDB 1.3 runtime deployment descriptor
        //if no RA-mid is specified, assume it is a 1.3 DD
        if (jndiName == null) { //something's wrong in DD
            logger.log (Level.SEVERE, "Missing Destination JNDI Name");
	    String msg = sm.getString("ajra.error_in_dd");
            throw new RuntimeException(msg);
        }
        
        String resourceAdapterMid = ConnectorRuntime.DEFAULT_JMS_ADAPTER;
        
        descriptor_.setResourceAdapterMid(resourceAdapterMid);


        String destName = getPhysicalDestinationFromConfiguration(jndiName);
        
        //1.3 jndi-name ==> 1.4 setDestination
        descriptor_.putRuntimeActivationConfigProperty(
                new EnvironmentProperty(DESTINATION, 
                        destName, null));
	
        
        //1.3 (standard) destination-type == 1.4 setDestinationType
        //XXX Do we really need this???
        if (descriptor_.getDestinationType() != null &&
                !"".equals(descriptor_.getDestinationType())) {
            descriptor_.putRuntimeActivationConfigProperty(
                    new EnvironmentProperty(DESTINATION_TYPE, 
                            descriptor_.getDestinationType(), null));
        } else {
            /*
             * If destination type is not provided by the MDB component
             * [typically used by EJB3.0 styled MDBs which create MDBs without
             * a destination type activation-config property] and the MDB is for
             * the default JMS RA, attempt to infer the destination type by trying
             * to find out if there has been any JMS destination resource already
             * defined for default JMS RA. This is a best attempt guess and if there
             * are no JMS destination resources/admin-objects defined, AS would pass
             * the properties as defined by the MDB.
             */
            ConfigBean[] cb;
            try {
                cb = ResourcesUtil.getInstance().getEnabledAdminObjectResources(
                        ConnectorConstants.DEFAULT_JMS_ADAPTER);
                for (int i = 0; i < cb.length; i++) {
                    AdminObjectResource aor = (AdminObjectResource) cb[i];
                    if (aor.getJndiName().equals(jndiName)) {
                        descriptor_.putRuntimeActivationConfigProperty(
                                new EnvironmentProperty(DESTINATION_TYPE, 
                                        aor.getResType(), null));
                        logger.log(Level.INFO, "endpoint.determine.destinationtype", new 
                                Object[]{aor.getResType() , aor.getJndiName() , descriptor_.getName()});                        
                    }
                }
            } catch (ConfigException e) {
                
            }
        }
        
        
        //1.3 durable-subscription-name == 1.4 setSubscriptionName
        descriptor_.putRuntimeActivationConfigProperty(
                new EnvironmentProperty(SUBSCRIPTION_NAME,
                        descriptor_.getDurableSubscriptionName(), null));

        String mdbCF = null;
	try {
	    mdbCF = descriptor_.getIASEjbExtraDescriptors().
                    getMdbConnectionFactory().getJndiName();
	} catch(NullPointerException ne ) {
	    // Dont process connection factory.
	}

        if (mdbCF != null && mdbCF != "") {
	    setValuesFromConfiguration(mdbCF, descriptor_);
        }

        // a null object is passes as a PoolDescriptor during recovery.
        // See com/sun/enterprise/resource/ResourceInstaller
        
        if (poolDescriptor != null) {
        descriptor_.putRuntimeActivationConfigProperty
            (new EnvironmentProperty (MAXPOOLSIZE, ""+
                 poolDescriptor.getMaxPoolSize(),"", "java.lang.Integer" ));
        descriptor_.putRuntimeActivationConfigProperty
            (new EnvironmentProperty (MINPOOLSIZE,""+ 
                 poolDescriptor.getSteadyPoolSize(),"", "java.lang.Integer"));
        descriptor_.putRuntimeActivationConfigProperty
            (new EnvironmentProperty (RESIZECOUNT,""+ 
                 poolDescriptor.getPoolResizeQuantity(),"", "java.lang.Integer"));
        descriptor_.putRuntimeActivationConfigProperty
            (new EnvironmentProperty (RESIZETIMEOUT,""+ 
                 poolDescriptor.getPoolIdleTimeoutInSeconds(),"", "java.lang.Integer"));
        descriptor_.putRuntimeActivationConfigProperty
            (new EnvironmentProperty (REDELIVERYCOUNT,""+ 
                 MdbContainerProps.getMaxRuntimeExceptions(),"", "java.lang.Integer"));
        }
        
        //Set SE/EE specific MQ-RA ActivationSpec properties
        try {
            boolean clustered = isClustered();
            logFine("Are we in a Clustered contained ? " + clustered);
            if (clustered) {
                setClusterActivationSpecProperties(descriptor_);
                logFine("Creating physical destination " + destName);
                logFine("Destination is Queue? " + descriptor_.hasQueueDest());
                if (descriptor_.hasQueueDest()) {
                    autoCreatePhysicalDest(destName, true);
                } else {
                    autoCreatePhysicalDest(destName, false);
                }
            } 
        } catch (ConfigException e) {
            ConnectorRuntimeException crex = new ConnectorRuntimeException(e.getMessage());
            throw (ConnectorRuntimeException)crex.initCause(e);
        }
    }

    void autoCreatePhysicalDest(String destName, boolean isQueue) 
                                throws ConnectorRuntimeException{
        MQAdministrator mqAdmin = new MQAdministrator();
        mqAdmin.createPhysicalDestination(destName, isQueue);
    }

    /**
     * Set SE/EE specific MQ-RA ActivationSpec properties
     * @param descriptor_
     * @throws ConfigException
     */
    private void setClusterActivationSpecProperties(EjbMessageBeanDescriptor 
                    descriptor_) throws ConfigException {
        //Set MDB Identifier in a clustered instance.
        descriptor_.putRuntimeActivationConfigProperty(new 
                        EnvironmentProperty(MDBIDENTIFIER,""+ 
                        getMDBIdentifier(descriptor_),"MDB Identifier", 
                        "java.lang.String"));
        logFine("CLUSTERED instance - setting MDB identifier as" + 
                        getMDBIdentifier(descriptor_));                
        
    }

    /**
     * Gets the MDBIdentifier for the message bean endpoint
     * @param descriptor_
     * @return
     * @throws ConfigException
     */
    private String getMDBIdentifier(EjbMessageBeanDescriptor descriptor_) throws ConfigException {
        return getDomainName() + SEPARATOR + getClusterName() + SEPARATOR + descriptor_.getUniqueId() ;
    }

    private String getPhysicalDestinationFromConfiguration(String logicalDest)
                                throws ConnectorRuntimeException{
	ElementProperty ep = null;
        try {
            ServerContext sc = ApplicationServer.getServerContext();
            ConfigContext ctx = sc.getConfigContext();
            Resources rbeans = 
                           ServerBeansFactory.getDomainBean(ctx).getResources();
            AdminObjectResource res = (AdminObjectResource) 
		           rbeans.getAdminObjectResourceByJndiName(logicalDest);
	    if (res == null) {
	        String msg = sm.getString("ajra.err_getting_dest", logicalDest );
		throw new ConnectorRuntimeException(msg);
	    }
		         
	    ep = res.getElementPropertyByName(PHYSICAL_DESTINATION);
        } catch(ConfigException ce) {
	    String msg = sm.getString("ajra.err_getting_dest", logicalDest);
	    ConnectorRuntimeException cre = new ConnectorRuntimeException( msg );
	    cre.initCause( ce );
            throw cre;
        }

        if (ep == null) {
	   String msg = sm.getString("ajra.cannot_find_phy_dest", ep);
           throw new ConnectorRuntimeException(msg);
        }

        return ep.getValue();
    }


    private void setValuesFromConfiguration(String cfName, EjbMessageBeanDescriptor 
                                     descriptor_) throws ConnectorRuntimeException{
	ElementProperty[] ep = null;
        try {
            ServerContext sc = ApplicationServer.getServerContext();
            ConfigContext ctx = sc.getConfigContext();
            Resources rbeans = ServerBeansFactory.getDomainBean(ctx).getResources();
            ConnectorResource res = (ConnectorResource) 
		                     rbeans.getConnectorResourceByJndiName(cfName);
	    if (res == null) {
	        String msg = sm.getString("ajra.mdb_cf_not_created", cfName);
		throw new ConnectorRuntimeException(msg);
	    }

	    ConnectorConnectionPool ccp = (ConnectorConnectionPool) 
		    rbeans.getConnectorConnectionPoolByName(res.getPoolName());
		         
	    ep = ccp.getElementProperty();
        } catch(ConfigException ce) {
	    String msg = sm.getString("ajra.mdb_cf_not_created", cfName);
	    ConnectorRuntimeException cre = new ConnectorRuntimeException( msg );
	    ce.initCause( ce );
            throw cre;
        }

        if (ep == null) {
	    String msg = sm.getString("ajra.cannot_find_phy_dest");
            throw new ConnectorRuntimeException( msg );
        }

	for (int i=0; i < ep.length; i++) {
	    ElementProperty prop = ep[i];
	    String name = prop.getName();
	    if (name.equals(MCFADDRESSLIST)) {
	        name = ADDRESSLIST;
	    }
	    String val = prop.getValue();
	    if (val == null || val.equals("")) {
		continue;
	    }
            descriptor_.putRuntimeActivationConfigProperty(
                new EnvironmentProperty(name, val, null));
	}

    }
    
    private static void logFine(String s) {
    	if (logger.isLoggable(Level.FINE)){
    		logger.fine(s);
    	}
    }
}
