package org.gluu.oxd.server.persistence.service; import org.gluu.oxd.common.ExpiredObject; import org.gluu.oxd.common.ExpiredObjectType; import org.gluu.oxd.common.Jackson2; import org.gluu.oxd.common.PersistenceConfigKeys; import org.gluu.oxd.server.OxdServerConfiguration; import org.gluu.oxd.server.Utils; import org.gluu.oxd.server.persistence.modal.OrganizationBranch; import org.gluu.oxd.server.persistence.modal.RpObject; import org.gluu.oxd.server.persistence.providers.GluuPersistenceConfiguration; import org.gluu.oxd.server.persistence.providers.PersistenceEntryManagerFactory; import org.gluu.oxd.server.service.MigrationService; import org.gluu.oxd.server.service.Rp; import org.gluu.persist.PersistenceEntryManager; import org.gluu.persist.exception.EntryPersistenceException; import org.gluu.persist.model.base.SimpleBranch; import org.gluu.search.filter.Filter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; public class GluuPersistenceService implements PersistenceService { private static final Logger LOG = LoggerFactory.getLogger(GluuPersistenceService.class); private OxdServerConfiguration configuration; private PersistenceEntryManager persistenceEntryManager; private String persistenceType; private String baseDn; public GluuPersistenceService(OxdServerConfiguration configuration) { this.configuration = configuration; } public GluuPersistenceService(OxdServerConfiguration configuration, String persistenceType) { this.configuration = configuration; this.persistenceType = persistenceType; } public void create() { LOG.debug("Creating GluuPersistenceService ..."); try { GluuPersistenceConfiguration gluuPersistenceConfiguration = new GluuPersistenceConfiguration(configuration); Properties props = gluuPersistenceConfiguration.getPersistenceProps(); this.baseDn = props.getProperty(PersistenceConfigKeys.BaseDn.getKeyName()); if (props.getProperty(PersistenceConfigKeys.PersistenceType.getKeyName()).equalsIgnoreCase("ldap") || props.getProperty(PersistenceConfigKeys.PersistenceType.getKeyName()).equalsIgnoreCase("hybrid")) { this.persistenceEntryManager = PersistenceEntryManagerFactory.createLdapPersistenceEntryManager(props); } else if (props.getProperty(PersistenceConfigKeys.PersistenceType.getKeyName()).equalsIgnoreCase("couchbase")) { this.persistenceEntryManager = PersistenceEntryManagerFactory.createCouchbasePersistenceEntryManager(props); } if (this.persistenceType != null && !this.persistenceType.equalsIgnoreCase(props.getProperty(PersistenceConfigKeys.PersistenceType.getKeyName()))) { LOG.error("The value of the `storage` field in `oxd-server.yml` does not matches with `persistence.type` in `gluu.property` file. \n `storage` value: {} \n `persistence.type` value : {}" , this.persistenceType, this.persistenceEntryManager.getPersistenceType()); throw new RuntimeException("The value of the `storage` field in `oxd-server.yml` does not matches with `persistence.type` in `gluu.property` file. \n `storage` value: " + this.persistenceType + " \n `persistence.type` value : " + this.persistenceEntryManager.getPersistenceType()); } prepareBranch(); } catch (Exception e) { throw new IllegalStateException("Error starting GluuPersistenceService", e); } } public void prepareBranch() { if (!this.persistenceEntryManager.hasBranchesSupport(this.baseDn)) { return; } //create `o=gluu` if not present if (!containsBranch(this.baseDn)) { addOrganizationBranch(this.baseDn, null); } //create `ou=configuration,o=gluu` if not present if (!containsBranch(String.format("%s,%s", ou("configuration"), this.baseDn))) { addBranch(String.format("%s,%s", ou("configuration"), this.baseDn), "configuration"); } //create `ou=oxd,ou=configuration,o=gluu` if not present if (!containsBranch(String.format("%s,%s,%s", ou("oxd"), ou("configuration"), this.baseDn))) { addBranch(String.format("%s,%s,%s", ou("oxd"), ou("configuration"), this.baseDn), "oxd"); } //create `ou=oxd,o=gluu` if not present if (!containsBranch(getOxdDn())) { addBranch(getOxdDn(), "oxd"); } //create `ou=rp,ou=oxd,o=gluu` if not present if (!containsBranch(String.format("%s,%s", getRpOu(), getOxdDn()))) { addBranch(String.format("%s,%s", getRpOu(), getOxdDn()), "rp"); } //create `ou=expiredObjects,ou=oxd,o=gluu` if not present if (!containsBranch(String.format("%s,%s", getExpiredObjOu(), getOxdDn()))) { addBranch(String.format("%s,%s", getExpiredObjOu(), getOxdDn()), "expiredObjects"); } } public boolean containsBranch(String dn) { return this.persistenceEntryManager.contains(dn, SimpleBranch.class); } public void addOrganizationBranch(String dn, String oName) { OrganizationBranch branch = new OrganizationBranch(); branch.setOrganizationName(oName); branch.setDn(dn); this.persistenceEntryManager.persist(branch); } public void addBranch(String dn, String ouName) { SimpleBranch branch = new SimpleBranch(); branch.setOrganizationalUnitName(ouName); branch.setDn(dn); this.persistenceEntryManager.persist(branch); } public boolean create(Rp rp) { try { RpObject rpObj = new RpObject(getDnForRp(rp.getOxdId()), rp.getOxdId(), Jackson2.serializeWithoutNulls(rp)); this.persistenceEntryManager.persist(rpObj); LOG.debug("RP created successfully. RP : {} ", rp); return true; } catch (Exception e) { LOG.error("Failed to create RP: {} ", rp, e); } return false; } public boolean createExpiredObject(ExpiredObject obj) { try { if (isExpiredObjectPresent(obj.getKey())) { LOG.warn("Expired_object already present. Object : {} ", obj.getKey()); return true; } obj.setTypeString(obj.getType().getValue()); obj.setDn(getDnForExpiredObj(obj.getKey())); this.persistenceEntryManager.persist(obj); LOG.debug("Expired_object created successfully. Object : {} ", obj.getKey()); return true; } catch (Exception e) { LOG.error("Failed to create ExpiredObject: {} ", obj.getKey(), e); } return false; } public boolean update(Rp rp) { try { RpObject rpObj = new RpObject(getDnForRp(rp.getOxdId()), rp.getOxdId(), Jackson2.serializeWithoutNulls(rp)); this.persistenceEntryManager.merge(rpObj); LOG.debug("RP updated successfully. RP : {} ", rpObj); return true; } catch (Exception e) { LOG.error("Failed to update RP: {} ", rp, e); } return false; } public Rp getRp(String oxdId) { try { RpObject rpFromGluuPersistance = getRpObject(oxdId, new String[0]); Rp rp = MigrationService.parseRp(rpFromGluuPersistance.getData()); if (rp != null) { LOG.debug("Found RP id: {}, RP : {} ", oxdId, rp); return rp; } LOG.error("Failed to fetch RP by id: {} ", oxdId); return null; } catch (Exception e) { LOG.error("Failed to update oxdId: {} ", oxdId, e); } return null; } private RpObject getRpObject(String oxdId, String... returnAttributes) { return (RpObject) this.persistenceEntryManager.find(getDnForRp(oxdId), RpObject.class, returnAttributes); } public ExpiredObject getExpiredObject(String key) { try { ExpiredObject expiredObject = (ExpiredObject) this.persistenceEntryManager.find(getDnForExpiredObj(key), ExpiredObject.class, null); if (expiredObject != null) { expiredObject.setType(ExpiredObjectType.fromValue(expiredObject.getTypeString())); LOG.debug("Found ExpiredObject id: {} , ExpiredObject : {} ", key, expiredObject); return expiredObject; } LOG.error("Failed to fetch ExpiredObject by id: {} ", key); return null; } catch (Exception e) { if (((e instanceof EntryPersistenceException)) && (e.getMessage().contains("Failed to find entry"))) { LOG.warn("Failed to fetch ExpiredObject by id: {}. {} ", key, e.getMessage()); return null; } LOG.error("Failed to fetch ExpiredObject by id: {} ", key, e); } return null; } public boolean isExpiredObjectPresent(String key) { return getExpiredObject(key) != null; } public boolean removeAllRps() { try { this.persistenceEntryManager.remove(String.format("%s,%s", new Object[]{getRpOu(), getOxdDn()}), RpObject.class, null, this.configuration.getPersistenceManagerRemoveCount()); LOG.debug("Removed all Rps successfully. "); return true; } catch (Exception e) { LOG.error("Failed to remove all Rps", e); } return false; } public Set<Rp> getRps() { try { List<RpObject> rpObjects = this.persistenceEntryManager.findEntries(String.format("%s,%s", new Object[]{getRpOu(), getOxdDn()}), RpObject.class, null); Set<Rp> result = new HashSet(); for (RpObject ele : rpObjects) { Rp rp = MigrationService.parseRp(ele.getData()); if (rp != null) { result.add(rp); } else { LOG.error("Failed to parse rp, id: {}, dn: {} ", ele.getId(), ele.getDn()); } } return result; } catch (Exception e) { if (((e instanceof EntryPersistenceException)) && (e.getMessage().contains("Failed to find entries"))) { LOG.warn("Failed to fetch RpObjects. {} ", e.getMessage()); return null; } LOG.error("Failed to fetch rps. Error: {} ", e.getMessage(), e); } return null; } public void destroy() { this.persistenceEntryManager.destroy(); } public boolean remove(String oxdId) { try { this.persistenceEntryManager.remove(getDnForRp(oxdId)); LOG.debug("Removed rp successfully. oxdId: {} ", oxdId); return true; } catch (Exception e) { LOG.error("Failed to remove rp with oxdId: {} ", oxdId, e); } return false; } public boolean deleteExpiredObjectsByKey(String key) { try { this.persistenceEntryManager.remove(getDnForExpiredObj(key)); LOG.debug("Removed expired_objects successfully: {} ", key); return true; } catch (Exception e) { LOG.error("Failed to remove expired_objects: {} ", key, e); } return false; } public boolean deleteAllExpiredObjects() { try { final Calendar cal = Calendar.getInstance(); final Date currentTime = cal.getTime(); Filter exirationDateFilter = Filter.createLessOrEqualFilter("exp", this.persistenceEntryManager.encodeTime(baseDn, currentTime)); this.persistenceEntryManager.remove(String.format("%s,%s", new Object[]{getExpiredObjOu(), getOxdDn()}), ExpiredObject.class, exirationDateFilter, this.configuration.getPersistenceManagerRemoveCount()); LOG.debug("Removed all expired_objects successfully. "); return true; } catch (Exception e) { LOG.error("Failed to remove expired_objects. ", e); } return false; } public String getDnForRp(String oxdId) { return String.format("oxId=%s,%s,%s", new Object[]{oxdId, getRpOu(), getOxdDn()}); } public String getDnForExpiredObj(String oxdId) { return String.format("oxId=%s,%s,%s", new Object[]{oxdId, getExpiredObjOu(), getOxdDn()}); } public String ou(String ouName) { return String.format("ou=%s", ouName); } private String getOxdDn() { return String.format("%s,%s", ou("oxd"), this.baseDn); } private String getRpOu() { return ou("rp"); } private String getExpiredObjOu() { return ou("expiredObjects"); } }