>From ae029d57c6362a4c70057aeb7e8ac015f850cfc5 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Tue, 15 Jul 2014 02:48:35 -0400 Subject: [PATCH 05/10] Add LDAPConfigStore class The LDAPConfigStore class is an IConfigStore that reads and writes its configuration to a given attribute and DN in an LDAP database. --- .../com/netscape/cmscore/base/LDAPConfigStore.java | 195 +++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 base/server/cmscore/src/com/netscape/cmscore/base/LDAPConfigStore.java diff --git a/base/server/cmscore/src/com/netscape/cmscore/base/LDAPConfigStore.java b/base/server/cmscore/src/com/netscape/cmscore/base/LDAPConfigStore.java new file mode 100644 index 0000000000000000000000000000000000000000..788ef6bc9a26f62ed779586818525df56c555cea --- /dev/null +++ b/base/server/cmscore/src/com/netscape/cmscore/base/LDAPConfigStore.java @@ -0,0 +1,195 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007, 2014 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cmscore.base; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.Map; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPException; +import netscape.ldap.LDAPModification; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.ldap.ILdapConnFactory; + +/** + * LDAPConfigStore: + * Extends PropConfigStore with methods to load/save from/to file for + * persistent storage. This is a configuration store agent who + * reads data from an LDAP entry. + *

+ * + * @version $Revision$, $Date$ + * @see PropConfigStore + */ +public class LDAPConfigStore extends PropConfigStore implements IConfigStore { + + private ILdapConnFactory dbFactory; + private String dn; + private String attr; + private LDAPAttribute[] createAttrs; + + /** + * + */ + private static final long serialVersionUID = 3642124526598175633L; + + /** + * Constructs an LDAP configuration store. + *

+ * + * @param dbFactory Database connection factory + * @param dn Distinguished name of record containing config store + * @param attr Name of attribute containing config store + * @param createAttrs Set of initial attributes if creating the entry. Should + * contain cn, objectclass and possibly other attributes. + * + * @exception EBaseException failed to create file configuration + */ + public LDAPConfigStore( + ILdapConnFactory dbFactory, + String dn, LDAPAttribute[] createAttrs, String attr + ) throws EBaseException { + super(null); // top-level store without a name + + this.dbFactory = dbFactory; + this.dn = dn; + this.createAttrs = createAttrs; + this.attr = attr; + + LDAPConnection conn = dbFactory.getConn(); + + String[] readAttrs = {attr}; + try { + LDAPEntry ldapEntry = conn.read(dn, readAttrs); + + Enumeration vals = ldapEntry.getAttribute(attr).getStringValues(); + InputStream data = new ByteArrayInputStream(vals.nextElement().getBytes()); + load(data); + } catch (LDAPException e) { + // if there is no such object, we will create it on commit() + if (e.getLDAPResultCode() != LDAPException.NO_SUCH_OBJECT) { + throw new EBaseException( + "Error reading LDAPConfigStore '" + + dn + "': " + e.toString() + ); + } + } catch (IOException e) { + throw new EBaseException( + "Error reading LDAPConfigStore '" + + dn + "': " + e.toString() + ); + } finally { + dbFactory.returnConn(conn); + } + } + + @Override + public void save(OutputStream out, String header) { + try (PrintWriter writer = new PrintWriter(out)) { + Map map = getProperties(); + for (String k : map.keySet()) { + writer.println(k + "=" + map.get(k)); + } + } + } + + /** + * Commit the configuration to the database. + * + * All uses of LDAPProfileStore at time of writing call with + * createBackup=false, so the argument is ignored. + * + * If backup becomes necessary, the constructor should be + * modified to take a String backupAttr, and the existing + * content be copied to that attribute. + * + * @param createBackup Ignored. + */ + public void commit(boolean createBackup) throws EBaseException { + ByteArrayOutputStream data = new ByteArrayOutputStream(); + save(data, null); + + LDAPAttribute configAttr = new LDAPAttribute(attr, data.toByteArray()); + + LDAPConnection conn = dbFactory.getConn(); + + // first attempt to modify; if modification fails (due + // to no such object), try and add the entry instead. + try { + try { + commitModify(conn, configAttr); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) { + commitAdd(conn, configAttr); + } else { + throw e; + } + } + } catch (LDAPException e) { + throw new EBaseException( + "Error writing LDAPConfigStore '" + + dn + "': " + e.toString() + ); + } finally { + dbFactory.returnConn(conn); + } + } + + /** + * Update the record via an LDAPModification. + * + * @param conn LDAP connection. + * @param configAttr Config store attribute. + * @return true on success, false if the entry does not exist. + */ + private void commitModify(LDAPConnection conn, LDAPAttribute configAttr) + throws LDAPException + { + LDAPModification ldapMod = + new LDAPModification(LDAPModification.REPLACE, configAttr); + conn.modify(dn, ldapMod); + } + + /** + * Add the LDAPEntry via LDAPConnection.add. + * + * @param conn LDAP connection. + * @param configAttr Config store attribute. + * @return true on success, false if the entry already exists. + */ + private void commitAdd(LDAPConnection conn, LDAPAttribute configAttr) + throws LDAPException + { + LDAPAttributeSet attrSet = new LDAPAttributeSet(createAttrs); + attrSet.add(configAttr); + LDAPEntry ldapEntry = new LDAPEntry(dn, attrSet); + conn.add(ldapEntry); + } +} -- 1.9.3