// --- 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 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package com.netscape.cmscore.dbs;
import java.util.Enumeration;
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 netscape.ldap.LDAPModificationSet;
import netscape.ldap.LDAPSearchConstraints;
import netscape.ldap.LDAPSearchResults;
import netscape.ldap.LDAPv2;
import netscape.ldap.controls.LDAPPersistSearchControl;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.ISubsystem;
import com.netscape.certsrv.dbs.EDBException;
import com.netscape.certsrv.dbs.EDBNotAvailException;
import com.netscape.certsrv.dbs.EDBRecordNotFoundException;
import com.netscape.certsrv.dbs.IDBObj;
import com.netscape.certsrv.dbs.IDBSSession;
import com.netscape.certsrv.dbs.IDBSearchResults;
import com.netscape.certsrv.dbs.IDBSubsystem;
import com.netscape.certsrv.dbs.IDBVirtualList;
import com.netscape.certsrv.dbs.Modification;
import com.netscape.certsrv.dbs.ModificationSet;
import com.netscape.certsrv.logging.ILogger;
/**
* A class represents the database session. Operations
* can be performed with a session.
*
* Transaction and Caching support can be integrated
* into session.
*
* @author thomask
* @version $Revision$, $Date$
*/
public class DBSSession implements IDBSSession {
private IDBSubsystem mDBSystem = null;
private LDAPConnection mConn = null;
private ILogger mLogger = CMS.getLogger();
/**
* Constructs a database session.
*
* @param system the database subsytem
* @param c the ldap connection
*/
public DBSSession(IDBSubsystem system, LDAPConnection c) {
mDBSystem = system;
mConn = c;
try {
// no limit
mConn.setOption(LDAPv2.SIZELIMIT, Integer.valueOf(0));
} catch (LDAPException e) {
}
}
/**
* Returns database subsystem.
*/
public ISubsystem getDBSubsystem() {
return mDBSystem;
}
/**
* Closes this session.
*/
public void close() throws EDBException {
// return ldap connection.
mDBSystem.returnConn(mConn);
}
/**
* Adds object to backend database. For example,
*
*
* session.add("cn=123459,o=certificate repository,o=airius.com",
* certRec);
*
*
* @param name the name of the ldap entry
* @param obj the DBobj that can be mapped to ldap attrubute set
*/
public void add(String name, IDBObj obj) throws EBaseException {
try {
LDAPAttributeSet attrs = mDBSystem.getRegistry(
).createLDAPAttributeSet(obj);
LDAPEntry e = new LDAPEntry(name, attrs);
/*LogDoc
*
* @phase local ldap add
* @message DBSSession: begin LDAP add
*/
mConn.add(e);
} catch (LDAPException e) {
if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
throw new EDBNotAvailException(
CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
name + " " + e.toString()));
}
}
/**
* Reads an object from the database.
* all attributes will be returned
*
* @param name the name of the ldap entry
*/
public IDBObj read(String name) throws EBaseException {
return read(name, null);
}
/**
* Reads an object from the database, and only populates
* the selected attributes.
*
* @param name the name of the ldap entry
* @param attrs the attributes to be selected
*/
public IDBObj read(String name, String attrs[])
throws EBaseException {
try {
String ldapattrs[] = null;
if (attrs != null) {
ldapattrs = mDBSystem.getRegistry(
).getLDAPAttributes(attrs);
}
/*LogDoc
*
* @phase local ldap read
* @message DBSSession: begin LDAP read
*/
LDAPSearchResults res = mConn.search(name,
LDAPv2.SCOPE_BASE, "(objectclass=*)",
ldapattrs, false);
LDAPEntry entry = (LDAPEntry) res.nextElement();
return mDBSystem.getRegistry().createObject(
entry.getAttributeSet());
} catch (LDAPException e) {
/*LogDoc
*
* @phase local ldap read
* @message DBSSession:
*/
mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_INFO, "DBSSession: " + e.toString());
if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
throw new EDBNotAvailException(
CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT)
throw new EDBRecordNotFoundException(
CMS.getUserMessage("CMS_DBS_RECORD_NOT_FOUND"));
throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
name + " " + e.toString()));
}
}
/**
* Deletes object from database.
*/
public void delete(String name) throws EBaseException {
try {
mConn.delete(name);
} catch (LDAPException e) {
if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
throw new EDBNotAvailException(
CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
name + " " + e.toString()));
}
}
/**
* Modify an object in the database.
*/
public void modify(String name, ModificationSet mods)
throws EBaseException {
try {
LDAPModificationSet ldapMods = new
LDAPModificationSet();
Enumeration> e = mods.getModifications();
while (e.hasMoreElements()) {
Modification mod = (Modification)
e.nextElement();
LDAPAttributeSet attrs = new LDAPAttributeSet();
mDBSystem.getRegistry().mapObject(null,
mod.getName(), mod.getValue(), attrs);
Enumeration> e0 = attrs.getAttributes();
while (e0.hasMoreElements()) {
ldapMods.add(toLdapModOp(mod.getOp()),
(LDAPAttribute)
e0.nextElement());
}
}
/*LogDoc
*
* @phase local ldap add
* @message DBSSession: begin LDAP modify
*/
mConn.modify(name, ldapMods);
} catch (LDAPException e) {
if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
throw new EDBNotAvailException(
CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
name + " " + e.toString()));
}
}
private int toLdapModOp(int modOp) throws EBaseException {
switch (modOp) {
case Modification.MOD_ADD:
return LDAPModification.ADD;
case Modification.MOD_DELETE:
return LDAPModification.DELETE;
case Modification.MOD_REPLACE:
return LDAPModification.REPLACE;
}
throw new EBaseException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
Integer.toString(modOp)));
}
/**
* Searchs for a list of objects that match the
* filter.
*/
public IDBSearchResults search(String base, String filter)
throws EBaseException {
return search(base, filter, null);
}
@SuppressWarnings("unchecked")
public IDBSearchResults search(String base, String filter, int maxSize)
throws EBaseException {
try {
String ldapattrs[] = null;
String ldapfilter =
mDBSystem.getRegistry().getFilter(filter);
LDAPSearchConstraints cons = new LDAPSearchConstraints();
cons.setMaxResults(maxSize);
LDAPSearchResults res = mConn.search(base,
LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons);
return new DBSearchResults(mDBSystem.getRegistry(),
res);
} catch (LDAPException e) {
if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
throw new EDBNotAvailException(
CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
// XXX error handling, should not raise exception if
// entry not found
throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
e.toString()));
}
}
@SuppressWarnings("unchecked")
public IDBSearchResults search(String base, String filter, int maxSize, int timeLimit)
throws EBaseException {
try {
String ldapattrs[] = null;
String ldapfilter =
mDBSystem.getRegistry().getFilter(filter);
LDAPSearchConstraints cons = new LDAPSearchConstraints();
cons.setMaxResults(maxSize);
cons.setServerTimeLimit(timeLimit);
LDAPSearchResults res = mConn.search(base,
LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons);
return new DBSearchResults(mDBSystem.getRegistry(),
res);
} catch (LDAPException e) {
if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
throw new EDBNotAvailException(
CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
// XXX error handling, should not raise exception if
// entry not found
throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
e.toString()));
}
}
/**
* Retrieves a list of object that satifies the given
* filter.
*/
@SuppressWarnings("unchecked")
public IDBSearchResults search(String base, String filter,
String attrs[]) throws EBaseException {
try {
String ldapattrs[] = null;
if (attrs != null) {
ldapattrs = mDBSystem.getRegistry(
).getLDAPAttributes(attrs);
}
String ldapfilter =
mDBSystem.getRegistry().getFilter(filter);
/*LogDoc
*
* @phase local ldap add
* @message DBSSession: begin LDAP search
*/
LDAPSearchConstraints cons = new LDAPSearchConstraints();
cons.setMaxResults(0);
LDAPSearchResults res = mConn.search(base,
LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons);
return new DBSearchResults(mDBSystem.getRegistry(),
res);
} catch (LDAPException e) {
if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
throw new EDBNotAvailException(
CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
// XXX error handling, should not raise exception if
// entry not found
throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
e.toString()));
}
}
public LDAPSearchResults persistentSearch(String base, String filter, String attrs[])
throws EBaseException {
try {
String ldapattrs[] = null;
if (attrs != null) {
ldapattrs = mDBSystem.getRegistry(
).getLDAPAttributes(attrs);
}
String ldapfilter =
mDBSystem.getRegistry().getFilter(filter);
Integer version = (Integer) (mConn.getOption(LDAPv2.PROTOCOL_VERSION));
// Only version 3 protocol supports persistent search.
if (version.intValue() == 2) {
mConn.setOption(LDAPv2.PROTOCOL_VERSION, Integer.valueOf(3));
}
int op = LDAPPersistSearchControl.MODIFY;
boolean changesOnly = true;
boolean returnControls = true;
boolean isCritical = true;
LDAPPersistSearchControl persistCtrl = new
LDAPPersistSearchControl(op, changesOnly,
returnControls, isCritical);
LDAPSearchConstraints cons = new LDAPSearchConstraints();
cons.setBatchSize(0);
cons.setServerControls(persistCtrl);
LDAPSearchResults res = mConn.search(base,
LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons);
return res;
} catch (LDAPException e) {
if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
throw new EDBNotAvailException(
CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
// XXX error handling, should not raise exception if
// entry not found
throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
e.toString()));
}
}
public void abandon(LDAPSearchResults results) throws EBaseException {
try {
mConn.abandon(results);
} catch (LDAPException e) {
if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
throw new EDBNotAvailException(
CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
// XXX error handling, should not raise exception if
// entry not found
throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
e.toString()));
}
}
/**
* Retrieves a list of objects.
*/
public IDBVirtualList createVirtualList(String base, String filter,
String attrs[]) throws EBaseException {
return new DBVirtualList(mDBSystem.getRegistry(), mConn, base,
filter, attrs);
}
/**
* Retrieves a list of objects.
*/
public IDBVirtualList createVirtualList(String base, String filter,
String attrs[], String sortKey[]) throws EBaseException {
return new DBVirtualList(mDBSystem.getRegistry(), mConn, base,
filter, attrs, sortKey);
}
/**
* Retrieves a list of objects.
*/
public IDBVirtualList> createVirtualList(String base, String filter,
String attrs[], String sortKey) throws EBaseException {
return new DBVirtualList(mDBSystem.getRegistry(), mConn, base,
filter, attrs, sortKey);
}
/**
* Retrieves a list of objects.
*/
public IDBVirtualList> createVirtualList(String base, String filter,
String attrs[], String sortKey[], int pageSize) throws EBaseException {
return new DBVirtualList(mDBSystem.getRegistry(), mConn, base,
filter, attrs, sortKey, pageSize);
}
/**
* Retrieves a list of objects.
*/
public IDBVirtualList createVirtualList(String base, String filter,
String attrs[], String sortKey, int pageSize) throws EBaseException {
return new DBVirtualList(mDBSystem.getRegistry(), mConn, base,
filter, attrs, sortKey, pageSize);
}
public IDBVirtualList createVirtualList(String base, String filter,
String attrs[], String startFrom, String sortKey, int pageSize) throws EBaseException {
return new DBVirtualList(mDBSystem.getRegistry(), mConn, base,
filter, attrs, startFrom, sortKey, pageSize);
}
/**
* Releases object to this interface. This allows us to
* use memory more efficiently.
*/
public void release(Object obj) {
// not implemented
}
}