/*
 * 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.io.Serializable;
import java.util.Iterator;

import com.sun.enterprise.util.Utility;

/**
 * Resource info for Jdbc Connection Pool.
 * IASRI #4626188
 * @author Sridatta Viswanath
 */
public class JdbcConnectionPool extends J2EEResourceBase implements Serializable {
    
    private String userName_;
    private String password_;

    private String datasourceClassname_;
    private String steadyPoolSize_;
    private String maxPoolSize_;
    private String maxWaitTimeInMillis_;
    // start IASRI 4667083
    // adding poolResizeQuantity
    private String poolResizeQuantity_;
    // end IASRI 4667083
    private String idleTimeoutInSeconds_;
    private boolean isConnectionValidationRequired_;
    private String connectionValidationMethod_;
    private String validationTableName_;
    private boolean failAllConnections_;

    // start IASRI 4691114
    private boolean perfMonitor = false;
    //end IASRI 4691114

    // start IASRI 6487826
    // adding resType, transactionIsolationLevel, and isIsolationLevelGuaranteed
    private String resType_;
    private String transactionIsolationLevel_;
    private boolean isIsolationLevelGuaranteed_;
    // end IASRI 6487826

    // start IASRI 4659935
    private transient Object cachedVendorDataSource = null;
    // end IASRI 4659935

    public JdbcConnectionPool(String name) {
        super(name);
    }
    
    protected J2EEResource doClone(String name) {
        JdbcConnectionPool clone = new JdbcConnectionPool(name);

        clone.setUserName(getUserName());
        clone.setPassword(getPassword());

        clone.setDatasourceClassname(getDatasourceClassname());
        clone.setMaxPoolSize(getMaxPoolSize());
        clone.setMaxWaitTimeInMillis(getMaxWaitTimeInMillis());
        clone.setPoolResizeQuantity(getPoolResizeQuantity());
        clone.setIdleTimeoutInSeconds(getIdleTimeoutInSeconds());
        clone.setIsConnectionValidationRequired(isIsConnectionValidationRequired());
        clone.setConnectionValidationMethod(getConnectionValidationMethod());
        clone.setValidationTableName(getValidationTableName());
        clone.setFailAllConnections(isFailAllConnections());

	// start IASRI 6487826
        clone.setResType(getResType());
        clone.setTransactionIsolationLevel(getTransactionIsolationLevel());
        clone.setIsIsolationLevelGuaranteed(isIsolationLevelGuaranteed());
	// end IASRI 6487826

        return clone;
    }
    
    public int getType() {
        return J2EEResource.JDBC_CONNECTION_POOL;
    }
   
    public String getUserName() {
        return userName_;
    }
    
    public void setUserName(String userName) {
        userName_ = userName;
    }
    
    public String getPassword() {
        return password_;
    }
    
    public void setPassword(String password) {
        password_ = password;
    }

    public String getDatasourceClassname() {
        return datasourceClassname_;
    }
    
    public void setDatasourceClassname(String datasourceClassname) {
        datasourceClassname_ = datasourceClassname;
    }
     
    public String getSteadyPoolSize() {
        return steadyPoolSize_;
    }
    
    public void setSteadyPoolSize(String steadyPoolSize) {
        steadyPoolSize_ = steadyPoolSize;
    }

    public String getMaxPoolSize() {
        return maxPoolSize_;
    }

    public void setMaxPoolSize(String maxPoolSize) {
        maxPoolSize_ = maxPoolSize;
    }

    public String getMaxWaitTimeInMillis() {
        return maxWaitTimeInMillis_;
    }
    
    public void setMaxWaitTimeInMillis(String maxWaitTimeInMillis) {
        maxWaitTimeInMillis_ = maxWaitTimeInMillis;
    }

    // start IASRI 4667083
    // adding poolResizeQuantity

    public String getPoolResizeQuantity() {
        return poolResizeQuantity_;
    }
    
    public void setPoolResizeQuantity(String poolResizeQuantity) {
        poolResizeQuantity_ = poolResizeQuantity;
    }

    // end IASRI 4667083

    public String getIdleTimeoutInSeconds() {
        return idleTimeoutInSeconds_;
    }
    
    public void setIdleTimeoutInSeconds(String idleTimeoutInSeconds) {
        idleTimeoutInSeconds_ = idleTimeoutInSeconds;
    }
    public boolean isIsConnectionValidationRequired() {
        return isConnectionValidationRequired_;
    }
    
    public void setIsConnectionValidationRequired(boolean isConnectionValidationRequired) {
        isConnectionValidationRequired_ = isConnectionValidationRequired;
    }
    public String getConnectionValidationMethod() {
        return connectionValidationMethod_;
    }
    
    public void setConnectionValidationMethod(String connectionValidationMethod) {
        connectionValidationMethod_ = connectionValidationMethod;
    }
    public String getValidationTableName() {
        return validationTableName_;
    }
    
    public void setValidationTableName(String validationTableName) {
        validationTableName_ = validationTableName;
    }
    public boolean isFailAllConnections() {
        return failAllConnections_;
    }
    
    public void setFailAllConnections(boolean failAllConnections) {
        failAllConnections_ = failAllConnections;
    }
    
    // start IASRI 6487826

    public String getResType() {
        return resType_;
    }
    
    public void setResType(String resType) {
        resType_ = resType;
    }

    public String getTransactionIsolationLevel() {
        return transactionIsolationLevel_;
    }
    
    public void setTransactionIsolationLevel(String transactionIsolationLevel) {
        transactionIsolationLevel_ = transactionIsolationLevel;
    }

    public boolean isIsolationLevelGuaranteed() {
        return isIsolationLevelGuaranteed_;
    }
    
    public void setIsIsolationLevelGuaranteed(boolean isIsolationLevelGuaranteed) {
        isIsolationLevelGuaranteed_ = isIsolationLevelGuaranteed;
    }
    // end IASRI 6487826

    public String toString() {
        return "< JDBC Connection Pool : " + getName() + "... >";    
    }

    // start IASRI 4659935
    
    /**
     * creates the Vendor DataSource associated with this pool
     *
     * @return vendor data source
     */
    public Object createDataSource() throws J2EEResourceException {
	// We can synchronize on this w/o concern about performance
	//	because this is only called once per creation of a connection
	synchronized(this) {
	    if (cachedVendorDataSource == null) {
		try {
		    // start IASRI 4669877
		    // mods:
		    //	- use the common class loader instead of system class loader
		    Class dataSourceClass = Utility.loadClass(getDatasourceClassname());
		    // end IASRI 4669877
		    cachedVendorDataSource = dataSourceClass.newInstance();
		    ResourceProperty next;
		    for(Iterator iter = getProperties().iterator(); iter.hasNext(); ) {
			next = (ResourceProperty) iter.next();
			Utility.invokeSetMethodCaseInsensitive(cachedVendorDataSource, next.getName(), 
						next.getValue().toString());
		    }
		} catch(Exception e) {
		    e.printStackTrace();
		    throw new J2EEResourceException(e);
		}
	    }
	}
        return cachedVendorDataSource;
    }

    // end IASRI 4659935
    
    /**
     * Returns true if res-type is javax.sql.XADataSource and the data source class name
     * implements javax.sql.XADataSource; else false. 
     *
     * @return    true if data source class name is XA
     */
    public boolean isXA() {

        boolean tf = false;

	// first check the res-type
	if (this.resType_ == null) {
	    // default to non-xa
	    return false;
	}

        if (this.resType_.equals("javax.sql.XADataSource")
	    	&& this.datasourceClassname_ != null) {

            try {
                // if data source class implements javax.sql.XADataSource 
                // interface this pool supports global transactions
                // start IASRI 4713958
                // use common classloader  
                // Class dsClass = Class.forName(this.datasourceClassname_);
                Class dsClass = Utility.loadClass(getDatasourceClassname());
                // end IASRI 4713958
                if (javax.sql.XADataSource.class.isAssignableFrom(dsClass)) {
                    tf = true;
                }
            } catch (ClassNotFoundException e) {
                // ignore; return false
            } 
        }

	return tf;
    }

    /**
     * Returns true if res-type is javax.sql.ConnectionPoolDataSource 
     * and the data * source class name implements 
     * javax.sql.ConnectionPoolDataSource; else false. 
     *
     * @return    true if data source is ConnectionPoolDataSource
     */
    public boolean isCP() {

        boolean tf = false;
	// first check the res-type
	if (this.resType_ == null) {
	    // default to non-cp
	    return false;
	}

        if (this.resType_.equals("javax.sql.ConnectionPoolDataSource")
	    	&& this.datasourceClassname_ != null) {

            try {
                // if data source class implements javax.sql.ConnectionPoolDataSource 
                // use common classloader  
                // Class dsClass = Class.forName(this.datasourceClassname_);
                Class dsClass = Utility.loadClass(getDatasourceClassname());
                // end IASRI 4713958
                if (javax.sql.ConnectionPoolDataSource.class.isAssignableFrom(dsClass)) {
                    tf = true;
                }
            } catch (ClassNotFoundException e) {
                // ignore; return false
            } 
        }

	return tf;
    }

    /**
     * This method overides super's to intercept and capture relevant properties.
     */
    public void addProperty(ResourceProperty property) {
	//don't need to check for null here.

	String propName = property.getName();

	if (propName.equalsIgnoreCase("user")) {
	    setUserName((String)property.getValue());
	} else if (propName.equalsIgnoreCase("password")) {
	    setPassword((String)property.getValue());
	}

	// start HACK for bug4695569
	if (propName.equalsIgnoreCase("xa-driver-does-not-support-non-tx-operations")) {
	    if (((String)property.getValue()).equalsIgnoreCase("true")) {
		this.noNonTxOps = true;
	    }
	    return;
	}
	// end HACK for bug4695569
        // start IASRI 4691114
        // check if this pool has enable internal performance monitoring
      	if (propName.equalsIgnoreCase("perf-monitor")) {
	    if (((String)property.getValue()).equalsIgnoreCase("true")) {
		this.perfMonitor = true;
	    }
	    return;
	}
        // end IASRI 4691114
        

	super.addProperty(property);
    }

    // start IASRI 4691114
    // check if this pool has enable internal performance monitoring
    public boolean isPerfMonitor() {
        return perfMonitor;
    }
    //end IASRI 4691114 

    // start HACK for bug4695569
    private boolean noNonTxOps = false;

    public boolean getNoNonTxOps() {
	return noNonTxOps;
    }
    // end HACK for bug4695569
}
