/*
* This file is part of aion-emu <aion-emu.com>.
*
* aion-emu 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 version 3 of the License, or
* (at your option) any later version.
*
* aion-emu 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 aion-emu. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aionemu.commons.database.dao;
import static com.aionemu.commons.database.DatabaseFactory.getDatabaseMajorVersion;
import static com.aionemu.commons.database.DatabaseFactory.getDatabaseMinorVersion;
import static com.aionemu.commons.database.DatabaseFactory.getDatabaseName;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import com.aionemu.commons.database.DatabaseConfig;
import com.aionemu.commons.scripting.scriptmanager.ScriptManager;
/**
* This class manages {@link DAO} implementations, it resolves valid implementation for current database
*
* @author SoulKeeper, Saelya
*/
public class DAOManager
{
/**
* Logger for DAOManager class
*/
private static final Logger log = Logger.getLogger(DAOManager.class);
/**
* Collection of registered DAOs
*/
private static final Map<String, DAO> daoMap = new HashMap<String, DAO>();
/**
* This script manager is responsible for loading {@link com.aionemu.commons.database.dao.DAO} implementations
*/
private static ScriptManager scriptManager;
/**
* Initializes DAOManager.
*/
public static void init()
{
try
{
scriptManager = new ScriptManager();
scriptManager.setGlobalClassListener(new DAOLoader());
scriptManager.load(DatabaseConfig.DATABASE_SCRIPTCONTEXT_DESCRIPTOR);
}
catch(Exception e)
{
throw new Error("Can't load database script context: " + DatabaseConfig.DATABASE_SCRIPTCONTEXT_DESCRIPTOR,
e);
}
log.info("Loaded " + daoMap.size() + " DAO implementations.");
}
/**
* Shutdown DAOManager
*/
public static void shutdown()
{
scriptManager.shutdown();
daoMap.clear();
scriptManager = null;
}
/**
* Returns DAO implementation by DAO class. Typical usage:
*
* <pre>
* AccountDAO dao = DAOManager.getDAO(AccountDAO.class);
* </pre>
*
* @param clazz
* Abstract DAO class implementation of which was registered
* @param <T>
* Subclass of DAO
* @return DAO implementation
* @throws DAONotFoundException
* if DAO implementation not found
*/
@SuppressWarnings("unchecked")
public static <T extends DAO> T getDAO(Class<T> clazz) throws DAONotFoundException
{
DAO result = daoMap.get(clazz.getName());
if(result == null)
{
String s = "DAO for class " + clazz.getName() + " not implemented";
log.error(s);
throw new DAONotFoundException(s);
}
return (T) result;
}
/**
* Registers {@link DAO}.<br>
* First it creates new instance of DAO, then invokes {@link DAO#supports(String, int, int)} <br>
* . If the result was possitive - it associates DAO instance with
* {@link com.aionemu.commons.database.dao.DAO#getClassName()} <br>
* If another DAO was registed - {@link com.aionemu.commons.database.dao.DAOAlreadyRegisteredException} will be
* thrown
*
* @param daoClass
* DAO implementation
* @throws DAOAlreadyRegisteredException
* if DAO is already registered
* @throws IllegalAccessException
* if something went wrong during instantiation of DAO
* @throws InstantiationException
* if something went wrong during instantiation of DAO
*/
public static void registerDAO(Class<? extends DAO> daoClass) throws DAOAlreadyRegisteredException,
IllegalAccessException, InstantiationException
{
DAO dao = daoClass.newInstance();
if(!dao.supports(getDatabaseName(), getDatabaseMajorVersion(), getDatabaseMinorVersion()))
{
return;
}
synchronized(DAOManager.class)
{
DAO oldDao = daoMap.get(dao.getClassName());
if(oldDao != null)
{
StringBuilder sb = new StringBuilder();
sb.append("DAO with className ").append(dao.getClassName()).append(" is used by ");
sb.append(oldDao.getClass().getName()).append(". Can't override with ");
sb.append(daoClass.getName()).append(".");
String s = sb.toString();
log.error(s);
throw new DAOAlreadyRegisteredException(s);
}
else
{
daoMap.put(dao.getClassName(), dao);
}
}
if(log.isDebugEnabled())
log.debug("DAO " + dao.getClassName() + " was successfuly registered.");
}
/**
* Unregisters DAO class
*
* @param daoClass
* DAO implementation to unregister
*/
public static void unregisterDAO(Class<? extends DAO> daoClass)
{
synchronized(DAOManager.class)
{
for(DAO dao : daoMap.values())
{
if(dao.getClass() == daoClass)
{
daoMap.remove(dao.getClassName());
if(log.isDebugEnabled())
log.debug("DAO " + dao.getClassName() + " was successfuly unregistered.");
break;
}
}
}
}
private DAOManager()
{
// empty
}
}