1   /**
2    * Copyright (c) 2000-2008 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.counter.service.persistence;
24  
25  import com.liferay.counter.model.Counter;
26  import com.liferay.counter.model.CounterRegister;
27  import com.liferay.portal.SystemException;
28  import com.liferay.portal.dao.orm.hibernate.SessionImpl;
29  import com.liferay.portal.kernel.dao.jdbc.DataAccess;
30  import com.liferay.portal.kernel.dao.orm.LockMode;
31  import com.liferay.portal.kernel.dao.orm.ObjectNotFoundException;
32  import com.liferay.portal.kernel.dao.orm.Query;
33  import com.liferay.portal.kernel.dao.orm.Session;
34  import com.liferay.portal.kernel.util.GetterUtil;
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  import java.sql.SQLException;
41  
42  import java.util.ArrayList;
43  import java.util.Collections;
44  import java.util.HashMap;
45  import java.util.Iterator;
46  import java.util.List;
47  import java.util.Map;
48  
49  import org.hibernate.SessionFactory;
50  
51  /**
52   * <a href="CounterPersistence.java.html"><b><i>View Source</i></b></a>
53   *
54   * @author Brian Wing Shun Chan
55   * @author Harry Mark
56   * @author Michael Young
57   *
58   */
59  public class CounterPersistence extends BasePersistenceImpl {
60  
61      public void afterPropertiesSet() throws SQLException {
62          _connection = getDataSource().getConnection();
63  
64          _connection.setAutoCommit(true);
65      }
66  
67      public void destroy() {
68          DataAccess.cleanUp(_connection);
69      }
70  
71      public List<String> getNames() throws SystemException {
72          Session session = null;
73  
74          try {
75              session = new SessionImpl(_sessionFactory.openSession(_connection));
76  
77              List<String> list = new ArrayList<String>();
78  
79              Query q = session.createQuery("FROM " + Counter.class.getName());
80  
81              Iterator<Counter> itr = q.iterate();
82  
83              while (itr.hasNext()) {
84                  Counter counter = itr.next();
85  
86                  list.add(counter.getName());
87              }
88  
89              Collections.sort(list);
90  
91              return list;
92          }
93          catch (Exception e) {
94              throw processException(e);
95          }
96          finally {
97              session.close();
98          }
99      }
100 
101     public long increment() throws SystemException {
102         return increment(_NAME);
103     }
104 
105     public long increment(String name) throws SystemException {
106         return increment(name, _MINIMUM_INCREMENT_SIZE);
107     }
108 
109     public long increment(String name, int size)
110         throws SystemException {
111 
112         if (size < _MINIMUM_INCREMENT_SIZE) {
113             size = _MINIMUM_INCREMENT_SIZE;
114         }
115 
116         CounterRegister register = getCounterRegister(name);
117 
118         synchronized (register) {
119             long newValue = register.getCurrentValue() + size;
120 
121             if (newValue > register.getRangeMax()) {
122                 Session session = null;
123 
124                 try {
125                     session = new SessionImpl(
126                         _sessionFactory.openSession(_connection));
127 
128                     Counter counter = (Counter)session.get(
129                         Counter.class, register.getName());
130 
131                     newValue = counter.getCurrentId() + 1;
132 
133                     long rangeMax =
134                         counter.getCurrentId() + register.getRangeSize();
135 
136                     counter.setCurrentId(rangeMax);
137 
138                     session.save(counter);
139                     session.flush();
140 
141                     register.setCurrentValue(newValue);
142                     register.setRangeMax(rangeMax);
143                 }
144                 catch (Exception e) {
145                     throw processException(e);
146                 }
147                 finally {
148                     session.close();
149                 }
150             }
151             else {
152                 register.setCurrentValue(newValue);
153             }
154 
155             return newValue;
156         }
157     }
158 
159     public void rename(String oldName, String newName)
160         throws SystemException {
161 
162         CounterRegister register = getCounterRegister(oldName);
163 
164         synchronized (register) {
165             if (_registerLookup.containsKey(newName)) {
166                 throw new SystemException(
167                     "Cannot rename " + oldName + " to " + newName);
168             }
169 
170             Session session = null;
171 
172             try {
173                 session = new SessionImpl(
174                     _sessionFactory.openSession(_connection));
175 
176                 Counter counter = (Counter)session.load(Counter.class, oldName);
177 
178                 long currentId = counter.getCurrentId();
179 
180                 session.delete(counter);
181 
182                 counter = new Counter();
183 
184                 counter.setName(newName);
185                 counter.setCurrentId(currentId);
186 
187                 session.save(counter);
188 
189                 session.flush();
190             }
191             catch (ObjectNotFoundException onfe) {
192             }
193             catch (Exception e) {
194                 throw processException(e);
195             }
196             finally {
197                 session.close();
198             }
199 
200             register.setName(newName);
201 
202             _registerLookup.put(newName, register);
203             _registerLookup.remove(oldName);
204         }
205     }
206 
207     public void reset(String name) throws SystemException {
208         CounterRegister register = getCounterRegister(name);
209 
210         synchronized (register) {
211             Session session = null;
212 
213             try {
214                 session = new SessionImpl(
215                     _sessionFactory.openSession(_connection));
216 
217                 Counter counter = (Counter)session.load(Counter.class, name);
218 
219                 session.delete(counter);
220 
221                 session.flush();
222             }
223             catch (ObjectNotFoundException onfe) {
224             }
225             catch (Exception e) {
226                 throw processException(e);
227             }
228             finally {
229                 session.close();
230             }
231 
232             _registerLookup.remove(name);
233         }
234     }
235 
236     public void reset(String name, long size) {
237         CounterRegister register = createCounterRegister(name, size);
238 
239         synchronized (register) {
240             _registerLookup.put(name, register);
241         }
242     }
243 
244     public void setSessionFactory(SessionFactory sessionFactory) {
245         _sessionFactory = sessionFactory;
246     }
247 
248     protected synchronized CounterRegister getCounterRegister(String name) {
249         CounterRegister register = _registerLookup.get(name);
250 
251         if (register == null) {
252             register = createCounterRegister(name);
253 
254             _registerLookup.put(name, register);
255         }
256 
257         return register;
258     }
259 
260     protected synchronized CounterRegister createCounterRegister(String name) {
261         return createCounterRegister(name, -1);
262     }
263 
264     protected synchronized CounterRegister createCounterRegister(
265         String name, long size) {
266 
267         long rangeMin = 0;
268         long rangeMax = 0;
269 
270         Session session = null;
271 
272         try {
273             session = new SessionImpl(_sessionFactory.openSession(_connection));
274 
275             Counter counter = (Counter)session.get(
276                 Counter.class, name, LockMode.UPGRADE);
277 
278             if (counter == null) {
279                 rangeMin = _DEFAULT_CURRENT_ID;
280 
281                 counter = new Counter();
282 
283                 counter.setName(name);
284             }
285             else {
286                 rangeMin = counter.getCurrentId();
287             }
288 
289             if (size >= _DEFAULT_CURRENT_ID) {
290                 rangeMin = size;
291             }
292 
293             rangeMax = rangeMin + _COUNTER_INCREMENT;
294 
295             counter.setCurrentId(rangeMax);
296 
297             session.save(counter);
298             session.flush();
299         }
300         finally {
301             session.close();
302         }
303 
304         CounterRegister register = new CounterRegister(
305             name, rangeMin, rangeMax, _COUNTER_INCREMENT);
306 
307         return register;
308     }
309 
310     private static final int _DEFAULT_CURRENT_ID = 0;
311 
312     private static final int _MINIMUM_INCREMENT_SIZE = 1;
313 
314     private static final int _COUNTER_INCREMENT = GetterUtil.getInteger(
315         PropsUtil.get(PropsKeys.COUNTER_INCREMENT), _MINIMUM_INCREMENT_SIZE);
316 
317     private static final String _NAME = Counter.class.getName();
318 
319     private static Map<String, CounterRegister> _registerLookup =
320         new HashMap<String, CounterRegister>();
321 
322     private Connection _connection;
323     private SessionFactory _sessionFactory;
324 
325 }