| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.oodt.commons.activity; |
| |
| import java.sql.Connection; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| import java.util.Iterator; |
| import java.util.List; |
| import javax.sql.DataSource; |
| |
| import org.apache.oodt.commons.database.DatabaseConnectionBuilder; |
| |
| /** |
| * <p> |
| * This class enables storage of activity incidents in just about any database |
| * management system. It should support MySQL, PostgreSQL, Oracle and Sybase. |
| * </p> |
| * |
| * <p> |
| * This class uses the following properties: |
| * <ul> |
| * <li><code>org.apache.oodt.commons.activity.SQLDatabaseStorage.driver</code><br> |
| * Must contain the name of the JDBC driver class. See the following examples: |
| * <ul> |
| * <li>com.mysql.jdbc.Driver</li> |
| * <li>org.postgresql.Driver</li> |
| * <li>oracle.jdbc.driver.OracleDriver</li> |
| * <li>com.sybase.jdbc2.jdbc.SybDriver</li> |
| * </ul> |
| * </li> |
| * |
| * <li><code>org.apache.oodt.commons.activity.SQLDatabaseStorage.url</code><br> |
| * Must contain the URL specification for the target database. See the following |
| * examples: |
| * <ul> |
| * <li>jdbc:mysql://host:port/database</li> |
| * <li>jdbc:postgresql://host:port/database</li> |
| * <li>jdbc:oracle:thin:@host:port:database</li> |
| * <li>jdbc:sybase::Tds:host:port/database</li> |
| * </ul> |
| * </li> |
| * |
| * <li><code>org.apache.oodt.commons.activity.SQLDatabaseStorage.user</code><br> |
| * Must contain the user name for the target database.</li> |
| * |
| * <li><code>org.apache.oodt.commons.activity.SQLDatabaseStorage.password</code> |
| * <br> |
| * Must contain the password for the target database.</li> |
| * |
| * </ul> |
| * </p> |
| * |
| * <p> |
| * This class expects the following table to exist in the target database (data |
| * types will vary depending on the vendor):<br> |
| * |
| * <pre> |
| * create table incidents ( |
| * activityID varchar(32) not null, |
| * className varchar(255) not null, |
| * occurTime bigint not null default 0, |
| * detail text null, |
| * primary key (activityID, className, occurTime)) |
| * </pre> |
| * |
| * </p> |
| * |
| * @author S. Hardman |
| * @version $Revision: 1.2 $ |
| */ |
| public class SQLDatabaseStorage implements Storage { |
| |
| /** |
| * The data source; |
| */ |
| private DataSource ds; |
| |
| /** |
| * Constructor given no arguments. |
| * |
| * This constructor grabs the necessary system properties and opens the |
| * database connection based on the property values. |
| */ |
| public SQLDatabaseStorage() { |
| |
| // Grab the properties and make sure they are all there. |
| String driver = System |
| .getProperty("org.apache.oodt.commons.activity.SQLDatabaseStorage.driver"); |
| String url = System |
| .getProperty("org.apache.oodt.commons.activity.SQLDatabaseStorage.url"); |
| String user = System |
| .getProperty("org.apache.oodt.commons.activity.SQLDatabaseStorage.user"); |
| String password = System |
| .getProperty("org.apache.oodt.commons.activity.SQLDatabaseStorage.password"); |
| |
| if ((driver == null) || (url == null) || (user == null) |
| || (password == null)) { |
| throw new IllegalStateException( |
| "SQLDatabaseStorage(): Required system properties `org.apache.oodt.commons.activity.SQLDatabaseStorage.[driver,url,user,password]' are not completely defined."); |
| } |
| |
| this.ds = DatabaseConnectionBuilder.buildDataSource(user, password, driver, |
| url); |
| } |
| |
| /** |
| * This method stores the list of incidents for the activity in the database |
| * table named "incidents". |
| * |
| * @param id |
| * The activity identifier. |
| * @param incidents |
| * A list of {@link Incident}. |
| */ |
| public void store(String id, List incidents) { |
| Statement statement = null; |
| Connection conn = null; |
| |
| try { |
| conn = this.ds.getConnection(); |
| statement = conn.createStatement(); |
| for (Iterator i = incidents.iterator(); i.hasNext();) { |
| Incident incident = (Incident) i.next(); |
| statement |
| .executeUpdate("insert into incidents (activityID, className, occurTime, detail) values ('" |
| + id |
| + "', '" |
| + incident.getClass().getName() |
| + "', " |
| + incident.getTime().getTime() |
| + ", '" |
| + escapeSingleQuote(incident.toString()) + "')"); |
| } |
| } catch (SQLException e) { |
| System.err |
| .println("SQLDatabaseStorage.store(): Ignoring an exception that occurred while inserting a row into the database. Specifically, exception '" |
| + e.getClass().getName() |
| + "' occurred with message '" |
| + e.getMessage() + "'"); |
| } finally { |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| } catch (SQLException ignore) { |
| } |
| conn = null; |
| conn = null; |
| } |
| } |
| } |
| |
| /** |
| * This method closes the database connection. |
| * |
| * @throws Throwable |
| * If something goes wrong. |
| */ |
| public void finalize() throws Throwable { |
| this.ds = null; |
| super.finalize(); |
| } |
| |
| /** |
| * This method will escape any single quotes found in the input string and |
| * return the escaped string. This will ready the string for insertion into a |
| * database. The single quote is escaped by inserting an additional single |
| * quote in front of it in the string. If some considerate developer has |
| * already escaped the single quotes in the input string, this method will |
| * essentially do nothing. |
| * |
| * @param inputString |
| * The string to be escaped. |
| * @return The escaped string. |
| */ |
| public static String escapeSingleQuote(String inputString) { |
| int index = inputString.indexOf('\''); |
| if (index == -1) { |
| return (inputString); |
| } |
| |
| String outputString = inputString; |
| while (index != -1) { |
| |
| // If the single quote is the last character in the string or |
| // the next character is not another single quote, insert a |
| // single quote in front of the current single quote. |
| if ((index == (outputString.length() - 1)) |
| || (outputString.charAt(index + 1) != '\'')) { |
| outputString = outputString.substring(0, index) + "'" |
| + outputString.substring(index); |
| } |
| |
| // If we are not at the end of the string, check for another |
| // single quote. |
| if ((index + 2) <= (outputString.length() - 1)) { |
| index = outputString.indexOf('\'', index + 2); |
| } else { |
| index = -1; |
| } |
| } |
| return (outputString); |
| } |
| } |