    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    }