001package org.apache.archiva.redback.users.cached;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.archiva.components.cache.Cache;
023import org.apache.archiva.redback.users.User;
024import org.apache.archiva.redback.users.UserManagerException;
025import org.apache.archiva.redback.users.UserManagerListener;
026import org.apache.archiva.redback.users.UserNotFoundException;
027import org.apache.archiva.redback.users.UserQuery;
028import org.apache.archiva.redback.users.UserManager;
029import org.slf4j.Logger;
030import org.slf4j.LoggerFactory;
031import org.springframework.stereotype.Service;
032
033import javax.annotation.PreDestroy;
034import javax.inject.Inject;
035import javax.inject.Named;
036import java.util.List;
037
038/**
039 * CachedUserManager
040 *
041 * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
042 */
043@Service("userManager#cached")
044public class CachedUserManager
045    implements UserManager, UserManagerListener
046{
047
048    private final Logger log = LoggerFactory.getLogger( getClass() );
049
050    @Inject
051    @Named(value = "userManager#default")
052    private UserManager userImpl;
053
054    @Inject
055    @Named(value = "cache#users")
056    private Cache<String, User> usersCache;
057
058    @Override
059    public boolean isReadOnly()
060    {
061        return userImpl.isReadOnly();
062    }
063
064    @Override
065    public User createGuestUser()
066        throws UserManagerException
067    {
068        return userImpl.createGuestUser();
069    }
070
071    @Override
072    public User addUser( User user )
073        throws UserManagerException
074    {
075        if ( user != null )
076        {
077            usersCache.remove( user.getUsername() );
078        }
079        return this.userImpl.addUser( user );
080    }
081
082    @Override
083    public void addUserManagerListener( UserManagerListener listener )
084    {
085        this.userImpl.addUserManagerListener( listener );
086    }
087
088    @Override
089    public void addUserUnchecked( User user )
090        throws UserManagerException
091    {
092        if ( user != null )
093        {
094            usersCache.remove( user.getUsername() );
095        }
096        this.userImpl.addUserUnchecked( user );
097    }
098
099    @Override
100    public User createUser( String username, String fullName, String emailAddress )
101        throws UserManagerException
102    {
103        usersCache.remove( username );
104        return this.userImpl.createUser( username, fullName, emailAddress );
105    }
106
107    @Override
108    public void deleteUser( String username )
109        throws UserNotFoundException, UserManagerException
110    {
111        usersCache.remove( username );
112        this.userImpl.deleteUser( username );
113    }
114
115    @Override
116    public void eraseDatabase()
117    {
118        try
119        {
120            this.userImpl.eraseDatabase();
121        }
122        finally
123        {
124            usersCache.clear();
125        }
126    }
127
128    @Override
129    public User findUser( String username )
130        throws UserNotFoundException, UserManagerException
131    {
132        if ( GUEST_USERNAME.equals( username ) )
133        {
134            return getGuestUser();
135        }
136
137        User el = usersCache.get( username );
138        if ( el != null )
139        {
140            return el;
141        }
142        else
143        {
144            User user = this.userImpl.findUser( username );
145            usersCache.put( username, user );
146            return user;
147        }
148    }
149
150    @Override
151    public User findUser( String username, boolean useCache )
152        throws UserNotFoundException, UserManagerException
153    {
154        // force use of cache here :-)
155        return findUser( username );
156    }
157
158    @Override
159    public User getGuestUser()
160        throws UserNotFoundException, UserManagerException
161    {
162        User el = usersCache.get( GUEST_USERNAME );
163        if ( el != null )
164        {
165            return el;
166        }
167        else
168        {
169            User user = this.userImpl.getGuestUser();
170            usersCache.put( GUEST_USERNAME, user );
171            return user;
172        }
173    }
174
175    @Override
176    public UserQuery createUserQuery()
177    {
178        return userImpl.createUserQuery();
179    }
180
181
182    @Override
183    public List<? extends User> findUsersByQuery( UserQuery query )
184        throws UserManagerException
185    {
186        log.debug( "NOT CACHED - .findUsersByQuery(UserQuery)" );
187        return this.userImpl.findUsersByQuery( query );
188    }
189
190    @Override
191    public List<? extends User> findUsersByEmailKey( String emailKey, boolean orderAscending )
192        throws UserManagerException
193    {
194        log.debug( "NOT CACHED - .findUsersByEmailKey(String, boolean)" );
195        return this.userImpl.findUsersByEmailKey( emailKey, orderAscending );
196    }
197
198    @Override
199    public List<? extends User> findUsersByFullNameKey( String fullNameKey, boolean orderAscending )
200        throws UserManagerException
201    {
202        log.debug( "NOT CACHED - .findUsersByFullNameKey(String, boolean)" );
203        return this.userImpl.findUsersByFullNameKey( fullNameKey, orderAscending );
204    }
205
206    @Override
207    public List<? extends User> findUsersByUsernameKey( String usernameKey, boolean orderAscending )
208        throws UserManagerException
209    {
210        log.debug( "NOT CACHED - .findUsersByUsernameKey(String, boolean)" );
211        return this.userImpl.findUsersByUsernameKey( usernameKey, orderAscending );
212    }
213
214    @Override
215    public String getId()
216    {
217        return "cached";
218    }
219
220    @Override
221    public List<? extends User> getUsers()
222        throws UserManagerException
223    {
224        log.debug( "NOT CACHED - .getUsers()" );
225        return this.userImpl.getUsers();
226    }
227
228    @Override
229    public List<? extends User> getUsers( boolean orderAscending )
230        throws UserManagerException
231    {
232        log.debug( "NOT CACHED - .getUsers(boolean)" );
233        return this.userImpl.getUsers( orderAscending );
234    }
235
236    @Override
237    public void removeUserManagerListener( UserManagerListener listener )
238    {
239        this.userImpl.removeUserManagerListener( listener );
240    }
241
242    @Override
243    public User updateUser( User user )
244        throws UserNotFoundException, UserManagerException
245    {
246        return updateUser( user, false );
247    }
248
249    @Override
250    public User updateUser( User user, boolean passwordChangeRequired )
251        throws UserNotFoundException, UserManagerException
252    {
253        if ( user != null )
254        {
255            usersCache.remove( user.getUsername() );
256        }
257        return this.userImpl.updateUser( user, passwordChangeRequired );
258    }
259
260    @Override
261    public boolean userExists( String userName )
262        throws UserManagerException
263    {
264        if ( usersCache.hasKey( userName ) )
265        {
266            return true;
267        }
268
269        return this.userImpl.userExists( userName );
270    }
271
272    @Override
273    public void userManagerInit( boolean freshDatabase )
274    {
275        if ( userImpl != null )
276        {
277            ( (UserManagerListener) this.userImpl ).userManagerInit( freshDatabase );
278        }
279
280        usersCache.clear();
281    }
282
283    @Override
284    public void userManagerUserAdded( User user )
285    {
286        if ( userImpl != null )
287        {
288            ( (UserManagerListener) this.userImpl ).userManagerUserAdded( user );
289        }
290
291        if ( user != null )
292        {
293            usersCache.remove( user.getUsername() );
294        }
295    }
296
297    @Override
298    public void userManagerUserRemoved( User user )
299    {
300        if ( userImpl != null )
301        {
302            ( (UserManagerListener) this.userImpl ).userManagerUserRemoved( user );
303        }
304
305        if ( user != null )
306        {
307            usersCache.remove( user.getUsername() );
308        }
309    }
310
311    @Override
312    public void userManagerUserUpdated( User user )
313    {
314        if ( userImpl != null )
315        {
316            ( (UserManagerListener) this.userImpl ).userManagerUserUpdated( user );
317        }
318
319        if ( user != null )
320        {
321            usersCache.remove( user.getUsername() );
322        }
323    }
324
325    public UserManager getUserImpl()
326    {
327        return userImpl;
328    }
329
330    public void setUserImpl( UserManager userImpl )
331    {
332        this.userImpl = userImpl;
333    }
334
335    public Cache<String, User> getUsersCache()
336    {
337        return usersCache;
338    }
339
340    public void setUsersCache( Cache<String, User> usersCache )
341    {
342        this.usersCache = usersCache;
343    }
344
345    @Override
346    public void initialize()
347    {
348        // no op configurable impl do the job
349    }
350
351    @Override
352    public boolean isFinalImplementation()
353    {
354        return false;
355    }
356
357    @Override
358    public String getDescriptionKey()
359    {
360        return "archiva.redback.usermanager.cached";
361    }
362
363    /**
364     * Clears the users cache
365     */
366    public void clearCache() {
367        usersCache.clear( );
368    }
369
370    @PreDestroy
371    public void shutdown() {
372        this.clearCache( );
373    }
374}