package com.netifera.platform.net.internal.model;
import java.util.Map;
import com.netifera.platform.api.model.AbstractEntity;
import com.netifera.platform.api.model.IEntity;
import com.netifera.platform.api.model.IModelService;
import com.netifera.platform.model.IWorkspaceEx;
import com.netifera.platform.net.model.ClientEntity;
import com.netifera.platform.net.model.ClientServiceConnectionEntity;
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.net.model.NetblockEntity;
import com.netifera.platform.net.model.PasswordEntity;
import com.netifera.platform.net.model.PortSetEntity;
import com.netifera.platform.net.model.ServiceEntity;
import com.netifera.platform.net.model.UserEntity;
import com.netifera.platform.net.model.UsernameAndPasswordEntity;
import com.netifera.platform.util.PortSet;
import com.netifera.platform.util.addresses.inet.InternetAddress;
import com.netifera.platform.util.addresses.inet.InternetNetblock;
import com.netifera.platform.util.locators.ISocketLocator;
import com.netifera.platform.util.locators.TCPSocketLocator;
import com.netifera.platform.util.locators.UDPSocketLocator;
public class NetworkEntityFactory implements INetworkEntityFactory {
private IModelService model;
protected void setModelService(IModelService model) {
this.model = model;
}
protected void unsetModelService(IModelService model) {
this.model = null;
}
private IWorkspaceEx getWorkspace() {
if(model.getCurrentWorkspace() == null) {
throw new IllegalStateException("Cannot create entities because no workspace is currently open");
}
return (IWorkspaceEx) model.getCurrentWorkspace();
}
public synchronized InternetAddressEntity createAddress(long realm, long spaceId, InternetAddress address) {
InternetAddressEntity addr = (InternetAddressEntity) getWorkspace().findByKey(InternetAddressEntity.createQueryKey(realm, address));
if(addr != null) {
addr.getHost().addToSpace(spaceId);
addr.addToSpace(spaceId);
return addr;
}
HostEntity hostEntity = new HostEntity(getWorkspace(), realm);
// First the HostEntity must be saved so that InternetAddressEntity can store a reference to it
hostEntity.save();
InternetAddressEntity addressEntity = new InternetAddressEntity(getWorkspace(), hostEntity, address.toString());
// Now save the address so that we can create a reference to it in the HostEntity
addressEntity.save();
addressEntity.addToSpace(spaceId);
// It's now safe to assign the InternetAddressEntity
hostEntity.addAddress(addressEntity);
hostEntity.save();
hostEntity.addToSpace(spaceId);
return addressEntity;
}
public synchronized NetblockEntity createNetblock(long realm, long spaceId, InternetNetblock netblock) {
// address needs to be the netblock's one (the first addr in netblock).
InternetAddress address = netblock.getNetworkAddress();
byte[] addressData = address.toBytes();
int maskBitCount = netblock.getCIDR();
NetblockEntity nb = (NetblockEntity) getWorkspace().findByKey(NetblockEntity.createQueryKey(realm, netblock));
if(nb != null) {
nb.addToSpace(spaceId);
return nb;
}
NetblockEntity netblockEntity = new NetblockEntity(getWorkspace(), realm);
netblockEntity.setData(addressData);
netblockEntity.setMaskBitCount(maskBitCount);
netblockEntity.save();
netblockEntity.addToSpace(spaceId);
// add IP if v4/32 or v6/128
if (address.getDataSize() == maskBitCount) {
createAddress(realm, spaceId, address);
}
return netblockEntity;
}
public synchronized void addOpenTCPPorts(long realm, long space, InternetAddress address,
PortSet ports) {
InternetAddressEntity addressEntity = createAddress(realm, space, address);
addOpenPorts(realm, space, addressEntity, ports, true);
}
public synchronized void addOpenUDPPorts(long realm, long space, InternetAddress address,
PortSet ports) {
InternetAddressEntity addressEntity = createAddress(realm, space, address);
addOpenPorts(realm, space, addressEntity, ports, false);
}
private void addOpenPorts(long realm, long spaceId, InternetAddressEntity addressEntity, PortSet ports,
boolean isTCP) {
PortSetEntity portsEntity =
isTCP ? addressEntity.getTcpPorts() : addressEntity.getUdpPorts();
if (portsEntity == null) {
portsEntity = new PortSetEntity(getWorkspace(), addressEntity,
isTCP ? "tcp" : "udp");
portsEntity.setPorts(ports.toString());
portsEntity.save();
if(isTCP) {
addressEntity.setTcpPorts(portsEntity);
} else {
addressEntity.setUdpPorts(portsEntity);
}
portsEntity.save();
portsEntity.addToSpace(spaceId);
addressEntity.save();
addressEntity.getHost().addToSpace(spaceId);
} else {
PortSet ports2 = new PortSet(portsEntity.getPorts());
for (int port: ports)
ports2.addPort(port);
portsEntity.addToSpace(spaceId);
if(portsEntity.getPorts().equals(ports2.toString())) {
// No change.
return;
}
portsEntity.setPorts(ports2.toString());
portsEntity.update();
}
}
private boolean updateAttribute(String name, Map<String, String> info, AbstractEntity e) {
if(!info.containsKey(name))
return false;
String value = info.get(name);
if (value == null || value.equals(e.getNamedAttribute(name)))
return false;
e.setNamedAttribute(name, value);
return true;
}
private boolean updateSystem(AbstractEntity entity, Map<String,String> info) {
boolean changed = false;
changed |= updateAttribute("os", info, entity);
changed |= updateAttribute("distribution", info, entity);
changed |= updateAttribute("arch", info, entity);
return changed;
}
public synchronized void setOperatingSystem(long realm, long spaceId, InternetAddress address, String os) {
InternetAddressEntity addressEntity = createAddress(realm, spaceId, address);
HostEntity hostEntity = addressEntity.getHost();
if(os != null && !os.equals(hostEntity.getNamedAttribute("os"))) {
hostEntity.setNamedAttribute("os", os);
hostEntity.update();
}
}
private ServiceEntity findService(long realm, ISocketLocator locator) {
return (ServiceEntity) getWorkspace().findByKey(ServiceEntity.createQueryKey(realm, locator.getAddress(), locator.getPort(), locator.getProtocol()));
}
private ServiceEntity createNewService(InternetAddressEntity address, ISocketLocator locator, String serviceType,
Map<String,String> info, long space) {
ServiceEntity answer = new ServiceEntity(getWorkspace(), address, locator.getPort(), locator.getProtocol(), serviceType);
if (info != null) {
updateAttribute(ServiceEntity.BANNER_KEY, info, answer);
updateAttribute(ServiceEntity.PRODUCT_KEY, info, answer);
updateAttribute(ServiceEntity.VERSION_KEY, info, answer);
updateSystem(answer, info);
}
answer.save();
answer.addToSpace(space);
return answer;
}
public synchronized ServiceEntity createService(long realm, long spaceId,
ISocketLocator locator, String serviceType, Map<String, String> info) {
if (serviceType == null)
throw new IllegalArgumentException("serviceType cannot be null");
InternetAddressEntity address = createAddress(realm, spaceId, locator.getAddress());
if(info != null) {
if (updateSystem(address.getHost(), info))
address.getHost().update();
}
ServiceEntity answer = findService(realm, locator);
if (answer == null) {
PortSet ports = new PortSet();
ports.addPort(locator.getPort());
if (locator instanceof UDPSocketLocator) {
addOpenPorts(realm, spaceId, address, ports, false);
} else if (locator instanceof TCPSocketLocator) {
addOpenPorts(realm, spaceId, address, ports, true);
}
answer = createNewService(address, locator, serviceType, info, spaceId);
} else {
if (info != null) {
boolean changed = false;
changed |= updateAttribute(ServiceEntity.BANNER_KEY, info, answer);
changed |= updateAttribute(ServiceEntity.PRODUCT_KEY, info, answer);
changed |= updateAttribute(ServiceEntity.VERSION_KEY, info, answer);
changed |= updateSystem(answer, info);
if(changed)
answer.update();
}
answer.addToSpace(spaceId);
}
if (info != null) {
if (info.containsKey("password")) {
if (info.containsKey("username"))
createUsernameAndPassword(realm, spaceId, locator, info.get("username"), info.get("password"));
else
createPassword(realm, spaceId, locator, info.get("password"));
}
if (info.containsKey("hostname")) {
address.addName(info.get("hostname"));
address.update();
// if (address.getHost().getLabel()==null)
// address.getHost().setLabel(info.get("hostname"));
address.getHost().update();
}
}
return answer;
}
private ClientEntity findClient(HostEntity host, String serviceType, String product) {
long realm = host.getRealmId();
String key = ClientEntity.createQueryKey(realm, host.getId(), serviceType, product);
ClientEntity clientEntity = (ClientEntity) getWorkspace().findByKey(key);
if (clientEntity != null)
return clientEntity;
key = ClientEntity.createQueryKey(realm, host.getId(), serviceType, null);
clientEntity = (ClientEntity) getWorkspace().findByKey(key);
if (clientEntity != null) {
clientEntity.setProduct(product);
clientEntity.update();
}
return clientEntity;
}
private ClientEntity createNewClient(long spaceId, HostEntity host, String serviceType, Map<String,String> info) {
ClientEntity answer = new ClientEntity(getWorkspace(), host, serviceType);
if (info != null) {
updateAttribute(ServiceEntity.BANNER_KEY, info, answer);
updateAttribute(ServiceEntity.PRODUCT_KEY, info, answer);
updateAttribute(ServiceEntity.VERSION_KEY, info, answer);
updateSystem(answer, info);
}
answer.save();
answer.addToSpace(spaceId);
return answer;
}
public synchronized ClientEntity createClient(long realm, long spaceId,
InternetAddress address, String serviceType, Map<String, String> info, ISocketLocator service) {
if (serviceType == null)
throw new IllegalArgumentException("serviceType cannot be null");
InternetAddressEntity addressEntity = createAddress(realm, spaceId, address);
HostEntity hostEntity = addressEntity.getHost();
if(info != null) {
if (updateSystem(hostEntity, info))
hostEntity.update();
}
ClientEntity answer = findClient(hostEntity, serviceType, info != null ? info.get("product") : null);
if (answer == null)
return createNewClient(spaceId, addressEntity.getHost(), serviceType, info);
else
answer.addToSpace(spaceId);
String identity = null;
if (info != null) {
boolean isChanged = false;
isChanged |= updateAttribute(ServiceEntity.BANNER_KEY, info, answer);
isChanged |= updateAttribute(ServiceEntity.PRODUCT_KEY, info, answer);
isChanged |= updateAttribute(ServiceEntity.VERSION_KEY, info, answer);
isChanged |= updateSystem(answer, info);
if(isChanged)
answer.update();
if (info.containsKey("identity"))
identity = info.get("identity");
else
identity = info.get("username"); // or null
if (info.containsKey("password")) {
if (info.containsKey("username"))
createUsernameAndPassword(realm, spaceId, service, info.get("username"), info.get("password"));
else
createPassword(realm, spaceId, service, info.get("password"));
}
}
if (service != null) {
ServiceEntity serviceEntity = findService(realm, service);
if (serviceEntity == null)
System.err.println("ERROR: connection to unknown service: "+address+" -> "+service);
else
createConnection(spaceId, answer, serviceEntity, identity);
}
return answer;
}
public ClientServiceConnectionEntity createConnection(long spaceId, ClientEntity client, ServiceEntity service, String identity) {
long realm = client.getRealmId();
long clientId = client.getId();
long serviceId = service.getId();
ClientServiceConnectionEntity answer = (ClientServiceConnectionEntity) getWorkspace().findByKey(ClientServiceConnectionEntity.createQueryKey(realm, clientId, serviceId, identity));
if(answer != null) {
answer.addToSpace(spaceId);
return answer;
}
answer = new ClientServiceConnectionEntity(getWorkspace(), client, service, identity);
answer.save();
answer.addToSpace(spaceId);
return answer;
}
public synchronized UserEntity createUser(long realm, long spaceId, InternetAddress address, String username) {
HostEntity hostEntity = createAddress(realm, spaceId, address).getHost();
UserEntity user = (UserEntity) getWorkspace().findByKey(UserEntity.createQueryKey(realm, username, hostEntity.getId()));
if(user != null) {
user.addToSpace(spaceId);
return user;
}
UserEntity answer = new UserEntity(getWorkspace(), hostEntity, username);
answer.save();
answer.addToSpace(spaceId);
return answer;
}
public synchronized PasswordEntity createPassword(long realm, long spaceId, ISocketLocator service, String password) {
IEntity serviceEntity = findService(realm, service);
PasswordEntity pw = (PasswordEntity) getWorkspace().findByKey(PasswordEntity.createQueryKey(realm, serviceEntity.getId(), password));
if(pw != null) {
pw.addToSpace(spaceId);
return pw;
}
PasswordEntity answer = new PasswordEntity(getWorkspace(), serviceEntity, password);
answer.save();
answer.addToSpace(spaceId);
return answer;
}
public synchronized UsernameAndPasswordEntity createUsernameAndPassword(long realm, long spaceId, ISocketLocator service, String username, String password) {
IEntity serviceEntity = findService(realm, service);
UsernameAndPasswordEntity unp = (UsernameAndPasswordEntity) getWorkspace().findByKey(UsernameAndPasswordEntity.createQueryKey(realm, serviceEntity.getId(), username, password));
if(unp != null) {
unp.addToSpace(spaceId);
return unp;
}
UsernameAndPasswordEntity answer = new UsernameAndPasswordEntity(getWorkspace(), serviceEntity, username, password);
answer.save();
answer.addToSpace(spaceId);
return answer;
}
}