001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.lucene.store.jdbc.dialect;
018:
019: import java.sql.Connection;
020: import java.sql.DatabaseMetaData;
021: import java.sql.SQLException;
022: import java.util.LinkedList;
023: import javax.sql.DataSource;
024:
025: import org.apache.lucene.store.jdbc.JdbcStoreException;
026: import org.apache.lucene.store.jdbc.datasource.DataSourceUtils;
027:
028: /**
029: * @author kimchy
030: */
031: public class DialectResolver {
032:
033: public static interface DatabaseMetaDataToDialectMapper {
034:
035: Class getDialect(DatabaseMetaData metaData) throws SQLException;
036: }
037:
038: public static class DatabaseNameToDialectMapper implements
039: DatabaseMetaDataToDialectMapper {
040:
041: private String databaseName;
042:
043: private Class dialect;
044:
045: public DatabaseNameToDialectMapper(String databaseName,
046: Class dialect) {
047: this .databaseName = databaseName;
048: this .dialect = dialect;
049: }
050:
051: public Class getDialect(DatabaseMetaData metaData)
052: throws SQLException {
053: if (metaData.getDatabaseProductName().equals(databaseName)) {
054: return dialect;
055: }
056: return null;
057: }
058: }
059:
060: public static class DatabaseNameStartsWithToDialectMapper implements
061: DatabaseMetaDataToDialectMapper {
062:
063: private String databaseName;
064:
065: private Class dialect;
066:
067: public DatabaseNameStartsWithToDialectMapper(
068: String databaseName, Class dialect) {
069: this .databaseName = databaseName;
070: this .dialect = dialect;
071: }
072:
073: public Class getDialect(DatabaseMetaData metaData)
074: throws SQLException {
075: if (metaData.getDatabaseProductName().startsWith(
076: databaseName)) {
077: return dialect;
078: }
079: return null;
080: }
081: }
082:
083: public static class DatabaseNameAndVersionToDialectMapper implements
084: DatabaseMetaDataToDialectMapper {
085:
086: private String databaseName;
087:
088: private Class dialect;
089:
090: private int version;
091:
092: public DatabaseNameAndVersionToDialectMapper(
093: String databaseName, int version, Class dialect) {
094: this .databaseName = databaseName;
095: this .dialect = dialect;
096: this .version = version;
097: }
098:
099: public Class getDialect(DatabaseMetaData metaData)
100: throws SQLException {
101: if (metaData.getDatabaseProductName().equals(databaseName)
102: && metaData.getDatabaseMajorVersion() == version) {
103: return dialect;
104: }
105: return null;
106: }
107: }
108:
109: private LinkedList mappers = new LinkedList();
110:
111: public DialectResolver() {
112: this (true);
113: }
114:
115: public DialectResolver(boolean useDefaultMappers) {
116: if (!useDefaultMappers) {
117: return;
118: }
119: mappers.add(new DatabaseNameToDialectMapper(
120: "HSQL Database Engine", HSQLDialect.class));
121: mappers.add(new DatabaseNameToDialectMapper("DB2/NT",
122: DB2Dialect.class));
123: mappers.add(new DatabaseNameToDialectMapper("MySQL",
124: MySQLDialect.class));
125: mappers.add(new DatabaseNameToDialectMapper("PostgreSQL",
126: PostgreSQLDialect.class));
127: mappers.add(new DatabaseNameStartsWithToDialectMapper(
128: "Microsoft SQL Server", SQLServerDialect.class));
129: mappers.add(new DatabaseNameToDialectMapper(
130: "Sybase SQL Server", SybaseDialect.class));
131: mappers.add(new DatabaseNameAndVersionToDialectMapper("Oracle",
132: 8, Oracle8Dialect.class));
133: mappers.add(new DatabaseNameAndVersionToDialectMapper("Oracle",
134: 9, Oracle9Dialect.class));
135: mappers.add(new DatabaseNameToDialectMapper("Oracle",
136: OracleDialect.class));
137: }
138:
139: public void addFirstMapper(DatabaseMetaDataToDialectMapper mapper) {
140: mappers.addFirst(mapper);
141: }
142:
143: public void addLastMapper(DatabaseMetaDataToDialectMapper mapper) {
144: mappers.addLast(mapper);
145: }
146:
147: public Dialect getDialect(DataSource dataSource)
148: throws JdbcStoreException {
149: Connection conn = DataSourceUtils.getConnection(dataSource);
150: String databaseName;
151: int databaseMajorVersion;
152: int databaseMinorVersion;
153: String driverName;
154: try {
155: DatabaseMetaData metaData = conn.getMetaData();
156: databaseName = metaData.getDatabaseProductName();
157: databaseMajorVersion = metaData.getDatabaseMajorVersion();
158: databaseMinorVersion = metaData.getDatabaseMinorVersion();
159: driverName = metaData.getDriverName();
160: for (int i = 0; i < mappers.size(); i++) {
161: DatabaseMetaDataToDialectMapper mapper = (DatabaseMetaDataToDialectMapper) mappers
162: .get(i);
163: Class dialectClass = mapper.getDialect(metaData);
164: if (dialectClass == null) {
165: continue;
166: }
167: return (Dialect) dialectClass.newInstance();
168: }
169: } catch (Exception e) {
170: throw new JdbcStoreException(
171: "Failed to auto detect dialect", e);
172: } finally {
173: DataSourceUtils.releaseConnection(conn);
174: }
175: throw new JdbcStoreException(
176: "Failed to auto detect dialect, no match found for database ["
177: + databaseName + "] version ["
178: + databaseMajorVersion + "/"
179: + databaseMinorVersion + "] driver ["
180: + driverName + "]");
181: }
182: }
|