/* * Copyright 2007 Zhang, Zheng <oldbig@gmail.com> Xu, Chuan <xuchuan@gmail.com> * * This file is part of ZOJ. * * ZOJ is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either revision 3 of the License, or (at your option) any later revision. * * ZOJ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with ZOJ. if not, see * <http://www.gnu.org/licenses/>. */ package cn.edu.zju.acm.onlinejudge.persistence.sql; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Collection; import java.util.Date; import java.util.Properties; import org.apache.commons.dbcp.BasicDataSource; import cn.edu.zju.acm.onlinejudge.persistence.PersistenceException; /** * <p> * Dateabase. * </p> * * @version 2.0 * @author Zhang, Zheng * @author Xu, Chuan */ public class Database { /** * The query to get last id. */ private static final String GET_LAST_ID = "SELECT LAST_INSERT_ID()"; /** * The data source config file. */ public static String CONFIG_FILE = "data_source.properties"; /** * A BasicDataSource instance used to create connection. */ private static BasicDataSource ds = null; /** * Private constructor. */ private Database() { // empty } static { try { Properties properties = new Properties(); try { properties.load(Database.class.getClassLoader().getResourceAsStream(Database.CONFIG_FILE)); } catch (IOException ioe) { throw new PersistenceException("IO error occurs when load " + Database.CONFIG_FILE + ".", ioe); } Database.ds = new BasicDataSource(); Database.ds.setDefaultAutoCommit("true".equalsIgnoreCase(Database.getStringProperty(properties, "DefaultAutoCommit"))); Database.ds.setDefaultCatalog(Database.getStringProperty(properties, "DefaultCatalog")); Database.ds.setDriverClassName(Database.getStringProperty(properties, "DriverClassName")); Database.ds.setMaxActive(Database.getIntegerProperty(properties, "MaxActive")); Database.ds.setMaxIdle(Database.getIntegerProperty(properties, "MaxIdle")); Database.ds.setMaxWait(Database.getLongProperty(properties, "MaxWait")); Database.ds.setUrl(Database.getStringProperty(properties, "Url")); Database.ds.setPassword(Database.getStringProperty(properties, "Password")); Database.ds.setUsername(Database.getStringProperty(properties, "Username")); } catch (Exception e) { throw new ExceptionInInitializerError(e); } } /** * Gets a connection. This method is synchronized. * * @return a connection * @throws PersistenceException * if any error occurs. */ public static Connection createConnection() throws PersistenceException { try { return Database.ds.getConnection(); } catch (SQLException e) { throw new PersistenceException("Failed to create connection", e); } } public static void dispose(PreparedStatement ps) { if (ps != null) { try { ps.close(); } catch (Exception e) {} } } public static void dispose(Connection conn) { if (conn != null) { try { conn.close(); } catch (Exception e) {} } } /** * Create a string containing given values. The string is like '(value1, value2, value3)' * * @param values * the values * @return a string like '(value1, value2, value3)' */ public static String createValues(Collection<String> values) { StringBuilder ret = new StringBuilder(); ret.append('('); for (String value : values) { if (ret.length() > 1) { ret.append(','); } ret.append('\'').append(value.replaceAll("'", "''")).append('\''); } ret.append(')'); return ret.toString(); } /** * Create a string containing given number values. The string is like '(value1, value2, value3)' * * @param values * the values * @return a string like '(value1, value2, value3)' */ public static String createNumberValues(Collection<Long> values) { StringBuilder ret = new StringBuilder(); ret.append('('); for (Long value : values) { if (ret.length() > 1) { ret.append(','); } ret.append(value); } ret.append(')'); return ret.toString(); } /** * Rollback given connection. * * @param conn * the connection */ public static void rollback(Connection conn) { try { if (conn != null) { conn.rollback(); } } catch (SQLException e) { // ignore } } /** * Gets the last id. * * @param conn * @param ps * @param rs * @return the last id * @throws SQLException */ public static long getLastId(Connection conn) throws SQLException { PreparedStatement ps = null; try { ps = conn.prepareStatement(Database.GET_LAST_ID); ResultSet rs = ps.executeQuery(); rs.next(); return rs.getLong(1); } finally { Database.dispose(ps); } } /** * Gets a date value from given ResultSet. * * @param rs * the ResultSet * @param column * the column name * @return a date value from given ResultSet. * @throws SQLException */ public static Date getDate(ResultSet rs, String column) throws SQLException { Timestamp date = rs.getTimestamp(column); if (date == null) { return null; } return new Date(date.getTime()); } /** * Convert given Date to Timestamp. * * @param date * the date * @return a Timestamp instance. */ public static Timestamp toTimestamp(Date date) { if (date == null) { return null; } return new Timestamp(date.getTime()); } /** * Gets the given string property * * @param properties * properties * @param key * property key * @return the property value in string */ private static String getStringProperty(Properties properties, String key) throws PersistenceException { String value = properties.getProperty(key); if (value == null) { throw new PersistenceException(key + " property is missing in " + Database.CONFIG_FILE); } return value; } /** * Gets the given int property * * @param properties * properties * @param key * property key * @return the property value in int */ private static int getIntegerProperty(Properties properties, String key) throws PersistenceException { String value = Database.getStringProperty(properties, key); try { return Integer.parseInt(value); } catch (NumberFormatException nfe) { throw new PersistenceException(key + " property is an invalid integer"); } } /** * Gets the given long property * * @param properties * properties * @param key * property key * @return the property value in long */ private static long getLongProperty(Properties properties, String key) throws PersistenceException { String value = Database.getStringProperty(properties, key); try { return Long.parseLong(value); } catch (NumberFormatException nfe) { throw new PersistenceException(key + " property is an invalid long"); } } }