View Javadoc

1   /*
2    * SymmetricDS is an open source database synchronization solution.
3    *   
4    * Copyright (C) Chris Henson <chenson42@users.sourceforge.net>
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 3 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, see
18   * <http://www.gnu.org/licenses/>.
19   */
20  
21  package org.jumpmind.symmetric.db;
22  
23  import java.sql.Connection;
24  import java.sql.DatabaseMetaData;
25  import java.sql.SQLException;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.ddlutils.Platform;
30  import org.apache.ddlutils.PlatformFactory;
31  import org.apache.ddlutils.platform.db2.Db2Platform;
32  import org.apache.ddlutils.platform.derby.DerbyPlatform;
33  import org.apache.ddlutils.platform.firebird.FirebirdPlatform;
34  import org.apache.ddlutils.platform.hsqldb.HsqlDbPlatform;
35  import org.apache.ddlutils.platform.mssql.MSSqlPlatform;
36  import org.apache.ddlutils.platform.mysql.MySqlPlatform;
37  import org.apache.ddlutils.platform.oracle.Oracle10Platform;
38  import org.apache.ddlutils.platform.oracle.Oracle8Platform;
39  import org.apache.ddlutils.platform.postgresql.PostgreSqlPlatform;
40  import org.springframework.beans.factory.BeanFactory;
41  import org.springframework.beans.factory.BeanFactoryAware;
42  import org.springframework.beans.factory.FactoryBean;
43  import org.springframework.dao.DataAccessException;
44  import org.springframework.jdbc.CannotGetJdbcConnectionException;
45  import org.springframework.jdbc.core.ConnectionCallback;
46  import org.springframework.jdbc.core.JdbcTemplate;
47  import org.springframework.transaction.support.TransactionTemplate;
48  
49  public class DbDialectFactory implements FactoryBean, BeanFactoryAware {
50  
51      private static final Log logger = LogFactory.getLog(DbDialectFactory.class);
52  
53      private JdbcTemplate jdbcTemplate;
54  
55      private BeanFactory beanFactory;
56  
57      public Object getObject() throws Exception {
58  
59          waitForAvailableDatabase();
60  
61          String productName = getDbProductName();
62          int majorVersion = getDbMajorVersion();
63  
64          // Try to use latest version of platform, then fallback on default
65          // platform
66          String productString = productName + majorVersion;
67          if (productName.startsWith("DB2")) {
68              productString = "DB2v8";
69          }
70          Platform pf = PlatformFactory.createNewPlatformInstance(productString);
71          if (pf == null) {
72              pf = PlatformFactory.createNewPlatformInstance(jdbcTemplate.getDataSource());
73          } else {
74              pf.setDataSource(jdbcTemplate.getDataSource());
75          }
76  
77          AbstractDbDialect dialect = null;
78  
79          if (pf instanceof MySqlPlatform) {
80              dialect = (AbstractDbDialect) beanFactory.getBean("mysqlDialect");
81          } else if (pf instanceof Oracle8Platform) {
82              dialect = (AbstractDbDialect) beanFactory.getBean("oracleDialect");
83          } else if (pf instanceof Oracle10Platform) {
84              dialect = (AbstractDbDialect) beanFactory.getBean("oracleDialect");
85          } else if (pf instanceof MSSqlPlatform) {
86              dialect = (AbstractDbDialect) beanFactory.getBean("msSqlDialect");
87          } else if (pf instanceof PostgreSqlPlatform) {
88              dialect = (AbstractDbDialect) beanFactory.getBean("postgresqlDialect");
89          } else if (pf instanceof DerbyPlatform) {
90              dialect = (AbstractDbDialect) beanFactory.getBean("derbyDialect");
91          } else if (pf instanceof HsqlDbPlatform) {
92              dialect = (AbstractDbDialect) beanFactory.getBean("hsqldbDialect");
93          } else if (pf instanceof Db2Platform) {
94              dialect = (AbstractDbDialect) beanFactory.getBean("db2Dialect");
95          } else if (pf instanceof FirebirdPlatform) {
96              dialect = (AbstractDbDialect) beanFactory.getBean("firebirdDialect");
97          } else {
98              throw new DbNotSupportedException();
99          }
100 
101         dialect.init(pf);
102         dialect.setTransactionTemplate((TransactionTemplate) beanFactory.getBean("currentTransactionTemplate"));
103         return dialect;
104     }
105 
106     private void waitForAvailableDatabase() {
107         boolean success = false;
108         while (!success) {
109             try {
110                 jdbcTemplate.execute(new ConnectionCallback() {
111                     public Object doInConnection(Connection con) throws SQLException, DataAccessException {
112                         return null;
113                     }
114                 });
115                 success = true;
116             } catch (CannotGetJdbcConnectionException ex) {
117                 logger.error("Could not get a connection to the database: " + ex.getMessage()
118                         + ".  Waiting for 10 seconds, before trying to connect to the database again.");
119                 try {
120                     Thread.sleep(10000);
121                 } catch (InterruptedException e) {
122                 }
123             }
124         }
125     }
126 
127     private int getDbMajorVersion() {
128         return (Integer) new JdbcTemplate(jdbcTemplate.getDataSource()).execute(new ConnectionCallback() {
129             public Object doInConnection(Connection c) throws SQLException, DataAccessException {
130                 DatabaseMetaData metaData = c.getMetaData();
131                 return metaData.getDatabaseMajorVersion();
132             }
133         });
134     }
135 
136     private String getDbProductName() {
137         return (String) new JdbcTemplate(jdbcTemplate.getDataSource()).execute(new ConnectionCallback() {
138             public Object doInConnection(Connection c) throws SQLException, DataAccessException {
139                 DatabaseMetaData metaData = c.getMetaData();
140                 return metaData.getDatabaseProductName();
141             }
142         });
143     }
144 
145     public Class<IDbDialect> getObjectType() {
146         return IDbDialect.class;
147     }
148 
149     public boolean isSingleton() {
150         return true;
151     }
152 
153     public void setBeanFactory(BeanFactory beanFactory) {
154         this.beanFactory = beanFactory;
155     }
156 
157     public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
158         this.jdbcTemplate = jdbcTemplate;
159     }
160 
161 }