package se.unlogic.eagledns.zoneproviders.db;
import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.xbill.DNS.Zone;
import se.unlogic.eagledns.SecondaryZone;
import se.unlogic.eagledns.ZoneProvider;
import se.unlogic.eagledns.zoneproviders.db.beans.DBRecord;
import se.unlogic.eagledns.zoneproviders.db.beans.DBSecondaryZone;
import se.unlogic.eagledns.zoneproviders.db.beans.DBZone;
import se.unlogic.standardutils.dao.AnnotatedDAO;
import se.unlogic.standardutils.dao.HighLevelQuery;
import se.unlogic.standardutils.dao.QueryParameterFactory;
import se.unlogic.standardutils.dao.SimpleAnnotatedDAOFactory;
import se.unlogic.standardutils.dao.SimpleDataSource;
import se.unlogic.standardutils.dao.TransactionHandler;
import se.unlogic.standardutils.reflection.ReflectionUtils;
public class DBZoneProvider implements ZoneProvider {
private static final Field RECORD_RELATION = ReflectionUtils.getField(DBZone.class, "records");
private Logger log = Logger.getLogger(this.getClass());
private String name;
private String driver;
private String url;
private String username;
private String password;
private SimpleAnnotatedDAOFactory annotatedDAOFactory;
private AnnotatedDAO<DBZone> zoneDAO;
private AnnotatedDAO<DBRecord> recordDAO;
private HighLevelQuery<DBZone> primaryZoneQuery;
private HighLevelQuery<DBZone> secondaryZoneQuery;
private QueryParameterFactory<DBZone, Integer> zoneIDQueryParameterFactory;
private QueryParameterFactory<DBRecord, DBZone> recordZoneQueryParameterFactory;
public void init(String name) throws ClassNotFoundException {
this.name = name;
DataSource dataSource;
try {
dataSource = new SimpleDataSource(driver, url, username, password);
} catch (ClassNotFoundException e) {
log.error("Unable to load JDBC driver " + driver, e);
throw e;
}
this.annotatedDAOFactory = new SimpleAnnotatedDAOFactory();
this.zoneDAO = new AnnotatedDAO<DBZone>(dataSource,DBZone.class, annotatedDAOFactory);
this.recordDAO = new AnnotatedDAO<DBRecord>(dataSource,DBRecord.class, annotatedDAOFactory);
QueryParameterFactory<DBZone, Boolean> zoneTypeParamFactory = zoneDAO.getParamFactory("secondary", boolean.class);
this.primaryZoneQuery = new HighLevelQuery<DBZone>(zoneTypeParamFactory.getParameter(false),RECORD_RELATION);
this.secondaryZoneQuery = new HighLevelQuery<DBZone>(zoneTypeParamFactory.getParameter(true),RECORD_RELATION);
this.zoneIDQueryParameterFactory = zoneDAO.getParamFactory("zoneID", Integer.class);
this.recordZoneQueryParameterFactory = recordDAO.getParamFactory("zone", DBZone.class);
}
public Collection<Zone> getPrimaryZones() {
try {
List<DBZone> dbZones = this.zoneDAO.getAll(primaryZoneQuery);
if(dbZones != null){
ArrayList<Zone> zones = new ArrayList<Zone>(dbZones.size());
for(DBZone dbZone : dbZones){
try {
zones.add(dbZone.toZone());
} catch (IOException e) {
log.error("Unable to parse zone " + dbZone.getName(),e);
}
}
return zones;
}
} catch (SQLException e) {
log.error("Error getting primary zones from DB zone provider " + name,e);
}
return null;
}
public Collection<SecondaryZone> getSecondaryZones() {
try {
List<DBZone> dbZones = this.zoneDAO.getAll(this.secondaryZoneQuery);
if(dbZones != null){
ArrayList<SecondaryZone> zones = new ArrayList<SecondaryZone>(dbZones.size());
for(DBZone dbZone : dbZones){
try {
DBSecondaryZone secondaryZone = new DBSecondaryZone(dbZone.getZoneID() ,dbZone.getName(), dbZone.getPrimaryDNS(), dbZone.getDclass());
if(dbZone.getRecords() != null){
secondaryZone.setZoneCopy(dbZone.toZone());
secondaryZone.setDownloaded(dbZone.getDownloaded());
}
zones.add(secondaryZone);
} catch (IOException e) {
log.error("Unable to parse zone " + dbZone.getName(),e);
}
}
return zones;
}
} catch (SQLException e) {
log.error("Error getting secondary zones from DB zone provider " + name,e);
}
return null;
}
public void zoneUpdated(SecondaryZone zone) {
if(!(zone instanceof DBSecondaryZone)){
log.warn(zone.getClass() + " is not an instance of " + DBSecondaryZone.class + ", ignoring zone update");
return;
}
Integer zoneID = ((DBSecondaryZone)zone).getZoneID();
TransactionHandler transactionHandler = null;
try {
transactionHandler = zoneDAO.createTransaction();
DBZone dbZone = this.zoneDAO.get(new HighLevelQuery<DBZone>(this.zoneIDQueryParameterFactory.getParameter(zoneID),(Field)null),transactionHandler);
if(dbZone == null){
log.warn("Unable to find secondary zone with zoneID " + zoneID + " in DB, ignoring zone update");
return;
}
dbZone.parse(zone.getZoneCopy(), true);
zoneDAO.update(dbZone,transactionHandler, null);
recordDAO.delete(new HighLevelQuery<DBRecord>(recordZoneQueryParameterFactory.getParameter(dbZone),(Field)null), transactionHandler);
if(dbZone.getRecords() != null){
for(DBRecord dbRecord : dbZone.getRecords()){
dbRecord.setZone(dbZone);
this.recordDAO.add(dbRecord, transactionHandler, null);
}
}
transactionHandler.commit();
log.debug("Changes in seconday zone " + dbZone + " saved");
} catch (SQLException e) {
log.error("Unable to save changes in secondary zone " + zone.getZoneName(), e);
TransactionHandler.autoClose(transactionHandler);
}
}
public void zoneChecked(SecondaryZone zone) {
if(!(zone instanceof DBSecondaryZone)){
log.warn(zone.getClass() + " is not an instance of " + DBSecondaryZone.class + ", ignoring zone check");
return;
}
Integer zoneID = ((DBSecondaryZone)zone).getZoneID();
TransactionHandler transactionHandler = null;
try {
transactionHandler = zoneDAO.createTransaction();
DBZone dbZone = this.zoneDAO.get(new HighLevelQuery<DBZone>(this.zoneIDQueryParameterFactory.getParameter(zoneID), (Field)null),transactionHandler);
if(dbZone == null){
log.warn("Unable to find secondary zone with zoneID " + zoneID + " in DB, ignoring zone update");
return;
}
dbZone.parse(zone.getZoneCopy(), true);
zoneDAO.update(dbZone,transactionHandler, null);
transactionHandler.commit();
log.debug("Changes in seconday zone " + dbZone + " saved");
} catch (SQLException e) {
log.error("Unable to save changes in secondary zone " + zone.getZoneName(), e);
TransactionHandler.autoClose(transactionHandler);
}
}
public void unload() {
//Nothing to do here...
}
public void setDriver(String driver) {
this.driver = driver;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setUrl(String url) {
this.url = url;
}
}