View Javadoc

1   /*
2    * GecosLdapAccountMapper.java
3    *
4    * Created on April 13, 2005, 4:21 PM
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   * Matches the DN with the account information retrieved from an LDAP server.
31   *
32   * @author Gabriele Carcassi, Jay Packard
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      // persistent variables
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 }