1 package org.apache.archiva.redback.users.jdo;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
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;
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;
48 import java.util.Date;
49 import java.util.List;
54 * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
57 @Service("userManager#jdo")
58 public class JdoUserManager
59 extends AbstractUserManager
61 @Inject @Named(value="jdoFactory#users")
62 private JdoFactory jdoFactory;
65 private UserSecurityPolicy userSecurityPolicy;
67 private PersistenceManagerFactory pmf;
71 return "JDO UserManager - " + this.getClass().getName();
75 public boolean isReadOnly()
80 public UserQuery createUserQuery()
82 return new JdoUserQuery();
85 // ------------------------------------------------------------------
87 public User createUser( String username, String fullname, String email )
89 User user = new JdoUser();
90 user.setUsername( username );
91 user.setFullName( fullname );
92 user.setEmail( email );
93 user.setAccountCreationDate( new Date() );
98 public List<User> getUsers()
100 return getAllObjectsDetached( null );
103 public List<User> getUsers( boolean orderAscending )
105 String ordering = orderAscending ? "username ascending" : "username descending";
107 return getAllObjectsDetached( ordering );
110 @SuppressWarnings("unchecked")
111 private List<User> getAllObjectsDetached( String ordering )
113 return PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager(), JdoUser.class, ordering, (String) null );
116 public List<User> findUsersByUsernameKey( String usernameKey, boolean orderAscending )
118 return findUsers( "username", usernameKey, orderAscending );
121 public List<User> findUsersByFullNameKey( String fullNameKey, boolean orderAscending )
123 return findUsers( "fullName", fullNameKey, orderAscending );
126 public List<User> findUsersByEmailKey( String emailKey, boolean orderAscending )
128 return findUsers( "email", emailKey, orderAscending );
131 @SuppressWarnings("unchecked")
132 public List<User> findUsersByQuery( UserQuery userQuery )
134 JdoUserQuery uq = (JdoUserQuery) userQuery;
136 PersistenceManager pm = getPersistenceManager();
138 Transaction tx = pm.currentTransaction();
144 Extent extent = pm.getExtent( JdoUser.class, true );
146 Query query = pm.newQuery( extent );
148 String ordering = uq.getOrdering();
150 query.setOrdering( ordering );
152 query.declareImports( "import java.lang.String" );
154 query.declareParameters( uq.getParameters() );
156 query.setFilter( uq.getFilter() );
158 query.setRange( uq.getFirstResult(),
159 uq.getMaxResults() < 0 ? Long.MAX_VALUE : uq.getFirstResult() + uq.getMaxResults() );
161 List<User> result = (List<User>) query.executeWithArray( uq.getSearchKeys() );
163 result = (List<User>) pm.detachCopyAll( result );
175 @SuppressWarnings("unchecked")
176 private List<User> findUsers( String searchField, String searchKey, boolean ascendingUsername )
178 PersistenceManager pm = getPersistenceManager();
180 Transaction tx = pm.currentTransaction();
186 Extent extent = pm.getExtent( JdoUser.class, true );
188 Query query = pm.newQuery( extent );
190 String ordering = ascendingUsername ? "username ascending" : "username descending";
192 query.setOrdering( ordering );
194 query.declareImports( "import java.lang.String" );
196 query.declareParameters( "String searchKey" );
198 query.setFilter( "this." + searchField + ".toLowerCase().indexOf(searchKey.toLowerCase()) > -1" );
200 List<User> result = (List<User>) query.execute( searchKey );
202 result = (List<User>) pm.detachCopyAll( result );
214 public User addUser( User user )
216 if ( !( user instanceof JdoUser ) )
218 throw new UserManagerException( "Unable to Add User. User object " + user.getClass().getName() +
219 " is not an instance of " + JdoUser.class.getName() );
222 if ( StringUtils.isEmpty( user.getUsername() ) )
224 throw new IllegalStateException(
225 Messages.getString( "user.manager.cannot.add.user.without.username" ) ); //$NON-NLS-1$
228 userSecurityPolicy.extensionChangePassword( user );
230 fireUserManagerUserAdded( user );
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() ) )
238 user.setPasswordChangeRequired( false );
242 user.setPasswordChangeRequired( true );
245 return (User) addObject( user );
248 public void deleteUser( Object principal )
252 User user = findUser( principal );
254 if ( user.isPermanent() )
256 throw new PermanentUserException( "Cannot delete permanent user [" + user.getUsername() + "]." );
259 fireUserManagerUserRemoved( user );
261 removeObject( user );
263 catch ( UserNotFoundException e )
265 log.warn( "Unable to delete user " + principal + ", user not found.", e );
269 public void deleteUser( String username )
273 User user = findUser( username );
275 if ( user.isPermanent() )
277 throw new PermanentUserException( "Cannot delete permanent user [" + user.getUsername() + "]." );
280 fireUserManagerUserRemoved( user );
282 PlexusJdoUtils.removeObject( getPersistenceManager(), user );
284 catch ( UserNotFoundException e )
286 log.warn( "Unable to delete user " + username + ", user not found.", e );
290 public void addUserUnchecked( User user )
292 if ( !( user instanceof JdoUser ) )
294 throw new UserManagerException( "Unable to Add User. User object " + user.getClass().getName() +
295 " is not an instance of " + JdoUser.class.getName() );
298 if ( StringUtils.isEmpty( user.getUsername() ) )
300 throw new IllegalStateException(
301 Messages.getString( "user.manager.cannot.add.user.without.username" ) ); //$NON-NLS-1$
307 public void eraseDatabase()
309 PlexusJdoUtils.removeAll( getPersistenceManager(), JdoUser.class );
310 PlexusJdoUtils.removeAll( getPersistenceManager(), UsersManagementModelloMetadata.class );
313 public User findUser( Object principal )
314 throws UserNotFoundException
316 if ( principal == null )
318 throw new UserNotFoundException( "Unable to find user based on null principal." );
323 return (User) PlexusJdoUtils.getObjectById( getPersistenceManager(), JdoUser.class, principal.toString(),
326 catch ( PlexusObjectNotFoundException e )
328 throw new UserNotFoundException( "Unable to find user: " + e.getMessage(), e );
330 catch ( PlexusStoreException e )
332 throw new UserNotFoundException( "Unable to find user: " + e.getMessage(), e );
336 public User findUser( String username )
337 throws UserNotFoundException
339 if ( StringUtils.isEmpty( username ) )
341 throw new UserNotFoundException( "User with empty username not found." );
344 return (User) getObjectById( username, null );
347 public boolean userExists( Object principal )
351 findUser( principal );
354 catch ( UserNotFoundException ne )
360 public User updateUser( User user )
361 throws UserNotFoundException
363 return updateUser( user, false );
366 public User updateUser( User user, boolean passwordChangeRequired )
367 throws UserNotFoundException
369 if ( !( user instanceof JdoUser ) )
371 throw new UserManagerException( "Unable to Update User. User object " + user.getClass().getName() +
372 " is not an instance of " + JdoUser.class.getName() );
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() ) )
379 userSecurityPolicy.extensionChangePassword( user, passwordChangeRequired );
382 updateObject( user );
384 fireUserManagerUserUpdated( user );
390 public void initialize()
392 JDOClassLoaderResolver d;
393 pmf = jdoFactory.getPersistenceManagerFactory();
396 public PersistenceManager getPersistenceManager()
398 PersistenceManager pm = pmf.getPersistenceManager();
400 pm.getFetchPlan().setMaxFetchDepth( -1 );
407 // ----------------------------------------------------------------------
408 // jdo utility methods
409 // ----------------------------------------------------------------------
411 private Object addObject( Object object )
413 return PlexusJdoUtils.addObject( getPersistenceManager(), object );
416 private Object getObjectById( String id, String fetchGroup )
417 throws UserNotFoundException, UserManagerException
421 return PlexusJdoUtils.getObjectById( getPersistenceManager(), JdoUser.class, id, fetchGroup );
423 catch ( PlexusObjectNotFoundException e )
425 throw new UserNotFoundException( e.getMessage() );
427 catch ( PlexusStoreException e )
429 throw new UserManagerException( "Unable to get object '" + JdoUser.class.getName() + "', id '" + id +
430 "', fetch-group '" + fetchGroup + "' from jdo store." );
434 private Object removeObject( Object o )
438 throw new UserManagerException( "Unable to remove null object" );
441 PlexusJdoUtils.removeObject( getPersistenceManager(), o );
445 private Object updateObject( Object object )
446 throws UserNotFoundException, UserManagerException
450 return PlexusJdoUtils.updateObject( getPersistenceManager(), object );
452 catch ( PlexusStoreException e )
454 throw new UserManagerException(
455 "Unable to update the '" + object.getClass().getName() + "' object in the jdo database.", e );
459 private void rollback( Transaction tx )
461 PlexusJdoUtils.rollbackIfActive( tx );
464 private boolean hasTriggeredInit = false;
466 public void triggerInit()
468 if ( !hasTriggeredInit )
470 hasTriggeredInit = true;
471 List<User> users = getAllObjectsDetached( null );
473 fireUserManagerInit( users.isEmpty() );
477 public JdoFactory getJdoFactory()
482 public void setJdoFactory( JdoFactory jdoFactory )
484 this.jdoFactory = jdoFactory;
487 public UserSecurityPolicy getUserSecurityPolicy()
489 return userSecurityPolicy;