001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.main;
029
030import org.opencms.file.CmsRequestContext;
031import org.opencms.util.CmsUUID;
032
033import java.io.Serializable;
034
035import org.apache.commons.collections.Buffer;
036import org.apache.commons.collections.BufferUtils;
037import org.apache.commons.collections.buffer.UnboundedFifoBuffer;
038
039/**
040 * Stores information about a user that has authenticated himself the OpenCms security system.<p>
041 *
042 * This object is used to provide information about all authenticated users in the system
043 * with the {@link org.opencms.main.CmsSessionManager}.<p>
044 *
045 * This object is available for all authenticated users after login.
046 * If a user has not logged in, he may have a session on the servlet engine,
047 * but he will have no session info object attached. For example the "Guest" user
048 * may have multiple sessions, but no session info is created for him.<p>
049 *
050 * @since 6.0.0
051 */
052public class CmsSessionInfo implements Comparable<CmsSessionInfo>, Serializable {
053
054    /** Name of the http session attribute the OpenCms session id is stored in. */
055    public static final String ATTRIBUTE_SESSION_ID = "__org.opencms.main.CmsSessionInfo#m_sessionId";
056
057    /** Maximum size of the broadcast queue for one user. */
058    public static final int QUEUE_SIZE = 10;
059
060    /** Serial version UID required for safe serialization. */
061    private static final long serialVersionUID = 927301527031117920L;
062
063    /** The broadcast queue buffer for the user of this session info. */
064    private transient Buffer m_broadcastQueue;
065
066    /** The maximum time, in seconds, this session info is allowed to be inactive. */
067    private int m_maxInactiveInterval;
068
069    /** The fully qualified name of the organizational unit. */
070    private String m_ouFqn;
071
072    /** The current project id of the user. */
073    private CmsUUID m_projectId;
074
075    /** The id of the (http) session this session info belongs to. */
076    private CmsUUID m_sessionId;
077
078    /** The current site of the user. */
079    private String m_siteRoot;
080
081    /** The time this session info was created. */
082    private long m_timeCreated;
083
084    /** The time this session info was last updated. */
085    private long m_timeUpdated;
086
087    /** The time of the last user action. */
088    private long m_timeLastAction;
089
090    /** The id of user to which this session info belongs. */
091    private CmsUUID m_userId;
092
093    /**
094     * Creates a new CmsSessionInfo object.<p>
095     *
096     * @param context the user context to create this session info for
097     * @param sessionId OpenCms id of the (http) session this session info belongs to
098     * @param maxInactiveInterval the maximum time, in seconds, this session info is allowed to be inactive
099     */
100    public CmsSessionInfo(CmsRequestContext context, CmsUUID sessionId, int maxInactiveInterval) {
101
102        m_timeCreated = System.currentTimeMillis();
103        m_sessionId = sessionId;
104        m_maxInactiveInterval = maxInactiveInterval;
105        m_userId = context.getCurrentUser().getId();
106        update(context);
107    }
108
109    /**
110     * Returns a string for given time.<p>
111     *
112     * @param time as timestamp
113     * @return string array containing string for hours, minutes, seconds
114     */
115    public static String[] getHourMinuteSecondTimeString(long time) {
116
117        int hours = (int)time / (1000 * 60 * 60);
118        int min = (int)(time - (hours * 1000 * 60 * 60)) / (1000 * 60);
119        int sec = (int)(time - (hours * 1000 * 60 * 60) - (min * 1000 * 60)) / 1000;
120
121        return new String[] {getTwoDigitsString(hours), getTwoDigitsString(min), getTwoDigitsString(sec)};
122    }
123
124    /**
125     * Formats an integer to a two chars string.<p>
126     *
127     * @param number to be formatted
128     * @return the string representation
129     */
130    private static String getTwoDigitsString(int number) {
131
132        return number < 10 ? "0" + number : String.valueOf(number);
133    }
134
135    /**
136     * Allows sorting session info according to the user names.<p>
137     *
138     * @see java.lang.Comparable#compareTo(java.lang.Object)
139     */
140    public int compareTo(CmsSessionInfo obj) {
141
142        if (obj == this) {
143            return 0;
144        }
145        return m_userId.compareTo(obj.getUserId());
146    }
147
148    /**
149     * @see java.lang.Object#equals(java.lang.Object)
150     */
151    @Override
152    public boolean equals(Object obj) {
153
154        if (obj == this) {
155            return true;
156        }
157        if (obj instanceof CmsSessionInfo) {
158            return m_userId.equals(((CmsSessionInfo)obj).getUserId());
159        }
160        return false;
161    }
162
163    /**
164     * Gets the age of the session formattet as HOURS:MINUTES.<p>
165     *
166     * @return string representation of session age
167     */
168    public String getAgeOfSession() {
169
170        String[] ret = getHourMinuteSecondTimeString(System.currentTimeMillis() - m_timeCreated);
171        return ret[0] + ":" + ret[1];
172
173    }
174
175    /**
176     * Returns the broadcast queue of the user to which this session info belongs.<p>
177     *
178     * @return the broadcast queue of the user to which this session info belongs
179     */
180    public Buffer getBroadcastQueue() {
181
182        if (m_broadcastQueue == null) {
183            m_broadcastQueue = BufferUtils.synchronizedBuffer(new UnboundedFifoBuffer(QUEUE_SIZE));
184        }
185        return m_broadcastQueue;
186    }
187
188    /**
189     * Returns the maximum time, in seconds, this session info is allowed to be inactive.<p>
190     *
191     * The inactive time is the time since the last call to the {@link #update(CmsRequestContext)}
192     * method. If the inactive time is greater then the maximum allowed time, this
193     * session info will be removed from the session manager.<p>
194     *
195     * @return the maximum time, in seconds, this session info is allowed to be inactive
196     *
197     * @see javax.servlet.http.HttpSession#getMaxInactiveInterval()
198     */
199    public int getMaxInactiveInterval() {
200
201        return m_maxInactiveInterval;
202    }
203
204    /**
205     * Returns the fully qualified name of the organizational unit for this session.<p>
206     *
207     * @return the fully qualified name of the organizational unit for this session
208     */
209    public String getOrganizationalUnitFqn() {
210
211        return m_ouFqn;
212    }
213
214    /**
215     * Returns the id of the project of the user.<p>
216     *
217     * @return the id of the project
218     */
219    public CmsUUID getProject() {
220
221        return m_projectId;
222    }
223
224    /**
225     * Returns the id of the OpenCms (http) session this session info belongs to.<p>
226     *
227     * @return the id of the OpenCms (http) session this session info belongs to
228     *
229     * @see javax.servlet.http.HttpSession#getId()
230     */
231    public CmsUUID getSessionId() {
232
233        return m_sessionId;
234    }
235
236    /**
237     * Returns the current site root of the user.<p>
238     *
239     * @return the current site root of the user
240     */
241    public String getSiteRoot() {
242
243        return m_siteRoot;
244    }
245
246    /**
247     * Returns the time, in milliseconds, this session has been active,
248     * that is the time of the last update minus the creation time.<p>
249     *
250     * @return the time, in milliseconds, this session has been active
251     */
252    public long getTimeActive() {
253
254        return m_timeUpdated - m_timeCreated;
255    }
256
257    /**
258     * Returns the time this session info was created.<p>
259     *
260     * @return the time this session info was created
261     */
262    public long getTimeCreated() {
263
264        return m_timeCreated;
265    }
266
267    /**
268     * Returns the time of the last user action.<p>
269     *
270     * @return the list user action time
271     */
272    public long getTimeLastAction() {
273
274        return m_timeLastAction;
275    }
276
277    /**
278     * Returns the time this session info was last updated.<p>
279     *
280     * @return the time this session info was last updated
281     */
282    public long getTimeUpdated() {
283
284        return m_timeUpdated;
285    }
286
287    /**
288     * Returns the id of the user to which this session info belongs.<p>
289     *
290     * @return the id of the user to which this session info belongs
291     */
292    public CmsUUID getUserId() {
293
294        return m_userId;
295    }
296
297    /**
298     * @see java.lang.Object#hashCode()
299     */
300    @Override
301    public int hashCode() {
302
303        return m_userId.hashCode();
304    }
305
306    /**
307     * Returns <code>true</code> if this session info has expired, that
308     * is it has not been updated in the time set by the maximum inactivity interval.<p>
309     *
310     * @return <code>true</code> if this session info has expired
311     */
312    public boolean isExpired() {
313
314        return ((System.currentTimeMillis() - m_timeUpdated) / 1000) > m_maxInactiveInterval;
315    }
316
317    /**
318     * @see java.lang.Object#toString()
319     */
320    @Override
321    public String toString() {
322
323        StringBuffer str = new StringBuffer(64);
324        str.append("[");
325        str.append("sessionId: ").append(m_sessionId).append(", ");
326        str.append("userId: ").append(m_userId).append(", ");
327        str.append("projectId: ").append(m_projectId).append(", ");
328        str.append("siteRoot: ").append(m_siteRoot).append(", ");
329        str.append("timeCreated: ").append(m_timeCreated).append(", ");
330        str.append("timeUpdated: ").append(m_timeUpdated).append(", ");
331        str.append("maxInactiveInterval: ").append(m_maxInactiveInterval);
332        str.append("ouFqn: ").append(m_ouFqn);
333        str.append("]");
334        return str.toString();
335    }
336
337    /**
338     * Sets the id of the current project of the user of this session info.<p>
339     *
340     * @param projectId the project id to set
341     */
342    protected void setProject(CmsUUID projectId) {
343
344        m_projectId = projectId;
345    }
346
347    /**
348     * Updates the session info object with the information from
349     * the given request context.<p>
350     *
351     * @param context the request context to update the session with
352     */
353    protected void update(CmsRequestContext context) {
354
355        update(context, false);
356    }
357
358    /**
359     * Updates the session info object with the information from
360     * the given request context.<p>
361     *
362     * @param context the request context to update the session with
363     * @param isHeartBeatRequest in case of heart beat requests
364     */
365    protected void update(CmsRequestContext context, boolean isHeartBeatRequest) {
366
367        m_timeUpdated = System.currentTimeMillis();
368        if (!isHeartBeatRequest) {
369            m_timeLastAction = m_timeUpdated;
370        }
371        m_siteRoot = context.getSiteRoot();
372        setProject(context.getCurrentProject().getUuid());
373        m_ouFqn = context.getOuFqn();
374    }
375}