org.eclipse.ecr.runtime.api.DataSourceHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ecr.runtime.api.DataSourceHelper.java

Source

/*
 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Nuxeo - initial API and implementation
 *
 * $Id$
 */

package org.eclipse.ecr.runtime.api;

import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.spi.NamingManager;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Helper class to look up {@link DataSource}s without having to deal with
 * vendor-specific JNDI prefixes.
 *
 * @author Thierry Delprat
 * @author Florent Guillaume
 */
public class DataSourceHelper {

    private DataSourceHelper() {
    }

    protected static final class TestingInitialContext extends InitialContext {
        protected TestingInitialContext() throws NamingException {
            super(false); // lazy mode is breaking jboss
        }

        // subclass in order to access the protected method
        @Override
        public Context getDefaultInitCtx() throws NamingException {
            return super.getDefaultInitCtx();
        }
    }

    private static final Log log = LogFactory.getLog(DataSourceHelper.class);

    public static final String PREFIX_PROPERTY = "org.eclipse.ecr.runtime.datasource.prefix";

    public static final String DEFAULT_PREFIX = "java:comp/env/jdbc";

    protected static String prefix;

    public static void autodetectPrefix() {
        Context ctx = getDefaultInitCtx();
        String name = ctx == null ? null : ctx.getClass().getName();
        if ("org.nuxeo.common.jndi.NamingContext".equals(name)) { // Nuxeo-Embedded
            prefix = DEFAULT_PREFIX;
        } else if ("org.jnp.interfaces.NamingContext".equals(name)) { // JBoss
            prefix = "java:";
        } else if ("org.apache.naming.SelectorContext".equals(name)) { // Tomcat
            prefix = DEFAULT_PREFIX;
        } else if ("org.mortbay.naming.local.localContextRoot".equals(name)) { // Jetty
            prefix = "jdbc";
        } else if ("com.sun.enterprise.naming.impl.SerialContext".equals(name)) { // GlassFish
            prefix = DEFAULT_PREFIX;
        } else {
            // unknown, use Java EE standard
            log.error("Unknown JNDI Context class: " + name);
            prefix = DEFAULT_PREFIX;
        }
        log.info("Using JDBC JNDI prefix: " + prefix);
    }

    public static Context getDefaultInitCtx() {
        try {
            return new TestingInitialContext().getDefaultInitCtx();
        } catch (NamingException e) {
            return null;
        }
    }

    /**
     * Get the JNDI prefix used for DataSource lookups.
     */
    public static String getDataSourceJNDIPrefix() {
        if (prefix == null) {
            if (Framework.isInitialized()) {
                String configuredPrefix = Framework.getProperty(PREFIX_PROPERTY);
                if (configuredPrefix != null) {
                    prefix = configuredPrefix;
                } else {
                    autodetectPrefix();
                }
            } else {
                prefix = DEFAULT_PREFIX;
            }
        }
        return prefix;
    }

    /**
     * Look up a datasource JNDI name given a partial name.
     * <p>
     * For a datasource {@code "jdbc/foo"}, then it's sufficient to pass {@code
     * "foo"} to this method.
     *
     * @param partialName the partial name
     * @return the datasource JNDI name
     */
    public static String getDataSourceJNDIName(String partialName) {
        String targetPrefix = getDataSourceJNDIPrefix();
        // keep suffix only (jdbc/foo -> foo)
        int idx = partialName.lastIndexOf("/");
        if (idx > 0) {
            partialName = partialName.substring(idx + 1);
        }
        // add prefix
        return targetPrefix + "/" + partialName;
    }

    /**
     * Look up a datasource given a partial name.
     * <p>
     * For a datasource {@code "jdbc/foo"}, then it's sufficient to pass {@code
     * "foo"} to this method.
     *
     * @param partialName the partial name
     * @return the datasource
     * @throws NamingException
     */
    public static DataSource getDataSource(String partialName) throws NamingException {
        String jndiName = getDataSourceJNDIName(partialName);
        InitialContext context = new InitialContext();
        Object resolved = context.lookup(jndiName);
        if (resolved instanceof Reference) {
            try {
                resolved = NamingManager.getObjectInstance(resolved, new CompositeName(jndiName), context, null);
            } catch (Exception e) {
                throw new Error("Cannot get access to " + jndiName, e);
            }
        }
        return (DataSource) resolved;
    }

}