Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/jeteam/session/HttpSessionCache.java


1   /*
2    * JETeam, Java Enterprise TeamWork
3    *
4    * Distributable under the GPL license.
5    * See terms of license at http://www.gnu.org
6    *
7    * $Source: /cvsroot/jeteam/jeteam/jeteam-swx/src/java/org/jeteam/session/HttpSessionCache.java,v $
8    * $Date: 2003/05/29 11:54:26 $
9    * $Author: draftdog $
10   * $Revision: 1.5 $
11   */
12  package org.jeteam.session;
13  
14  import org.jeteam.bean.common.SettingConstants;
15  import org.jeteam.bean.config.SettingDTO;
16  import org.jeteam.bean.config.SettingServiceUtil;
17  import org.jeteam.bean.project.ProjectDTO;
18  import org.jeteam.bean.user.UserDTO;
19  import org.jeteam.bean.user.UserServiceRemote;
20  import org.jeteam.bean.user.UserServiceUtil;
21  
22  import javax.servlet.http.HttpServletRequest;
23  import javax.servlet.http.HttpSession;
24  import javax.naming.NamingException;
25  import java.text.DateFormatSymbols;
26  import java.util.Calendar;
27  import java.util.Date;
28  import java.util.GregorianCalendar;
29  import java.util.Hashtable;
30  import java.util.Locale;
31  
32  /**
33   * This cache keeps a java.util.Map internally to quickly lookup information that is associated with a specific session,
34   * this is to avoid to perform possibly costly operations more than necessary. In fact, the java.util.Map implementation
35   * maps HttpSessions instances to HttpSessionCache instance.
36   * <p>
37   * Get an instance for your session by passing the original request to the <code>getInstance(HttpServletRequest)</code>
38   * method.
39   * <p>
40   * It is also possible to invalidate the cache in case you want to make sure the cache is rebuilt the next time
41   * you do a call to <code>getInstance(HttpServletRequest)</code>.
42   * <p>
43   * You can do this in one call, by using <code>getInstance(HttpServletRequest,boolean)</code> and passing
44   * <code>true</code> as the second argument, this will force the cache to be replaced by the more recent one.
45   * <p>
46   * Furthermore, there are getter method for all available cache information.
47   * <p>
48   * This class is thread-safe in that it uses a java.util.Hashtable as the java.util.Map implementation.
49   *
50   * @see java.util.Hashtable
51   */
52  public class HttpSessionCache
53  {
54     /**
55      * This is the singleton instance map. We need it to be synchronized since many clients could access it
56      * simultanously, that's why we prefer a Hastable over a HashMap.
57      */
58     private final static Hashtable instanceMap = new Hashtable();
59  
60     private UserDTO user = null;
61     private ProjectDTO projectContext = null;
62     private SettingDTO[] settings = null;
63     private ProjectDTO[] projects = null;
64     private String[] days = null;
65     private String[] months = null;
66     private String[] years = null;
67     private String[] percentages = null;
68  
69     /**
70      * This class should not be instantiated directly.
71      * <p>
72      * By declaring it <code>private</code> we respect the singleton pattern.
73      */
74     private HttpSessionCache(HttpServletRequest request)
75     {
76        try
77        {
78           String userName = request.getUserPrincipal().getName();
79           UserServiceRemote userService = UserServiceUtil.getHome().create();
80  
81           /*
82            * Set the business properties
83            */
84           user = userService.getUser(userName);
85           settings = userService.getSettings(user);
86           projects = userService.getProjects(user);
87  
88           projectContext = getDefaultProjectContext();
89  
90           // set percentages
91           percentages = new String[21];
92           for (int i = 0; i < percentages.length; i++)
93           {
94              percentages[i] = String.valueOf(i * 5);
95           }
96  
97           // set date: days, months, years
98           Locale locale = request.getLocale();
99  
100          // days
101          days = new String[31];
102          for (int i = 0; i < days.length; i++)
103             days[i] = String.valueOf(i + 1);
104 
105          /**
106           * months
107           *
108           * apparently the months returned by DateFormatSymbols contain an additional
109           * empty String at the 13th index.
110           */
111          months = new String[12];
112          String[] dateMonths = new DateFormatSymbols(locale).getMonths();
113          for (int i = 0; i < 12; i++)
114          {
115             months[i] = dateMonths[i];
116          }
117 
118          // years
119          GregorianCalendar calendar = new GregorianCalendar(locale);
120          calendar.setTime(new Date());
121          int year = calendar.get(Calendar.YEAR);
122          years = new String[5];
123          for (int i = 0; i < years.length; i++)
124             years[i] = String.valueOf(year + i);
125       }
126       catch (Exception e)
127       {
128          request.getSession().invalidate();
129          throw new IllegalStateException("Unable to setup session attributes: " + e);
130       }
131    }
132 
133    /**
134     * Gets the singleton instance for the cache.
135     * <p>
136     * This is identical to calling <code>getInstance(request, false)</code>.
137     *
138     * @param request The request from which the cache will be built.
139     * @return The cache that is built from the argument request.
140     */
141    public static HttpSessionCache getInstance(HttpServletRequest request)
142    {
143       return getInstance(request, false);
144    }
145 
146    /**
147     * Gets the singleton instance for the cache.
148     * <p>
149     * In case there is a session for the argument request and the session is known
150     * internally the cache will be returned immediately, otherwise the cache is
151     * constructed and returned.
152     * <p>
153     * Use the <code>force</code> parameter if you want to reconstruct the cache even if it
154     * already exists.
155     * <p>
156     * Please note that doing so implicitely invalidates the cache.
157     *
158     * @param request The request from which the cache will be built.
159     * @param force Set this to <code>true</code> if you want to make sure the cache is a recent as possible, this
160     *              means you will not reuse the existing one (if any). Set to <code>false</code> otherwise.
161     * @return The cache that is built from the argument request.
162     */
163    public static HttpSessionCache getInstance(HttpServletRequest request, boolean force)
164    {
165       HttpSession session = request.getSession();
166       HttpSessionCache instance = (HttpSessionCache) instanceMap.get(session);
167 
168       if (force || (instance == null))
169       {
170          instance = new HttpSessionCache(request);
171          instanceMap.put(session, instance);
172       }
173 
174       return instance;
175    }
176 
177    /**
178     * Invalidates this cache, the next time you need it you should get the instance by calling
179     * <code>getInstance(HttpServletRequest)</code> again.
180     * <p>
181     * Do this when you know the members of the cache have been updated by an external process.
182     * <p>
183     * <strong>IMPORTANT</strong>:
184     * <br>
185     * Do not use a cache instance after calling this method on a request which shares the same session as
186     * that cache. Each request from the same session uses the same cache.
187     *
188     * @param request The request who's cache will be invalidated.
189     */
190    public static void invalidateInstance(HttpServletRequest request)
191    {
192       instanceMap.remove(request.getSession());
193    }
194 
195 
196    /**
197     * Gets the ProjectDTO instance with the given name, please note that only projects associated with this
198     * session's user are being taken into account.
199     *
200     * @param projectName The project name to use in order to find the ProjectDTO instance, if the argument
201     *        equals <code>null</code> it will be directly returned.
202     * @return The associated ProjectDTO instance with the given name, or <code>null</code>
203     *         when no project can be found for the user.
204     */
205    private final ProjectDTO getProject(String projectName)
206    {
207       if (projectName == null)
208       {
209          return null;
210       }
211 
212       ProjectDTO project = null;
213 
214       for (int i = 0; i < projects.length; i++)
215       {
216          project = projects[i];
217          if (project.getName().equals(projectName))
218          {
219             break;
220          }
221       }
222 
223       return project;
224    }
225 
226    /**
227     * Searches the user's settings for a default project context name, this value is returned
228     * when found. In case it is not found this method returns <code>null</code>.
229     *
230     * @return The default project context name or <code>null</code> in case it cannot be found.
231     */
232    private final String getDefaultProjectContextName()
233    {
234       for (int i = 0; i < settings.length; i++)
235       {
236          SettingDTO setting = settings[i];
237          if (SettingConstants.DEFAULT_PROJECT.equals( setting.getKey() ))
238          {
239             return setting.getValue();
240          }
241       }
242       return null;
243    }
244 
245    /**
246     * Checks if the user has a setting for a default project, if this is the case the corresponding ProjectDTO
247     * instance is returned. In case the user does not have such a setting or it is invalid for some reason the first
248     * project this user is assigned to will be returned and this value will be set as a new setting for that user.
249     *
250     * @return The ProjectDTO instance that represents the default project context for this user, or <code>null</code>
251     *         if the user is not assigned to any projects.
252     */
253    private ProjectDTO getDefaultProjectContext()
254    {
255       ProjectDTO project = getProject( getDefaultProjectContextName() );
256 
257       // the user has no setting for default project but is assigned to at least one project
258       if ( (project == null) && (projects.length > 0) )
259       {
260          project = projects[0];
261          SettingDTO setting = new SettingDTO(SettingConstants.DEFAULT_PROJECT, project.getName());
262          try
263          {
264             SettingServiceUtil.getHome().create().createSetting(setting,user);
265             settings = UserServiceUtil.getHome().create().getSettings(user);
266          }
267          catch (Exception e)
268          {
269             // do nothing, let this method return null
270          }
271       }
272 
273       return project;
274    }
275 
276    /**
277     * Returns the user value object that is cached, the information
278     * is derived from the request's principal.
279     *
280     * @return The user.
281     */
282    public UserDTO getUser()
283    {
284       return user;
285    }
286 
287    /**
288     * Returns an array of SettingDTO instances that represent the user's preferences or settings.
289     *
290     * @return An array of SettingDTO's.
291     */
292    public SettingDTO[] getSettings()
293    {
294       return settings;
295    }
296 
297    /**
298     * Returns an array of ProjectDTO instances that represent the user's projects.
299     *
300     * @return An array of ProjectDTO's.
301     */
302    public ProjectDTO[] getProjects()
303    {
304       return projects;
305    }
306 
307    /**
308     * Returns an array of String instances that represent the days in a month.
309     *
310     * @return String instances "1" ... "31"
311     */
312    public String[] getDays()
313    {
314       return days;
315    }
316 
317    /**
318     * The months of a year in the user's locale.
319     *
320     * @return The equivalent of <code>DateFormatSymbols.getMonths();</code>
321     */
322    public String[] getMonths()
323    {
324       return months;
325    }
326 
327    /**
328     * Five years starting from today.
329     *
330     * @return The next five years.
331     */
332    public String[] getYears()
333    {
334       return years;
335    }
336 
337    /**
338     * Percentages starting from 0 to 100, each time incremented by 5.
339     *
340     * @return The list of percentages
341     */
342    public String[] getPercentages()
343    {
344       return percentages;
345    }
346 
347    /**
348     * The current project context, this value will be used when creating for example
349     * a task and no project is explicitely specified.
350     *
351     * @return The project
352     */
353    public ProjectDTO getProjectContext()
354    {
355       return projectContext;
356    }
357 
358 }