1
2
3
4
5
6
7 package gov.bnl.gums;
8
9 import java.io.PrintStream;
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.Date;
13 import java.util.Hashtable;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Map;
17 import org.apache.commons.collections.MultiHashMap;
18 import org.apache.commons.collections.MultiMap;
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21
22 /*** Retrieves the map from the NIS server and provide a logic to match name and
23 * surname to an account.
24 *
25 * @author Gabriele Carcassi
26 */
27 public class GecosMap {
28 private Log log = LogFactory.getLog(NisClient.class);
29 private Log resourceAdminLog = LogFactory.getLog(GUMS.resourceAdminLog);
30 private Map accountToGecos = new Hashtable();
31 private Map accountToName = new Hashtable();
32 private Map accountToSurname = new Hashtable();
33 private MultiMap nameToAccount = new MultiHashMap();
34 private MultiMap surnameToAccount = new MultiHashMap();
35
36 public String findAccount(String name, String surname) {
37 Collection accountsWithName = (Collection) nameToAccount.get(name.toLowerCase());
38 Collection accountsWithSurname = (Collection) surnameToAccount.get(surname.toLowerCase());
39 log.trace("Account matching. Name: " + accountsWithName + "- Surname: " + accountsWithSurname);
40 if ((accountsWithName != null) && (accountsWithSurname != null)) {
41
42 List commonAccounts = new ArrayList(accountsWithName);
43 commonAccounts.retainAll(accountsWithSurname);
44 if (commonAccounts.size() == 1) {
45
46
47 String username = (String) commonAccounts.get(0);
48 log.trace("NIS account Name/Surname single match. Name: " + name + " - Surname: " + surname + " - username: " + username);
49 return username;
50 } else if (commonAccounts.size() > 1) {
51
52
53
54
55 Iterator iter = commonAccounts.iterator();
56 String matchingAccount = null;
57 while (iter.hasNext()) {
58 String account = (String) iter.next();
59 if (account.indexOf(surname.toLowerCase()) != -1) {
60 if (matchingAccount == null) {
61 matchingAccount = account;
62 } else {
63
64 log.trace("NIS account Name/Surname multiple match, multiple username with surname." +
65 " Name: " + name + " - Surname: " + surname + " - username: not defined");
66 resourceAdminLog.warn("NIS mapping: couldn't find single match for surname='" + surname + "' name='" + name + "'. Undecided between " + commonAccounts);
67 return null;
68 }
69 }
70 }
71 if (matchingAccount != null) {
72
73
74 log.trace("NIS account Name/Surname multiple match, single username with surname." +
75 " Name: " + name + " - Surname: " + surname + " - username: " + matchingAccount);
76 return matchingAccount;
77 }
78
79 log.trace("NIS account Name/Surname multiple match, no username with surname." +
80 " Name: " + name + " - Surname: " + surname + " - username: not defined");
81 resourceAdminLog.warn("NIS mapping: couldn't find single match for surname='" + surname + "' name='" + name + "'. Undecided between " + commonAccounts);
82 return null;
83 }
84
85 }
86 if (accountsWithSurname != null) {
87 if (accountsWithSurname.size() == 1) {
88 String username = (String) accountsWithSurname.iterator().next();
89 log.trace("NIS account Surname single match, no match on Name. Name: " + name + " - Surname: " + surname + " - username: " + username);
90 return username;
91 } else {
92 log.trace("NIS account Surname multiple match, no match on Name. Name: " + name + " - Surname: " + surname + " - username: undefined");
93 resourceAdminLog.warn("NIS mapping: couldn't find single match for surname='" + surname + "' name='" + name + "'. Undecided between " + accountsWithSurname);
94 return null;
95 }
96 }
97 log.trace("NIS account no match on Surname. Name: " + name + " - Surname: " + surname + " - username: undefined");
98
99 accountsWithName = (Collection) nameToAccount.get(surname.toLowerCase());
100 accountsWithSurname = (Collection) surnameToAccount.get(name.toLowerCase());
101 if ((accountsWithName != null) && (accountsWithSurname != null)) {
102
103 List commonAccounts = new ArrayList(accountsWithName);
104 commonAccounts.retainAll(accountsWithSurname);
105 if (commonAccounts.size() == 1) {
106
107
108 String username = (String) commonAccounts.get(0);
109 log.trace("NIS account inverted Name/Surname single match. Name: " + surname + " - Surname: " + name + " - username: " + username);
110 return username;
111 }
112 }
113 return null;
114 }
115
116 private Date lastUpdate = null;
117 private long expiration = 60*60*1000;
118 public boolean isValid() {
119 if (lastUpdate == null) return false;
120 if ((System.currentTimeMillis() - lastUpdate.getTime()) > expiration) return false;
121 return true;
122 }
123
124 private String retrieveName(String gecos) {
125 gecos = gecos.trim();
126 int comma = gecos.indexOf(',');
127 if (comma != -1) {
128 gecos = gecos.substring(0, comma);
129 }
130 int index = gecos.lastIndexOf(' ');
131 if (index == -1) return "";
132 return gecos.substring(0, gecos.indexOf(' '));
133 }
134
135 private String retrieveSurname(String gecos) {
136 gecos = gecos.trim();
137 int comma = gecos.indexOf(',');
138 if (comma != -1) {
139 gecos = gecos.substring(0, comma);
140 }
141 int index = gecos.lastIndexOf(' ');
142 if (index == -1) return gecos;
143 return gecos.substring(gecos.lastIndexOf(' ')+1);
144 }
145
146 public void addEntry(String username, String gecos) {
147 String name = retrieveName(gecos);
148 String surname = retrieveSurname(gecos);
149 log.trace("Adding user '" + username + "': GECOS='" + gecos + "' name='" + name + "' surname='" + surname + "'");
150 accountToGecos.put(username, gecos);
151 if (name != null) {
152 accountToName.put(username, name);
153 nameToAccount.put(name.toLowerCase(), username);
154 }
155 accountToSurname.put(username, surname);
156 surnameToAccount.put(surname.toLowerCase(), username);
157 lastUpdate = new Date();
158 }
159
160 public void printMaps(PrintStream out) {
161 out.println("username to gecos map");
162 out.println("---------------------");
163 out.println();
164 Iterator accounts = accountToGecos.keySet().iterator();
165 while (accounts.hasNext()) {
166 String username = (String) accounts.next();
167 String gecos = (String) accountToGecos.get(username);
168 String name = (String) accountToName.get(username);
169 String surname = (String) accountToSurname.get(username);
170 out.print(username);
171 for (int n = username.length(); n < 15; n++) {
172 out.print(' ');
173 }
174 out.print(gecos);
175 for (int n = gecos.length(); n < 30; n++) {
176 out.print(' ');
177 }
178 out.print(name);
179 for (int n = name.length(); n < 15; n++) {
180 out.print(' ');
181 }
182 out.println(surname);
183 }
184 }
185
186 private void printMap(PrintStream out, Map map, int offset) {
187 Iterator accounts = map.keySet().iterator();
188 while (accounts.hasNext()) {
189 String username = (String) accounts.next();
190 String gecos = (String) map.get(username);
191 out.print(username);
192 for (int n = username.length(); n < offset; n++) {
193 out.print(' ');
194 }
195 out.println(gecos);
196
197 }
198 }
199
200 /***
201 * How long the map will be valid since the last change.
202 * <p>
203 * By default is 60*60*1000 (one hour).
204 * @return Time of validity in ms.
205 */
206 public long getExpiration() {
207
208 return this.expiration;
209 }
210
211 /***
212 * How long the map will be valid since the last change.
213 * @param expiration Time of validity in ms.
214 */
215 public void setExpiration(long expiration) {
216
217 this.expiration = expiration;
218 }
219
220 }