summaryrefslogtreecommitdiffstats
path: root/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java
blob: 4c3ac8dfb4f15bb57fbf63856886f46936f1ed83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package com.netscape.cmscore.dbs;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;

import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.dbs.IDBAttrMapper;
import com.netscape.certsrv.dbs.IDBObj;
import com.netscape.certsrv.dbs.IDBRegistry;
import com.netscape.certsrv.dbs.IDBSSession;
import com.netscape.certsrv.dbs.IDBSearchResults;
import com.netscape.certsrv.dbs.IDBSubsystem;
import com.netscape.certsrv.dbs.Modification;
import com.netscape.certsrv.dbs.ModificationSet;

/**
 * This class implements LDAP database.
 *
 * @author Endi S. Dewata
 */
public abstract class LDAPDatabase<E extends IDBObj> extends Database<E> {

    public IDBSubsystem dbSubsystem;
    public String baseDN;
    public Class<E> recordType;

    public LDAPDatabase(String name, IDBSubsystem dbSubsystem, String baseDN, Class<E> recordType) throws EBaseException {
        super(name);

        this.dbSubsystem = dbSubsystem;
        this.baseDN = baseDN;
        this.recordType = recordType;

        register(recordType);
    }

    public IDBAttrMapper createMapper(Class<?> attrType, DBAttribute dbAttribute) throws EBaseException {
        String attrName = dbAttribute.value();

        if (attrType == String.class) {
            return new StringMapper(attrName);

        } else if (attrType == Date.class) {
            return new DateMapper(attrName);

        } else {
            // TODO: add other mappers
            throw new EBaseException("Unsupported attribute type: " + attrType);
        }
    }

    public void register(Class<E> recordType) throws EBaseException {
        IDBRegistry dbRegistry = dbSubsystem.getRegistry();

        // register object classes
        DBObjectClasses dbObjectClasses = recordType.getAnnotation(DBObjectClasses.class);
        if (dbObjectClasses == null) {
            throw new EBaseException("Missing object class mapping in " + recordType.getName());
        }
        dbRegistry.registerObjectClass(recordType.getName(), dbObjectClasses.value());

        // register attributes defined in setters/getters
        for (Method method : recordType.getMethods()) {
            DBAttribute dbAttribute = method.getAnnotation(DBAttribute.class);
            if (dbAttribute == null) continue;

            String name = method.getName();
            if (!name.matches("^set.+") && !name.matches("^get.+")) continue;

            // get attribute name from method name
            name = Character.toLowerCase(name.charAt(3)) + name.substring(4);

            Class<?> attrType = method.getReturnType();
            IDBAttrMapper mapper = createMapper(attrType, dbAttribute);

            dbRegistry.registerAttribute(name, mapper);
        }

        // register attributes defined in fields
        for (Field field : recordType.getFields()) {
            DBAttribute dbAttribute = field.getAnnotation(DBAttribute.class);
            if (dbAttribute == null) continue;

            String name = field.getName();
            Class<?> attrType = field.getType();
            IDBAttrMapper mapper = createMapper(attrType, dbAttribute);

            dbRegistry.registerAttribute(name, mapper);
        }
    }

    public abstract String createDN(String id);
    public abstract String createFilter(String filter);

    @Override
    public Collection<E> findRecords(String filter) throws Exception {
        CMS.debug("LDAPDatabase: findRecords()");

        try (IDBSSession session = dbSubsystem.createSession()) {
            Collection<E> list = new ArrayList<E>();
            filter = createFilter(filter);
            CMS.debug("LDAPDatabase: searching " + baseDN + " with filter " + filter);
            IDBSearchResults results = session.search(baseDN, filter);

            while (results.hasMoreElements()) {
                @SuppressWarnings("unchecked")
                E result = (E)results.nextElement();
                list.add(result);
            }

            return list;
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public E getRecord(String id) throws Exception {
        CMS.debug("LDAPDatabase: getRecord(\"" + id + "\")");
        try (IDBSSession session = dbSubsystem.createSession()) {
            String dn = createDN(id);
            CMS.debug("LDAPDatabase: reading " + baseDN);
            return (E)session.read(dn);
        }
    }

    @Override
    public void addRecord(String id, E record) throws Exception {
        CMS.debug("LDAPDatabase: addRecord(\"" + id + "\")");
        try (IDBSSession session = dbSubsystem.createSession()) {
            String dn = createDN(id);

            CMS.debug("LDAPDatabase: adding " + dn);
            session.add(dn, record);
        }
    }

    @Override
    public void updateRecord(String id, E record) throws Exception {
        CMS.debug("LDAPDatabase: updateRecord(\"" + id + "\")");
        try (IDBSSession session = dbSubsystem.createSession()) {
            String dn = createDN(id);

            ModificationSet mods = new ModificationSet();
            for (Enumeration<String> names = record.getSerializableAttrNames(); names.hasMoreElements(); ) {
                String name = names.nextElement();
                Object value = record.get(name);
                mods.add(name, Modification.MOD_REPLACE, value);
            }

            CMS.debug("LDAPDatabase: modifying " + dn);
            session.modify(dn, mods);
        }
    }

    @Override
    public void removeRecord(String id) throws Exception {
        CMS.debug("LDAPDatabase: removeRecord(\"" + id + "\")");
        try (IDBSSession session = dbSubsystem.createSession()) {
            String dn = createDN(id);

            CMS.debug("LDAPDatabase: removing " + dn);
            session.delete(dn);
        }
    }
}