View Javadoc

1   /*
2    * ManualUserGroup.java
3    *
4    * Created on May 25, 2004, 4:48 PM
5    */
6   
7   package gov.bnl.gums.userGroup;
8   
9   import java.io.BufferedReader;
10  import java.io.FileReader;
11  import java.io.InputStreamReader;
12  import java.net.URL;
13  import java.net.URLConnection;
14  import java.security.Security;
15  import java.util.ArrayList;
16  import java.util.Calendar;
17  import java.util.Date;
18  import java.util.Iterator;
19  import java.util.List;
20  import java.util.Properties;
21  import java.util.regex.Matcher;
22  import java.util.regex.Pattern;
23  
24  import org.apache.log4j.Logger;
25  
26  import gov.bnl.gums.configuration.Configuration;
27  import gov.bnl.gums.db.ManualUserGroupDB;
28  import gov.bnl.gums.FQAN;
29  import gov.bnl.gums.GridUser;
30  import gov.bnl.gums.RWLock;
31  
32  /** 
33   * A user group that is defined by a list of users stored in some way, allowing
34   * to add and remove users. The persistance layer is implemented through an
35   * interface, allowing different storage frameworks (i.e. database, LDAP, file)
36   * <p>
37   * This class will provide also configurable data caching.
38   *
39   * @author Gabriele Carcassi, Jay Packard
40   */
41  public class ManualUserGroup extends UserGroup {
42      static public String getTypeStatic() {
43  		return "manual";
44  	}
45      
46      private Logger log = Logger.getLogger(ManualUserGroup.class);
47      private ManualUserGroupDB db;
48  	private String persistenceFactory = "";
49  	private String membersUri = "";
50  	private String nonMembersUri = "";
51  	private List patternList = new ArrayList();
52  	private boolean needsRefresh = true;
53  	private RWLock rWLock = new RWLock();
54  	protected Date patternListLastUpdated;
55  	protected int secondsBetweenPatternRefresh = 60;
56  	protected int adminSecondsBetweenPatternRefresh = 10;
57      
58      /**
59       * Create a new manual user group. This empty constructor is needed by the XML Digestor.
60       */
61      public ManualUserGroup() {
62      	super();
63      	
64      	Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
65  		Properties properties = System.getProperties();
66  		String handlers = System.getProperty("java.protocol.handler.pkgs");
67  		if (handlers == null) {
68  		    // nothing specified yet (expected case)
69  		    properties.put("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
70  		}
71  		else {
72  		    // something already there, put ourselves out front
73  		    properties.put("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol|".concat(handlers));		    
74  		}
75  
76      }
77      
78      /**
79       * Create a new manual user group with a configuration.
80       */
81      public ManualUserGroup(Configuration configuration) {
82      	super(configuration);
83      }
84      
85      /**
86       * Create a new manual user group with a configuration and a name.
87       */
88  	public ManualUserGroup(Configuration configuration, String name) {
89  		super(configuration, name);
90  	}
91      
92      public void addMember(GridUser user) {
93      	rWLock.getReadLock();
94      	try {
95  	        getDB().addMember(user);
96  	        needsRefresh = true;
97      	}
98      	catch(Exception e) {
99      		log.error(e);
100     	}
101     	finally {
102     		rWLock.releaseLock();
103     	}
104     }
105     
106     public UserGroup clone(Configuration configuration) {
107     	ManualUserGroup userGroup = new ManualUserGroup(configuration, new String(getName()));
108     	userGroup.setDescription(new String(getDescription()));
109     	userGroup.setAccess(new String(getAccess()));
110     	userGroup.setMembersUri(new String(membersUri));
111     	userGroup.setNonMembersUri(new String(nonMembersUri));
112     	userGroup.setPersistenceFactory(new String(persistenceFactory));
113     	return userGroup;
114     }
115     
116     private ManualUserGroupDB getDB() {
117     	if (db==null)
118     		db = getConfiguration().getPersistenceFactory(persistenceFactory).retrieveManualUserGroupDB( getName() );
119     	return db;
120     }
121     
122     public java.util.List getMemberList() {
123         return getDB().retrieveMembers();
124     }
125 
126     public String getMembersUri() {
127     	return membersUri;
128     }
129 
130     public String getNonMembersUri() {
131     	return nonMembersUri;
132     }
133     
134     /**
135      * Setter for property persistenceFactory.
136      * 
137      * @return persistence factory as string.
138      */
139     public String getPersistenceFactory() {
140         return persistenceFactory;
141     }
142     
143     public String getType() {
144 		return "manual";
145 	}
146     
147     public boolean isInGroup(GridUser user) {
148     	boolean returnVal = false;
149 		
150     	try {
151     		rWLock.getReadLock();
152     		Calendar cal = Calendar.getInstance();
153             cal.add(Calendar.SECOND, accessIndex==0 ? -adminSecondsBetweenPatternRefresh : -secondsBetweenPatternRefresh);
154         	if (needsRefresh || patternListLastUpdated.before(cal.getTime())) {
155         		rWLock.releaseLock();
156         		refreshPatternList();
157             	rWLock.getReadLock();
158         	}
159         	
160     		Iterator it = patternList.iterator();
161 	    	while (it.hasNext()) {
162 	    		Pattern p = (Pattern)it.next();
163 	    		Matcher m = p.matcher(concatDNFqan(user));
164 	    		if (log.isTraceEnabled())
165 	    			log.trace("trying to match user "+concatDNFqan(user)+" against "+m.toString());
166 	    		if (m.matches()) {
167 	    			returnVal = true;
168 	    			break;
169 	    		}
170 	    	}
171 		}
172 		catch(Exception e) {
173 			log.error(e);
174 		}
175 		finally {
176 			rWLock.releaseLock();
177 		}
178     	
179         return returnVal;
180     }
181     
182     public boolean removeMember(GridUser user) {
183     	rWLock.getReadLock();
184     	boolean value = false;
185     	try {
186     		value = getDB().removeMember(user);
187     		needsRefresh = true;
188 		}
189 		catch(Exception e) {
190 			log.error(e);
191 		}
192 		finally {
193 			rWLock.releaseLock();
194 		}
195         return value;
196     }
197     
198     /**
199      * Setter for property persistenceFactory
200      * 
201      * @param persistenceFactory
202      */
203     public void setPersistenceFactory(String persistenceFactory) {
204         this.persistenceFactory = persistenceFactory;
205     }
206     
207     public void setMembersUri(String membersUri) {
208     	this.membersUri = membersUri;
209     }
210 
211     public void setNonMembersUri(String nonMembersUri) {
212     	this.nonMembersUri = nonMembersUri;
213     }
214 
215     public String toString() {
216         if (persistenceFactory == null) {
217             return "ManualUserGroup: persistenceFactory=null - group='" + getName() + "'";
218         } else {
219             return "ManualUserGroup: persistenceFactory='" + persistenceFactory + "' - group='" + getName() + "'";
220         }
221     }
222  
223     public String toString(String bgColor) {
224     	return "<td bgcolor=\""+bgColor+"\"><a href=\"userGroups.jsp?command=edit&name=" + getName() + "\">" + getName() + "</a></td><td bgcolor=\""+bgColor+"\">" + getType() + "</td><td bgcolor=\""+bgColor+"\">&nbsp;</td><td bgcolor=\""+bgColor+"\">&nbsp;</td><td bgcolor=\""+bgColor+"\">&nbsp;</td><td bgcolor=\""+bgColor+"\">&nbsp;</td>";
225     }
226     
227     public String toXML() {
228     	return "\t\t<manualUserGroup\n"+
229 		"\t\t\tname='"+getName()+"'\n"+
230 		"\t\t\taccess='"+accessTypes[accessIndex]+"'\n" +
231 		"\t\t\tdescription='"+getDescription()+"'\n"+
232 		"\t\t\tpersistenceFactory='"+persistenceFactory+"'\n" +
233 		"\t\t\tmembersUri='"+membersUri+"'\n" +
234 		"\t\t\tnonMembersUri='"+nonMembersUri+"'/>\n\n";
235     }    
236     
237     public void updateMembers() {
238     	rWLock.getReadLock();
239     	try {
240 	    	if (membersUri.length()>0) {
241 	    		BufferedReader in = null;
242 	    		if (membersUri.startsWith("http")) {
243 	    			URL url = new URL(membersUri);
244 	    			URLConnection connection = url.openConnection();
245 		    		in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
246 	    		}
247 	    		else if (membersUri.startsWith("file://")) {
248 		    		in = new BufferedReader(new FileReader(membersUri.substring(7)));	    			
249 	    		}
250 	    		else {
251 	    			String message = "Unsupported members URI: " + membersUri;
252 	    			log.error(message);
253 	    			throw new RuntimeException(message);
254 	    		}
255 	    		List members = getMemberList();
256 	    		String line;
257 	    		while ((line = in.readLine()) != null) {
258 	    			line = line.trim();
259 	    			if (line.length()==0)
260 	    				continue;
261 	    			String[] elements = line.split(",");
262 	    			GridUser user = new GridUser();
263 	    			if (elements.length >= 1)
264 	    				user.setCertificateDN(elements[0]);
265 	    			if (elements.length >= 2)
266 	    				user.setVoFQAN(new FQAN(elements[1], false));
267 	    			if (!members.contains(user)) {
268 	    				log.info("Added user "+user+" to "+getName()+" user group");
269 	    				getDB().addMember(user);
270 	    			}
271 	    		}
272 	    		if (in!=null)
273 	    			in.close();
274 	    	}
275 	    } catch (Throwable e) {
276 	    	String message = "Couldn't retrieve users from URI " + membersUri + ": ";
277 	        log.error(message, e);
278 	        throw new RuntimeException(message + ": " + e.getMessage());
279 	    } finally {
280 	    	rWLock.releaseLock();
281 	    }
282 	    		
283 	    rWLock.getReadLock();
284 	    try {
285 	    	if (nonMembersUri.length()>0) {
286 	    		BufferedReader in;
287 	    		if (nonMembersUri.startsWith("http")) {
288 	    			URL url = new URL(nonMembersUri);
289 	    			URLConnection connection = url.openConnection();
290 		    		in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
291 	    		}
292 	    		else if (nonMembersUri.startsWith("file://")) {
293 		    		in = new BufferedReader(new FileReader(nonMembersUri.substring(7)));	    			
294 	    		}
295 	    		else {
296 	    			String message = "Unsupported non-members URI: " + membersUri;
297 	    			log.error(message);
298 	    			throw new RuntimeException(message);
299 	    		}
300 	    		List members = getMemberList();
301 	    		String line;
302 	    		while ((line = in.readLine()) != null) {
303 	    			line = line.trim();
304 	    			if (line.length()==0)
305 	    				continue;
306 	    			String[] elements = line.split(",");
307 	    			GridUser user = new GridUser();
308 	    			if (elements.length >= 1)
309 	    				user.setCertificateDN(elements[0]);
310 	    			if (elements.length >= 2)
311 	    				user.setVoFQAN(new FQAN(elements[1], false));
312 	    			if (members.contains(user)) {
313 	    				log.info("Removed user "+user+" from "+getName()+" user group");
314 	    				getDB().removeMember(user);
315 	    			}
316 	    		}
317 	    		if (in!=null)
318 	    			in.close();
319 	    	}
320 	    } catch (Throwable e) {
321 	    	String message = "Couldn't retrieve users from URI " + nonMembersUri + ": ";
322 	        log.error(message, e);
323 	        throw new RuntimeException(message + ": " + e.getMessage());
324 	    } finally {
325 	    	rWLock.releaseLock();
326 	    }
327        	
328        	needsRefresh = true;
329     }
330     
331     private String concatDNFqan(GridUser user) {
332     	return (user.getCertificateDN()!=null?user.getCertificateDN():"") + "," + (user.getVoFQAN()!=null?user.getVoFQAN().getFqan():"");
333     }
334     
335     private void refreshPatternList() {
336     	rWLock.getWriteLock();
337     	try {
338     		log.trace("refreshed pattern list for usergroup "+getName());
339 	 		patternList.clear();
340 	 		List members = getDB().retrieveMembers();
341 	 		Iterator it = members.iterator();
342 	 		while (it.hasNext()) 
343 	 		{
344 	 			GridUser itUser = (GridUser)it.next();
345 	 			Pattern p = Pattern.compile(concatDNFqan(itUser));
346 				patternList.add(p);
347 	 		}
348 			needsRefresh = false;
349 			patternListLastUpdated = Calendar.getInstance().getTime();
350 		}
351 		catch(Exception e) {
352 			log.error(e);
353 		}
354 		finally {
355 			rWLock.releaseLock();
356 		}
357     }
358 }