package com.netifera.platform.net.dns.internal.model;
import java.util.Locale;
import com.netifera.platform.api.model.IModelService;
import com.netifera.platform.model.IWorkspaceEx;
import com.netifera.platform.net.dns.model.AAAARecordEntity;
import com.netifera.platform.net.dns.model.ARecordEntity;
import com.netifera.platform.net.dns.model.DNSRecordEntity;
import com.netifera.platform.net.dns.model.DomainEntity;
import com.netifera.platform.net.dns.model.EmailAddressEntity;
import com.netifera.platform.net.dns.model.IDomainEntityFactory;
import com.netifera.platform.net.dns.model.MXRecordEntity;
import com.netifera.platform.net.dns.model.NSRecordEntity;
import com.netifera.platform.net.dns.model.PTRRecordEntity;
import com.netifera.platform.net.model.HostEntity;
import com.netifera.platform.net.model.INetworkEntityFactory;
import com.netifera.platform.net.model.InternetAddressEntity;
import com.netifera.platform.util.addresses.inet.IPv4Address;
import com.netifera.platform.util.addresses.inet.IPv6Address;
import com.netifera.platform.util.addresses.inet.InternetAddress;
import com.netifera.platform.util.locators.TCPSocketLocator;
public class DomainEntityFactory implements IDomainEntityFactory {
private IModelService model;
private INetworkEntityFactory networkEntityFactory;
protected void setModelService(IModelService model) {
this.model = model;
}
protected void unsetModelService(IModelService model) {
this.model = null;
}
protected void setNetworkEntityFactory(INetworkEntityFactory factory) {
networkEntityFactory = factory;
}
protected void unsetNetworkEntityFactory(INetworkEntityFactory factory) {
networkEntityFactory = null;
}
private String normalized(String fqdm) {
if (fqdm.endsWith(".")) fqdm = fqdm.substring(0, fqdm.length()-1);
return fqdm.toLowerCase(Locale.ENGLISH);
}
public synchronized DomainEntity createDomain(long realm, long spaceId, String fqdm) {
fqdm = normalized(fqdm);
DomainEntity domain = (DomainEntity) getWorkspace().findByKey(DomainEntity.createQueryKey(realm, fqdm));
if(domain != null) {
if(canAddDomainToSpace(domain))
domain.addToSpace(spaceId);
return domain;
}
// make sure to create the parent domain
DomainEntity parent = null;
int dotIndex = fqdm.indexOf('.');
if (dotIndex >= 0)
parent = createDomain(realm, spaceId, fqdm.substring(dotIndex+1));
DomainEntity answer = new DomainEntity(getWorkspace(), realm, parent, fqdm);
answer.save();
if(canAddDomainToSpace(answer))
answer.addToSpace(spaceId);
return answer;
}
private boolean canAddDomainToSpace(DomainEntity e) {
return e != null && !e.isTLD() && e.getParent() != null && e.getParent().isTLD();
}
private DomainEntity findDomain(long realm, String fqdm) {
fqdm = normalized(fqdm);
return (DomainEntity) getWorkspace().findByKey(DomainEntity.createQueryKey(realm, fqdm));
}
public synchronized NSRecordEntity createNSRecord(long realm, long spaceId, String domainName, String target) {
domainName = normalized(domainName);
DomainEntity domainEntity = createDomain(realm, spaceId, domainName);
target = normalized(target);
NSRecordEntity record = (NSRecordEntity) getWorkspace().findByKey(NSRecordEntity.createQueryKey(realm, target, domainEntity.getId()));
if(record != null) {
record.addToSpace(spaceId);
return record;
}
record = new NSRecordEntity(getWorkspace(), realm, domainEntity.createReference(), target);
record.save();
record.addToSpace(spaceId); // FIXME if !arpa?
return record;
}
public synchronized MXRecordEntity createMXRecord(long realm, long spaceId, String domainName, String target, Integer priority) {
domainName = normalized(domainName);
DomainEntity domainEntity = createDomain(realm, spaceId, domainName);
target = normalized(target);
MXRecordEntity record = (MXRecordEntity) getWorkspace().findByKey(MXRecordEntity.createQueryKey(realm, target, domainEntity.getId()));
if(record != null) {
record.addToSpace(spaceId);
return record;
}
record = new MXRecordEntity(getWorkspace(), realm, domainEntity.createReference(), target, priority);
record.save();
record.addToSpace(spaceId);
return record;
}
public synchronized EmailAddressEntity createEmailAddress(long realm, long spaceId, String address) {
String accountName = address.substring(0, address.indexOf('@'));
/*
* first check IP address literal (surrounded by square braces)
*/
if (address.contains("[")) {
InternetAddressEntity addressEntity;
String ip = address.substring(address.indexOf('[') + 1, address.indexOf(']'));
InternetAddress inAddr = InternetAddress.fromString(ip);
try {
addressEntity = networkEntityFactory.createAddress(realm, spaceId, inAddr);
} catch (IllegalArgumentException e) {
e.printStackTrace();
return null;
}
HostEntity hostEntity = addressEntity.getHost();
if (hostEntity.getLabel() == null) { //XXX WTF?
hostEntity.setLabel(ip);
hostEntity.update();
}
TCPSocketLocator locator = new TCPSocketLocator(inAddr, 25);
networkEntityFactory.createService(realm, spaceId, locator, "SMTP", null);
// FIXME: no EmailAddressEntity created (because no StringDomain)
return null;
}
/*
* if no IP address literal assume MX domain name.
* normalize domain name (but no accountname, see RFC 2821).
*/
String domainName = address.substring(address.indexOf('@') + 1).toLowerCase(Locale.ENGLISH);
String normalizedAddress = accountName + "@" + domainName;
EmailAddressEntity email = (EmailAddressEntity) getWorkspace().findByKey(EmailAddressEntity.createQueryKey(realm, normalizedAddress));
if(email != null) {
email.addToSpace(spaceId);
return email;
}
DomainEntity domain = createDomain(realm, spaceId, domainName);
email = new EmailAddressEntity(getWorkspace(), realm, normalizedAddress, domain.createReference());
// email.addTag("@"+domainName);
email.save();
email.addToSpace(spaceId);
return email;
}
public synchronized EmailAddressEntity createEmailAddress(long realm, long spaceId, String name, String address) {
EmailAddressEntity entity = createEmailAddress(realm, spaceId, address);
if (entity.getName() != null && entity.getName().equals(name))
return entity; // no change
entity.setName(name);
entity.update();
return entity;
}
public synchronized ARecordEntity createARecord(long realm, long spaceId, String name, IPv4Address address) {
return (ARecordEntity)createAddressRecord(realm, spaceId, name, address);
}
public synchronized AAAARecordEntity createAAAARecord(long realm, long spaceId, String name, IPv6Address address) {
return (AAAARecordEntity)createAddressRecord(realm, spaceId, name, address);
}
private synchronized DNSRecordEntity createAddressRecord(long realm, long spaceId, String fqdm, InternetAddress address) {
final String finalName = normalized(fqdm);
final String addressString = address.toString();
DNSRecordEntity record;
if (address instanceof IPv4Address) {
record = (ARecordEntity) getWorkspace().findByKey(ARecordEntity.createQueryKey(realm, addressString, finalName));
} else {
record = (AAAARecordEntity) getWorkspace().findByKey(AAAARecordEntity.createQueryKey(realm, addressString, finalName));
}
if(record != null) {
record.addToSpace(spaceId);
return record;
}
// use spaceId=0 to avoid commiting to the space yet, we'll commit once the entity is tagged
InternetAddressEntity addressEntity = networkEntityFactory.createAddress(realm, 0, address);
addressEntity.addName(finalName);
addressEntity.save();
HostEntity hostEntity = addressEntity.getHost();
if (hostEntity.getLabel() == null) { //just set the first name discovered
hostEntity.setLabel(finalName+" ("+address+")");
}
DomainEntity domainEntity = findDomain(realm, finalName); // XXX eh? look for .name?
if (domainEntity == null) {
String domain = finalName.substring(finalName.indexOf('.')+1);
domainEntity = createDomain(realm, spaceId, domain);
}
if (!domainEntity.isTLD()) {
hostEntity.addTag(domainEntity.getLevel(2).getFQDM());
} else {
hostEntity.addTag(finalName);
}
hostEntity.update();
hostEntity.addToSpace(spaceId);
if (address instanceof IPv4Address) {
record = new ARecordEntity(getWorkspace(), realm, domainEntity.createReference(), finalName, addressEntity.createReference());
} else {
record = new AAAARecordEntity(getWorkspace(), realm, domainEntity.createReference(), finalName, addressEntity.createReference());
}
record.save();
record.addToSpace(spaceId);
return record;
}
public synchronized PTRRecordEntity createPTRRecord(long realm, long spaceId, InternetAddress address, String fqdm) {
fqdm = normalized(fqdm);;
if (fqdm.endsWith(".arpa")) { // invalid PTR entry (mostly error in bind zone
return null;
}
String addressString = address.toString();
PTRRecordEntity ptr = (PTRRecordEntity) getWorkspace().findByKey(PTRRecordEntity.createQueryKey(realm, addressString, fqdm));
if(ptr != null) {
ptr.addToSpace(spaceId);
return ptr;
}
// use spaceId=0 to avoid commiting to the space yet, we'll commit once the entity is tagged
InternetAddressEntity addressEntity = networkEntityFactory.createAddress(realm, 0, address);
addressEntity.addName(fqdm);
addressEntity.save();
HostEntity hostEntity = addressEntity.getHost();
if (hostEntity.getLabel() == null) { //just set the first name discovered
hostEntity.setLabel(fqdm+" ("+address+")");
}
DomainEntity domainEntity = findDomain(realm, fqdm);
if (domainEntity == null) {
String domain = fqdm.substring(fqdm.indexOf(".")+1);
domainEntity = createDomain(realm, spaceId, domain);
}
if (!domainEntity.isTLD())
hostEntity.addTag(domainEntity.getLevel(2).getFQDM());
else
hostEntity.addTag(fqdm);
hostEntity.update();
hostEntity.addToSpace(spaceId);
ptr = new PTRRecordEntity(getWorkspace(), realm, domainEntity.createReference(), addressEntity.createReference(), fqdm);
ptr.save();
ptr.addToSpace(spaceId);
return ptr;
}
private IWorkspaceEx getWorkspace() {
if(model == null || model.getCurrentWorkspace() == null) {
throw new IllegalStateException("Cannot create DNS entities because no workspace is currently open");
}
return (IWorkspaceEx) model.getCurrentWorkspace();
}
}