001
014
015 package com.liferay.portal.verify;
016
017 import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
018 import com.liferay.portal.kernel.concurrent.ThrowableAwareRunnable;
019 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.util.StringBundler;
023 import com.liferay.portal.kernel.util.StringPool;
024 import com.liferay.portal.security.auth.FullNameGenerator;
025 import com.liferay.portal.security.auth.FullNameGeneratorFactory;
026 import com.liferay.portal.verify.model.VerifiableAuditedModel;
027
028 import java.sql.Connection;
029 import java.sql.PreparedStatement;
030 import java.sql.ResultSet;
031 import java.sql.Timestamp;
032
033 import java.util.ArrayList;
034 import java.util.Collection;
035 import java.util.List;
036 import java.util.Map;
037
038
042 public class VerifyAuditedModel extends VerifyProcess {
043
044 public void verify(VerifiableAuditedModel ... verifiableAuditedModels)
045 throws Exception {
046
047 List<String> unverifiedTableNames = new ArrayList<>();
048
049 for (VerifiableAuditedModel verifiableAuditedModel :
050 verifiableAuditedModels) {
051
052 unverifiedTableNames.add(verifiableAuditedModel.getTableName());
053 }
054
055 List<VerifyAuditedModelRunnable> verifyAuditedModelRunnables =
056 new ArrayList<>(unverifiedTableNames.size());
057
058 while (!unverifiedTableNames.isEmpty()) {
059 int count = unverifiedTableNames.size();
060
061 for (VerifiableAuditedModel verifiableAuditedModel :
062 verifiableAuditedModels) {
063
064 if (unverifiedTableNames.contains(
065 verifiableAuditedModel.getJoinByTableName()) ||
066 !unverifiedTableNames.contains(
067 verifiableAuditedModel.getTableName())) {
068
069 continue;
070 }
071
072 VerifyAuditedModelRunnable verifyAuditedModelRunnable =
073 new VerifyAuditedModelRunnable(verifiableAuditedModel);
074
075 verifyAuditedModelRunnables.add(verifyAuditedModelRunnable);
076
077 unverifiedTableNames.remove(
078 verifiableAuditedModel.getTableName());
079 }
080
081 if (unverifiedTableNames.size() == count) {
082 throw new VerifyException(
083 "Circular dependency detected " + unverifiedTableNames);
084 }
085 }
086
087 doVerify(verifyAuditedModelRunnables);
088 }
089
090 @Override
091 protected void doVerify() throws Exception {
092 Map<String, VerifiableAuditedModel> verifiableAuditedModelsMap =
093 PortalBeanLocatorUtil.locate(VerifiableAuditedModel.class);
094
095 Collection<VerifiableAuditedModel> verifiableAuditedModels =
096 verifiableAuditedModelsMap.values();
097
098 verify(
099 verifiableAuditedModels.toArray(
100 new VerifiableAuditedModel[verifiableAuditedModels.size()]));
101 }
102
103 protected Object[] getAuditedModelArray(
104 Connection con, String tableName, String pkColumnName, long primKey)
105 throws Exception {
106
107 PreparedStatement ps = null;
108 ResultSet rs = null;
109
110 try {
111 ps = con.prepareStatement(
112 "select companyId, userId, createDate, modifiedDate from " +
113 tableName + " where " + pkColumnName + " = ?");
114
115 ps.setLong(1, primKey);
116
117 rs = ps.executeQuery();
118
119 if (rs.next()) {
120 long companyId = rs.getLong("companyId");
121 long userId = rs.getLong("userId");
122 Timestamp createDate = rs.getTimestamp("createDate");
123 Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
124
125 return new Object[] {
126 companyId, userId, getUserName(con, userId), createDate,
127 modifiedDate
128 };
129 }
130
131 if (_log.isDebugEnabled()) {
132 _log.debug("Unable to find " + tableName + " " + primKey);
133 }
134
135 return null;
136 }
137 finally {
138 DataAccess.cleanUp(null, ps, rs);
139 }
140 }
141
142 protected Object[] getDefaultUserArray(Connection con, long companyId)
143 throws Exception {
144
145 PreparedStatement ps = null;
146 ResultSet rs = null;
147
148 try {
149 ps = con.prepareStatement(
150 "select userId, firstName, middleName, lastName from User_" +
151 " where companyId = ? and defaultUser = ?");
152
153 ps.setLong(1, companyId);
154 ps.setBoolean(2, true);
155
156 rs = ps.executeQuery();
157
158 if (rs.next()) {
159 long userId = rs.getLong("userId");
160 String firstName = rs.getString("firstName");
161 String middleName = rs.getString("middleName");
162 String lastName = rs.getString("lastName");
163
164 FullNameGenerator fullNameGenerator =
165 FullNameGeneratorFactory.getInstance();
166
167 String userName = fullNameGenerator.getFullName(
168 firstName, middleName, lastName);
169
170 Timestamp createDate = new Timestamp(
171 System.currentTimeMillis());
172
173 return new Object[] {
174 companyId, userId, userName, createDate, createDate
175 };
176 }
177
178 return null;
179 }
180 finally {
181 DataAccess.cleanUp(null, ps, rs);
182 }
183 }
184
185 protected String getUserName(Connection con, long userId) throws Exception {
186 PreparedStatement ps = null;
187 ResultSet rs = null;
188
189 try {
190 ps = con.prepareStatement(
191 "select firstName, middleName, lastName from User_ where " +
192 "userId = ?");
193
194 ps.setLong(1, userId);
195
196 rs = ps.executeQuery();
197
198 if (rs.next()) {
199 String firstName = rs.getString("firstName");
200 String middleName = rs.getString("middleName");
201 String lastName = rs.getString("lastName");
202
203 FullNameGenerator fullNameGenerator =
204 FullNameGeneratorFactory.getInstance();
205
206 return fullNameGenerator.getFullName(
207 firstName, middleName, lastName);
208 }
209
210 return StringPool.BLANK;
211 }
212 finally {
213 DataAccess.cleanUp(null, ps, rs);
214 }
215 }
216
217 protected void verifyAuditedModel(
218 Connection con, String tableName, String primaryKeyColumnName,
219 long primKey, Object[] auditedModelArray, boolean updateDates)
220 throws Exception {
221
222 PreparedStatement ps = null;
223
224 try {
225 long companyId = (Long)auditedModelArray[0];
226
227 if (auditedModelArray[2] == null) {
228 auditedModelArray = getDefaultUserArray(con, companyId);
229
230 if (auditedModelArray == null) {
231 return;
232 }
233 }
234
235 long userId = (Long)auditedModelArray[1];
236 String userName = (String)auditedModelArray[2];
237 Timestamp createDate = (Timestamp)auditedModelArray[3];
238 Timestamp modifiedDate = (Timestamp)auditedModelArray[4];
239
240 StringBundler sb = new StringBundler(7);
241
242 sb.append("update ");
243 sb.append(tableName);
244 sb.append(" set companyId = ?, userId = ?, userName = ?");
245
246 if (updateDates) {
247 sb.append(", createDate = ?, modifiedDate = ?");
248 }
249
250 sb.append(" where ");
251 sb.append(primaryKeyColumnName);
252 sb.append(" = ?");
253
254 ps = con.prepareStatement(sb.toString());
255
256 ps.setLong(1, companyId);
257 ps.setLong(2, userId);
258 ps.setString(3, userName);
259
260 if (updateDates) {
261 ps.setTimestamp(4, createDate);
262 ps.setTimestamp(5, modifiedDate);
263 ps.setLong(6, primKey);
264 }
265 else {
266 ps.setLong(4, primKey);
267 }
268
269 ps.executeUpdate();
270 }
271 catch (Exception e) {
272 if (_log.isWarnEnabled()) {
273 _log.warn("Unable to verify model " + tableName, e);
274 }
275 }
276 finally {
277 DataAccess.cleanUp(ps);
278 }
279 }
280
281 protected void verifyAuditedModel(
282 VerifiableAuditedModel verifiableAuditedModel)
283 throws Exception {
284
285 PreparedStatement ps = null;
286 ResultSet rs = null;
287
288 try (Connection con = DataAccess.getUpgradeOptimizedConnection()) {
289 StringBundler sb = new StringBundler(8);
290
291 sb.append("select ");
292 sb.append(verifiableAuditedModel.getPrimaryKeyColumnName());
293 sb.append(", companyId");
294
295 if (verifiableAuditedModel.getJoinByTableName() != null) {
296 sb.append(StringPool.COMMA_AND_SPACE);
297 sb.append(verifiableAuditedModel.getJoinByTableName());
298 }
299
300 sb.append(" from ");
301 sb.append(verifiableAuditedModel.getTableName());
302 sb.append(" where userName is null order by companyId");
303
304 ps = con.prepareStatement(sb.toString());
305
306 rs = ps.executeQuery();
307
308 Object[] auditedModelArray = null;
309
310 long previousCompanyId = 0;
311
312 while (rs.next()) {
313 long companyId = rs.getLong("companyId");
314 long primKey = rs.getLong(
315 verifiableAuditedModel.getPrimaryKeyColumnName());
316
317 if (verifiableAuditedModel.getJoinByTableName() != null) {
318 long relatedPrimKey = rs.getLong(
319 verifiableAuditedModel.getJoinByTableName());
320
321 auditedModelArray = getAuditedModelArray(
322 con, verifiableAuditedModel.getRelatedModelName(),
323 verifiableAuditedModel.getRelatedPKColumnName(),
324 relatedPrimKey);
325 }
326 else if (previousCompanyId != companyId) {
327 auditedModelArray = getDefaultUserArray(con, companyId);
328
329 previousCompanyId = companyId;
330 }
331
332 if (auditedModelArray == null) {
333 continue;
334 }
335
336 verifyAuditedModel(
337 con, verifiableAuditedModel.getTableName(),
338 verifiableAuditedModel.getPrimaryKeyColumnName(), primKey,
339 auditedModelArray, verifiableAuditedModel.isUpdateDates());
340 }
341 }
342 finally {
343 DataAccess.cleanUp(null, ps, rs);
344 }
345 }
346
347 private static final Log _log = LogFactoryUtil.getLog(
348 VerifyAuditedModel.class);
349
350 private class VerifyAuditedModelRunnable extends ThrowableAwareRunnable {
351
352 public VerifyAuditedModelRunnable(
353 VerifiableAuditedModel verifiableAuditedModel) {
354
355 _verifiableAuditedModel = verifiableAuditedModel;
356 }
357
358 @Override
359 protected void doRun() throws Exception {
360 verifyAuditedModel(_verifiableAuditedModel);
361 }
362
363 private final VerifiableAuditedModel _verifiableAuditedModel;
364
365 }
366
367 }