1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.mail.util;
24  
25  import com.liferay.util.CollectionFactory;
26  
27  import java.util.Map;
28  
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpSession;
31  
32  /**
33   * <a href="MailSessionLock.java.html"><b><i>View Source</i></b></a>
34   *
35   * @author Alexander Chow
36   *
37   */
38  public class MailSessionLock {
39  
40      public static void cleanUp(HttpSession ses) {
41          _instance._cleanUp(ses);
42      }
43  
44      public static void lock(HttpServletRequest req) {
45          _instance._lock(req.getSession().getId());
46      }
47  
48      public static void unlock(HttpServletRequest req) {
49          _instance._unlock(req.getSession().getId());
50      }
51  
52      private MailSessionLock() {
53      }
54  
55      private void _cleanUp(HttpSession ses) {
56          try {
57              MailUtil.cleanUp(ses);
58          }
59          catch (Exception ex) {
60          }
61  
62          synchronized (_sessionMap) {
63              _sessionMap.remove(ses.getId());
64          }
65      }
66  
67      private void _lock(String sessionId) {
68          ThreadLocal threadLocal = null;
69  
70          for (;;) {
71              synchronized (_sessionMap) {
72                  threadLocal = (ThreadLocal)_sessionMap.get(sessionId);
73  
74                  if (threadLocal == null) {
75  
76                      // Initialize reentrant counter.
77  
78                      threadLocal = new ThreadLocal();
79  
80                      threadLocal.set(new Long(0));
81  
82                      _sessionMap.put(sessionId, threadLocal);
83  
84                      break;
85                  }
86                  else if (threadLocal.get() != null) {
87  
88                      // This thread instantiated the thread local. Increment the
89                      // reentrant counter.
90  
91                      Long count = (Long)threadLocal.get();
92  
93                      threadLocal.set(new Long(count.longValue() + 1L));
94  
95                      break;
96                  }
97              }
98  
99              // Another thread instantiated the thread local. Wait until that
100             // thread is done.
101 
102             try {
103                 wait(100);
104             }
105             catch (Exception ex) {
106             }
107         }
108     }
109 
110     private void _unlock(String sessionId) {
111         ThreadLocal threadLocal = null;
112 
113         synchronized (_sessionMap) {
114             threadLocal = (ThreadLocal)_sessionMap.get(sessionId);
115 
116             // The variable can be null at this time if a method called unlock()
117             // twice or cleanUp() was called.
118 
119             if (threadLocal != null) {
120                 Long count = (Long)threadLocal.get();
121 
122                 if (count.longValue() == 0L) {
123 
124                     // All reentrant calls have completed
125 
126                     _sessionMap.remove(sessionId);
127                 }
128                 else {
129 
130                     // Finished one of the reentrant calls
131 
132                     count = new Long(count.longValue() - 1L);
133 
134                     threadLocal.set(count);
135                 }
136             }
137         }
138     }
139 
140     private static MailSessionLock _instance = new MailSessionLock();
141 
142     private Map _sessionMap = CollectionFactory.getHashMap();
143 
144 }