]> source.dussan.org Git - archiva.git/blob
9d0125f1a97ae476f6c585af745888c6712958bf
[archiva.git] /
1 package org.apache.archiva.redback.users.jdo;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import org.apache.archiva.redback.policy.UserSecurityPolicy;
23 import org.apache.archiva.redback.users.AbstractUserManager;
24 import org.apache.archiva.redback.users.User;
25 import org.apache.archiva.redback.users.UserManagerException;
26 import org.apache.archiva.redback.users.UserNotFoundException;
27 import org.codehaus.plexus.jdo.JdoFactory;
28 import org.codehaus.plexus.jdo.PlexusJdoUtils;
29 import org.codehaus.plexus.jdo.PlexusObjectNotFoundException;
30 import org.codehaus.plexus.jdo.PlexusStoreException;
31 import org.apache.archiva.redback.users.PermanentUserException;
32 import org.apache.archiva.redback.users.UserQuery;
33 import org.codehaus.plexus.redback.users.jdo.JdoUser;
34 import org.codehaus.plexus.redback.users.jdo.UsersManagementModelloMetadata;
35 import org.codehaus.plexus.util.StringUtils;
36 import org.jpox.JDOClassLoaderResolver;
37 import org.springframework.stereotype.Service;
38
39 import javax.annotation.PostConstruct;
40 import javax.inject.Inject;
41 import javax.inject.Named;
42 import javax.jdo.Extent;
43 import javax.jdo.PersistenceManager;
44 import javax.jdo.PersistenceManagerFactory;
45 import javax.jdo.Query;
46 import javax.jdo.Transaction;
47
48 import java.util.Date;
49 import java.util.List;
50
51 /**
52  * JdoUserManager
53  *
54  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
55  * @version $Id$
56  */
57 @Service("userManager#jdo")
58 public class JdoUserManager
59     extends AbstractUserManager
60 {
61     @Inject @Named(value="jdoFactory#users")
62     private JdoFactory jdoFactory;
63
64     @Inject
65     private UserSecurityPolicy userSecurityPolicy;
66
67     private PersistenceManagerFactory pmf;
68
69     public String getId()
70     {
71         return "JDO UserManager - " + this.getClass().getName();
72     }
73
74
75     public boolean isReadOnly()
76     {
77         return false;
78     }
79
80     public UserQuery createUserQuery()
81     {
82         return new JdoUserQuery();
83     }
84
85     // ------------------------------------------------------------------
86
87     public User createUser( String username, String fullname, String email )
88     {
89         User user = new JdoUser();
90         user.setUsername( username );
91         user.setFullName( fullname );
92         user.setEmail( email );
93         user.setAccountCreationDate( new Date() );
94
95         return user;
96     }
97
98     public List<User> getUsers()
99     {
100         return getAllObjectsDetached( null );
101     }
102
103     public List<User> getUsers( boolean orderAscending )
104     {
105         String ordering = orderAscending ? "username ascending" : "username descending";
106
107         return getAllObjectsDetached( ordering );
108     }
109
110     @SuppressWarnings("unchecked")
111     private List<User> getAllObjectsDetached( String ordering )
112     {
113         return PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager(), JdoUser.class, ordering, (String) null );
114     }
115
116     public List<User> findUsersByUsernameKey( String usernameKey, boolean orderAscending )
117     {
118         return findUsers( "username", usernameKey, orderAscending );
119     }
120
121     public List<User> findUsersByFullNameKey( String fullNameKey, boolean orderAscending )
122     {
123         return findUsers( "fullName", fullNameKey, orderAscending );
124     }
125
126     public List<User> findUsersByEmailKey( String emailKey, boolean orderAscending )
127     {
128         return findUsers( "email", emailKey, orderAscending );
129     }
130
131     @SuppressWarnings("unchecked")
132     public List<User> findUsersByQuery( UserQuery userQuery )
133     {
134         JdoUserQuery uq = (JdoUserQuery) userQuery;
135
136         PersistenceManager pm = getPersistenceManager();
137
138         Transaction tx = pm.currentTransaction();
139
140         try
141         {
142             tx.begin();
143
144             Extent extent = pm.getExtent( JdoUser.class, true );
145
146             Query query = pm.newQuery( extent );
147
148             String ordering = uq.getOrdering();
149
150             query.setOrdering( ordering );
151
152             query.declareImports( "import java.lang.String" );
153
154             query.declareParameters( uq.getParameters() );
155
156             query.setFilter( uq.getFilter() );
157
158             query.setRange( uq.getFirstResult(),
159                             uq.getMaxResults() < 0 ? Long.MAX_VALUE : uq.getFirstResult() + uq.getMaxResults() );
160
161             List<User> result = (List<User>) query.executeWithArray( uq.getSearchKeys() );
162
163             result = (List<User>) pm.detachCopyAll( result );
164
165             tx.commit();
166
167             return result;
168         }
169         finally
170         {
171             rollback( tx );
172         }
173     }
174
175     @SuppressWarnings("unchecked")
176     private List<User> findUsers( String searchField, String searchKey, boolean ascendingUsername )
177     {
178         PersistenceManager pm = getPersistenceManager();
179
180         Transaction tx = pm.currentTransaction();
181
182         try
183         {
184             tx.begin();
185
186             Extent extent = pm.getExtent( JdoUser.class, true );
187
188             Query query = pm.newQuery( extent );
189
190             String ordering = ascendingUsername ? "username ascending" : "username descending";
191
192             query.setOrdering( ordering );
193
194             query.declareImports( "import java.lang.String" );
195
196             query.declareParameters( "String searchKey" );
197
198             query.setFilter( "this." + searchField + ".toLowerCase().indexOf(searchKey.toLowerCase()) > -1" );
199
200             List<User> result = (List<User>) query.execute( searchKey );
201
202             result = (List<User>) pm.detachCopyAll( result );
203
204             tx.commit();
205
206             return result;
207         }
208         finally
209         {
210             rollback( tx );
211         }
212     }
213
214     public User addUser( User user )
215     {
216         if ( !( user instanceof JdoUser ) )
217         {
218             throw new UserManagerException( "Unable to Add User. User object " + user.getClass().getName() +
219                 " is not an instance of " + JdoUser.class.getName() );
220         }
221
222         if ( StringUtils.isEmpty( user.getUsername() ) )
223         {
224             throw new IllegalStateException(
225                 Messages.getString( "user.manager.cannot.add.user.without.username" ) ); //$NON-NLS-1$
226         }
227
228         userSecurityPolicy.extensionChangePassword( user );
229
230         fireUserManagerUserAdded( user );
231
232         // TODO: find a better solution
233         // workaround for avoiding the admin from providing another password on the next login after the
234         // admin account has been created
235         // extensionChangePassword by default sets the password change status to false
236         if ( "admin".equals( user.getUsername() ) )
237         {
238             user.setPasswordChangeRequired( false );
239         }
240         else
241         {
242             user.setPasswordChangeRequired( true );
243         }
244
245         return (User) addObject( user );
246     }
247
248     public void deleteUser( Object principal )
249     {
250         try
251         {
252             User user = findUser( principal );
253
254             if ( user.isPermanent() )
255             {
256                 throw new PermanentUserException( "Cannot delete permanent user [" + user.getUsername() + "]." );
257             }
258
259             fireUserManagerUserRemoved( user );
260
261             removeObject( user );
262         }
263         catch ( UserNotFoundException e )
264         {
265             log.warn( "Unable to delete user " + principal + ", user not found.", e );
266         }
267     }
268
269     public void deleteUser( String username )
270     {
271         try
272         {
273             User user = findUser( username );
274
275             if ( user.isPermanent() )
276             {
277                 throw new PermanentUserException( "Cannot delete permanent user [" + user.getUsername() + "]." );
278             }
279
280             fireUserManagerUserRemoved( user );
281
282             PlexusJdoUtils.removeObject( getPersistenceManager(), user );
283         }
284         catch ( UserNotFoundException e )
285         {
286             log.warn( "Unable to delete user " + username + ", user not found.", e );
287         }
288     }
289
290     public void addUserUnchecked( User user )
291     {
292         if ( !( user instanceof JdoUser ) )
293         {
294             throw new UserManagerException( "Unable to Add User. User object " + user.getClass().getName() +
295                 " is not an instance of " + JdoUser.class.getName() );
296         }
297
298         if ( StringUtils.isEmpty( user.getUsername() ) )
299         {
300             throw new IllegalStateException(
301                 Messages.getString( "user.manager.cannot.add.user.without.username" ) ); //$NON-NLS-1$
302         }
303
304         addObject( user );
305     }
306
307     public void eraseDatabase()
308     {
309         PlexusJdoUtils.removeAll( getPersistenceManager(), JdoUser.class );
310         PlexusJdoUtils.removeAll( getPersistenceManager(), UsersManagementModelloMetadata.class );
311     }
312
313     public User findUser( Object principal )
314         throws UserNotFoundException
315     {
316         if ( principal == null )
317         {
318             throw new UserNotFoundException( "Unable to find user based on null principal." );
319         }
320
321         try
322         {
323             return (User) PlexusJdoUtils.getObjectById( getPersistenceManager(), JdoUser.class, principal.toString(),
324                                                         null );
325         }
326         catch ( PlexusObjectNotFoundException e )
327         {
328             throw new UserNotFoundException( "Unable to find user: " + e.getMessage(), e );
329         }
330         catch ( PlexusStoreException e )
331         {
332             throw new UserNotFoundException( "Unable to find user: " + e.getMessage(), e );
333         }
334     }
335
336     public User findUser( String username )
337         throws UserNotFoundException
338     {
339         if ( StringUtils.isEmpty( username ) )
340         {
341             throw new UserNotFoundException( "User with empty username not found." );
342         }
343
344         return (User) getObjectById( username, null );
345     }
346
347     public boolean userExists( Object principal )
348     {
349         try
350         {
351             findUser( principal );
352             return true;
353         }
354         catch ( UserNotFoundException ne )
355         {
356             return false;
357         }
358     }
359
360     public User updateUser( User user )
361         throws UserNotFoundException
362     {
363         return updateUser( user, false );
364     }
365
366     public User updateUser( User user, boolean passwordChangeRequired )
367         throws UserNotFoundException
368     {
369         if ( !( user instanceof JdoUser ) )
370         {
371             throw new UserManagerException( "Unable to Update User. User object " + user.getClass().getName() +
372                 " is not an instance of " + JdoUser.class.getName() );
373         }
374
375         // If password is supplied, assume changing of password.
376         // TODO: Consider adding a boolean to the updateUser indicating a password change or not.
377         if ( StringUtils.isNotEmpty( user.getPassword() ) )
378         {
379             userSecurityPolicy.extensionChangePassword( user, passwordChangeRequired );
380         }
381
382         updateObject( user );
383
384         fireUserManagerUserUpdated( user );
385
386         return user;
387     }
388
389     @PostConstruct
390     public void initialize()
391     {
392         JDOClassLoaderResolver d;
393         pmf = jdoFactory.getPersistenceManagerFactory();
394     }
395
396     public PersistenceManager getPersistenceManager()
397     {
398         PersistenceManager pm = pmf.getPersistenceManager();
399
400         pm.getFetchPlan().setMaxFetchDepth( -1 );
401
402         triggerInit();
403
404         return pm;
405     }
406
407     // ----------------------------------------------------------------------
408     // jdo utility methods
409     // ----------------------------------------------------------------------
410
411     private Object addObject( Object object )
412     {
413         return PlexusJdoUtils.addObject( getPersistenceManager(), object );
414     }
415
416     private Object getObjectById( String id, String fetchGroup )
417         throws UserNotFoundException, UserManagerException
418     {
419         try
420         {
421             return PlexusJdoUtils.getObjectById( getPersistenceManager(), JdoUser.class, id, fetchGroup );
422         }
423         catch ( PlexusObjectNotFoundException e )
424         {
425             throw new UserNotFoundException( e.getMessage() );
426         }
427         catch ( PlexusStoreException e )
428         {
429             throw new UserManagerException( "Unable to get object '" + JdoUser.class.getName() + "', id '" + id +
430                 "', fetch-group '" + fetchGroup + "' from jdo store." );
431         }
432     }
433
434     private Object removeObject( Object o )
435     {
436         if ( o == null )
437         {
438             throw new UserManagerException( "Unable to remove null object" );
439         }
440
441         PlexusJdoUtils.removeObject( getPersistenceManager(), o );
442         return o;
443     }
444
445     private Object updateObject( Object object )
446         throws UserNotFoundException, UserManagerException
447     {
448         try
449         {
450             return PlexusJdoUtils.updateObject( getPersistenceManager(), object );
451         }
452         catch ( PlexusStoreException e )
453         {
454             throw new UserManagerException(
455                 "Unable to update the '" + object.getClass().getName() + "' object in the jdo database.", e );
456         }
457     }
458
459     private void rollback( Transaction tx )
460     {
461         PlexusJdoUtils.rollbackIfActive( tx );
462     }
463
464     private boolean hasTriggeredInit = false;
465
466     public void triggerInit()
467     {
468         if ( !hasTriggeredInit )
469         {
470             hasTriggeredInit = true;
471             List<User> users = getAllObjectsDetached( null );
472
473             fireUserManagerInit( users.isEmpty() );
474         }
475     }
476
477     public JdoFactory getJdoFactory()
478     {
479         return jdoFactory;
480     }
481
482     public void setJdoFactory( JdoFactory jdoFactory )
483     {
484         this.jdoFactory = jdoFactory;
485     }
486
487     public UserSecurityPolicy getUserSecurityPolicy()
488     {
489         return userSecurityPolicy;
490     }
491 }