/*
 * 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.repository;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.lang.reflect.Method;
import java.io.Serializable;
import java.util.*;
import javax.naming.*;
import javax.resource.spi.*;
import javax.resource.ResourceException;
import com.sun.enterprise.util.Utility;
import com.sun.enterprise.util.JarClassLoader;
import com.sun.enterprise.resource.*;
import com.sun.enterprise.deployment.ConnectorDescriptor;
import com.sun.enterprise.deployment.EnvironmentProperty;
import com.sun.enterprise.Switch;
import com.sun.enterprise.log.Log;
// IASRI 4660742 START
import java.util.logging.*;
import com.sun.logging.*;
// IASRI 4660742 END

import com.sun.enterprise.connectors.ConnectionManagerImpl;
/**
 * Resource info for Connector connection factories
 *
 * @author Tony Ng
 */ 
public class ConnectorResource extends J2EEResourceBase implements Serializable {

// IASRI 4660742 START
    private static Logger _logger=null;
    static{
       _logger=LogDomains.getLogger(LogDomains.ROOT_LOGGER);
        }
// IASRI 4660742 END
    static public final String CONNECTOR_OBJECT_FACTORY =
        "com.sun.enterprise.naming.factory.ConnectorObjectFactory";

    private String dbuser_;
    private String dbpassword_;
    private String connectorname_;
    private String appname_;
    private String connectionFactoryClass_;
    
    public ConnectorResource(String name) {
        super(name);
        dbuser_ = "";
        dbpassword_ = "";
        appname_ = "";
    }

    protected J2EEResource doClone(String name) {
        ConnectorResource clone = new ConnectorResource(name);
        clone.setDbuser(getDbuser());
        clone.setDbpassword(getDbpassword());
        clone.setConnectorName(getConnectorName());
        clone.setApplicationName(getApplicationName());
        clone.setConnectionFactoryClass(getConnectionFactoryClass());
        return clone;
    }

    public int getType() {
        return J2EEResource.CONNECTOR_RESOURCE;
    }

    public String getApplicationName() {
        return appname_;
    }

    public void setApplicationName(String appname) {
        if (appname == null) {
            appname_ = "";
        } else {
            appname_ = appname;
        }
    }

    public String getConnectorName() {
        return connectorname_;
    }

    public void setConnectorName(String connectorname) {
        connectorname_ = connectorname;
    }

    public String getConnectionFactoryClass() {
        return connectionFactoryClass_;
    }

    public void setConnectionFactoryClass(String cfclass) {
        connectionFactoryClass_ = cfclass;
    }

    public String getDbuser() {
        return dbuser_;
    }

    public void setDbuser(String dbuser) {
        if (dbuser == null) {
            dbuser_ = "";
        } else {
            dbuser_ = dbuser;
        }
    }

    public String getDbpassword() {
        return dbpassword_;
    }

    public void setDbpassword(String dbpassword) {
        if (dbpassword == null) {
            dbpassword_ = "";
        } else {
            dbpassword_ = dbpassword;
        }
    }


    public Reference createConnectionFactoryReference() {
        Reference ref = 
            new Reference(getConnectionFactoryClass(),
                          new StringRefAddr("jndiName", getName()),
                          CONNECTOR_OBJECT_FACTORY, null);
        return ref;
    }


    // this can be invoked when a component looks up a connection
    // factory from JNDI. Need doPrivileged actions
    public ManagedConnectionFactory 
        createManagedConnectionFactory(ClassLoader jcl)
        throws PoolingException {

        try {
            if (jcl == null) {
                // use context class loader
                jcl = (ClassLoader) AccessController.doPrivileged
                    (new PrivilegedAction() {
                        public Object run() {
                            return Thread.currentThread().getContextClassLoader();
                        }
                    });
            }
                
            ResourceInstaller ri = Switch.getSwitch().getResourceInstaller();
            ConnectorDescriptor desc =
                ri.getDescriptorByConnectorName(getApplicationName(),
                                                getConnectorName());
            String jndiName = getName();
            String mcfClass = desc.getManagedConnectionFactoryImpl();

            String appName = getApplicationName();

            /* debug
//IASRI 4660742            System.err.println("ClassLoader: " + jcl.getClass());
//IASRI 4660742            System.err.println("ClassLoader: " + jcl.getParent().getClass());
//IASRI 4660742            System.err.println("ClassLoader: " + jcl.getParent().getParent().getClass());
            */
// START OF IASRI 4660742
		_logger.log(Level.FINE,"ClassLoader: " + jcl.getClass());
		_logger.log(Level.FINE,"ClassLoader: " + jcl.getParent().getClass());
		_logger.log(Level.FINE,"ClassLoader: " + jcl.getParent().getParent().getClass());
// END OF IASRI 4660742
            ManagedConnectionFactory mcf = (ManagedConnectionFactory)
                Class.forName(mcfClass, true, jcl).newInstance();
            AccessController.doPrivileged
                (new SetMethodAction(mcf, desc));
            return mcf;
        } catch (PrivilegedActionException ex) {
            Exception nested = ex.getException();
//IASRI 4660742            Log.err.println(nested);
// START OF IASRI 4660742
		_logger.log(Level.SEVERE,"enterprise.privilegedaction_exception",nested.toString());
// END OF IASRI 4660742
            Log.err.flush();
            throw new PoolingException(nested.toString(), nested);
        } catch (Exception ex) {
//IASRI 4660742            Log.err.println(ex);
// START OF IASRI 4660742
		_logger.log(Level.SEVERE,"enterprise.managedconnfactory_exception",ex.toString());
// END OF IASRI 4660742
            Log.err.flush();
            throw new PoolingException(ex.toString(), ex);
        }

    }

    // called by com.sun.enterprise.naming.ConnectorObjectFactory
    public Object createConnectionFactory()
        throws PoolingException {

        ManagedConnectionFactory mcf = createManagedConnectionFactory(null);
        try {
            Object cf = mcf.createConnectionFactory
                (new ConnectionManagerImpl(getName()));
            return cf;
        } catch (ResourceException ex) {
//IASRI 4660742            Log.err.println(ex);
// START OF IASRI 4660742
		_logger.log(Level.SEVERE,"enterprise.resource_exception",ex.toString());
// END OF IASRI 4660742
            Log.err.flush();
            throw new PoolingException(ex.toString(), ex);
        }
    }

    // invokes setMethods on ManagedConnectionFactory
    class SetMethodAction implements PrivilegedExceptionAction {
        ManagedConnectionFactory mcf;
        ConnectorDescriptor desc;

        SetMethodAction(ManagedConnectionFactory mcf,
                        ConnectorDescriptor desc) {
            this.mcf = mcf;
            this.desc = desc;
        }

        public Object run() throws Exception {

            Iterator iter = desc.getConfigProperties().iterator();
            while (iter.hasNext()) {
                EnvironmentProperty envProp = 
                    (EnvironmentProperty) iter.next();
                String propName = envProp.getName();
                String propType = envProp.getType();
                String propValue = (String) getProperty(propName).getValue();
                // use EnvironmentProperty to get valueObject
                EnvironmentProperty newProp =
                    new EnvironmentProperty(propName, propValue, "", propType);

                // set properties on managed connection factory
                // change first letter to uppercase
                String setMeth = 
                    "set" + propName.substring(0,1).toUpperCase() +
                    propName.substring(1);
                Method meth = mcf.getClass().getMethod
                    (setMeth, new  Class[] {newProp.getValueType()});
                meth.invoke(mcf, new Object[] {newProp.getValueObject()});
            }
            return null;
        }

    }

    public String toString() {
        return "< Connector Resource : " + getName() + 
            " , " + getApplicationName() +
            " , " + getConnectorName() + " , " + getDbuser() +
            " , " + getDbpassword() + " >";
            
    }
}
