001/* 002 * (C) Copyright 2006-2013 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 */ 020 021package org.nuxeo.runtime.datasource; 022 023import java.util.Enumeration; 024import java.util.HashMap; 025import java.util.Map; 026 027import javax.naming.Context; 028import javax.naming.NameClassPair; 029import javax.naming.NamingException; 030import javax.sql.DataSource; 031import javax.sql.XADataSource; 032 033import org.nuxeo.runtime.api.Framework; 034import org.nuxeo.runtime.jtajca.NuxeoContainer; 035 036/** 037 * Helper class to look up {@link DataSource}s without having to deal with vendor-specific JNDI prefixes. 038 * 039 * @author Thierry Delprat 040 * @author Florent Guillaume 041 */ 042public class DataSourceHelper { 043 044 private DataSourceHelper() { 045 } 046 047 /** 048 * Get the JNDI prefix used for DataSource lookups. 049 */ 050 public static String getDataSourceJNDIPrefix() { 051 return NuxeoContainer.nameOf("jdbc"); 052 } 053 054 /** 055 * Look up a datasource JNDI name given a partial name. 056 * <p> 057 * For a datasource {@code "jdbc/foo"}, then it's sufficient to pass {@code "foo"} to this method. 058 * 059 * @param partialName the partial name 060 * @return the datasource JNDI name 061 */ 062 public static String getDataSourceJNDIName(String name) { 063 return NuxeoContainer.nameOf(relativize(name)); 064 } 065 066 protected static String relativize(String name) { 067 int idx = name.lastIndexOf("/"); 068 if (idx > 0) { 069 name = name.substring(idx + 1); 070 } 071 return "jdbc/".concat(name); 072 } 073 074 /** 075 * Look up a datasource given a partial name. 076 * <p> 077 * For a datasource {@code "jdbc/foo"}, then it's sufficient to pass {@code "foo"} to this method. 078 * 079 * @param partialName the partial name 080 * @return the datasource 081 * @throws NamingException 082 */ 083 public static DataSource getDataSource(String partialName) throws NamingException { 084 return getDataSource(partialName, DataSource.class); 085 } 086 087 public static XADataSource getXADataSource(String partialName) throws NamingException { 088 return getDataSource(partialName, XADataSource.class); 089 } 090 091 public static <T> T getDataSource(String name, Class<T> clazz) throws NamingException { 092 PooledDataSourceRegistry pools = Framework.getService(PooledDataSourceRegistry.class); 093 if (pools == null) { 094 throw new NamingException("runtime datasource no installed"); 095 } 096 T ds = pools.getPool(relativize(name), clazz); 097 if (ds == null) { 098 return NuxeoContainer.lookup(name, clazz); 099 } 100 return ds; 101 } 102 103 public static Map<String, DataSource> getDatasources() throws NamingException { 104 String prefix = getDataSourceJNDIPrefix(); 105 Context naming = NuxeoContainer.getRootContext(); 106 if (naming == null) { 107 throw new NamingException("No root context"); 108 } 109 Context jdbc = (Context) naming.lookup(prefix); 110 Enumeration<NameClassPair> namesPair = jdbc.list(""); 111 Map<String, DataSource> datasourcesByName = new HashMap<>(); 112 while (namesPair.hasMoreElements()) { 113 NameClassPair pair = namesPair.nextElement(); 114 String name = pair.getName(); 115 if (pair.isRelative()) { 116 name = prefix + "/" + name; 117 } 118 Object ds = naming.lookup(name); 119 if (ds instanceof DataSource) { 120 datasourcesByName.put(name, (DataSource) ds); 121 } 122 } 123 return datasourcesByName; 124 } 125 126}