001/* 002 * Copyright (c) 2006-2013 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Nuxeo - initial API and implementation 011 * 012 */ 013 014package org.nuxeo.runtime.datasource; 015 016import java.util.Enumeration; 017import java.util.HashMap; 018import java.util.Map; 019 020import javax.naming.Context; 021import javax.naming.NameClassPair; 022import javax.naming.NameNotFoundException; 023import javax.naming.NamingException; 024import javax.sql.DataSource; 025import javax.sql.XADataSource; 026 027import org.nuxeo.runtime.api.Framework; 028import org.nuxeo.runtime.jtajca.NuxeoContainer; 029 030/** 031 * Helper class to look up {@link DataSource}s without having to deal with vendor-specific JNDI prefixes. 032 * 033 * @author Thierry Delprat 034 * @author Florent Guillaume 035 */ 036public class DataSourceHelper { 037 038 private DataSourceHelper() { 039 } 040 041 /** 042 * Get the JNDI prefix used for DataSource lookups. 043 */ 044 public static String getDataSourceJNDIPrefix() { 045 return NuxeoContainer.nameOf("jdbc"); 046 } 047 048 /** 049 * Look up a datasource JNDI name given a partial name. 050 * <p> 051 * For a datasource {@code "jdbc/foo"}, then it's sufficient to pass {@code "foo"} to this method. 052 * 053 * @param partialName the partial name 054 * @return the datasource JNDI name 055 */ 056 public static String getDataSourceJNDIName(String name) { 057 return NuxeoContainer.nameOf(relativize(name)); 058 } 059 060 protected static String relativize(String name) { 061 int idx = name.lastIndexOf("/"); 062 if (idx > 0) { 063 name = name.substring(idx + 1); 064 } 065 return "jdbc/".concat(name); 066 } 067 068 /** 069 * Look up a datasource given a partial name. 070 * <p> 071 * For a datasource {@code "jdbc/foo"}, then it's sufficient to pass {@code "foo"} to this method. 072 * 073 * @param partialName the partial name 074 * @return the datasource 075 * @throws NamingException 076 */ 077 public static DataSource getDataSource(String partialName) throws NamingException { 078 return getDataSource(partialName, DataSource.class); 079 } 080 081 public static XADataSource getXADataSource(String partialName) throws NamingException { 082 return getDataSource(partialName, XADataSource.class); 083 } 084 085 public static <T> T getDataSource(String name, Class<T> clazz) throws NamingException { 086 PooledDataSourceRegistry pools = Framework.getService(PooledDataSourceRegistry.class); 087 if (pools == null) { 088 throw new NamingException("runtime datasource no installed"); 089 } 090 T ds = pools.getPool(relativize(name), clazz); 091 if (ds == null) { 092 throw new NameNotFoundException(name + " not found in container"); 093 } 094 return ds; 095 } 096 097 public static Map<String, DataSource> getDatasources() throws NamingException { 098 String prefix = getDataSourceJNDIPrefix(); 099 Context naming = NuxeoContainer.getRootContext(); 100 if (naming == null) { 101 throw new NamingException("No root context"); 102 } 103 Context jdbc = (Context) naming.lookup(prefix); 104 Enumeration<NameClassPair> namesPair = jdbc.list(""); 105 Map<String, DataSource> datasourcesByName = new HashMap<String, DataSource>(); 106 while (namesPair.hasMoreElements()) { 107 NameClassPair pair = namesPair.nextElement(); 108 String name = pair.getName(); 109 if (pair.isRelative()) { 110 name = prefix + "/" + name; 111 } 112 Object ds = naming.lookup(name); 113 if (ds instanceof DataSource) { 114 datasourcesByName.put(name, (DataSource) ds); 115 } 116 } 117 return datasourcesByName; 118 } 119 120 /** 121 * @param repositoryName 122 * @return 123 * @since TODO 124 */ 125 public static String getDataSourceRepositoryJNDIName(String repositoryName) { 126 return getDataSourceJNDIName(ConnectionHelper.getPseudoDataSourceNameForRepository(repositoryName)); 127 } 128}