View Javadoc

1   /* 
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.security.spi.impl;
18  
19  import java.security.Principal;
20  import java.util.Collection;
21  import java.util.HashSet;
22  import java.util.Iterator;
23  import java.util.Set;
24  import java.util.prefs.Preferences;
25  
26  import org.apache.jetspeed.security.HierarchyResolver;
27  import org.apache.jetspeed.security.SecurityException;
28  import org.apache.jetspeed.security.impl.GeneralizationHierarchyResolver;
29  import org.apache.jetspeed.security.impl.GroupPrincipalImpl;
30  import org.apache.jetspeed.security.impl.RolePrincipalImpl;
31  import org.apache.jetspeed.security.impl.UserPrincipalImpl;
32  import org.apache.jetspeed.security.om.InternalGroupPrincipal;
33  import org.apache.jetspeed.security.om.InternalRolePrincipal;
34  import org.apache.jetspeed.security.om.InternalUserPrincipal;
35  import org.apache.jetspeed.security.om.impl.InternalGroupPrincipalImpl;
36  import org.apache.jetspeed.security.om.impl.InternalUserPrincipalImpl;
37  import org.apache.jetspeed.security.spi.SecurityAccess;
38  import org.apache.jetspeed.security.spi.SecurityMappingHandler;
39  
40  /***
41   * @see org.apache.jetspeed.security.spi.SecurityMappingHandler
42   * @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
43   */
44  public class DefaultSecurityMappingHandler implements SecurityMappingHandler
45  {
46  
47      /*** The role hierarchy resolver. */
48      HierarchyResolver roleHierarchyResolver = new GeneralizationHierarchyResolver();
49  
50      /*** The group hierarchy resolver. */
51      HierarchyResolver groupHierarchyResolver = new GeneralizationHierarchyResolver();
52  
53      /*** Common queries. */
54      private SecurityAccess commonQueries = null;
55  
56      /***
57       * <p>
58       * Constructor providing access to the common queries.
59       * </p>
60       */
61      public DefaultSecurityMappingHandler(SecurityAccess commonQueries)
62      {
63          this.commonQueries = commonQueries;
64      }
65  
66      /***
67       * <p>
68       * Constructor providing access to the common queries and hierarchy
69       * resolvers.
70       * </p>
71       */
72      public DefaultSecurityMappingHandler(SecurityAccess commonQueries, HierarchyResolver roleHierarchyResolver,
73              HierarchyResolver groupHierarchyResolver)
74      {
75          this.commonQueries = commonQueries;
76          if (null != roleHierarchyResolver)
77          {
78              this.roleHierarchyResolver = roleHierarchyResolver;
79          }
80          if (null != groupHierarchyResolver)
81          {
82              this.groupHierarchyResolver = groupHierarchyResolver;
83          }
84      }
85  
86      /***
87       * @return Returns the roleHierarchyResolver.
88       */
89      public HierarchyResolver getRoleHierarchyResolver()
90      {
91          return roleHierarchyResolver;
92      }
93  
94      /***
95       * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#setRoleHierarchyResolver(org.apache.jetspeed.security.HierarchyResolver)
96       */
97      public void setRoleHierarchyResolver(HierarchyResolver roleHierarchyResolver)
98      {
99          this.roleHierarchyResolver = roleHierarchyResolver;
100     }
101 
102     /***
103      * @return Returns the groupHierarchyResolver.
104      */
105     public HierarchyResolver getGroupHierarchyResolver()
106     {
107         return groupHierarchyResolver;
108     }
109 
110     /***
111      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#setGroupHierarchyResolver(org.apache.jetspeed.security.HierarchyResolver)
112      */
113     public void setGroupHierarchyResolver(HierarchyResolver groupHierarchyResolver)
114     {
115         this.groupHierarchyResolver = groupHierarchyResolver;
116     }
117 
118     /***
119      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#getRolePrincipals(java.lang.String)
120      */
121     public Set getRolePrincipals(String username)
122     {
123         Set rolePrincipals = new HashSet();
124         InternalUserPrincipal internalUser = commonQueries.getInternalUserPrincipal(username);
125         if (null != internalUser)
126         {
127             Collection internalRoles = internalUser.getRolePrincipals();
128             if (null != internalRoles)
129             {
130                 Iterator internalRolesIter = internalRoles.iterator();
131                 while (internalRolesIter.hasNext())
132                 {
133                     InternalRolePrincipal internalRole = (InternalRolePrincipal) internalRolesIter.next();
134                     Preferences preferences = Preferences.userRoot().node(internalRole.getFullPath());
135                     String[] fullPaths = roleHierarchyResolver.resolve(preferences);
136                     for (int i = 0; i < fullPaths.length; i++)
137                     {
138                         Principal rolePrincipal = new RolePrincipalImpl(RolePrincipalImpl
139                                 .getPrincipalNameFromFullPath(fullPaths[i]));
140                         if (!rolePrincipals.contains(rolePrincipal))
141                         {
142                             rolePrincipals.add(rolePrincipal);
143                         }
144                     }
145                 }
146             }
147         }
148         return rolePrincipals;
149     }
150 
151     /***
152      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#setUserPrincipalInRole(java.lang.String,
153      *      java.lang.String)
154      */
155     public void setUserPrincipalInRole(String username, String roleFullPathName) throws SecurityException
156     {
157         InternalUserPrincipal internalUser = commonQueries.getInternalUserPrincipal(username);
158         boolean isMappingOnly = false;
159         if (null == internalUser)
160         {
161             // This is a record for mapping only.
162             isMappingOnly = true;
163             internalUser = new InternalUserPrincipalImpl(UserPrincipalImpl.getFullPathFromPrincipalName(username));
164         }
165         Collection internalRoles = internalUser.getRolePrincipals();
166         // This should not be null. Check for null should be made by the caller.
167         InternalRolePrincipal internalRole = commonQueries.getInternalRolePrincipal(RolePrincipalImpl
168                 .getFullPathFromPrincipalName(roleFullPathName));
169         // Check anyway.
170         if (null == internalRole)
171         {
172             throw new SecurityException(SecurityException.ROLE_DOES_NOT_EXIST.create(roleFullPathName));
173         }
174         internalRoles.add(internalRole);
175         internalUser.setRolePrincipals(internalRoles);
176         commonQueries.setInternalUserPrincipal(internalUser, isMappingOnly);
177     }
178 
179     /***
180      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#removeUserPrincipalInRole(java.lang.String,
181      *      java.lang.String)
182      */
183     public void removeUserPrincipalInRole(String username, String roleFullPathName) throws SecurityException
184     {
185         boolean isMappingOnly = false;
186         // Check is the record is used for mapping only.
187         InternalUserPrincipal internalUser = commonQueries.getInternalUserPrincipal(username, false);
188         if (null == internalUser)
189         {
190             internalUser = commonQueries.getInternalUserPrincipal(username, true);
191             isMappingOnly = true;
192         }
193         if (null != internalUser)
194         {
195             Collection internalRoles = internalUser.getRolePrincipals();
196             // This should not be null. Check for null should be made by the caller.
197             InternalRolePrincipal internalRole = commonQueries.getInternalRolePrincipal(RolePrincipalImpl
198                     .getFullPathFromPrincipalName(roleFullPathName));
199             // Check anyway.
200             if (null == internalRole)
201             {
202                 throw new SecurityException(SecurityException.ROLE_DOES_NOT_EXIST.create(roleFullPathName));
203             }
204             internalRoles.remove(internalRole);
205             // Remove dead mapping records. I.e. No mapping is associated with the specific record.
206             if (isMappingOnly && internalRoles.isEmpty() && internalUser.getGroupPrincipals().isEmpty()
207                     && internalUser.getPermissions().isEmpty())
208             {
209                 commonQueries.removeInternalUserPrincipal(internalUser);
210             }
211             else
212             {
213                 internalUser.setRolePrincipals(internalRoles);
214                 commonQueries.setInternalUserPrincipal(internalUser, isMappingOnly);
215             }
216         }
217         else
218         {
219             throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
220         }
221     }
222 
223     /***
224      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#getRolePrincipalsInGroup(java.lang.String)
225      */
226     public Set getRolePrincipalsInGroup(String groupFullPathName)
227     {
228         Set rolePrincipals = new HashSet();
229 
230         Preferences preferences = Preferences.userRoot().node(
231                 GroupPrincipalImpl.getFullPathFromPrincipalName(groupFullPathName));
232         String[] fullPaths = groupHierarchyResolver.resolve(preferences);
233         for (int i = 0; i < fullPaths.length; i++)
234         {
235             InternalGroupPrincipal internalGroup = commonQueries.getInternalGroupPrincipal(fullPaths[i]);
236             if (null != internalGroup)
237             {
238                 Collection internalRoles = internalGroup.getRolePrincipals();
239                 if (null != internalRoles)
240                 {
241                     Iterator internalRolesIter = internalRoles.iterator();
242                     while (internalRolesIter.hasNext())
243                     {
244                         InternalRolePrincipal internalRole = (InternalRolePrincipal) internalRolesIter.next();
245                         Principal rolePrincipal = new RolePrincipalImpl(UserPrincipalImpl
246                                 .getPrincipalNameFromFullPath(internalRole.getFullPath()));
247                         if (!rolePrincipals.contains(rolePrincipal))
248                         {
249                             rolePrincipals.add(rolePrincipal);
250                         }
251                     }
252                 }
253             }
254         }
255         return rolePrincipals;
256     }
257 
258     /***
259      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#setRolePrincipalInGroup(java.lang.String,
260      *      java.lang.String)
261      */
262     public void setRolePrincipalInGroup(String groupFullPathName, String roleFullPathName) throws SecurityException
263     {
264         InternalGroupPrincipal internalGroup = commonQueries.getInternalGroupPrincipal(GroupPrincipalImpl
265                 .getFullPathFromPrincipalName(groupFullPathName));
266         boolean isMappingOnly = false;
267         if (null == internalGroup)
268         {
269             // This is a record for mapping only.
270             isMappingOnly = true;
271             internalGroup = new InternalGroupPrincipalImpl(groupFullPathName);
272         }        
273         Collection internalRoles = internalGroup.getRolePrincipals();
274         InternalRolePrincipal internalRole = commonQueries.getInternalRolePrincipal(RolePrincipalImpl
275                 .getFullPathFromPrincipalName(roleFullPathName));
276         internalRoles.add(internalRole);
277         internalGroup.setRolePrincipals(internalRoles);
278         commonQueries.setInternalGroupPrincipal(internalGroup, isMappingOnly);
279     }
280 
281     /***
282      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#removeRolePrincipalInGroup(java.lang.String,
283      *      java.lang.String)
284      */
285     public void removeRolePrincipalInGroup(String groupFullPathName, String roleFullPathName) throws SecurityException
286     {
287         InternalGroupPrincipal internalGroup = commonQueries.getInternalGroupPrincipal(GroupPrincipalImpl
288                 .getFullPathFromPrincipalName(groupFullPathName));
289         boolean isMappingOnly = false;
290         if (null == internalGroup)
291         {
292             // This is a record for mapping only.
293             isMappingOnly = true;
294             internalGroup = new InternalGroupPrincipalImpl(groupFullPathName);
295         }                
296         if (null == internalGroup)
297         {
298             throw new SecurityException(SecurityException.GROUP_DOES_NOT_EXIST.create(internalGroup));
299         }
300         Collection internalRoles = internalGroup.getRolePrincipals();
301         InternalRolePrincipal internalRole = commonQueries.getInternalRolePrincipal(RolePrincipalImpl
302                 .getFullPathFromPrincipalName(roleFullPathName));
303         internalRoles.remove(internalRole);
304         internalGroup.setRolePrincipals(internalRoles);
305         commonQueries.setInternalGroupPrincipal(internalGroup, isMappingOnly);
306     }
307 
308     /***
309      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#getGroupPrincipals(java.lang.String)
310      */
311     public Set getGroupPrincipals(String username)
312     {
313         Set groupPrincipals = new HashSet();
314         InternalUserPrincipal internalUser = commonQueries.getInternalUserPrincipal(username);
315         if (null != internalUser)
316         {
317             Collection internalGroups = internalUser.getGroupPrincipals();
318             if (null != internalGroups)
319             {
320                 Iterator internalGroupsIter = internalGroups.iterator();
321                 while (internalGroupsIter.hasNext())
322                 {
323                     InternalGroupPrincipal internalGroup = (InternalGroupPrincipal) internalGroupsIter.next();
324                     Preferences preferences = Preferences.userRoot().node(internalGroup.getFullPath());
325                     String[] fullPaths = groupHierarchyResolver.resolve(preferences);
326                     for (int i = 0; i < fullPaths.length; i++)
327                     {
328                         groupPrincipals.add(new GroupPrincipalImpl(GroupPrincipalImpl
329                                 .getPrincipalNameFromFullPath(fullPaths[i])));
330                     }
331                 }
332             }
333         }
334         return groupPrincipals;
335     }
336 
337     /***
338      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#getGroupPrincipalsInRole(java.lang.String)
339      */
340     public Set getGroupPrincipalsInRole(String roleFullPathName)
341     {
342         Set groupPrincipals = new HashSet();
343 
344         Preferences preferences = Preferences.userRoot().node(
345                 RolePrincipalImpl.getFullPathFromPrincipalName(roleFullPathName));
346         String[] fullPaths = roleHierarchyResolver.resolve(preferences);
347         for (int i = 0; i < fullPaths.length; i++)
348         {
349             InternalRolePrincipal internalRole = commonQueries.getInternalRolePrincipal(fullPaths[i]);
350             if (null != internalRole)
351             {
352                 Collection internalGroups = internalRole.getGroupPrincipals();
353                 if (null != internalGroups)
354                 {
355                     Iterator internalGroupsIter = internalGroups.iterator();
356                     while (internalGroupsIter.hasNext())
357                     {
358                         InternalGroupPrincipal internalGroup = (InternalGroupPrincipal) internalGroupsIter.next();
359                         Principal groupPrincipal = new GroupPrincipalImpl(GroupPrincipalImpl
360                                 .getPrincipalNameFromFullPath(internalGroup.getFullPath()));
361                         if (!groupPrincipals.contains(groupPrincipal))
362                         {
363                             groupPrincipals.add(groupPrincipal);
364                         }
365                     }
366                 }
367             }
368         }
369         return groupPrincipals;
370     }
371 
372     /***
373      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#getUserPrincipalsInRole(java.lang.String)
374      */
375     public Set getUserPrincipalsInRole(String roleFullPathName)
376     {
377         Set userPrincipals = new HashSet();
378 
379         Preferences preferences = Preferences.userRoot().node(
380                 RolePrincipalImpl.getFullPathFromPrincipalName(roleFullPathName));
381         String[] fullPaths = roleHierarchyResolver.resolve(preferences);
382         for (int i = 0; i < fullPaths.length; i++)
383         {
384             InternalRolePrincipal internalRole = commonQueries.getInternalRolePrincipal(fullPaths[i]);
385             if (null != internalRole)
386             {
387                 Collection internalUsers = internalRole.getUserPrincipals();
388                 if (null != internalUsers)
389                 {
390                     Iterator internalUsersIter = internalUsers.iterator();
391                     while (internalUsersIter.hasNext())
392                     {
393                         InternalUserPrincipal internalUser = (InternalUserPrincipal) internalUsersIter.next();
394                         Principal userPrincipal = new UserPrincipalImpl(UserPrincipalImpl
395                                 .getPrincipalNameFromFullPath(internalUser.getFullPath()));
396                         if (!userPrincipals.contains(userPrincipal))
397                         {
398                             userPrincipals.add(userPrincipal);
399                         }
400                     }
401                 }
402             }
403         }
404         return userPrincipals;
405     }
406 
407     /***
408      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#getUserPrincipalsInGroup(java.lang.String)
409      */
410     public Set getUserPrincipalsInGroup(String groupFullPathName)
411     {
412         Set userPrincipals = new HashSet();
413 
414         Preferences preferences = Preferences.userRoot().node(
415                 GroupPrincipalImpl.getFullPathFromPrincipalName(groupFullPathName));
416         String[] fullPaths = groupHierarchyResolver.resolve(preferences);
417         for (int i = 0; i < fullPaths.length; i++)
418         {
419             InternalGroupPrincipal internalGroup = commonQueries.getInternalGroupPrincipal(fullPaths[i]);
420             if (null != internalGroup)
421             {
422                 Collection internalUsers = internalGroup.getUserPrincipals();
423                 if (null != internalUsers)
424                 {
425                     Iterator internalUsersIter = internalUsers.iterator();
426                     while (internalUsersIter.hasNext())
427                     {
428                         InternalUserPrincipal internalUser = (InternalUserPrincipal) internalUsersIter.next();
429                         Principal userPrincipal = new UserPrincipalImpl(UserPrincipalImpl
430                                 .getPrincipalNameFromFullPath(internalUser.getFullPath()));
431                         if (!userPrincipals.contains(userPrincipal))
432                         {
433                             userPrincipals.add(userPrincipal);
434                         }
435                     }
436                 }
437             }
438         }
439         return userPrincipals;
440     }
441 
442     /***
443      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#setUserPrincipalInGroup(java.lang.String,
444      *      java.lang.String)
445      */
446     public void setUserPrincipalInGroup(String username, String groupFullPathName) throws SecurityException
447     {
448         InternalUserPrincipal internalUser = commonQueries.getInternalUserPrincipal(username);
449         boolean isMappingOnly = false;
450         if (null == internalUser)
451         {
452             // This is a record for mapping only.
453             isMappingOnly = true;
454             internalUser = new InternalUserPrincipalImpl(UserPrincipalImpl.getFullPathFromPrincipalName(username));
455         }
456         Collection internalGroups = internalUser.getGroupPrincipals();
457         // This should not be null. Check for null should be made by the caller.
458         InternalGroupPrincipal internalGroup = commonQueries.getInternalGroupPrincipal(GroupPrincipalImpl
459                 .getFullPathFromPrincipalName(groupFullPathName));
460         // Check anyway.
461         if (null == internalGroup)
462         {
463             throw new SecurityException(SecurityException.GROUP_DOES_NOT_EXIST.create(groupFullPathName));
464         }
465         internalGroups.add(internalGroup);
466         internalUser.setGroupPrincipals(internalGroups);
467         commonQueries.setInternalUserPrincipal(internalUser, isMappingOnly);
468     }
469 
470     /***
471      * @see org.apache.jetspeed.security.spi.SecurityMappingHandler#removeUserPrincipalInGroup(java.lang.String,
472      *      java.lang.String)
473      */
474     public void removeUserPrincipalInGroup(String username, String groupFullPathName) throws SecurityException
475     {
476         boolean isMappingOnly = false;
477         // Check is the record is used for mapping only.
478         InternalUserPrincipal internalUser = commonQueries.getInternalUserPrincipal(username, false);
479         if (null == internalUser)
480         {
481             internalUser = commonQueries.getInternalUserPrincipal(username, true);
482             isMappingOnly = true;
483         }
484         if (null != internalUser)
485         {
486             Collection internalGroups = internalUser.getGroupPrincipals();
487             // This should not be null. Check for null should be made by the caller.
488             InternalGroupPrincipal internalGroup = commonQueries.getInternalGroupPrincipal(GroupPrincipalImpl
489                     .getFullPathFromPrincipalName(groupFullPathName));
490             // Check anyway.
491             if (null == internalGroup)
492             {
493                 throw new SecurityException(SecurityException.GROUP_DOES_NOT_EXIST.create(groupFullPathName));
494             }
495             internalGroups.remove(internalGroup);
496             // Remove dead mapping records. I.e. No mapping is associated with the specific record.
497             if (isMappingOnly && internalGroups.isEmpty() && internalUser.getRolePrincipals().isEmpty()
498                     && internalUser.getPermissions().isEmpty())
499             {
500                 commonQueries.removeInternalUserPrincipal(internalUser);
501             }
502             else
503             {
504             internalUser.setGroupPrincipals(internalGroups);
505             commonQueries.setInternalUserPrincipal(internalUser, isMappingOnly);
506             }
507         }
508         else
509         {
510             throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
511         }
512     }
513     
514 }