/*
 * Copyright (C) 2005 NTT DATA Corporation
 * 
 */
package org.postgresforest.vm;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class HashLoader extends ClassLoader {

	private static HashLoader m_instance = null; //インスタンス（シングルトン）
	private Connection m_con = null;

	/**
	 * 外部からコンストラクタを呼ばれないように
	 */
	private HashLoader() {
		super();
	}


	/**
 	 * ローダーのインスタンスを返却
	 * @param isNew		true:新しいインスタンスを生成する。false:インスタンスが生成されていないときのみインスタンスを生成する。
	 * @return
	 */
	public static synchronized HashLoader getIncetance(boolean isNew) {
		if (m_instance == null || isNew) {
			m_instance = new HashLoader();
		}
		return m_instance;
	}


	/*
	 * (非 Javadoc)
	 * 
	 * @see java.lang.ClassLoader#findClass(java.lang.String)
	 */
	protected Class findClass(String name) throws ClassNotFoundException {

		byte[] byteImg = loadClassData(name);
		if(byteImg == null){
			throw new ClassNotFoundException();
		}
		
		return defineClass(name, byteImg, 0, byteImg.length);

	}


	/* (非 Javadoc)
	 * @see java.lang.ClassLoader#loadClass(java.lang.String)
	 */
	public synchronized Class loadClass(String name,Connection con) throws ClassNotFoundException {

		//クラスロード時に使用するGSCへの接続を保持。
		//このメソッドがsynchronizedされているので、m_conを参照するときは排他されるはず。
		m_con = con;
		try {
			return super.loadClass(name);
		}finally{
			m_con = null;
		}
	}

	/**
	 * ハッシュ関数取得.
	 * 指定された名前のクラスをデータベースから取得する。
	 * @param name
	 * @return
	 */
	protected byte[] loadClassData(String name) {

		if(m_con == null){
			return null;
		}
		
		String sql = "select CLASS from FOREST_HASH " + "where NAME = '" + name
				+ "' ";

		Statement smt = null;
		ResultSet rs;
		try {

			smt = m_con.createStatement();
			rs = smt.executeQuery(sql);

			rs.next();
			return rs.getBytes("CLASS");

		} catch (SQLException e) {
			
		} finally {
			try {
				smt.close();
			} catch (SQLException e1) {
			}
		}

		return null;

	}


}