001/* 
002    Licensed to the Apache Software Foundation (ASF) under one
003    or more contributor license agreements.  See the NOTICE file
004    distributed with this work for additional information
005    regarding copyright ownership.  The ASF licenses this file
006    to you under the Apache License, Version 2.0 (the
007    "License"); you may not use this file except in compliance
008    with the License.  You may obtain a copy of the License at
009
010       http://www.apache.org/licenses/LICENSE-2.0
011
012    Unless required by applicable law or agreed to in writing,
013    software distributed under the License is distributed on an
014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015    KIND, either express or implied.  See the License for the
016    specific language governing permissions and limitations
017    under the License.  
018 */
019package org.apache.wiki.auth.user;
020
021import java.io.Serializable;
022import java.util.Date;
023import java.util.HashMap;
024import java.util.Map;
025
026import javax.servlet.http.HttpServletRequest;
027
028import org.apache.commons.lang.StringUtils;
029import org.apache.wiki.WikiSession;
030
031/**
032 * Default implementation for representing wiki user information, such as the
033 * login name, full name, wiki name, and e-mail address.
034 * @since 2.3
035 */
036
037public final class DefaultUserProfile implements UserProfile
038{
039    private static final long serialVersionUID = -5600466893735300647L;
040
041    private static final String EMPTY_STRING = "";
042
043    private static final String WHITESPACE = "\\s";
044    
045    private Map<String,Serializable> attributes = new HashMap<>();
046
047    private Date     created   = null;
048
049    private String   email     = null;
050
051    private String   fullname  = null;
052    
053    private Date lockExpiry = null;
054
055    private String   loginName = null;
056
057    private Date     modified  = null;
058
059    private String   password  = null;
060    
061    private String uid = null;
062
063    private String   wikiname  = null;
064
065    /**
066     * Private constructor to prevent direct instantiation.
067     */
068    private DefaultUserProfile() {}
069
070    /**
071     * Static factory method that creates a new DefaultUserProfile
072     * and sets a unique identifier (uid) for the supplied UserDatabase.
073     * @param db the UserDatabase for which the uid should be
074     * created
075     * @return the new profile
076     */
077    protected static UserProfile newProfile( UserDatabase db )
078    {
079        UserProfile profile = new DefaultUserProfile();
080        profile.setUid( AbstractUserDatabase.generateUid( db ) );
081        return profile;
082    }
083
084    /**
085     * {@inheritDoc}
086     */
087    @Override
088    public boolean equals( Object o )
089    {
090        if ( ( o != null ) && ( o instanceof UserProfile ) )
091        {
092            DefaultUserProfile u = (DefaultUserProfile) o;
093            return  same( fullname, u.fullname ) && same( password, u.password )
094                    && same( loginName, u.loginName ) && same(StringUtils.lowerCase( email ), StringUtils.lowerCase( u.email ) ) && same( wikiname,
095                    u.wikiname );
096        }
097
098        return false;
099    }
100
101    @Override
102    public int hashCode()
103    {
104        return (fullname  != null ? fullname.hashCode()  : 0) ^
105               (password  != null ? password.hashCode()  : 0) ^
106               (loginName != null ? loginName.hashCode() : 0) ^
107               (wikiname  != null ? wikiname.hashCode()  : 0) ^
108               (email     != null ? StringUtils.lowerCase( email ).hashCode()     : 0);
109    }
110
111    /**
112     * Returns the creation date
113     * @return the creation date
114     * @see org.apache.wiki.auth.user.UserProfile#getCreated()
115     */
116    @Override
117    public Date getCreated()
118    {
119        return created;
120    }
121
122    /**
123     * Returns the user's e-mail address.
124     * @return the e-mail address
125     */
126    @Override
127    public String getEmail()
128    {
129        return email;
130    }
131
132    /**
133     * Returns the user's full name.
134     * @return the full name
135     */
136    @Override
137    public String getFullname()
138    {
139        return fullname;
140    }
141
142    /**
143     * Returns the last-modified date.
144     * @return the last-modified date
145     * @see org.apache.wiki.auth.user.UserProfile#getLastModified()
146     */
147    @Override
148    public Date getLastModified()
149    {
150        return modified;
151    }
152
153    /**
154     * Returns the user's login name.
155     * @return the login name
156     */
157    @Override
158    public String getLoginName()
159    {
160        return loginName;
161    }
162
163    /**
164     * Returns the user password for use with custom authentication. Note that
165     * the password field is not meaningful for container authentication; the
166     * user's private credentials are generally stored elsewhere. While it
167     * depends on the {@link UserDatabase}implementation, in most cases the
168     * value returned by this method will be a password hash, not the password
169     * itself.
170     * @return the password
171     */
172    @Override
173    public String getPassword()
174    {
175        return password;
176    }
177
178    /**
179     * Returns the user's wiki name.
180     * @return the wiki name.
181     */
182    @Override
183    public String getWikiName()
184    {
185        return wikiname;
186    }
187
188    /**
189     * Returns <code>true</code> if the user profile is
190     * new. This implementation checks whether
191     * {@link #getLastModified()} returns <code>null</code>
192     * to determine the status.
193     * @see org.apache.wiki.auth.user.UserProfile#isNew()
194     */
195    @Override
196    public boolean isNew()
197    {
198        return  modified == null;
199    }
200
201    /**
202     * @param date the creation date
203     * @see org.apache.wiki.auth.user.UserProfile#setCreated(java.util.Date)
204     */
205    @Override
206    public void setCreated(Date date)
207    {
208        created = date;
209    }
210
211    /**
212     * Sets the user's e-mail address.
213     * @param email the e-mail address
214     */
215    @Override
216    public void setEmail( String email )
217    {
218        this.email = email;
219    }
220
221    /**
222     * Sets the user's full name. For example, "Janne Jalkanen."
223     * @param arg the full name
224     */
225    @Override
226    public void setFullname( String arg )
227    {
228        fullname = arg;
229
230        // Compute wiki name
231        if ( fullname != null )
232        {
233            wikiname = fullname.replaceAll(WHITESPACE, EMPTY_STRING);
234        }
235    }
236
237    /**
238     * Sets the last-modified date.
239     * @param date the last-modified date
240     * @see org.apache.wiki.auth.user.UserProfile#setLastModified(java.util.Date)
241     */
242    @Override
243    public void setLastModified( Date date )
244    {
245        modified = date;
246    }
247
248    /**
249     * Sets the name by which the user logs in. The login name is used as the
250     * username for custom authentication (see
251     * {@link org.apache.wiki.auth.AuthenticationManager#login(WikiSession,HttpServletRequest, String, String)}).
252     * The login name is typically a short name ("jannej"). In contrast, the
253     * wiki name is typically of type FirstnameLastName ("JanneJalkanen").
254     * @param name the login name
255     */
256    @Override
257    public void setLoginName( String name )
258    {
259        loginName = name;
260    }
261
262    /**
263     * Sets the user's password for use with custom authentication. It is
264     * <em>not</em> the responsibility of implementing classes to hash the
265     * password; that responsibility is borne by the UserDatabase implementation
266     * during save operations (see {@link UserDatabase#save(UserProfile)}).
267     * Note that the password field is not meaningful for container
268     * authentication; the user's private credentials are generally stored
269     * elsewhere.
270     * @param arg the password
271     */
272    @Override
273    public void setPassword( String arg )
274    {
275        password = arg;
276    }
277
278    /**
279     * No-op method. In previous versions of JSPWiki, the method
280     * set the user's wiki name directly. Now, the wiki name is automatically
281     * calculated based on the full name.
282     * @param name the wiki name
283     * @deprecated This method will be removed in a future release.
284     */
285    @Deprecated
286    @Override
287    public void setWikiName( String name )
288    {
289    }
290
291    /**
292     * Returns a string representation of this user profile.
293     * @return the string
294     */
295    @Override
296    public String toString()
297    {
298        return "[DefaultUserProfile: '" + getFullname() + "']";
299    }
300
301    /**
302     * Private method that compares two objects and determines whether they are
303     * equal. Two nulls are considered equal.
304     * @param arg1 the first object
305     * @param arg2 the second object
306     * @return the result of the comparison
307     */
308    private boolean same( Object arg1, Object arg2 )
309    {
310        if ( arg1 == null && arg2 == null )
311        {
312            return true;
313        }
314        if ( arg1 == null || arg2 == null )
315        {
316            return false;
317        }
318        return arg1.equals( arg2 );
319    }
320
321    //--------------------------- Attribute and lock interface implementations ---------------------------
322    
323    /**
324     * {@inheritDoc}
325     */
326    @Override
327    public Map<String,Serializable> getAttributes()
328    {
329        return attributes;
330    }
331
332    /**
333     * {@inheritDoc}
334     */
335    @Override
336    public Date getLockExpiry()
337    {
338        return isLocked() ? lockExpiry : null;
339    }
340    
341    /**
342     * {@inheritDoc}
343     */
344    @Override
345    public String getUid()
346    {
347        return uid;
348    }
349
350    /**
351     * {@inheritDoc}
352     */
353    @Override
354    public boolean isLocked()
355    {
356        boolean locked =  lockExpiry != null && System.currentTimeMillis() < lockExpiry.getTime();
357
358        // Clear the lock if it's expired already
359        if ( !locked && lockExpiry != null )
360        {
361            lockExpiry = null;
362        }
363        return locked;
364    }
365
366    /**
367     * {@inheritDoc}
368     */
369    @Override
370    public void setLockExpiry( Date expiry )
371    {
372        this.lockExpiry = expiry;
373    }
374    
375    /**
376     * {@inheritDoc}
377     */
378    @Override
379    public void setUid( String uid )
380    {
381        this.uid = uid;
382    }
383}