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