1
2
3
4
5
6
7 package gov.bnl.gums.userGroup;
8
9 import gov.bnl.gums.GridUser;
10 import gov.bnl.gums.configuration.ConfigElement;
11 import gov.bnl.gums.configuration.Configuration;
12 import gov.bnl.gums.util.RWLock;
13
14 import java.util.*;
15 import java.util.regex.Matcher;
16 import java.util.regex.Pattern;
17
18 import javax.persistence.CascadeType;
19 import javax.persistence.DiscriminatorColumn;
20 import javax.persistence.DiscriminatorType;
21 import javax.persistence.Entity;
22 import javax.persistence.Inheritance;
23 import javax.persistence.InheritanceType;
24 import javax.persistence.OneToMany;
25
26 import org.apache.log4j.Logger;
27
28
29
30
31
32
33
34
35 @Entity
36 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
37 @DiscriminatorColumn(
38 name="type",
39 discriminatorType=DiscriminatorType.STRING
40 )
41 public abstract class UserGroup extends ConfigElement {
42 protected static String[] accessTypes = {"write", "read all", "read self"};
43 private static Logger log = Logger.getLogger(UserGroup.class);
44
45 protected List<Pattern> dnFqanPatternList = new ArrayList<Pattern>();
46 protected List<Pattern> dnPatternList = new ArrayList<Pattern>();
47 protected Date patternListLastUpdated = null;
48 protected RWLock patternRWLock = new RWLock();
49 protected int secondsBetweenPatternRefresh = 30;
50 protected boolean hasCache = false;
51 protected int accessIndex = 2;
52 protected String access = accessTypes[accessIndex];
53
54
55 protected Date lastUpdate;
56 protected Set<GridUser> members = new HashSet<GridUser>();
57
58
59
60
61 public UserGroup() {
62 }
63
64
65
66
67
68
69
70 public UserGroup(Configuration configuration, String name) {
71 super(configuration, name);
72 }
73
74 public void clearCachedItems() {
75 if (hasCache)
76 members.clear();
77 }
78
79 public ConfigElement clone(Configuration conf, boolean allowReplace) {
80 UserGroup userGroup = (UserGroup)super.clone(conf, allowReplace);
81 userGroup.setMembers(new HashSet<GridUser>(members));
82 return userGroup;
83 }
84
85
86
87
88
89
90
91 public String getAccess() {
92 return access;
93 }
94
95 public Date getLastUpdate() {
96 return lastUpdate;
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111 @OneToMany(cascade=CascadeType.ALL, mappedBy="userGroup")
112 @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
113 public Set<GridUser> getMembers() {
114 return members;
115 }
116
117
118
119
120 public boolean hasReadAllAccess() {
121 return (accessIndex<=1);
122 }
123
124
125
126
127 public boolean hasReadSelfAccess() {
128 return (accessIndex<=2);
129 }
130
131
132
133 public boolean hasWriteAccess() {
134 return (accessIndex==0);
135 }
136
137 public boolean isMember(GridUser user) {
138 return isMember(user, false);
139 }
140
141
142
143
144
145
146
147 public boolean isMember(GridUser user, boolean ignoreFqan) {
148 boolean returnVal = false;
149
150 Calendar cal = Calendar.getInstance();
151 cal.add(Calendar.SECOND, -secondsBetweenPatternRefresh);
152 if (patternListLastUpdated == null || patternListLastUpdated.before(cal.getTime()))
153 refreshPatternList();
154
155 try {
156 patternRWLock.getReadLock();
157 Iterator<Pattern> it;
158 if (ignoreFqan)
159 it = dnPatternList.iterator();
160 else
161 it = dnFqanPatternList.iterator();
162 while (it.hasNext()) {
163 Pattern p = (Pattern)it.next();
164 Matcher m;
165 if (ignoreFqan)
166 m = p.matcher(user.getDn());
167 else
168 m = p.matcher(user.toString());
169 if (log.isTraceEnabled())
170 log.trace("trying to match user "+user+" against "+m.toString());
171 if (m.matches()) {
172 returnVal = true;
173 break;
174 }
175 }
176 }
177 catch(Exception e) {
178 log.error(e);
179 }
180 finally {
181 patternRWLock.releaseLock();
182 }
183
184 return returnVal;
185 }
186
187
188
189
190 public void refreshPatternList() {
191 patternRWLock.getWriteLock();
192 try {
193 log.debug("refreshed pattern list for usergroup "+getName());
194 dnPatternList.clear();
195 dnFqanPatternList.clear();
196 synchronized(members) {
197 Iterator<GridUser> it = members.iterator();
198 while (it.hasNext())
199 {
200 GridUser itUser = it.next();
201 Pattern p = Pattern.compile(itUser.getDn());
202 dnPatternList.add(p);
203 p = Pattern.compile(itUser.toString());
204 dnFqanPatternList.add(p);
205 }
206 }
207 patternListLastUpdated = Calendar.getInstance().getTime();
208 }
209 catch(Exception e) {
210 log.error(e);
211 }
212 finally {
213 patternRWLock.releaseLock();
214 }
215 }
216
217 @ConfigFieldAnnotation(label="GUMS Access", help="GUMS access by members of this user group", choices="write, read all, read self", order=4)
218 public void setAccess(String access) {
219 for(int i=0; i<accessTypes.length; i++) {
220 if ( accessTypes[i].equalsIgnoreCase(access) ) {
221 this.access = access;
222 this.accessIndex = i;
223 return;
224 }
225 }
226 throw new RuntimeException("Invalid access type: "+access);
227 }
228
229 public void setLastUpdate(Date lastUpdate) {
230 this.lastUpdate = lastUpdate;
231 }
232
233 private void setMembers(Set<GridUser> members) {
234 if (members==null)
235 return;
236 this.members = members;
237 for (GridUser m: members)
238 m.setUserGroup(this);
239 }
240
241
242
243
244
245
246
247
248
249 public final void updateMembers() {
250 synchronized(members) {
251 members.clear();
252 members.addAll(retrieveMembers());
253 for (GridUser gu: members)
254 gu.setUserGroup(this);
255 }
256 refreshPatternList();
257 }
258
259 protected abstract Set<GridUser> retrieveMembers();
260 }