package com.plexobject.rbac.repository.bdb;
import org.apache.commons.validator.GenericValidator;
import com.plexobject.rbac.domain.Domain;
import com.plexobject.rbac.domain.Subject;
import com.plexobject.rbac.repository.DomainRepository;
import com.plexobject.rbac.repository.NotFoundException;
import com.plexobject.rbac.repository.PersistenceException;
import com.plexobject.rbac.repository.RepositoryFactory;
import com.plexobject.rbac.utils.CurrentRequest;
import com.sleepycat.persist.EntityStore;
public class DomainRepositoryImpl extends BaseRepositoryImpl<Domain, String>
implements DomainRepository {
private final DatabaseStore databaseStore;
private final RepositoryFactory repositoryFactory;
public DomainRepositoryImpl(final EntityStore entityStore,
final DatabaseStore databaseStore,
final RepositoryFactory repositoryFactory) {
super(entityStore);
this.databaseStore = databaseStore;
this.repositoryFactory = repositoryFactory;
}
@Override
public boolean remove(final String id) throws PersistenceException {
if (GenericValidator.isBlankOrNull(id)) {
throw new IllegalArgumentException("domain name is not specified");
}
if (Domain.DEFAULT_DOMAIN_NAME.equals(id)) {
throw new IllegalStateException(Domain.DEFAULT_DOMAIN_NAME
+ " cannot be removed");
}
try {
databaseStore.beginTransaction();
Domain domain = super.findById(id);
if (domain == null) {
throw new IllegalStateException("domain with name " + id
+ " does not exist");
}
boolean success = super.remove(id);
if (success) {
databaseStore.removeDatabase(id);
}
databaseStore.commitTransaction();
return success;
} catch (RuntimeException e) {
databaseStore.abortTransaction();
throw e;
}
}
@Override
public Domain save(final Domain domain) throws PersistenceException {
if (domain == null) {
throw new IllegalArgumentException("domain is not specified");
}
String subjectName = CurrentRequest.getSubjectName();
String originalSubjectName = subjectName;
try {
databaseStore.beginTransaction();
if (Domain.DEFAULT_DOMAIN_NAME.equals(domain.getId())) {
CurrentRequest.setSubjectName(Subject.SUPER_ADMIN.getId());
subjectName = repositoryFactory.getSuperAdmin().getId();
repositoryFactory.getSubjectRepository(domain.getId())
.getOrCreateSubject(Subject.SUPER_ADMIN);
}
if (GenericValidator.isBlankOrNull(subjectName)) {
throw new IllegalArgumentException(
"current subjectName is not specified");
}
// now assigning current subject to the domain as owner
domain.addOwner(subjectName);
Domain saved = super.save(domain);
// Each domain will be stored as a different database, it
// encapsulates subject/roles/permissions for each domain in a
// different database physically.
if (!databaseStore.getAllDatabases().contains(domain.getId())) {
databaseStore.createDatabase(domain.getId());
}
databaseStore.commitTransaction();
if (LOGGER.isInfoEnabled()) {
LOGGER.info("****** Saved new domain " + saved);
}
return saved;
} catch (RuntimeException e) {
databaseStore.abortTransaction();
throw new PersistenceException("Failed to save " + domain, e);
} finally {
CurrentRequest.setSubjectName(originalSubjectName);
}
}
@Override
public Domain getOrCreateDomain(final String name) {
if (GenericValidator.isBlankOrNull(name)) {
throw new IllegalArgumentException("domain name is not specified");
}
try {
return super.findById(name);
} catch (NotFoundException e) {
return save(new Domain(name, name));
}
}
@Override
public boolean isSubjectOwner(String domainName, String subjectName) {
if (GenericValidator.isBlankOrNull(domainName)) {
throw new IllegalArgumentException("domain name is not specified");
}
if (GenericValidator.isBlankOrNull(subjectName)) {
throw new IllegalArgumentException("subjectName is not specified");
}
Domain domain = super.findById(domainName);
return domain != null
&& domain.getOwnerSubjectNames().contains(subjectName);
}
}