001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (c) 2004-2008 Paul Ferraro 004 * 005 * This library is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Lesser General Public License as published by the 007 * Free Software Foundation; either version 2.1 of the License, or (at your 008 * option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, but WITHOUT 011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 013 * for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License 016 * along with this library; if not, write to the Free Software Foundation, 017 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018 * 019 * Contact: ferraro@users.sourceforge.net 020 */ 021package net.sf.hajdbc.sql; 022 023import java.beans.IntrospectionException; 024import java.beans.Introspector; 025import java.beans.PropertyDescriptor; 026import java.beans.PropertyEditor; 027import java.beans.PropertyEditorManager; 028import java.lang.reflect.InvocationTargetException; 029import java.util.Properties; 030 031import javax.management.DynamicMBean; 032import javax.management.NotCompliantMBeanException; 033import javax.management.StandardMBean; 034import javax.naming.Context; 035import javax.naming.InitialContext; 036import javax.naming.NamingException; 037 038import net.sf.hajdbc.Messages; 039 040/** 041 * A database described by a data source. 042 * @author Paul Ferraro 043 * @param <D> <code>javax.sql</code> data source interface 044 */ 045public abstract class CommonDataSourceDatabase<D> extends AbstractDatabase<D> implements InactiveDataSourceDatabaseMBean 046{ 047 private String name; 048 private Class<D> targetClass; 049 050 protected CommonDataSourceDatabase(Class<D> targetClass) 051 { 052 this.targetClass = targetClass; 053 } 054 055 /** 056 * @see net.sf.hajdbc.sql.ActiveDataSourceDatabaseMBean#getName() 057 */ 058 @Override 059 public String getName() 060 { 061 return this.name; 062 } 063 064 /** 065 * @see net.sf.hajdbc.sql.InactiveDataSourceDatabaseMBean#setName(java.lang.String) 066 */ 067 @Override 068 public void setName(String name) 069 { 070 this.checkDirty(this.name, name); 071 this.name = name; 072 } 073 074 /** 075 * @see net.sf.hajdbc.Database#createConnectionFactory() 076 */ 077 @Override 078 public D createConnectionFactory() 079 { 080 try 081 { 082 Class<?> dataSourceClass = Class.forName(this.name); 083 084 return this.createDataSource(dataSourceClass.asSubclass(this.targetClass)); 085 } 086 catch (ClassNotFoundException e) 087 { 088 return this.createDataSource(); 089 } 090 } 091 092 private D createDataSource() 093 { 094 try 095 { 096 Context context = new InitialContext(this.getProperties()); 097 098 return this.targetClass.cast(context.lookup(this.name)); 099 } 100 catch (NamingException e) 101 { 102 throw new IllegalArgumentException(Messages.getMessage(Messages.JNDI_LOOKUP_FAILED, this.name), e); 103 } 104 } 105 106 private D createDataSource(Class<? extends D> dataSourceClass) 107 { 108 Properties properties = this.getProperties(); 109 110 try 111 { 112 D dataSource = dataSourceClass.newInstance(); 113 114 for (PropertyDescriptor descriptor: Introspector.getBeanInfo(dataSourceClass).getPropertyDescriptors()) 115 { 116 String value = properties.getProperty(descriptor.getName()); 117 118 if (value != null) 119 { 120 PropertyEditor editor = PropertyEditorManager.findEditor(descriptor.getPropertyType()); 121 122 editor.setAsText(value); 123 124 descriptor.getWriteMethod().invoke(dataSource, editor.getValue()); 125 } 126 } 127 128 return dataSource; 129 } 130 catch (InstantiationException e) 131 { 132 throw new IllegalArgumentException(e.toString(), e); 133 } 134 catch (IllegalAccessException e) 135 { 136 throw new IllegalArgumentException(e.toString(), e); 137 } 138 catch (IntrospectionException e) 139 { 140 throw new IllegalArgumentException(e.toString(), e); 141 } 142 catch (InvocationTargetException e) 143 { 144 throw new IllegalArgumentException(e.getTargetException().toString(), e); 145 } 146 } 147 148 /** 149 * @see net.sf.hajdbc.Database#getActiveMBean() 150 */ 151 @Override 152 public DynamicMBean getActiveMBean() 153 { 154 try 155 { 156 return new StandardMBean(this, ActiveDataSourceDatabaseMBean.class); 157 } 158 catch (NotCompliantMBeanException e) 159 { 160 throw new IllegalStateException(e); 161 } 162 } 163 164 /** 165 * @see net.sf.hajdbc.Database#getInactiveMBean() 166 */ 167 @Override 168 public DynamicMBean getInactiveMBean() 169 { 170 try 171 { 172 return new StandardMBean(this, InactiveDataSourceDatabaseMBean.class); 173 } 174 catch (NotCompliantMBeanException e) 175 { 176 throw new IllegalStateException(e); 177 } 178 } 179}