View Javadoc
1   package net.avcompris.commons3.core.impl;
2   
3   import static com.google.common.base.Preconditions.checkNotNull;
4   
5   import java.io.IOException;
6   import java.sql.SQLException;
7   import java.util.ConcurrentModificationException;
8   
9   import javax.annotation.Nullable;
10  
11  import org.apache.commons.logging.Log;
12  import org.apache.commons.logging.LogFactory;
13  
14  import net.avcompris.commons3.api.EntitiesQuery;
15  import net.avcompris.commons3.api.exception.DaoException;
16  import net.avcompris.commons3.api.exception.IllegalStateUpdateException;
17  import net.avcompris.commons3.api.exception.ServiceException;
18  import net.avcompris.commons3.core.Permissions;
19  import net.avcompris.commons3.dao.exception.ForeignEntityViolationException;
20  import net.avcompris.commons3.utils.Clock;
21  
22  public abstract class AbstractServiceImpl {
23  
24  	protected final Permissions permissions;
25  	protected final Clock clock;
26  
27  	private static final Log logger = LogFactory.getLog(AbstractServiceImpl.class);
28  
29  	protected AbstractServiceImpl(final Permissions permissions, final Clock clock) {
30  
31  		this.permissions = checkNotNull(permissions, "permissions");
32  		this.clock = checkNotNull(clock, "clock");
33  	}
34  
35  	protected static void wrap(final ActionVoid action) throws ServiceException {
36  
37  		try {
38  
39  			action.execute();
40  
41  		} catch (final ConcurrentModificationException e) {
42  
43  			throw new IllegalStateUpdateException(e);
44  
45  		} catch (final SQLException | IOException e) {
46  
47  			throw new DaoException(e);
48  		}
49  	}
50  
51  	protected static <T> T wrap(final Action<T> action) throws ServiceException {
52  
53  		try {
54  
55  			return action.execute();
56  
57  		} catch (final ConcurrentModificationException e) {
58  
59  			throw new IllegalStateUpdateException(e);
60  
61  		} catch (final SQLException | IOException e) {
62  
63  			throw new DaoException(e);
64  		}
65  	}
66  
67  	protected static void unchecked(final ActionVoid action) {
68  
69  		try {
70  
71  			action.execute();
72  
73  		} catch (final ServiceException e) {
74  
75  			throw new RuntimeException(e);
76  
77  		} catch (final SQLException | IOException e) {
78  
79  			throw new RuntimeException(e);
80  		}
81  	}
82  
83  	@FunctionalInterface
84  	protected interface ActionVoid {
85  
86  		void execute() throws SQLException, IOException, ServiceException;
87  	}
88  
89  	@FunctionalInterface
90  	protected interface Action<T> {
91  
92  		T execute() throws SQLException, IOException, ServiceException;
93  	}
94  
95  	@FunctionalInterface
96  	protected interface ServiceAction<T> {
97  
98  		T execute() throws ServiceException;
99  	}
100 
101 	protected final int getQueryStart(@Nullable final EntitiesQuery<?, ?> query, final int defaultValue) {
102 
103 		final Integer start = (query == null) ? null : query.getStart();
104 
105 		return (start != null) ? start : defaultValue;
106 	}
107 
108 	protected final int getQueryLimit(@Nullable final EntitiesQuery<?, ?> query, final int defaultValue) {
109 
110 		final Integer limit = (query == null) ? null : query.getLimit();
111 
112 		return (limit != null) ? limit : defaultValue;
113 	}
114 
115 	@FunctionalInterface
116 	protected interface DaoAction<T> {
117 
118 		T action() throws SQLException, IOException, ServiceException;
119 	}
120 
121 	@FunctionalInterface
122 	protected interface DaoActionWithForeignEntity<T> {
123 
124 		T action() throws SQLException, IOException, ForeignEntityViolationException;
125 	}
126 
127 	protected static <T> T retryDaoUntil(final long timeoutMs, final long delayMs, final DaoAction<T> action)
128 			throws SQLException, IOException, ServiceException {
129 
130 		return retryDaoUntil(timeoutMs, delayMs, true, action);
131 	}
132 
133 	protected static <T> T retryDaoWithForeignEntityUntil(final long timeoutMs, final long delayMs,
134 			final DaoActionWithForeignEntity<T> action)
135 			throws SQLException, IOException, ForeignEntityViolationException {
136 
137 		return retryDaoWithForeignEntityUntil(timeoutMs, delayMs, true, action);
138 	}
139 
140 	protected static <T> T retryDaoUntil(final long timeoutMs, final long delayMs,
141 			final boolean throwExceptionInCaseOfTimeout, final DaoAction<T> action)
142 			throws SQLException, IOException, ServiceException {
143 
144 		checkNotNull(action, "action");
145 
146 		for (final long startMs = System.currentTimeMillis(); System.currentTimeMillis() < startMs + timeoutMs;) {
147 
148 			T result = null;
149 
150 			try {
151 
152 				result = action.action();
153 
154 			} catch (final SQLException | IOException | RuntimeException | Error e) {
155 
156 				throw e;
157 
158 			} catch (final Exception e) {
159 
160 				throw new RuntimeException(e);
161 			}
162 
163 			if (result != null) {
164 
165 				return result;
166 			}
167 
168 			try {
169 
170 				Thread.sleep(delayMs);
171 
172 			} catch (final InterruptedException e) {
173 
174 				e.printStackTrace();
175 
176 				// do nothing
177 			}
178 		}
179 
180 		logger.error("A timeout occurs (" + timeoutMs + " ms)");
181 
182 		if (throwExceptionInCaseOfTimeout) {
183 
184 			throw new RuntimeException("Timeout after: " + timeoutMs + " ms");
185 
186 		} else {
187 
188 			return null;
189 		}
190 	}
191 
192 	protected static <T> T retryDaoWithForeignEntityUntil(final long timeoutMs, final long delayMs,
193 			final boolean throwExceptionInCaseOfTimeout, final DaoActionWithForeignEntity<T> action)
194 			throws SQLException, IOException, ForeignEntityViolationException {
195 
196 		checkNotNull(action, "action");
197 
198 		for (final long startMs = System.currentTimeMillis(); System.currentTimeMillis() < startMs + timeoutMs;) {
199 
200 			T result = null;
201 
202 			try {
203 
204 				result = action.action();
205 
206 			} catch (final SQLException | IOException | RuntimeException | ForeignEntityViolationException | Error e) {
207 
208 				throw e;
209 
210 			} catch (final Exception e) {
211 
212 				throw new RuntimeException(e);
213 			}
214 
215 			if (result != null) {
216 
217 				return result;
218 			}
219 
220 			try {
221 
222 				Thread.sleep(delayMs);
223 
224 			} catch (final InterruptedException e) {
225 
226 				e.printStackTrace();
227 
228 				// do nothing
229 			}
230 		}
231 
232 		logger.error("A timeout occurs (" + timeoutMs + " ms)");
233 
234 		if (throwExceptionInCaseOfTimeout) {
235 
236 			throw new RuntimeException("Timeout after: " + timeoutMs + " ms");
237 
238 		} else {
239 
240 			return null;
241 		}
242 	}
243 }