1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.counter.service.persistence;
21  
22  import com.liferay.counter.model.Counter;
23  import com.liferay.counter.model.CounterRegister;
24  import com.liferay.portal.SystemException;
25  import com.liferay.portal.dao.orm.hibernate.SessionImpl;
26  import com.liferay.portal.kernel.dao.jdbc.DataAccess;
27  import com.liferay.portal.kernel.dao.orm.LockMode;
28  import com.liferay.portal.kernel.dao.orm.ObjectNotFoundException;
29  import com.liferay.portal.kernel.dao.orm.Query;
30  import com.liferay.portal.kernel.dao.orm.Session;
31  import com.liferay.portal.kernel.job.IntervalJob;
32  import com.liferay.portal.kernel.job.JobSchedulerUtil;
33  import com.liferay.portal.kernel.util.GetterUtil;
34  import com.liferay.portal.kernel.util.ListUtil;
35  import com.liferay.portal.service.persistence.impl.BasePersistenceImpl;
36  import com.liferay.portal.util.PropsKeys;
37  import com.liferay.portal.util.PropsUtil;
38  
39  import java.sql.Connection;
40  
41  import java.util.ArrayList;
42  import java.util.HashMap;
43  import java.util.Iterator;
44  import java.util.List;
45  import java.util.Map;
46  
47  import org.hibernate.SessionFactory;
48  
49  /**
50   * <a href="CounterPersistence.java.html"><b><i>View Source</i></b></a>
51   *
52   * @author Brian Wing Shun Chan
53   * @author Harry Mark
54   * @author Michael Young
55   *
56   */
57  public class CounterPersistence extends BasePersistenceImpl {
58  
59      public static int getCounterIncrement() {
60          return _COUNTER_INCREMENT;
61      }
62  
63      public void afterPropertiesSet() {
64          JobSchedulerUtil.schedule(_connectionHeartbeatJob);
65      }
66  
67      public synchronized Connection getConnection() throws Exception {
68          if ((_connection == null) || _connection.isClosed()) {
69              _connection = getDataSource().getConnection();
70  
71              _connection.setAutoCommit(true);
72          }
73  
74          return _connection;
75      }
76  
77      public void destroy() {
78          JobSchedulerUtil.unschedule(_connectionHeartbeatJob);
79  
80          DataAccess.cleanUp(_connection);
81      }
82  
83      public List<String> getNames() throws SystemException {
84          Session session = null;
85  
86          try {
87              Connection connection = getConnection();
88  
89              session = new SessionImpl(_sessionFactory.openSession(connection));
90  
91              List<String> list = new ArrayList<String>();
92  
93              Query q = session.createQuery("FROM " + Counter.class.getName());
94  
95              Iterator<Counter> itr = q.iterate();
96  
97              while (itr.hasNext()) {
98                  Counter counter = itr.next();
99  
100                 list.add(counter.getName());
101             }
102 
103             return ListUtil.sort(list);
104         }
105         catch (Exception e) {
106             throw processException(e);
107         }
108         finally {
109             session.close();
110         }
111     }
112 
113     public long increment() throws SystemException {
114         return increment(_NAME);
115     }
116 
117     public long increment(String name) throws SystemException {
118         return increment(name, _MINIMUM_INCREMENT_SIZE);
119     }
120 
121     public long increment(String name, int size)
122         throws SystemException {
123 
124         if (size < _MINIMUM_INCREMENT_SIZE) {
125             size = _MINIMUM_INCREMENT_SIZE;
126         }
127 
128         CounterRegister register = getCounterRegister(name);
129 
130         synchronized (register) {
131             long newValue = register.getCurrentValue() + size;
132 
133             if (newValue > register.getRangeMax()) {
134                 Session session = null;
135 
136                 try {
137                     Connection connection = getConnection();
138 
139                     session = new SessionImpl(
140                         _sessionFactory.openSession(connection));
141 
142                     Counter counter = (Counter)session.get(
143                         Counter.class, register.getName());
144 
145                     newValue = counter.getCurrentId() + 1;
146 
147                     long rangeMax =
148                         counter.getCurrentId() + register.getRangeSize();
149 
150                     counter.setCurrentId(rangeMax);
151 
152                     session.save(counter);
153                     session.flush();
154 
155                     register.setCurrentValue(newValue);
156                     register.setRangeMax(rangeMax);
157                 }
158                 catch (Exception e) {
159                     throw processException(e);
160                 }
161                 finally {
162                     session.close();
163                 }
164             }
165             else {
166                 register.setCurrentValue(newValue);
167             }
168 
169             return newValue;
170         }
171     }
172 
173     public void rename(String oldName, String newName)
174         throws SystemException {
175 
176         CounterRegister register = getCounterRegister(oldName);
177 
178         synchronized (register) {
179             if (_registerLookup.containsKey(newName)) {
180                 throw new SystemException(
181                     "Cannot rename " + oldName + " to " + newName);
182             }
183 
184             Session session = null;
185 
186             try {
187                 Connection connection = getConnection();
188 
189                 session = new SessionImpl(
190                     _sessionFactory.openSession(connection));
191 
192                 Counter counter = (Counter)session.load(Counter.class, oldName);
193 
194                 long currentId = counter.getCurrentId();
195 
196                 session.delete(counter);
197 
198                 counter = new Counter();
199 
200                 counter.setName(newName);
201                 counter.setCurrentId(currentId);
202 
203                 session.save(counter);
204 
205                 session.flush();
206             }
207             catch (ObjectNotFoundException onfe) {
208             }
209             catch (Exception e) {
210                 throw processException(e);
211             }
212             finally {
213                 session.close();
214             }
215 
216             register.setName(newName);
217 
218             _registerLookup.put(newName, register);
219             _registerLookup.remove(oldName);
220         }
221     }
222 
223     public void reset(String name) throws SystemException {
224         CounterRegister register = getCounterRegister(name);
225 
226         synchronized (register) {
227             Session session = null;
228 
229             try {
230                 Connection connection = getConnection();
231 
232                 session = new SessionImpl(
233                     _sessionFactory.openSession(connection));
234 
235                 Counter counter = (Counter)session.load(Counter.class, name);
236 
237                 session.delete(counter);
238 
239                 session.flush();
240             }
241             catch (ObjectNotFoundException onfe) {
242             }
243             catch (Exception e) {
244                 throw processException(e);
245             }
246             finally {
247                 session.close();
248             }
249 
250             _registerLookup.remove(name);
251         }
252     }
253 
254     public void reset(String name, long size) throws SystemException {
255         CounterRegister register = createCounterRegister(name, size);
256 
257         synchronized (register) {
258             _registerLookup.put(name, register);
259         }
260     }
261 
262     public void setConnectionHeartbeatJob(IntervalJob connectionHeartbeatJob) {
263         _connectionHeartbeatJob = connectionHeartbeatJob;
264     }
265 
266     public void setSessionFactory(SessionFactory sessionFactory) {
267         _sessionFactory = sessionFactory;
268     }
269 
270     protected synchronized CounterRegister getCounterRegister(String name)
271         throws SystemException {
272 
273         CounterRegister register = _registerLookup.get(name);
274 
275         if (register == null) {
276             register = createCounterRegister(name);
277 
278             _registerLookup.put(name, register);
279         }
280 
281         return register;
282     }
283 
284     protected synchronized CounterRegister createCounterRegister(String name)
285         throws SystemException {
286 
287         return createCounterRegister(name, -1);
288     }
289 
290     protected synchronized CounterRegister createCounterRegister(
291             String name, long size)
292         throws SystemException {
293 
294         long rangeMin = 0;
295         long rangeMax = 0;
296 
297         Session session = null;
298 
299         try {
300             Connection connection = getConnection();
301 
302             session = new SessionImpl(
303                 _sessionFactory.openSession(connection));
304 
305             Counter counter = (Counter)session.get(
306                 Counter.class, name, LockMode.UPGRADE);
307 
308             if (counter == null) {
309                 rangeMin = _DEFAULT_CURRENT_ID;
310 
311                 counter = new Counter();
312 
313                 counter.setName(name);
314             }
315             else {
316                 rangeMin = counter.getCurrentId();
317             }
318 
319             if (size >= _DEFAULT_CURRENT_ID) {
320                 rangeMin = size;
321             }
322 
323             rangeMax = rangeMin + _COUNTER_INCREMENT;
324 
325             counter.setCurrentId(rangeMax);
326 
327             session.save(counter);
328             session.flush();
329         }
330         catch (Exception e) {
331             throw processException(e);
332         }
333         finally {
334             session.close();
335         }
336 
337         CounterRegister register = new CounterRegister(
338             name, rangeMin, rangeMax, _COUNTER_INCREMENT);
339 
340         return register;
341     }
342 
343     private static final int _DEFAULT_CURRENT_ID = 0;
344 
345     private static final int _MINIMUM_INCREMENT_SIZE = 1;
346 
347     private static final int _COUNTER_INCREMENT = GetterUtil.getInteger(
348         PropsUtil.get(PropsKeys.COUNTER_INCREMENT), _MINIMUM_INCREMENT_SIZE);
349 
350     private static final String _NAME = Counter.class.getName();
351 
352     private static Map<String, CounterRegister> _registerLookup =
353         new HashMap<String, CounterRegister>();
354 
355     private Connection _connection;
356     private IntervalJob _connectionHeartbeatJob;
357     private SessionFactory _sessionFactory;
358 
359 }