Package com.sun.enterprise.connectors

Source Code of com.sun.enterprise.connectors.ConnectionManagerImpl

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, 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/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package com.sun.enterprise.connectors;

import com.sun.appserv.connectors.internal.api.ConnectorConstants;
import com.sun.appserv.connectors.internal.api.ConnectorRuntimeException;
import com.sun.appserv.connectors.internal.api.ConnectorsUtil;
import com.sun.appserv.connectors.internal.api.PoolingException;
import com.sun.appserv.connectors.internal.spi.ConnectionManager;
import com.sun.enterprise.config.serverbeans.BindableResource;
import com.sun.enterprise.connectors.authentication.AuthenticationService;
import com.sun.enterprise.connectors.util.ConnectionPoolObjectsUtils;
import com.sun.enterprise.connectors.util.ResourcesUtil;
import com.sun.enterprise.deployment.ConnectorDescriptor;
import com.sun.enterprise.deployment.ResourcePrincipal;
import com.sun.enterprise.deployment.ResourceReferenceDescriptor;
import com.sun.enterprise.resource.ClientSecurityInfo;
import com.sun.enterprise.resource.ResourceSpec;
import com.sun.enterprise.resource.allocator.ConnectorAllocator;
import com.sun.enterprise.resource.allocator.LocalTxConnectorAllocator;
import com.sun.enterprise.resource.allocator.NoTxConnectorAllocator;
import com.sun.enterprise.resource.allocator.ResourceAllocator;
import com.sun.enterprise.resource.pool.PoolManager;
import com.sun.enterprise.security.SecurityContext;
import com.sun.enterprise.util.i18n.StringManager;
import com.sun.logging.LogDomains;
import org.glassfish.resourcebase.resources.api.PoolInfo;
import org.glassfish.resourcebase.resources.api.ResourceInfo;

import javax.resource.ResourceException;
import javax.resource.spi.*;
import javax.resource.spi.IllegalStateException;
import javax.security.auth.Subject;
import java.io.Serializable;
import java.security.Principal;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
* @author Tony Ng
*/
public class ConnectionManagerImpl implements ConnectionManager, Serializable {

    protected String jndiName;
    protected String logicalName;
    protected PoolInfo poolInfo;
    protected ResourceInfo resourceInfo;

    private volatile static Logger logger = LogDomains.getLogger(
            ConnectionManagerImpl.class,LogDomains.RSR_LOGGER);
    private volatile static StringManager localStrings = StringManager.getManager(
            ConnectionManagerImpl.class);

    protected String rarName;

    private transient BindableResource resourceConfiguration;

    protected ResourcePrincipal defaultPrin = null;

    public ConnectionManagerImpl(PoolInfo poolInfo, ResourceInfo resourceInfo) {
        this.poolInfo = poolInfo;
        this.resourceInfo = resourceInfo;
    }

    public void setJndiName(String jndiName) {
        this.jndiName = jndiName;
    }

    public String getJndiName() {
        return jndiName;
    }

    public void setLogicalName(String logicalName) {
        this.logicalName = logicalName;
    }

    public String getLogicalName() {
        return logicalName;
    }


/*
    public void setPoolInfo(PoolInfo poolInfo) {
        this.poolInfo = poolInfo;
    }
*/

    /**
     * Allocate a non transactional connection. This connection, even if
     * acquired in the context of an existing transaction, will never
     * be associated with a transaction
     * The typical use case may be to check the original contents of an EIS
     * when a transacted connection is changing the contents, and the tx
     * is yet to be committed.
     * <p/>
     * We create a ResourceSpec for a non tx connection with a name ending
     * in __nontx. This is to maintain uniformity with the scheme of having
     * __pm connections.
     * If one were to create a resource with a jndiName ending with __nontx
     * the same functionality might be achieved.
     */
    public Object allocateNonTxConnection(ManagedConnectionFactory mcf,
                                          ConnectionRequestInfo cxRequestInfo) throws ResourceException {
        String localJndiName = jndiName;

        logFine("Allocating NonTxConnection");

        //If a resource has been created with __nontx, we don't want to
        //add it again.
        //Otherwise we need to add __nontx at the end to ensure that the
        //mechanism to check for the correct resource manager still works
        //We do the addition if and only if we are getting this call
        //from a normal datasource and not a __nontx datasource.
        if (!jndiName.endsWith(ConnectorConstants.NON_TX_JNDI_SUFFIX)) {
            localJndiName = jndiName + ConnectorConstants.NON_TX_JNDI_SUFFIX;
            logFine("Adding __nontx to jndiname");
        } else {
            logFine("lookup happened from a __nontx datasource directly");
        }
        return allocateConnection(mcf, cxRequestInfo, localJndiName);
    }

    public Object allocateConnection(ManagedConnectionFactory mcf, ConnectionRequestInfo cxRequestInfo)
            throws ResourceException {
        return this.allocateConnection(mcf, cxRequestInfo, jndiName);
    }

    public Object allocateConnection(ManagedConnectionFactory mcf, ConnectionRequestInfo cxRequestInfo,
                                     String jndiNameToUse) throws ResourceException {
        return this.allocateConnection(mcf, cxRequestInfo, jndiNameToUse, null);
    }

    public Object allocateConnection(ManagedConnectionFactory mcf,
                                     ConnectionRequestInfo cxRequestInfo, String jndiNameToUse, Object conn)
            throws ResourceException {
        validateResourceAndPool();
        PoolManager poolmgr = ConnectorRuntime.getRuntime().getPoolManager();
        boolean resourceShareable = true;

        ResourceReferenceDescriptor ref =  poolmgr.getResourceReference(jndiNameToUse, logicalName);

        if (ref != null) {
            String shareableStr = ref.getSharingScope();

            if (shareableStr.equals(ref.RESOURCE_UNSHAREABLE)) {
                resourceShareable = false;
            }
        }

        //TODO V3 refactor all the 3 cases viz, no res-ref, app-auth, cont-auth.
        if (ref == null) {
            if(getLogger().isLoggable(Level.FINE)) {
                getLogger().log(Level.FINE, "poolmgr.no_resource_reference", jndiNameToUse);
            }
            return internalGetConnection(mcf, defaultPrin, cxRequestInfo,
                    resourceShareable, jndiNameToUse, conn, true);
        }
        String auth = ref.getAuthorization();

        if (auth.equals(ResourceReferenceDescriptor.APPLICATION_AUTHORIZATION)) {
            if (cxRequestInfo == null) {

                String msg = getLocalStrings().getString("con_mgr.null_userpass");
                throw new ResourceException(msg);
            }
            ConnectorRuntime.getRuntime().switchOnMatching(rarName, poolInfo);
            return internalGetConnection(mcf, null, cxRequestInfo,
                    resourceShareable, jndiNameToUse, conn, false);
        } else {
            ResourcePrincipal prin = null;
            Set principalSet = null;
            Principal callerPrincipal = null;
            SecurityContext securityContext = null;
            ConnectorRuntime connectorRuntime = ConnectorRuntime.getRuntime();
            //TODO V3 is SecurityContext.getCurrent() the right way ? Does it need to be injected ?
            if (connectorRuntime.isServer() &&
                    (securityContext = SecurityContext.getCurrent()) != null &&
                    (callerPrincipal = securityContext.getCallerPrincipal()) != null &&
                    (principalSet = securityContext.getPrincipalSet()) != null) {
                AuthenticationService authService =
                        connectorRuntime.getAuthenticationService(rarName, poolInfo);
                if (authService != null) {
                    prin = (ResourcePrincipal) authService.mapPrincipal(
                            callerPrincipal, principalSet);
                }
            }

            if (prin == null) {
                prin = ref.getResourcePrincipal();
                if (prin == null) {
                    if (getLogger().isLoggable(Level.FINE)) {
                        getLogger().log(Level.FINE, "default-resource-principal not"
                                + "specified for " + jndiNameToUse + ". Defaulting to"
                                + " user/password specified in the pool");
                    }
                    prin = defaultPrin;
                } else if (!prin.equals(defaultPrin)) {
                    ConnectorRuntime.getRuntime().switchOnMatching(rarName, poolInfo);
                }
            }
            return internalGetConnection(mcf, prin, cxRequestInfo,
                    resourceShareable, jndiNameToUse, conn, false);
        }
    }

    protected Object internalGetConnection(ManagedConnectionFactory mcf,
                                           final ResourcePrincipal prin, ConnectionRequestInfo cxRequestInfo,
                                           boolean shareable, String jndiNameToUse, Object conn, boolean isUnknownAuth)
            throws ResourceException {
        try {
            PoolManager poolmgr = ConnectorRuntime.getRuntime().getPoolManager();
            ConnectorRegistry registry = ConnectorRegistry.getInstance();
            PoolMetaData pmd = registry.getPoolMetaData(poolInfo);

            ResourceSpec spec = new ResourceSpec(jndiNameToUse,
                    ResourceSpec.JNDI_NAME, pmd);
            spec.setPoolInfo(this.poolInfo);
            ManagedConnectionFactory freshMCF = pmd.getMCF();

            if (getLogger().isLoggable(Level.INFO)) {
                if (!freshMCF.equals(mcf)) {
                    getLogger().info("conmgr.mcf_not_equal");
                }
            }
            ConnectorDescriptor desc = registry.getDescriptor(rarName);

            Subject subject = null;
            ClientSecurityInfo info = null;
            boolean subjectDefined = false;
            if (isUnknownAuth && rarName.equals(ConnectorConstants.DEFAULT_JMS_ADAPTER)
                    && !(pmd.isAuthCredentialsDefinedInPool())) {
                //System.out.println("Unkown Auth - pobably nonACC client");
                //Unknown authorization. This is the case for standalone java clients,
                //where the authorization is neither container nor component
                //managed. In this case we associate an non-null Subject with no
                //credentials, so that the RA can either use its own custom logic
                //for figuring out the credentials. Relevant connector spec section
                //is 9.1.8.2.
                //create non-null Subject associated with no credentials
                //System.out.println("RAR name "+ rarName);
                subject = ConnectionPoolObjectsUtils.createSubject(mcf, null);
            } else {
                if (prin == null) {
                    info = new ClientSecurityInfo(cxRequestInfo);
                } else {
                    info = new ClientSecurityInfo(prin);
                    if (prin.equals(defaultPrin)) {
                        subject = pmd.getSubject();
                    } else {
                        subject = ConnectionPoolObjectsUtils.createSubject(mcf, prin);
                    }
                }
            }

            int txLevel = pmd.getTransactionSupport();
            if (getLogger().isLoggable(Level.FINE)) {
                logFine("ConnectionMgr: poolName " + poolInfo +
                        "  txLevel : " + txLevel);
            }

             if ( conn != null ) {
                 spec.setConnectionToAssociate( conn );
             }


            return getResource(txLevel, poolmgr, mcf, spec, subject, cxRequestInfo, info, desc, shareable);

        } catch (PoolingException ex) {
            Object[] params = new Object[]{poolInfo, ex};
            getLogger().log(Level.WARNING, "poolmgr.get_connection_failure", params);
            String i18nMsg = getLocalStrings().getString("con_mgr.error_creating_connection", ex.getMessage());
            ResourceAllocationException rae = new ResourceAllocationException(i18nMsg);
            rae.initCause(ex);
            throw rae;
        }
    }

    private Object getResource(int txLevel, PoolManager poolmgr, ManagedConnectionFactory mcf, ResourceSpec spec,
                               Subject subject, ConnectionRequestInfo cxRequestInfo, ClientSecurityInfo info,
                               ConnectorDescriptor desc, boolean shareable)
            throws PoolingException, ResourceAllocationException, IllegalStateException, RetryableUnavailableException {
        ResourceAllocator alloc;

        switch (txLevel) {
            case ConnectorConstants.NO_TRANSACTION_INT:
                alloc = new NoTxConnectorAllocator(poolmgr, mcf, spec, subject, cxRequestInfo, info, desc);
                break;
            case ConnectorConstants.LOCAL_TRANSACTION_INT:
                alloc = new LocalTxConnectorAllocator(poolmgr, mcf, spec, subject, cxRequestInfo, info, desc, shareable);
                break;
            case ConnectorConstants.XA_TRANSACTION_INT:
                if (rarName.equals(ConnectorRuntime.DEFAULT_JMS_ADAPTER)) {
                    shareable = false;
                }
                spec.markAsXA();
                alloc = new ConnectorAllocator(poolmgr, mcf, spec, subject, cxRequestInfo, info, desc, shareable);
                return poolmgr.getResource(spec, alloc, info);
           
            default:
                String i18nMsg = getLocalStrings().getString("con_mgr.illegal_tx_level", txLevel + " ");
                throw new IllegalStateException(i18nMsg);
        }
        return poolmgr.getResource(spec, alloc, info);
    }


    public void setRarName(String _rarName) {
        rarName = _rarName;
    }

    public String getRarName() {
        return rarName;
    }

    /*
    * This method is called from the ConnectorObjectFactory lookup
    * With this we move all the housekeeping work in allocateConnection
    * up-front
    */
    public void initialize() throws ConnectorRuntimeException {

        ConnectorRuntime runtime = ConnectorRuntime.getRuntime();

        if(runtime.isNonACCRuntime()){
            jndiName = ConnectorsUtil.getPMJndiName(jndiName);
        }
        ConnectorRegistry registry = ConnectorRegistry.getInstance();
        PoolMetaData pmd = registry.getPoolMetaData(poolInfo);
        defaultPrin = pmd.getResourcePrincipal();
    }

    private void validateResourceAndPool() throws ResourceException {
        ResourceInfo resourceInfo = this.resourceInfo;
        ResourcesUtil resourcesUtil = ResourcesUtil.createInstance();

        ConnectorRuntime runtime = ConnectorRuntime.getRuntime();
        ConnectorRegistry registry = ConnectorRegistry.getInstance();
        // adding a perf. optimization check so that "config-bean" is not accessed at all for
        // cases where the resource is enabled (deployed). Only for cases where resource
        // is not available, we look further and determine whether resource/resource-ref
        // are disabled.
        if (!registry.isResourceDeployed(resourceInfo)) {
            if(logger.isLoggable(Level.FINEST)){
                logger.log(Level.FINEST,"resourceInfo not found in connector-registry : " + resourceInfo);
            }
            boolean isDefaultResource = false;
            boolean isSunRAResource = false;
            ConnectorDescriptor descriptor = registry.getDescriptor(rarName);
            if (descriptor != null) {
                isDefaultResource = descriptor.getDefaultResourcesNames().contains(resourceInfo.getName());
                if (descriptor.getSunDescriptor() != null) {
                    com.sun.enterprise.deployment.runtime.connector.ResourceAdapter rar =
                            descriptor.getSunDescriptor().getResourceAdapter();
                    if (rar != null) {
                        String sunRAJndiName = (String)
                                rar.getValue(com.sun.enterprise.deployment.runtime.connector.ResourceAdapter.JNDI_NAME);
                        isSunRAResource = resourceInfo.getName().equals(sunRAJndiName);
                    }
                }
            }

            if ((runtime.isServer() || runtime.isEmbedded()) &&
                    (!resourceInfo.getName().contains(ConnectorConstants.DATASOURCE_DEFINITION_JNDINAME_PREFIX) &&
                            (!isDefaultResource) && (!isSunRAResource))) {
                // performance optimization so that resource configuration is not retrieved from
                // resources config bean each time.
                if (resourceConfiguration == null) {
                    resourceConfiguration =
                            (BindableResource) resourcesUtil.getResource(resourceInfo, BindableResource.class);
                    if (resourceConfiguration == null) {
                        String suffix = ConnectorsUtil.getValidSuffix(resourceInfo.getName());
                        // it is possible that the resource is a __PM or __NONTX suffixed resource used by JPA/EJB Container
                        // check for the enabled status and existence using non-prefixed resource-name
                        if (suffix != null) {
                            String nonPrefixedName = resourceInfo.getName().substring(0, resourceInfo.getName().lastIndexOf(suffix));
                            resourceInfo = new ResourceInfo(nonPrefixedName, resourceInfo.getApplicationName(),
                                    resourceInfo.getModuleName());
                            resourceConfiguration = (BindableResource)
                                    resourcesUtil.getResource(resourceInfo, BindableResource.class);
                        }
                    }
                } else {
                    // we cache the resourceConfiguration for performance optimization.
                    // make sure that appropriate (actual) resourceInfo is used for validation.
                    String suffix = ConnectorsUtil.getValidSuffix(resourceInfo.getName());
                    // it is possible that the resource is a __PM or __NONTX suffixed resource used by JPA/EJB Container
                    // check for the enabled status and existence using non-prefixed resource-name
                    if (suffix != null) {
                        String nonPrefixedName = resourceInfo.getName().substring(0, resourceInfo.getName().lastIndexOf(suffix));
                        resourceInfo = new ResourceInfo(nonPrefixedName, resourceInfo.getApplicationName(),
                                resourceInfo.getModuleName());
                    }
                }
                if (resourceConfiguration == null) {
                    throw new ResourceException("No such resource : " + resourceInfo);
                }
                if (!resourcesUtil.isEnabled(resourceConfiguration, resourceInfo)) {
                    throw new ResourceException(resourceInfo + " is not enabled");
                }
            }
        }

        if (registry.getPoolMetaData(poolInfo) == null) {
            String msg = getLocalStrings().getString("con_mgr.no_pool_meta_data", poolInfo);
            throw new ResourceException(poolInfo + ": " + msg);
        }
    }

    public void logFine(String message) {
        if (getLogger().isLoggable(Level.FINE)) {
            getLogger().fine(message);
        }
    }

    private static StringManager getLocalStrings() {
        if (localStrings == null) {
            synchronized (ConnectionManagerImpl.class) {
                if (localStrings == null) {
                    localStrings = StringManager.getManager(ConnectionManagerImpl.class);
                }
            }
        }
        return localStrings;
    }

    protected static Logger getLogger() {
        if (logger == null){
            synchronized(ConnectionManagerImpl.class) {
                if(logger == null) {
                    logger = LogDomains.getLogger(ConnectionManagerImpl.class,LogDomains.RSR_LOGGER);
                }
            }
        }
        return logger;
    }
}
TOP

Related Classes of com.sun.enterprise.connectors.ConnectionManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.