Package com.googlecode.psiprobe.beans

Source Code of com.googlecode.psiprobe.beans.ResourceResolverBean

/*
* Licensed under the GPL License.  You may not use this file except in
* compliance with the License.  You may obtain a copy of the License at
*
*     http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
package com.googlecode.psiprobe.beans;

import com.googlecode.psiprobe.model.ApplicationResource;
import com.googlecode.psiprobe.model.DataSourceInfo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.apache.catalina.Context;
import org.apache.catalina.deploy.ContextResource;
import org.apache.catalina.deploy.ContextResourceLink;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.modeler.Registry;
import org.apache.naming.ContextBindings;

public class ResourceResolverBean implements ResourceResolver {

    private Log logger = LogFactory.getLog(getClass());

    /**
     * The default resource prefix for JNDI objects in the global scope:
     * <code>java:</code>.
     */
    public static final String DEFAULT_GLOBAL_RESOURCE_PREFIX = "java:";

    /**
     * The default resource prefix for objects in a private application scope:
     * <code>java:comp/env/</code>.
     */
    public static final String DEFAULT_RESOURCE_PREFIX = DEFAULT_GLOBAL_RESOURCE_PREFIX + "comp/env/";

    private List datasourceMappers;

    public List getApplicationResources() throws NamingException {
        logger.info("Reading GLOBAL resources");
        List resources = new ArrayList();

        MBeanServer server = getMBeanServer();
        if (server != null) {
            try {
                Set dsNames = server.queryNames(new ObjectName("Catalina:type=Resource,resourcetype=Global,*"), null);
                for (Iterator it = dsNames.iterator(); it.hasNext();) {
                    ObjectName objectName = (ObjectName) it.next();
                    ApplicationResource resource = new ApplicationResource();

                    logger.info("reading resource: " + objectName);
                    resource.setName(getStringAttribute(server, objectName, "name"));
                    resource.setType(getStringAttribute(server, objectName, "type"));
                    resource.setScope(getStringAttribute(server, objectName, "scope"));
                    resource.setAuth(getStringAttribute(server, objectName, "auth"));
                    resource.setDescription(getStringAttribute(server, objectName, "description"));

                    lookupResource(resource, true, true);

                    resources.add(resource);
                }
            } catch (Exception e) {
                logger.error("There was an error querying JMX server:", e);
            }
        }
        return resources;
    }

    public synchronized List getApplicationResources(Context context) throws NamingException {

        List resourceList = new ArrayList();

        if (context.getAvailable()) {

            logger.info("Reading CONTEXT " + context.getName());

            boolean contextBound = false;

            try {
                ContextBindings.bindClassLoader(context, null, Thread.currentThread().getContextClassLoader());
                contextBound = true;
            } catch (NamingException e) {
                logger.error("Cannot bind to context. useNaming=false ?");
                logger.debug(e);
            }

            try {
                ContextResource[] resources = context.getNamingResources().findResources();
                for (int i = 0; i < resources.length; i++) {
                    ContextResource contextResource = resources[i];
                    ApplicationResource resource = new ApplicationResource();

                    logger.info("reading resource: " + contextResource.getName());
                    resource.setApplicationName(context.getName());
                    resource.setName(contextResource.getName());
                    resource.setType(contextResource.getType());
                    resource.setScope(contextResource.getScope());
                    resource.setAuth(contextResource.getAuth());
                    resource.setDescription(contextResource.getDescription());

                    lookupResource(resource, contextBound, false);

                    resourceList.add(resource);
                }

                ContextResourceLink[] resourceLinks = context.getNamingResources().findResourceLinks();
                for (int i = 0; i < resourceLinks.length; i++) {
                    ContextResourceLink link = resourceLinks[i];

                    ApplicationResource resource = new ApplicationResource();
                    logger.debug("reading resourceLink: " + link.getName());
                    resource.setApplicationName(context.getName());
                    resource.setName(link.getName());
                    resource.setType(link.getType());
                    resource.setLinkTo(link.getGlobal());

                    lookupResource(resource, contextBound, false);
                   
                    resourceList.add(resource);
                }
            } finally {

                if (contextBound) {
                    ContextBindings.unbindClassLoader(context, null, Thread.currentThread().getContextClassLoader());
                }
            }
        }

        return resourceList;
    }

    public void lookupResource(ApplicationResource resource, boolean contextBound, boolean global) {
        DataSourceInfo dataSourceInfo = null;
        if (contextBound) {
            try {
                String jndiName = resolveJndiName(resource.getName(), global);
                Object o = new InitialContext().lookup(jndiName);
                resource.setLookedUp(true);
                for (Iterator it = datasourceMappers.iterator(); it.hasNext();) {
                    DatasourceAccessor accessor = (DatasourceAccessor) it.next();
                    dataSourceInfo = accessor.getInfo(o);
                    if (dataSourceInfo != null) {
                        break;
                    }
                }

            } catch (Throwable e) {
                resource.setLookedUp(false);
                dataSourceInfo = null;
                logger.error("Failed to lookup: " + resource.getName(), e);
                //
                // make sure we always re-throw ThreadDeath
                //
                if (e instanceof ThreadDeath) {
                    throw (ThreadDeath) e;
                }
            }
        } else {
            resource.setLookedUp(false);
        }

        //
        // Tomcat 5.0.x DBCP datasources would have URL set to null if they incorrectly configured
        // so we need to deal with this little feature
        //
        if (dataSourceInfo != null && dataSourceInfo.getJdbcURL() == null) {
            resource.setLookedUp(false);
        }

        if (resource.isLookedUp() && dataSourceInfo != null) {
            resource.setDataSourceInfo(dataSourceInfo);
        }
    }

    public synchronized boolean resetResource(final Context context, String resourceName) throws NamingException {
        if (context != null) {
            ContextBindings.bindClassLoader(context, null, Thread.currentThread().getContextClassLoader());
        }
        try {
            String jndiName = resolveJndiName(resourceName, (context == null));
            Object o = new InitialContext().lookup(jndiName);
            try {
                for (Iterator it = datasourceMappers.iterator(); it.hasNext();) {
                    DatasourceAccessor accessor = (DatasourceAccessor) it.next();
                    if (accessor.reset(o)) {
                        return true;
                    }
                }
                return false;
            } catch (Throwable e) {
                //
                // make sure we always re-throw ThreadDeath
                //
                if (e instanceof ThreadDeath) {
                    throw (ThreadDeath) e;
                }
                return false;
            }
        } finally {
            if (context != null) {
                ContextBindings.unbindClassLoader(context, null, Thread.currentThread().getContextClassLoader());
            }
        }
    }

    public synchronized DataSource lookupDataSource(final Context context, String resourceName) throws NamingException {
        if (context != null) {
            ContextBindings.bindClassLoader(context, null, Thread.currentThread().getContextClassLoader());
        }
        try {
            String jndiName = resolveJndiName(resourceName, (context == null));
            Object o = new InitialContext().lookup(jndiName);

            if (o instanceof DataSource) {
                return (DataSource) o;
            } else {
                return null;
            }
        } finally {
            if (context != null) {
                ContextBindings.unbindClassLoader(context, null, Thread.currentThread().getContextClassLoader());
            }
        }
    }

    public List getDatasourceMappers() {
        return datasourceMappers;
    }

    public void setDatasourceMappers(List datasourceMappers) {
        this.datasourceMappers = datasourceMappers;
    }

    public boolean supportsPrivateResources() {
        return true;
    }

    public boolean supportsGlobalResources() {
        return true;
    }

    public boolean supportsDataSourceLookup() {
        return true;
    }

    public MBeanServer getMBeanServer() {
        return new Registry().getMBeanServer();
    }

    /**
     * Resolves a JNDI resource name by prepending the scope-appropriate prefix.
     *
     * @param global whether to use the global prefix
     * @param name the JNDI name of the resource
     *
     * @return the JNDI resource name with the prefix appended
     *
     * @see #DEFAULT_GOBAL_RESOURCE_PREFIX
     * @see #DEFAULT_RESOURCE_PREFIX
     */
    protected static String resolveJndiName(String name, boolean global) {
        return (global ? DEFAULT_GLOBAL_RESOURCE_PREFIX : DEFAULT_RESOURCE_PREFIX) + name;
    }

    private String getStringAttribute(MBeanServer server, ObjectName objectName, String attributeName) {
        try {
            return (String) server.getAttribute(objectName, attributeName);
        } catch (Exception e) {
            logger.error("Error getting attribute '" + attributeName + "' from '" + objectName + "'", e);
            return null;
        }
    }

}
TOP

Related Classes of com.googlecode.psiprobe.beans.ResourceResolverBean

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.