1
2
3
4
5
6
7 package gov.bnl.gums.account;
8
9 import gov.bnl.gums.SiteUser;
10 import gov.bnl.gums.configuration.Configuration;
11 import gov.bnl.gums.util.CertToolkit;
12 import gov.bnl.gums.util.GecosMap;
13
14 import java.util.Hashtable;
15 import java.util.Map;
16 import java.util.Properties;
17
18 import javax.naming.NamingEnumeration;
19 import javax.naming.directory.Attribute;
20 import javax.naming.directory.Attributes;
21 import javax.naming.directory.DirContext;
22 import javax.naming.directory.InitialDirContext;
23 import javax.naming.directory.SearchResult;
24 import javax.persistence.Entity;
25 import javax.persistence.Transient;
26
27 import org.apache.log4j.Logger;
28
29
30
31
32
33
34 @Entity
35 public class GecosLdapAccountMapper extends LdapAccountMapper {
36 static private Logger log = Logger.getLogger(GecosLdapAccountMapper.class);
37 static private Map<String, GecosMap> gecosMaps = new Hashtable<String, GecosMap>();
38
39
40 protected String gecosField = "gecos";
41
42 public GecosLdapAccountMapper() {
43 super();
44 }
45
46 public GecosLdapAccountMapper(Configuration configuration, String name) {
47 super(configuration, name);
48 }
49
50 public String getGecosField() {
51 return gecosField;
52 }
53
54 public SiteUser mapDn(String dn, boolean createIfDoesNotExist) {
55 String[] nameSurname = CertToolkit.parseNameAndSurname(dn);
56 GecosMap map = gecosMap();
57 log.trace("GECOS findAccount. Name: " + nameSurname[0] + " - Surname: " + nameSurname[1] + " - GECOSMap: " + gecosMap());
58 String account = map.findAccount(nameSurname[0], nameSurname[1]);
59 return account!=null ? new SiteUser(account) : null;
60 }
61
62 @ConfigFieldAnnotation(label="Full Name Field", example="gecos")
63 public void setGecosField(String gecosField) {
64 this.gecosField = gecosField;
65 }
66
67 protected GecosMap createMap() {
68 Properties jndiProperties = getProperties();
69 int nTries = 5;
70 Exception lastException = null;
71 int i = 0;
72 for (; i < nTries; i++) {
73 GecosMap map = new GecosMap();
74 log.debug("Attempt " + i + " to retrieve map for '" + jndiLdapUrl + "'");
75 try {
76 DirContext jndiCtx = new InitialDirContext(jndiProperties);
77 NamingEnumeration<SearchResult> nisMap = jndiCtx.search(peopleObject, "("+accountField+"=*)", null);
78 log.trace("Server responded");
79 while (nisMap.hasMore()) {
80 SearchResult res = (SearchResult) nisMap.next();
81 Attributes atts = res.getAttributes();
82 String account = (String) atts.get(accountField).get();
83 Attribute gecosAtt = atts.get(gecosField);
84 if (gecosAtt != null) {
85 String gecos = gecosAtt.get().toString();
86 map.addEntry(account, gecos);
87 } else {
88 log.trace("Found user '" + account + "' with no GECOS field");
89 }
90 }
91 jndiCtx.close();
92 return map;
93 } catch (javax.naming.NamingException ne) {
94 log.warn("Error filling the maps for NIS "+jndiLdapUrl, ne);
95 lastException = ne;
96 try {
97 Thread.sleep(100);
98 } catch (InterruptedException e) {
99 log.warn("Interrupted", e);
100 }
101 } catch (Exception e) {
102 log.warn("Error filling the maps for NIS "+jndiLdapUrl, e);
103 lastException = e;
104 try {
105 Thread.sleep(100);
106 } catch (InterruptedException ie) {
107 log.warn("Interrupted", e);
108 }
109 }
110 }
111 if (i == nTries) {
112 throw new RuntimeException("Couldn't retrieve NIS maps from " + jndiLdapUrl, lastException);
113 }
114 return null;
115 }
116
117 protected GecosMap gecosMap() {
118 synchronized (gecosMaps) {
119 GecosMap map = (GecosMap) gecosMaps.get(getMapName());
120 if (map != null) {
121 if (map.isValid()) {
122 log.trace("Reusing GECOS map for '" + getMapName() +"'");
123 return map;
124 } else {
125 log.trace("Invalidating expired GECOS map for '" + getMapName() +"'");
126 gecosMaps.remove(getMapName());
127 }
128 }
129 log.debug("Creating new GECOS map for '" + getMapName() + "'");
130 map = createMap();
131 gecosMaps.put(getMapName(), map);
132 return map;
133 }
134 }
135
136 @Transient
137 protected String getMapName() {
138 return jndiLdapUrl;
139 }
140 }