001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (C) 2012 Paul Ferraro 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Lesser General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package net.sf.hajdbc; 019 020import java.io.IOException; 021import java.io.ObjectInputStream; 022import java.io.ObjectOutputStream; 023import java.sql.SQLException; 024import java.util.Hashtable; 025import java.util.Map; 026 027import javax.naming.Context; 028import javax.naming.InitialContext; 029import javax.naming.NamingException; 030 031/** 032 * @author Paul Ferraro 033 */ 034public class ContextDatabaseClusterConfigurationFactory<Z, D extends Database<Z>> implements DatabaseClusterConfigurationFactory<Z, D> 035{ 036 private static final long serialVersionUID = -914797510468986091L; 037 038 private final Class<? extends DatabaseClusterConfiguration<Z, D>> targetClass; 039 private final String name; 040 private transient Context context; 041 042 public ContextDatabaseClusterConfigurationFactory(Class<? extends DatabaseClusterConfiguration<Z, D>> targetClass, String name) throws NamingException 043 { 044 this(targetClass, name, new InitialContext()); 045 } 046 047 public ContextDatabaseClusterConfigurationFactory(Class<? extends DatabaseClusterConfiguration<Z, D>> targetClass, String name, Hashtable<?, ?> env) throws NamingException 048 { 049 this(targetClass, name, new InitialContext(env)); 050 } 051 052 public ContextDatabaseClusterConfigurationFactory(Class<? extends DatabaseClusterConfiguration<Z, D>> targetClass, String name, Context context) 053 { 054 this.targetClass = targetClass; 055 this.name = name; 056 this.context = context; 057 } 058 059 /** 060 * {@inheritDoc} 061 * @see net.sf.hajdbc.DatabaseClusterConfigurationFactory#createConfiguration() 062 */ 063 @Override 064 public DatabaseClusterConfiguration<Z, D> createConfiguration() throws SQLException 065 { 066 try 067 { 068 return this.targetClass.cast(this.context.lookup(this.name)); 069 } 070 catch (NamingException e) 071 { 072 throw new SQLException(e); 073 } 074 } 075 076 /** 077 * {@inheritDoc} 078 * @see net.sf.hajdbc.DatabaseClusterConfigurationListener#added(net.sf.hajdbc.Database, net.sf.hajdbc.DatabaseClusterConfiguration) 079 */ 080 @Override 081 public void added(D database, DatabaseClusterConfiguration<Z, D> configuration) 082 { 083 this.rebind(configuration); 084 } 085 086 /** 087 * {@inheritDoc} 088 * @see net.sf.hajdbc.DatabaseClusterConfigurationListener#removed(net.sf.hajdbc.Database, net.sf.hajdbc.DatabaseClusterConfiguration) 089 */ 090 @Override 091 public void removed(D database, DatabaseClusterConfiguration<Z, D> configuration) 092 { 093 this.rebind(configuration); 094 } 095 096 private void rebind(DatabaseClusterConfiguration<Z, D> configuration) 097 { 098 try 099 { 100 this.context.rebind(this.name, configuration); 101 } 102 catch (NamingException e) 103 { 104 105 } 106 } 107 108 private void writeObject(ObjectOutputStream output) throws IOException 109 { 110 output.defaultWriteObject(); 111 112 try 113 { 114 Hashtable<?, ?> env = this.context.getEnvironment(); 115 116 output.writeInt((env != null) ? env.size() : 0); 117 118 for (Map.Entry<?, ?> entry: env.entrySet()) 119 { 120 output.writeUTF((String) entry.getKey()); 121 output.writeUTF((String) entry.getValue()); 122 } 123 } 124 catch (NamingException e) 125 { 126 throw new IOException(e); 127 } 128 } 129 130 private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException 131 { 132 input.defaultReadObject(); 133 134 int size = input.readInt(); 135 136 Hashtable<String, String> env = (size > 0) ? new Hashtable<String, String>() : null; 137 138 for (int i = 0; i < input.readInt(); ++i) 139 { 140 env.put(input.readUTF(), input.readUTF()); 141 } 142 143 try 144 { 145 this.context = new InitialContext(env); 146 } 147 catch (NamingException e) 148 { 149 throw new IOException(e); 150 } 151 } 152}