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 boolean allowAnonymousUser, long previousUserId)
106 throws Exception {
107
108 PreparedStatement ps = null;
109 ResultSet rs = null;
110
111 try {
112 ps = con.prepareStatement(
113 "select companyId, userId, createDate, modifiedDate from " +
114 tableName + " where " + pkColumnName + " = ?");
115
116 ps.setLong(1, primKey);
117
118 rs = ps.executeQuery();
119
120 if (rs.next()) {
121 long companyId = rs.getLong("companyId");
122
123 long userId = 0;
124 String userName = null;
125
126 if (allowAnonymousUser) {
127 userId = previousUserId;
128 userName = "Anonymous";
129 }
130 else {
131 userId = rs.getLong("userId");
132 userName = getUserName(con, userId);
133 }
134
135 Timestamp createDate = rs.getTimestamp("createDate");
136 Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
137
138 return new Object[] {
139 companyId, userId, userName, createDate, modifiedDate
140 };
141 }
142
143 if (_log.isDebugEnabled()) {
144 _log.debug("Unable to find " + tableName + " " + primKey);
145 }
146
147 return null;
148 }
149 finally {
150 DataAccess.cleanUp(ps, rs);
151 }
152 }
153
154 protected Object[] getDefaultUserArray(Connection con, long companyId)
155 throws Exception {
156
157 PreparedStatement ps = null;
158 ResultSet rs = null;
159
160 try {
161 ps = con.prepareStatement(
162 "select userId, firstName, middleName, lastName from User_" +
163 " where companyId = ? and defaultUser = ?");
164
165 ps.setLong(1, companyId);
166 ps.setBoolean(2, true);
167
168 rs = ps.executeQuery();
169
170 if (rs.next()) {
171 long userId = rs.getLong("userId");
172 String firstName = rs.getString("firstName");
173 String middleName = rs.getString("middleName");
174 String lastName = rs.getString("lastName");
175
176 FullNameGenerator fullNameGenerator =
177 FullNameGeneratorFactory.getInstance();
178
179 String userName = fullNameGenerator.getFullName(
180 firstName, middleName, lastName);
181
182 Timestamp createDate = new Timestamp(
183 System.currentTimeMillis());
184
185 return new Object[] {
186 companyId, userId, userName, createDate, createDate
187 };
188 }
189
190 return null;
191 }
192 finally {
193 DataAccess.cleanUp(ps, rs);
194 }
195 }
196
197 protected String getUserName(Connection con, long userId) throws Exception {
198 PreparedStatement ps = null;
199 ResultSet rs = null;
200
201 try {
202 ps = con.prepareStatement(
203 "select firstName, middleName, lastName from User_ where " +
204 "userId = ?");
205
206 ps.setLong(1, userId);
207
208 rs = ps.executeQuery();
209
210 if (rs.next()) {
211 String firstName = rs.getString("firstName");
212 String middleName = rs.getString("middleName");
213 String lastName = rs.getString("lastName");
214
215 FullNameGenerator fullNameGenerator =
216 FullNameGeneratorFactory.getInstance();
217
218 return fullNameGenerator.getFullName(
219 firstName, middleName, lastName);
220 }
221
222 return StringPool.BLANK;
223 }
224 finally {
225 DataAccess.cleanUp(ps, rs);
226 }
227 }
228
229 protected void verifyAuditedModel(
230 Connection con, String tableName, String primaryKeyColumnName,
231 long primKey, Object[] auditedModelArray, boolean updateDates)
232 throws Exception {
233
234 PreparedStatement ps = null;
235
236 try {
237 long companyId = (Long)auditedModelArray[0];
238
239 if (auditedModelArray[2] == null) {
240 auditedModelArray = getDefaultUserArray(con, companyId);
241
242 if (auditedModelArray == null) {
243 return;
244 }
245 }
246
247 long userId = (Long)auditedModelArray[1];
248 String userName = (String)auditedModelArray[2];
249 Timestamp createDate = (Timestamp)auditedModelArray[3];
250 Timestamp modifiedDate = (Timestamp)auditedModelArray[4];
251
252 StringBundler sb = new StringBundler(7);
253
254 sb.append("update ");
255 sb.append(tableName);
256 sb.append(" set companyId = ?, userId = ?, userName = ?");
257
258 if (updateDates) {
259 sb.append(", createDate = ?, modifiedDate = ?");
260 }
261
262 sb.append(" where ");
263 sb.append(primaryKeyColumnName);
264 sb.append(" = ?");
265
266 ps = con.prepareStatement(sb.toString());
267
268 ps.setLong(1, companyId);
269 ps.setLong(2, userId);
270 ps.setString(3, userName);
271
272 if (updateDates) {
273 ps.setTimestamp(4, createDate);
274 ps.setTimestamp(5, modifiedDate);
275 ps.setLong(6, primKey);
276 }
277 else {
278 ps.setLong(4, primKey);
279 }
280
281 ps.executeUpdate();
282 }
283 catch (Exception e) {
284 if (_log.isWarnEnabled()) {
285 _log.warn("Unable to verify model " + tableName, e);
286 }
287 }
288 finally {
289 DataAccess.cleanUp(ps);
290 }
291 }
292
293 protected void verifyAuditedModel(
294 VerifiableAuditedModel verifiableAuditedModel)
295 throws Exception {
296
297 PreparedStatement ps = null;
298 ResultSet rs = null;
299
300 try (Connection con = DataAccess.getUpgradeOptimizedConnection()) {
301 StringBundler sb = new StringBundler(8);
302
303 sb.append("select ");
304 sb.append(verifiableAuditedModel.getPrimaryKeyColumnName());
305 sb.append(", companyId, userId");
306
307 if (verifiableAuditedModel.getJoinByTableName() != null) {
308 sb.append(StringPool.COMMA_AND_SPACE);
309 sb.append(verifiableAuditedModel.getJoinByTableName());
310 }
311
312 sb.append(" from ");
313 sb.append(verifiableAuditedModel.getTableName());
314 sb.append(" where userName is null order by companyId");
315
316 ps = con.prepareStatement(sb.toString());
317
318 rs = ps.executeQuery();
319
320 Object[] auditedModelArray = null;
321
322 long previousCompanyId = 0;
323
324 while (rs.next()) {
325 long companyId = rs.getLong("companyId");
326 long primKey = rs.getLong(
327 verifiableAuditedModel.getPrimaryKeyColumnName());
328 long previousUserId = rs.getLong("userId");
329
330 if (verifiableAuditedModel.getJoinByTableName() != null) {
331 long relatedPrimKey = rs.getLong(
332 verifiableAuditedModel.getJoinByTableName());
333
334 auditedModelArray = getAuditedModelArray(
335 con, verifiableAuditedModel.getRelatedModelName(),
336 verifiableAuditedModel.getRelatedPKColumnName(),
337 relatedPrimKey,
338 verifiableAuditedModel.isAnonymousUserAllowed(),
339 previousUserId);
340 }
341 else if (previousCompanyId != companyId) {
342 auditedModelArray = getDefaultUserArray(con, companyId);
343
344 previousCompanyId = companyId;
345 }
346
347 if (auditedModelArray == null) {
348 continue;
349 }
350
351 verifyAuditedModel(
352 con, verifiableAuditedModel.getTableName(),
353 verifiableAuditedModel.getPrimaryKeyColumnName(), primKey,
354 auditedModelArray, verifiableAuditedModel.isUpdateDates());
355 }
356 }
357 finally {
358 DataAccess.cleanUp(ps, rs);
359 }
360 }
361
362 private static final Log _log = LogFactoryUtil.getLog(
363 VerifyAuditedModel.class);
364
365 private class VerifyAuditedModelRunnable extends ThrowableAwareRunnable {
366
367 public VerifyAuditedModelRunnable(
368 VerifiableAuditedModel verifiableAuditedModel) {
369
370 _verifiableAuditedModel = verifiableAuditedModel;
371 }
372
373 @Override
374 protected void doRun() throws Exception {
375 verifyAuditedModel(_verifiableAuditedModel);
376 }
377
378 private final VerifiableAuditedModel _verifiableAuditedModel;
379
380 }
381
382 }