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.impl;
18  
19  import java.security.Principal;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.Iterator;
23  import java.util.LinkedList;
24  import java.util.List;
25  import java.util.Set;
26  import java.util.prefs.BackingStoreException;
27  import java.util.prefs.Preferences;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.jetspeed.i18n.KeyedMessage;
32  import org.apache.jetspeed.security.AuthenticationProviderProxy;
33  import org.apache.jetspeed.security.Group;
34  import org.apache.jetspeed.security.GroupManager;
35  import org.apache.jetspeed.security.GroupPrincipal;
36  import org.apache.jetspeed.security.SecurityException;
37  import org.apache.jetspeed.security.SecurityProvider;
38  import org.apache.jetspeed.security.spi.GroupSecurityHandler;
39  import org.apache.jetspeed.security.spi.SecurityMappingHandler;
40  import org.apache.jetspeed.util.ArgUtil;
41  
42  /***
43   * <p>
44   * Describes the service interface for managing groups.
45   * </p>
46   * <p>
47   * Group hierarchy elements are being returned as a {@link Group}collection.
48   * The backing implementation must appropriately map the group hierarchy to a
49   * preferences sub-tree.
50   * </p>
51   * <p>
52   * The convention {principal}.{subprincipal} has been chosen to name groups
53   * hierachies. Implementation follow the conventions enforced by the
54   * {@link Preferences}API.
55   * </p>
56   * 
57   * @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
58   * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
59   */
60  public class GroupManagerImpl implements GroupManager
61  {
62  
63      /*** The logger. */
64      private static final Log log = LogFactory.getLog(GroupManagerImpl.class);
65  
66      /*** The authentication provider proxy. */
67      private AuthenticationProviderProxy atnProviderProxy = null;
68  
69      /*** The group security handler. */
70      private GroupSecurityHandler groupSecurityHandler = null;
71  
72      /*** The security mapping handler. */
73      private SecurityMappingHandler securityMappingHandler = null;
74  
75      /***
76       * @param securityProvider
77       *            The security provider.
78       */
79      public GroupManagerImpl(SecurityProvider securityProvider)
80      {
81          this.atnProviderProxy = securityProvider
82                  .getAuthenticationProviderProxy();
83          this.groupSecurityHandler = securityProvider.getGroupSecurityHandler();
84          this.securityMappingHandler = securityProvider
85                  .getSecurityMappingHandler();
86      }
87  
88      /***
89       * @see org.apache.jetspeed.security.GroupManager#addGroup(java.lang.String)
90       */
91      public void addGroup(String groupFullPathName) throws SecurityException
92      {
93          ArgUtil.notNull(new Object[]
94          { groupFullPathName}, new String[]
95          { "groupFullPathName"}, "addGroup(java.lang.String)");
96  
97          // Check if group already exists.
98          if (groupExists(groupFullPathName)) {  
99              throw new SecurityException(SecurityException.GROUP_ALREADY_EXISTS.create(groupFullPathName)); 
100         }
101 
102         GroupPrincipal groupPrincipal = new GroupPrincipalImpl(
103                 groupFullPathName);
104         String fullPath = groupPrincipal.getFullPath();
105         // Add the preferences.
106         Preferences preferences = Preferences.userRoot().node(fullPath);
107         if (log.isDebugEnabled())
108         {
109             log.debug("Added group preferences node: " + fullPath);
110         }
111         try
112         {
113             if ((null != preferences)
114                     && preferences.absolutePath().equals(fullPath))
115             {
116                 // Add role principal.
117                 groupSecurityHandler.setGroupPrincipal(groupPrincipal);
118                 if (log.isDebugEnabled())
119                 {
120                     log.debug("Added group: " + fullPath);
121                 }
122             }
123         } catch (SecurityException se)
124         {
125             String msg = "Unable to create the role.";
126             log.error(msg, se);
127 
128             // Remove the preferences node.
129             try
130             {
131                 preferences.removeNode();
132             } catch (BackingStoreException bse)
133             {
134                 bse.printStackTrace();
135             }
136             throw se;
137         }
138     }
139 
140     /***
141      * @see org.apache.jetspeed.security.GroupManager#removeGroup(java.lang.String)
142      */
143     public void removeGroup(String groupFullPathName) throws SecurityException
144     {
145         ArgUtil.notNull(new Object[]
146         { groupFullPathName}, new String[]
147         { "groupFullPathName"}, "removeGroup(java.lang.String)");
148 
149         // Resolve the group hierarchy.
150         Preferences prefs = Preferences.userRoot().node(
151                 GroupPrincipalImpl
152                         .getFullPathFromPrincipalName(groupFullPathName));
153         String[] groups = securityMappingHandler.getGroupHierarchyResolver()
154                 .resolveChildren(prefs);
155         for (int i = 0; i < groups.length; i++)
156         {
157             try
158             {
159                 groupSecurityHandler
160                         .removeGroupPrincipal(new GroupPrincipalImpl(
161                                 GroupPrincipalImpl
162                                         .getPrincipalNameFromFullPath(groups[i])));
163             } catch (SecurityException se)
164             {
165                 throw se;
166             } catch (Exception e)
167             {
168                 KeyedMessage msg = 
169                     SecurityException.UNEXPECTED.create("GroupManager.removeGroup",
170                                                         "GroupSecurityHandler.removeGroupPrincipal("+
171                         GroupPrincipalImpl.getPrincipalNameFromFullPath(groups[i])+")", 
172                         e.getMessage());
173                 log.error(msg, e);
174                 throw new SecurityException(msg, e);
175             }
176             // Remove preferences
177             Preferences groupPref = Preferences.userRoot().node(
178                     groups[i]);
179             try
180             {
181                 groupPref.removeNode();
182             } catch (BackingStoreException bse)
183             {
184                 KeyedMessage msg =
185                     SecurityException.UNEXPECTED.create("Preferences.removeNode("+groups[i]+")", 
186                                                         bse.getMessage());
187                 log.error(msg, bse);
188                 throw new SecurityException(msg, bse);
189             }
190         }
191     }
192 
193     /***
194      * @see org.apache.jetspeed.security.GroupManager#groupExists(java.lang.String)
195      */
196     public boolean groupExists(String groupFullPathName)
197     {
198         ArgUtil.notNull(new Object[]
199         { groupFullPathName}, new String[]
200         { "groupFullPathName"}, "groupExists(java.lang.String)");
201 
202         Principal principal = groupSecurityHandler
203                 .getGroupPrincipal(groupFullPathName);
204         boolean groupExists = (null != principal);
205         if (log.isDebugEnabled())
206         {
207             log.debug("Role exists: " + groupExists);
208             log.debug("Role: " + groupFullPathName);
209         }
210         return groupExists;
211     }
212 
213     /***
214      * @see org.apache.jetspeed.security.GroupManager#getGroup(java.lang.String)
215      */
216     public Group getGroup(String groupFullPathName) throws SecurityException
217     {
218         ArgUtil.notNull(new Object[]
219         { groupFullPathName}, new String[]
220         { "groupFullPathName"}, "getGroup(java.lang.String)");
221 
222         String fullPath = GroupPrincipalImpl
223                 .getFullPathFromPrincipalName(groupFullPathName);
224 
225         Principal groupPrincipal = groupSecurityHandler
226                 .getGroupPrincipal(groupFullPathName);
227         if (null == groupPrincipal) { 
228             throw new SecurityException(
229                 SecurityException.GROUP_DOES_NOT_EXIST.create(groupFullPathName)); 
230         }
231         Preferences preferences = Preferences.userRoot().node(fullPath);
232         Group group = new GroupImpl(groupPrincipal, preferences);
233         return group;
234     }
235 
236     /***
237      * @see org.apache.jetspeed.security.GroupManager#getGroupsForUser(java.lang.String)
238      */
239     public Collection getGroupsForUser(String username)
240             throws SecurityException
241     {
242         ArgUtil.notNull(new Object[]
243         { username}, new String[]
244         { "username"}, "getGroupsForUser(java.lang.String)");
245 
246         Collection groups = new ArrayList();
247 
248         Set groupPrincipals = securityMappingHandler
249                 .getGroupPrincipals(username);
250         Iterator groupPrincipalsIter = groupPrincipals.iterator();
251         while (groupPrincipalsIter.hasNext())
252         {
253             Principal groupPrincipal = (Principal) groupPrincipalsIter.next();
254             Preferences preferences = Preferences.userRoot().node(
255                     GroupPrincipalImpl
256                             .getFullPathFromPrincipalName(groupPrincipal
257                                     .getName()));
258             groups.add(new GroupImpl(groupPrincipal, preferences));
259         }
260         return groups;
261     }
262 
263     /***
264      * @see org.apache.jetspeed.security.GroupManager#getGroupsInRole(java.lang.String)
265      */
266     public Collection getGroupsInRole(String roleFullPathName)
267             throws SecurityException
268     {
269         ArgUtil.notNull(new Object[]
270         { roleFullPathName}, new String[]
271         { "roleFullPathName"}, "getGroupsInRole(java.lang.String)");
272 
273         Collection groups = new ArrayList();
274 
275         Set groupPrincipals = securityMappingHandler
276                 .getGroupPrincipalsInRole(roleFullPathName);
277         Iterator groupPrincipalsIter = groupPrincipals.iterator();
278         while (groupPrincipalsIter.hasNext())
279         {
280             Principal groupPrincipal = (Principal) groupPrincipalsIter.next();
281             Preferences preferences = Preferences.userRoot().node(
282                     GroupPrincipalImpl
283                             .getFullPathFromPrincipalName(groupPrincipal
284                                     .getName()));
285             groups.add(new GroupImpl(groupPrincipal, preferences));
286         }
287         return groups;
288     }
289 
290     /***
291      * @see org.apache.jetspeed.security.GroupManager#addUserToGroup(java.lang.String,
292      *      java.lang.String)
293      */
294     public void addUserToGroup(String username, String groupFullPathName)
295             throws SecurityException
296     {
297         ArgUtil.notNull(new Object[]
298         { username, groupFullPathName}, new String[]
299         { "username", "groupFullPathName"},
300                 "addUserToGroup(java.lang.String, java.lang.String)");
301 
302         // Get the group principal to add to user.
303         GroupPrincipal groupPrincipal = groupSecurityHandler.getGroupPrincipal(groupFullPathName);
304         if (null == groupPrincipal) { 
305             throw new SecurityException(SecurityException.GROUP_DOES_NOT_EXIST.create(groupFullPathName)); 
306         }
307         // Check that user exists.
308         Principal userPrincipal = atnProviderProxy.getUserPrincipal(username);
309         if (null == userPrincipal) { 
310             throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
311         }
312         // Get the user groups.
313         Set groupPrincipals = securityMappingHandler.getGroupPrincipals(username);
314         // Add group to user.
315         if (!groupPrincipals.contains(groupPrincipal))
316         {
317             securityMappingHandler.setUserPrincipalInGroup(username,groupFullPathName);
318         }
319     }
320 
321     /***
322      * @see org.apache.jetspeed.security.GroupManager#removeUserFromGroup(java.lang.String,
323      *      java.lang.String)
324      */
325     public void removeUserFromGroup(String username, String groupFullPathName)
326             throws SecurityException
327     {
328         ArgUtil.notNull(new Object[]
329         { username, groupFullPathName}, new String[]
330         { "username", "groupFullPathName"},
331                 "removeUserFromGroup(java.lang.String, java.lang.String)");
332 
333         // Check that user exists.
334         Principal userPrincipal = atnProviderProxy.getUserPrincipal(username);
335         if (null == userPrincipal) { 
336             throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
337         }
338         // Get the group principal to remove.
339         Principal groupPrincipal = groupSecurityHandler
340                 .getGroupPrincipal(groupFullPathName);
341         if (null != groupPrincipal)
342         {
343             securityMappingHandler.removeUserPrincipalInGroup(username,
344                     groupFullPathName);
345         }
346     }
347 
348     /***
349      * @see org.apache.jetspeed.security.GroupManager#isUserInGroup(java.lang.String,
350      *      java.lang.String)
351      */
352     public boolean isUserInGroup(String username, String groupFullPathName)
353             throws SecurityException
354     {
355         ArgUtil.notNull(new Object[]
356         { username, groupFullPathName}, new String[]
357         { "username", "groupFullPathName"},
358                 "isUserInGroup(java.lang.String, java.lang.String)");
359 
360         boolean isUserInGroup = false;
361 
362         Set groupPrincipals = securityMappingHandler
363                 .getGroupPrincipals(username);
364         Principal groupPrincipal = new GroupPrincipalImpl(groupFullPathName);
365         if (groupPrincipals.contains(groupPrincipal))
366         {
367             isUserInGroup = true;
368         }
369         return isUserInGroup;
370     }
371 
372     /***
373      * @see org.apache.jetspeed.security.GroupManager#getGroups(java.lang.String)
374      */
375     public Iterator getGroups(String filter) throws SecurityException
376     {
377         List groups = new LinkedList();
378         Iterator groupPrincipals = groupSecurityHandler.getGroupPrincipals(filter).iterator();
379         while (groupPrincipals.hasNext())
380         {
381             String groupName = ((Principal) groupPrincipals.next()).getName();
382             Group group = getGroup(groupName);
383             groups.add(group);
384         }
385         return groups.iterator();
386     }
387     
388     /***
389      * @see org.apache.jetspeed.security.GroupManager#setGroupEnabled(java.lang.String, boolean)
390      */
391     public void setGroupEnabled(String groupFullPathName, boolean enabled) throws SecurityException
392     {
393         ArgUtil.notNull(new Object[] { groupFullPathName }, new String[] { "groupFullPathName" },
394                 "setGroupEnabled(java.lang.String,boolean)");
395 
396         GroupPrincipalImpl groupPrincipal = (GroupPrincipalImpl)groupSecurityHandler.getGroupPrincipal(groupFullPathName);
397         if (null == groupPrincipal)
398         {
399             throw new SecurityException(SecurityException.GROUP_DOES_NOT_EXIST.create(groupFullPathName));
400         }
401         if ( enabled != groupPrincipal.isEnabled() )
402         {
403             groupPrincipal.setEnabled(enabled);
404             groupSecurityHandler.setGroupPrincipal(groupPrincipal);
405         }
406     }
407 }