/*
 * $Id: MySQLSelect.java,v 1.2 2005/11/26 17:08:42 rampil Exp $
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 *
 */
package org.logical_paradox.koike.rss.tools.docb.impl;

import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.logical_paradox.koike.rss.tools.DataSourceException;
import org.logical_paradox.koike.rss.tools.docb.Query;
import org.logical_paradox.koike.rss.tools.docb.Select;
import org.logical_paradox.rss.rcm.df.DataFilter;
import org.logical_paradox.rss.rcm.df.DataFilterFactory;

/**
 * mysqlに特化したデータソースアクセスインターフェース
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.2 $
 */
public class MySQLSelect implements Select {
	/** JDBCドライバクラス */
	public static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
	/** URLダイジェストによるクエリー */
	public static final String QUERY_BY_URL = "SELECT contents FROM contents WHERE mkey=?";
	/** ドキュメント番号によるクエリー */
	public static final String QUERY_BY_DOCNO = "SELECT contents FROM contents WHERE cid=?";

	/** ロガー */
	private static final Log log = LogFactory.getLog(MySQLSelect.class);
	/** データベース接続オブジェクト */
	private Connection con;
	/** データフィルタ */
	private DataFilter filter = null;

	/**
	 * データソースに接続する．
	 * @param connstr 接続文字列
	 * @throws DataSourceException データソースとの接続に失敗した
	 */
	public void open(String connstr) throws DataSourceException {
		try {
			Class.forName(JDBC_DRIVER);
			con = DriverManager.getConnection(connstr);

			// データフィルタの作成
			filter = DataFilterFactory.getFilter(DataFilterFactory.GZIP);
		} catch(Exception e) {
			log.error("JDBCドライバのロードに失敗しました:", e);
			throw new DataSourceException(e);
		}
	}

	/**
	 * データソースとの接続を切る．
	 * @throws DataSourceException データソースとの切断に失敗した
	 */
	public void close() throws DataSourceException {
		if(con != null) {
			try {
				con.close();
			} catch(SQLException e) {
				// 何もしない
			} finally {
				con = null;
			}
		}
	}

	/**
	 * 問い合わせを実行する．
	 * @param q 問い合わせオブジェクト
	 * @return 選択されたコンテンツ
	 * @throws DataSourceException データソースとの接続に失敗
	 */
	public String executeQuery(Query q) throws DataSourceException {
		log.trace("コンテンツを照会しています");

		String url = q.getUrl();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String contents = null;

		try {
			if(url != null && url.trim().length() > 0) {
				pstmt = con.prepareStatement(QUERY_BY_URL);
				pstmt.setString(1, filter.filterURL(url));
				log.debug(QUERY_BY_URL);
			} else {
				pstmt = con.prepareStatement(QUERY_BY_DOCNO);
				pstmt.setInt(1, q.getDocno());
				log.debug(QUERY_BY_DOCNO);
			}

			// 問い合わせ
			rs = pstmt.executeQuery();
			if(rs.next()) {
				log.trace("コンテンツの照会完了．コンテンツをデコードしています");
				Blob blob = rs.getBlob("contents");
				byte[] bstream = blob.getBytes(1L, (int)blob.length());
				// 取得できたコンテンツをデコードする(gzipで圧縮されているため)
				contents = new String(filter.decompressContents(bstream));
			}

			log.trace("完了．");
			return contents;
		} catch(Exception e) {
			throw new DataSourceException(e);
		} finally {
			// リソースの解放
			try {
				if(rs != null) {
					rs.close();
				}
				if(pstmt != null) {
					pstmt.close();
				}
			} catch(SQLException e) {
				// もう何もしない
			}
		}
	}

}
