View Javadoc

1   /**
2    * This file Copyright (c) 2003-2011 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.cms.security;
35  
36  import info.magnolia.cms.security.auth.ACL;
37  
38  import java.util.Collection;
39  import java.util.Map;
40  
41  import javax.jcr.Value;
42  import javax.security.auth.Subject;
43  
44  
45  /**
46   * A {@link UserManager} delegating to a set of user managers. The first user manager which does not
47   * through an {@link UnsupportedOperationException} will be used.
48   * @author gjoseph
49   * @version $Revision: $ ($Author: $)
50   */
51  public class DelegatingUserManager implements UserManager {
52      private final Map<String, UserManager> delegates;
53  
54      /**
55       * @param delegates <String realm, UserManager delegate>
56       */
57      public DelegatingUserManager(Map<String, UserManager> delegates) {
58          this.delegates = delegates;
59      }
60  
61      @Override
62      public User createUser(final String name, final String pw) throws UnsupportedOperationException {
63          final Op<User> op = new Op<User>() {
64              @Override
65              public User delegate(UserManager um) {
66                  return um.createUser(name, pw);
67              }
68          };
69          return delegateUntilSupported(op);
70      }
71  
72      @Override
73      public User changePassword(User user, String newPassword) throws UnsupportedOperationException {
74          throw new UnsupportedOperationException("Please use a specific instance of UserManager to do this.");
75      }
76  
77      @Override
78      public User getAnonymousUser() {
79          return delegateUntilSupported(new Op<User>() {
80              @Override
81              public User delegate(UserManager um) {
82                  return um.getAnonymousUser();
83              }
84          });
85      }
86  
87      @Override
88      public User getSystemUser() {
89          return delegateUntilSupported(new Op<User>() {
90              @Override
91              public User delegate(UserManager um) {
92                  return um.getSystemUser();
93              }
94          });
95      }
96  
97      @Override
98      public User getUser(final String name) throws UnsupportedOperationException {
99          return delegateUntilNotNull(new Op<User>() {
100             @Override
101             public User delegate(UserManager um) {
102                 return um.getUser(name);
103             }
104         });
105     }
106 
107     @Override
108     public User getUser(final Subject subject) throws UnsupportedOperationException {
109         return delegateUntilNotNull(new Op<User>() {
110             @Override
111             public User delegate(UserManager um) {
112                 return um.getUser(subject);
113             }
114         });
115     }
116 
117     // TODO : this should maybe aggregate results, but ExternalUserManager throws an UnsupportedOperationException
118     // TODO : also not that this is seemingly never used (or maybe through reflection or other ide-search unfriendly mechanisms)
119     @Override
120     public Collection<User> getAllUsers() throws UnsupportedOperationException {
121         return delegateUntilSupported(new Op<Collection<User>>() {
122             @Override
123             public Collection<User> delegate(UserManager um) {
124                 return um.getAllUsers();
125             }
126         });
127     }
128 
129     @Override
130     public void updateLastAccessTimestamp(final User user) {
131         delegateUntilSupported(new Op<Void>() {
132             @Override
133             public Void delegate(UserManager um) {
134                 um.updateLastAccessTimestamp(user);
135                 return null;
136             }
137         });
138     }
139 
140     private <RT> RT delegateUntilSupported(Op<RT> op) {
141         for (String realmName : delegates.keySet()) {
142             final UserManager um = delegates.get(realmName);
143             try {
144                 return op.delegate(um);
145             } catch (UnsupportedOperationException e) {
146                 // try the next delegate
147             }
148         }
149         throw new UnsupportedOperationException("None of the delegate UserManager supports this operation.");
150     }
151 
152     private <RT> RT delegateUntilNotNull(Op<RT> op) {
153         for (String realmName : delegates.keySet()) {
154             final UserManager um = delegates.get(realmName);
155             final RT result = op.delegate(um);
156             if (result != null) {
157                 return result;
158             }
159         }
160         return null;
161     }
162 
163     private interface Op<RT> {
164         RT delegate(UserManager um);
165     }
166 
167     @Override
168     public boolean hasAny(final String principal, final String resourceName, final String resourceTypeName) {
169         return delegateUntilSupported(new Op<Boolean>() {
170             @Override
171             public Boolean delegate(UserManager um) {
172                 return um.hasAny(principal, resourceName, resourceTypeName);
173             }
174         });
175     }
176 
177     @Override
178     public Map<String,ACL> getACLs(final User user) {
179         return delegateUntilSupported(new Op<Map<String,ACL>>() {
180             @Override
181             public Map<String,ACL> delegate(UserManager um) {
182                 return um.getACLs(user);
183             }
184         });
185     }
186 
187     @Override
188     public User addRole(final User user, final String roleName) {
189         return delegateUntilSupported(new Op<User>() {
190             @Override
191             public User delegate(UserManager um) {
192                 return um.addRole(user, roleName);
193             }
194         });
195     }
196 
197     @Override
198     public User addGroup(final User user, final String groupName) {
199         return delegateUntilSupported(new Op<User>() {
200             @Override
201             public User delegate(UserManager um) {
202                 return um.addGroup(user, groupName);
203             }
204         });
205     }
206 
207     @Override
208     public int getLockTimePeriod() throws UnsupportedOperationException {
209         return delegateUntilSupported(new Op<Integer>() {
210             @Override
211             public Integer delegate(UserManager userManager) {
212                 return userManager.getLockTimePeriod();
213             }
214         });
215     }
216 
217     @Override
218     public int getMaxFailedLoginAttempts() throws UnsupportedOperationException {
219         return delegateUntilSupported(new Op<Integer>() {
220             @Override
221             public Integer delegate(UserManager userManager) {
222                 return userManager.getMaxFailedLoginAttempts();
223             }
224         });
225     }
226 
227     @Override
228     public void setLockTimePeriod(final int lockTimePeriod) throws UnsupportedOperationException {
229         delegateUntilSupported(new Op<Void>() {
230             @Override
231             public Void delegate(UserManager userManager) {
232                 userManager.setLockTimePeriod(lockTimePeriod);
233                 return null;
234             }
235         });
236     }
237 
238     @Override
239     public void setMaxFailedLoginAttempts(final int maxFailedLoginAttempts) throws UnsupportedOperationException {
240         delegateUntilSupported(new Op<Void>() {
241             @Override
242             public Void delegate(UserManager userManager) {
243                 userManager.setMaxFailedLoginAttempts(maxFailedLoginAttempts);
244                 return null;
245             }
246         });
247     }
248 
249     @Override
250     public User setProperty(final User user, final String propertyName, final Value propertyValue) throws UnsupportedOperationException {
251         return delegateUntilSupported(new Op<User>() {
252             @Override
253             public User delegate(UserManager userManager) {
254                 return userManager.setProperty(user, propertyName, propertyValue);
255             }
256         });
257     }
258 }