/******************************************************************************* * Copyright (c) 2009, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Zend Technologies *******************************************************************************/ package org.eclipse.dltk.internal.core.index.sql.h2; import java.io.File; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.IPreferencesService; import org.eclipse.dltk.core.index.sql.DbFactory; import org.eclipse.dltk.core.index.sql.IContainerDao; import org.eclipse.dltk.core.index.sql.IElementDao; import org.eclipse.dltk.core.index.sql.IFileDao; import org.eclipse.dltk.core.index.sql.SqlIndex; import org.eclipse.dltk.core.index.sql.h2.H2Index; import org.eclipse.dltk.core.index.sql.h2.H2IndexPreferences; import org.h2.jdbcx.JdbcConnectionPool; import org.h2.tools.DeleteDbFiles; /** * Abstract database access factory * * @author michael * */ public class H2DbFactory extends DbFactory { private static final String DB_NAME = "model"; //$NON-NLS-1$ private static final String DB_USER = ""; //$NON-NLS-1$ private static final String DB_PASS = ""; //$NON-NLS-1$ private JdbcConnectionPool pool; public H2DbFactory() throws Exception { try { Class.forName("org.h2.Driver"); } catch (ClassNotFoundException e) { } IPath dbPath = H2Index.getDefault().getStateLocation(); String connString = getConnectionString(dbPath); pool = JdbcConnectionPool.create(connString, DB_USER, DB_PASS); Schema schema = new Schema(); boolean initializeSchema = false; int tries = 2; // Tries for opening database Connection connection = null; do { try { connection = pool.getConnection(); try { try (Statement statement = connection.createStatement()) { statement.executeQuery( "SELECT COUNT(*) FROM FILES WHERE 1=0;"); initializeSchema = !schema.isCompatible(); } catch (SQLException e) { // Basic table doesn't exist initializeSchema = true; } if (initializeSchema) { connection.close(); pool.dispose(); // Destroy schema by removing DB (if exists) DeleteDbFiles.execute(dbPath.toOSString(), DB_NAME, true); pool = JdbcConnectionPool.create(connString, DB_USER, DB_PASS); connection = pool.getConnection(); schema.initialize(connection); } } finally { if (connection != null) { connection.close(); } } } catch (SQLException e) { SqlIndex.error( "An exception occurred while connecting to a database. Retrying ...", e); // remove corrupted DB try { if (tries == 1) { // try force delete File folder = new File(dbPath.toOSString()); for (File f : folder.listFiles()) { if (f.getName().startsWith(DB_NAME + ".")) { //$NON-NLS-1$ f.delete(); } } initializeSchema = true; } else { DeleteDbFiles.execute(dbPath.toOSString(), DB_NAME, true); } } catch (Exception e1) { SqlIndex.error( "An exception has occurred while removing corrupted DB: " + dbPath.toOSString(), e1); throw e1; } } } while (connection == null && --tries >= 0); } /** * Generates connection string using user preferences * * @param dbPath * Path to the database files * @return */ private String getConnectionString(IPath dbPath) { IPreferencesService preferencesService = Platform .getPreferencesService(); StringBuilder buf = new StringBuilder("jdbc:h2:") .append(dbPath.append(DB_NAME).toOSString()); buf.append(";UNDO_LOG=0"); buf.append(";LOCK_MODE=").append(preferencesService.getInt( H2Index.PLUGIN_ID, H2IndexPreferences.DB_LOCK_MODE, 0, null)); buf.append(";CACHE_TYPE=") .append(preferencesService.getString(H2Index.PLUGIN_ID, H2IndexPreferences.DB_CACHE_TYPE, null, null)); buf.append(";CACHE_SIZE=").append(preferencesService.getInt( H2Index.PLUGIN_ID, H2IndexPreferences.DB_CACHE_SIZE, 0, null)); buf.append(";QUERY_CACHE_SIZE=") .append(preferencesService.getInt(H2Index.PLUGIN_ID, H2IndexPreferences.DB_QUERY_CACHE_SIZE, 0, null)); buf.append(";LARGE_RESULT_BUFFER_SIZE=") .append(preferencesService.getInt(H2Index.PLUGIN_ID, H2IndexPreferences.DB_LARGE_RESULT_BUFFER_SIZE, 0, null)); buf.append(";FILE_LOCK=NO"); return buf.toString(); } @Override public Connection createConnection() throws SQLException { return pool == null ? null : pool.getConnection(); } @Override public void dispose() throws SQLException { if (pool != null) { pool.dispose(); pool = null; } } @Override public IContainerDao getContainerDao() { return new H2ContainerDao(); } @Override public IElementDao getElementDao() { return new H2ElementDao(); } @Override public IFileDao getFileDao() { return new H2FileDao(); } }