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.state.sql;
019
020import java.sql.Driver;
021import java.sql.DriverManager;
022import java.sql.SQLException;
023import java.text.MessageFormat;
024import java.util.Collections;
025
026import net.sf.hajdbc.Database;
027import net.sf.hajdbc.DatabaseCluster;
028import net.sf.hajdbc.logging.Level;
029import net.sf.hajdbc.logging.Logger;
030import net.sf.hajdbc.logging.LoggerFactory;
031import net.sf.hajdbc.pool.generic.GenericObjectPoolConfiguration;
032import net.sf.hajdbc.pool.generic.GenericObjectPoolFactory;
033import net.sf.hajdbc.sql.DriverDatabase;
034import net.sf.hajdbc.state.StateManager;
035import net.sf.hajdbc.state.StateManagerFactory;
036import net.sf.hajdbc.util.Strings;
037
038/**
039 * @author Paul Ferraro
040 */
041public class SQLStateManagerFactory extends GenericObjectPoolConfiguration implements StateManagerFactory
042{
043        private static final long serialVersionUID = -544548607415128414L;
044        
045        private Logger logger = LoggerFactory.getLogger(this.getClass());
046        
047        enum EmbeddedVendor
048        {
049                H2("jdbc:h2:{1}/{0}"),
050                HSQLDB("jdbc:hsqldb:{1}/{0}"),
051                DERBY("jdbc:derby:{1}/{0};create=true")
052                ;
053                
054                final String pattern;
055                
056                EmbeddedVendor(String pattern)
057                {
058                        this.pattern = pattern;
059                }
060        }
061        
062        private String urlPattern = defaultUrlPattern();
063        private String user;
064        private String password;
065        
066        private static String defaultUrlPattern()
067        {
068                for (EmbeddedVendor vendor: EmbeddedVendor.values())
069                {
070                        String url = MessageFormat.format(vendor.pattern, "test", Strings.HA_JDBC_HOME);
071                        
072                        try
073                        {
074                                for (Driver driver: Collections.list(DriverManager.getDrivers()))
075                                {
076                                        if (driver.acceptsURL(url))
077                                        {
078                                                return vendor.pattern;
079                                        }
080                                }
081                        }
082                        catch (SQLException e)
083                        {
084                                // Skip vendor
085                        }
086                }
087                
088                return null;
089        }
090        
091        @Override
092        public String getId()
093        {
094                return "sql";
095        }
096
097        /**
098         * {@inheritDoc}
099         * @see net.sf.hajdbc.state.StateManagerFactory#createStateManager(net.sf.hajdbc.DatabaseCluster)
100         */
101        @Override
102        public <Z, D extends Database<Z>> StateManager createStateManager(DatabaseCluster<Z, D> cluster)
103        {
104                if (this.urlPattern == null)
105                {
106                        throw new IllegalArgumentException("No embedded database driver was detected on the classpath.");
107                }
108                
109                String url = MessageFormat.format(this.urlPattern, cluster.getId(), Strings.HA_JDBC_HOME);
110                DriverDatabase database = new DriverDatabase();
111                database.setLocation(url);
112                database.setUser(this.user);
113                database.setPassword(this.password);
114                
115                this.logger.log(Level.INFO, "State for database cluster {0} will be persisted to {1}", cluster, url);
116                
117                return new SQLStateManager<Z, D>(cluster, database, new GenericObjectPoolFactory(this));
118        }
119        
120        public String getUrlPattern()
121        {
122                return this.urlPattern;
123        }
124        
125        public void setUrlPattern(String urlPattern)
126        {
127                this.urlPattern = urlPattern;
128        }
129
130        public String getUser()
131        {
132                return this.user;
133        }
134        
135        public void setUser(String user)
136        {
137                this.user = user;
138        }
139
140        public String getPassword()
141        {
142                return this.password;
143        }
144        
145        public void setPassword(String password)
146        {
147                this.password = password;
148        }
149}