001    package org.apache.turbine.services.security.torque;
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    
022    import java.io.ByteArrayOutputStream;
023    import java.io.PrintWriter;
024    import java.sql.Connection;
025    import java.util.Date;
026    import java.util.Hashtable;
027    
028    import javax.servlet.http.HttpSessionBindingEvent;
029    
030    import org.apache.torque.om.Persistent;
031    import org.apache.turbine.om.security.User;
032    import org.apache.turbine.services.security.TurbineSecurity;
033    import org.apache.turbine.util.ObjectUtils;
034    import org.apache.turbine.util.security.TurbineSecurityException;
035    
036    /**
037     * This is the User class used by the TorqueSecurity Service. It decouples
038     * all the database peer access from the actual Peer object
039     *
040     * @author <a href="mailto:josh@stonecottage.com">Josh Lucas</a>
041     * @author <a href="mailto:jon@collab.net">Jon S. Stevens</a>
042     * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
043     * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
044     * @author <a href="mailto:cberry@gluecode.com">Craig D. Berry</a>
045     * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
046     * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
047     * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
048     * @version $Id: TorqueUser.java 1096130 2011-04-23 10:37:19Z ludwig $
049     */
050    
051    public class TorqueUser
052        extends TorqueObject
053        implements User
054    {
055        /** Serial Version UID */
056        private static final long serialVersionUID = 6623129207135917717L;
057    
058        /** The date on which the user last accessed the application. */
059        private Date lastAccessDate = null;
060    
061        /** This is data that will survive a servlet engine restart. */
062        private Hashtable permStorage = null;
063    
064        /** This is data that will not survive a servlet engine restart. */
065        private Hashtable tempStorage = null;
066    
067        /**
068         * Constructor.
069         * Create a new User and set the createDate.
070         */
071        public TorqueUser()
072        {
073            super();
074            setCreateDate(new Date());
075            tempStorage = new Hashtable(10);
076            setHasLoggedIn(Boolean.FALSE);
077        }
078    
079        /**
080         * This Constructor is used when the UserPeerManager
081         * has retrieved a list of Database Objects from the peer and
082         * must 'wrap' them into TorqueRole Objects. You should not use it directly!
083         *
084         * @param obj An Object from the peer
085         */
086        public TorqueUser(Persistent obj)
087        {
088            super(obj);
089    
090            // Do not set creation date. This is only called on retrieval from
091            // storage!
092    
093            tempStorage = new Hashtable(10);
094            setHasLoggedIn(Boolean.FALSE);
095        }
096    
097        /**
098         * Returns the underlying Object for the Peer
099         *
100         * Used in the UserPeerManager when building a new Criteria.
101         *
102         * @return The underlying persistent object
103         *
104         */
105    
106        public Persistent getPersistentObj()
107        {
108            if (obj == null)
109            {
110                obj = UserPeerManager.newPersistentInstance();
111            }
112            return obj;
113        }
114    
115        /**
116         * Stores the object in the database.  If the object is new,
117         * it inserts it; otherwise an update is performed.
118         *
119         * @param torqueName The name under which the object should be stored.
120         *
121         * @exception Exception This method might throw an exceptions
122         */
123        public void save(String torqueName)
124                throws Exception
125        {
126            setObjectdata(ObjectUtils.serializeHashtable(getPermStorage()));
127            super.save(torqueName);
128        }
129    
130        /**
131         * Stores the object in the database.  If the object is new,
132         * it inserts it; otherwise an update is performed.  This method
133         * is meant to be used as part of a transaction, otherwise use
134         * the save() method and the connection details will be handled
135         * internally
136         *
137         * @param con A Connection object to save the object
138         *
139         * @exception Exception This method might throw an exceptions
140         */
141        public void save(Connection con)
142            throws Exception
143        {
144            setObjectdata(ObjectUtils.serializeHashtable(getPermStorage()));
145            super.save(con);
146        }
147    
148        /**
149         * Makes changes made to the User attributes permanent.
150         *
151         * @throws TurbineSecurityException if there is a problem while
152         *  saving data.
153         */
154        public void save()
155            throws TurbineSecurityException
156        {
157            //
158            // This is inconsistent with all the other security classes
159            // because it calls save() on the underlying object directly.
160            // But the UserManager calls ((Persistent)user).save()
161            // so if we do TurbineSecurity.saveUser(this) here, we get
162            // a nice endless loop. :-(
163            //
164            // Users seem to be a special kind of security objects...
165            //
166    
167            try
168            {
169                setObjectdata(ObjectUtils.serializeHashtable(getPermStorage()));
170                getPersistentObj().save();
171            }
172            catch (Exception e)
173            {
174                throw new TurbineSecurityException("User object said "
175                        + e.getMessage(), e);
176            }
177        }
178    
179        /**
180         * Returns the name of this object.
181         *
182         * @return The name of the object.
183         */
184        public String getName()
185        {
186            return UserPeerManager.getName(getPersistentObj());
187        }
188    
189        /**
190         * Sets the name of this object
191         *
192         * @param name The name of the object
193         */
194        public void setName(String name)
195        {
196            setUserName(name);
197        }
198    
199        /**
200         * Gets the Id of this object
201         *
202         * @return The Id of the object
203         */
204        public int getId()
205        {
206            return UserPeerManager.getIdAsObj(getPersistentObj()).intValue();
207        }
208    
209        /**
210         * Gets the Id of this object
211         *
212         * @return The Id of the object
213         */
214        public Integer getIdAsObj()
215        {
216            return UserPeerManager.getIdAsObj(getPersistentObj());
217        }
218    
219        /**
220         * Sets the Id of this object
221         *
222         * @param id The new Id
223         */
224        public void setId(int id)
225        {
226            UserPeerManager.setId(getPersistentObj(), id);
227        }
228    
229        /**
230         * Returns the name of this user.
231         *
232         * @return The name of the user.
233         * @deprecated Use getName() instead.
234         */
235        public String getUserName()
236        {
237            return getName();
238        }
239    
240        /**
241         * Sets the name of this user.
242         *
243         * @param name The name of the user.
244         */
245        public void setUserName(String name)
246        {
247            UserPeerManager.setUserName(getPersistentObj(), name);
248        }
249    
250        /**
251         * Returns the password of the User
252         *
253         * @return The password of the User
254         */
255        public String getPassword()
256        {
257            return UserPeerManager.getUserPassword(getPersistentObj());
258        }
259    
260        /**
261         * Sets the password of the User
262         *
263         * @param password The new password of the User
264         */
265        public void setPassword(String password)
266        {
267            UserPeerManager.setUserPassword(getPersistentObj(), password);
268        }
269    
270        /**
271         * Returns the first name of the User
272         *
273         * @return The first name of the User
274         */
275        public String getFirstName()
276        {
277            return UserPeerManager.getUserFirstName(getPersistentObj());
278        }
279    
280        /**
281         * Sets the first name of the User
282         *
283         * @param firstName The new first name of the User
284         */
285        public void setFirstName(String firstName)
286        {
287            UserPeerManager.setUserFirstName(getPersistentObj(), firstName);
288        }
289    
290        /**
291         * Returns the last name of the User
292         *
293         * @return The last name of the User
294         */
295        public String getLastName()
296        {
297            return UserPeerManager.getUserLastName(getPersistentObj());
298        }
299    
300        /**
301         * Sets the last name of User
302         *
303         * @param lastName The new last name of the User
304         */
305        public void setLastName(String lastName)
306        {
307            UserPeerManager.setUserLastName(getPersistentObj(), lastName);
308        }
309    
310        /**
311         * Returns the email address of the user
312         *
313         * @return The email address of the user
314         */
315        public String getEmail()
316        {
317            return UserPeerManager.getUserEmail(getPersistentObj());
318        }
319    
320        /**
321         * Sets the new email address of the user
322         *
323         * @param email The new email address of the user
324         */
325        public void setEmail(String email)
326        {
327            UserPeerManager.setUserEmail(getPersistentObj(), email);
328        }
329    
330        /**
331         * Returns the confirm value of the user
332         *
333         * @return The confirm value of the user
334         */
335        public String getConfirmed()
336        {
337            return UserPeerManager.getUserConfirmed(getPersistentObj());
338        }
339    
340        /**
341         * Sets the new confirm value of the user
342         *
343         * @param confirm The new confirm value of the user
344         */
345        public void setConfirmed(String confirm)
346        {
347            UserPeerManager.setUserConfirmed(getPersistentObj(), confirm);
348        }
349    
350        /**
351         * Returns the creation date of the user
352         *
353         * @return The creation date of the user
354         */
355        public java.util.Date getCreateDate()
356        {
357            return UserPeerManager.getUserCreateDate(getPersistentObj());
358        }
359    
360        /**
361         * Sets the new creation date of the user
362         *
363         * @param createDate The new creation date of the user
364         */
365        public void setCreateDate(java.util.Date createDate)
366        {
367            UserPeerManager.setUserCreateDate(getPersistentObj(), createDate);
368        }
369    
370        /**
371         * Returns the date of the last login of the user
372         *
373         * @return The date of the last login of the user
374         */
375        public java.util.Date getLastLogin()
376        {
377            return UserPeerManager.getUserLastLogin(getPersistentObj());
378        }
379    
380        /**
381         * Sets the new date of the last login of the user
382         *
383         * @param lastLogin The new the date of the last login of the user
384         */
385        public void setLastLogin(java.util.Date lastLogin)
386        {
387            UserPeerManager.setUserLastLogin(getPersistentObj(), lastLogin);
388        }
389    
390        /**
391         * Returns the value of the objectdata for this user.
392         * Objectdata is a VARBINARY column in the table used
393         * to store the permanent storage table from the User
394         * object.
395         *
396         * @return The bytes in the objectdata for this user
397         */
398        public byte [] getObjectdata()
399        {
400            return UserPeerManager.getUserObjectdata(getPersistentObj());
401        }
402    
403        /**
404         * Sets the value of the objectdata for the user
405         *
406         * @param objectdata The new the date of the last login of the user
407         */
408        public void setObjectdata(byte [] objectdata)
409        {
410            UserPeerManager.setUserObjectdata(getPersistentObj(), objectdata);
411        }
412    
413    
414        /**
415         * Gets the access counter for a user from perm storage.
416         *
417         * @return The access counter for the user.
418         */
419        public int getAccessCounter()
420        {
421            try
422            {
423                return ((Integer) getPerm(User.ACCESS_COUNTER)).intValue();
424            }
425            catch (Exception e)
426            {
427                return 0;
428            }
429        }
430    
431        /**
432         * Gets the access counter for a user during a session.
433         *
434         * @return The access counter for the user for the session.
435         */
436        public int getAccessCounterForSession()
437        {
438            try
439            {
440                return ((Integer) getTemp(User.SESSION_ACCESS_COUNTER)).intValue();
441            }
442            catch (Exception e)
443            {
444                return 0;
445            }
446        }
447    
448        /**
449         * Increments the permanent hit counter for the user.
450         */
451        public void incrementAccessCounter()
452        {
453            // Ugh. Race city, here I come...
454            setAccessCounter(getAccessCounter() + 1);
455        }
456    
457        /**
458         * Increments the session hit counter for the user.
459         */
460        public void incrementAccessCounterForSession()
461        {
462            setAccessCounterForSession(getAccessCounterForSession() + 1);
463        }
464    
465        /**
466         * Sets the access counter for a user, saved in perm storage.
467         *
468         * @param cnt The new count.
469         */
470        public void setAccessCounter(int cnt)
471        {
472            setPerm(User.ACCESS_COUNTER, new Integer(cnt));
473        }
474    
475        /**
476         * Sets the session access counter for a user, saved in temp
477         * storage.
478         *
479         * @param cnt The new count.
480         */
481        public void setAccessCounterForSession(int cnt)
482        {
483            setTemp(User.SESSION_ACCESS_COUNTER, new Integer(cnt));
484        }
485    
486        /**
487         * This method reports whether or not the user has been confirmed
488         * in the system by checking the User.CONFIRM_VALUE
489         * column in the users record to see if it is equal to
490         * User.CONFIRM_DATA.
491         *
492         * @return True if the user has been confirmed.
493         */
494        public boolean isConfirmed()
495        {
496            String value = getConfirmed();
497            return (value != null && value.equals(User.CONFIRM_DATA));
498        }
499    
500        /**
501         * The user is considered logged in if they have not timed out.
502         *
503         * @return Whether the user has logged in.
504         */
505        public boolean hasLoggedIn()
506        {
507            Boolean loggedIn = getHasLoggedIn();
508            return (loggedIn != null && loggedIn.booleanValue());
509        }
510    
511        /**
512         * This sets whether or not someone has logged in.  hasLoggedIn()
513         * returns this value.
514         *
515         * @param value Whether someone has logged in or not.
516         */
517        public void setHasLoggedIn(Boolean value)
518        {
519            setTemp(User.HAS_LOGGED_IN, value);
520        }
521    
522        /**
523         * Gets the last access date for this User.  This is the last time
524         * that the user object was referenced.
525         *
526         * @return A Java Date with the last access date for the user.
527         */
528        public java.util.Date getLastAccessDate()
529        {
530            if (lastAccessDate == null)
531            {
532                setLastAccessDate();
533            }
534            return lastAccessDate;
535        }
536    
537        /**
538         * Sets the last access date for this User. This is the last time
539         * that the user object was referenced.
540         */
541        public void setLastAccessDate()
542        {
543            lastAccessDate = new java.util.Date();
544        }
545    
546        /**
547         * Returns the permanent storage. This is implemented
548         * as a Hashtable and backed by an VARBINARY column in
549         * the database.
550         *
551         * @return A Hashtable.
552         */
553        public Hashtable getPermStorage()
554        {
555            if (permStorage == null)
556            {
557                byte [] objectdata = getObjectdata();
558    
559                if (objectdata != null)
560                {
561                    permStorage = (Hashtable) ObjectUtils.deserialize(objectdata);
562                }
563    
564                if (permStorage == null)
565                {
566                    permStorage = new Hashtable();
567                }
568            }
569    
570            return permStorage;
571        }
572    
573        /**
574         * This should only be used in the case where we want to save the
575         * data to the database.
576         *
577         * @param storage A Hashtable.
578         */
579        public void setPermStorage(Hashtable permStorage)
580        {
581            if (permStorage != null)
582            {
583                this.permStorage = permStorage;
584            }
585        }
586    
587        /**
588         * Returns the temporary storage. This is implemented
589         * as a Hashtable
590         *
591         * @return A Hashtable.
592         */
593        public Hashtable getTempStorage()
594        {
595            if (tempStorage == null)
596            {
597                tempStorage = new Hashtable();
598            }
599            return tempStorage;
600        }
601    
602        /**
603         * This should only be used in the case where we want to save the
604         * data to the database.
605         *
606         * @param storage A Hashtable.
607         */
608        public void setTempStorage(Hashtable tempStorage)
609        {
610            if (tempStorage != null)
611            {
612                this.tempStorage = tempStorage;
613            }
614        }
615    
616        /**
617         * Get an object from permanent storage.
618         *
619         * @param name The object's name.
620         * @return An Object with the given name.
621         */
622        public Object getPerm(String name)
623        {
624            return getPermStorage().get(name);
625        }
626    
627        /**
628         * Get an object from permanent storage; return default if value
629         * is null.
630         *
631         * @param name The object's name.
632         * @param def A default value to return.
633         * @return An Object with the given name.
634         */
635        public Object getPerm(String name, Object def)
636        {
637            try
638            {
639                Object val = getPermStorage().get(name);
640                return (val == null ? def : val);
641            }
642            catch (Exception e)
643            {
644                return def;
645            }
646        }
647    
648        /**
649         * Put an object into permanent storage. If the value is null,
650         * it will convert that to a "" because the underlying storage
651         * mechanism within TorqueUser is currently a Hashtable and
652         * null is not a valid value.
653         *
654         * @param name The object's name.
655         * @param value The object.
656         */
657        public void setPerm(String name, Object value)
658        {
659            getPermStorage().put(name, (value == null) ? "" : value);
660        }
661    
662        /**
663         * Get an object from temporary storage.
664         *
665         * @param name The object's name.
666         * @return An Object with the given name.
667         */
668        public Object getTemp(String name)
669        {
670            return getTempStorage().get(name);
671        }
672    
673        /**
674         * Get an object from temporary storage; return default if value
675         * is null.
676         *
677         * @param name The object's name.
678         * @param def A default value to return.
679         * @return An Object with the given name.
680         */
681        public Object getTemp(String name, Object def)
682        {
683            Object val;
684            try
685            {
686                val = getTempStorage().get(name);
687                if (val == null)
688                {
689                    val = def;
690                }
691            }
692            catch (Exception e)
693            {
694                val = def;
695            }
696            return val;
697        }
698    
699        /**
700         * Put an object into temporary storage. If the value is null,
701         * it will convert that to a "" because the underlying storage
702         * mechanism within TorqueUser is currently a Hashtable and
703         * null is not a valid value.
704         *
705         * @param name The object's name.
706         * @param value The object.
707         */
708        public void setTemp(String name, Object value)
709        {
710            getTempStorage().put(name, (value == null) ? "" : value);
711        }
712    
713        /**
714         * Remove an object from temporary storage and return the object.
715         *
716         * @param name The name of the object to remove.
717         * @return An Object.
718         */
719        public Object removeTemp(String name)
720        {
721            return getTempStorage().remove(name);
722        }
723    
724        /**
725         * Updates the last login date in the database.
726         *
727         * @exception Exception A generic exception.
728         */
729        public void updateLastLogin()
730            throws Exception
731        {
732            setLastLogin(new java.util.Date());
733        }
734    
735        /**
736         * Implement this method if you wish to be notified when the User
737         * has been Bound to the session.
738         *
739         * @param event Indication of value/session binding.
740         */
741        public void valueBound(HttpSessionBindingEvent hsbe)
742        {
743            // Currently we have no need for this method.
744        }
745    
746        /**
747         * Implement this method if you wish to be notified when the User
748         * has been Unbound from the session.
749         *
750         * @param event Indication of value/session unbinding.
751         */
752        public void valueUnbound(HttpSessionBindingEvent hsbe)
753        {
754            try
755            {
756                if (hasLoggedIn())
757                {
758                    TurbineSecurity.saveOnSessionUnbind(this);
759                }
760            }
761            catch (Exception e)
762            {
763                //Log.error("TorqueUser.valueUnbound(): " + e.getMessage(), e);
764    
765                // To prevent messages being lost in case the logging system
766                // goes away before sessions get unbound on servlet container
767                // shutdown, print the stcktrace to the container's console.
768                ByteArrayOutputStream ostr = new ByteArrayOutputStream();
769                e.printStackTrace(new PrintWriter(ostr, true));
770                String stackTrace = ostr.toString();
771                System.out.println(stackTrace);
772            }
773        }
774    
775        /**
776         * This gets whether or not someone has logged in.  hasLoggedIn()
777         * returns this value as a boolean.  This is private because you
778         * should use hasLoggedIn() instead.
779         *
780         * @return True if someone has logged in.
781         */
782        private Boolean getHasLoggedIn()
783        {
784            return (Boolean) getTemp(User.HAS_LOGGED_IN);
785        }
786    
787    }