/*
* (C) Copyright 2006-2013 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Nuxeo - initial API and implementation
*
*/
package org.nuxeo.runtime.datasource;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.naming.Context;
import javax.naming.NameClassPair;
import javax.naming.NamingException;
import javax.sql.DataSource;
import javax.sql.XADataSource;
import org.nuxeo.runtime.api.Framework;
import org.nuxeo.runtime.jtajca.NuxeoContainer;
/**
* 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() {
}
/**
* Get the JNDI prefix used for DataSource lookups.
*/
public static String getDataSourceJNDIPrefix() {
return NuxeoContainer.nameOf("jdbc");
}
/**
* 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 name) {
return NuxeoContainer.nameOf(relativize(name));
}
protected static String relativize(String name) {
int idx = name.lastIndexOf("/");
if (idx > 0) {
name = name.substring(idx + 1);
}
return "jdbc/".concat(name);
}
/**
* 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 {
return getDataSource(partialName, DataSource.class);
}
public static XADataSource getXADataSource(String partialName) throws NamingException {
return getDataSource(partialName, XADataSource.class);
}
public static <T> T getDataSource(String name, Class<T> clazz) throws NamingException {
PooledDataSourceRegistry pools = Framework.getService(PooledDataSourceRegistry.class);
if (pools == null) {
throw new NamingException("runtime datasource no installed");
}
T ds = pools.getPool(relativize(name), clazz);
if (ds == null) {
return NuxeoContainer.lookup(name, clazz);
}
return ds;
}
public static Map<String, DataSource> getDatasources() throws NamingException {
String prefix = getDataSourceJNDIPrefix();
Context naming = NuxeoContainer.getRootContext();
if (naming == null) {
throw new NamingException("No root context");
}
Context jdbc = (Context) naming.lookup(prefix);
Enumeration<NameClassPair> namesPair = jdbc.list("");
Map<String, DataSource> datasourcesByName = new HashMap<>();
while (namesPair.hasMoreElements()) {
NameClassPair pair = namesPair.nextElement();
String name = pair.getName();
if (pair.isRelative()) {
name = prefix + "/" + name;
}
Object ds = naming.lookup(name);
if (ds instanceof DataSource) {
datasourcesByName.put(name, (DataSource) ds);
}
}
return datasourcesByName;
}
}