001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.verify;
016    
017    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
018    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.StringBundler;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.security.auth.FullNameGenerator;
024    import com.liferay.portal.security.auth.FullNameGeneratorFactory;
025    import com.liferay.portal.verify.model.VerifiableAuditedModel;
026    
027    import java.sql.Connection;
028    import java.sql.PreparedStatement;
029    import java.sql.ResultSet;
030    import java.sql.Timestamp;
031    
032    import java.util.ArrayList;
033    import java.util.Collection;
034    import java.util.List;
035    import java.util.Map;
036    
037    /**
038     * @author Michael C. Han
039     * @author Shinn Lok
040     */
041    public class VerifyAuditedModel extends VerifyProcess {
042    
043            public void verify(VerifiableAuditedModel ... verifiableAuditedModels)
044                    throws Exception {
045    
046                    List<String> unverifiedTableNames = new ArrayList<String>();
047    
048                    for (VerifiableAuditedModel verifiableAuditedModel :
049                                    verifiableAuditedModels) {
050    
051                            unverifiedTableNames.add(verifiableAuditedModel.getTableName());
052                    }
053    
054                    while (!unverifiedTableNames.isEmpty()) {
055                            int count = unverifiedTableNames.size();
056    
057                            for (VerifiableAuditedModel verifiableAuditedModel :
058                                            verifiableAuditedModels) {
059    
060                                    if (unverifiedTableNames.contains(
061                                                    verifiableAuditedModel.getJoinByTableName()) ||
062                                            !unverifiedTableNames.contains(
063                                                    verifiableAuditedModel.getTableName())) {
064    
065                                            continue;
066                                    }
067    
068                                    verifyAuditedModel(verifiableAuditedModel);
069    
070                                    unverifiedTableNames.remove(
071                                            verifiableAuditedModel.getTableName());
072                            }
073    
074                            if (unverifiedTableNames.size() == count) {
075                                    throw new VerifyException(
076                                            "Circular dependency detected " + unverifiedTableNames);
077                            }
078                    }
079            }
080    
081            @Override
082            protected void doVerify() throws Exception {
083                    Map<String, VerifiableAuditedModel> verifiableAuditedModelsMap =
084                            PortalBeanLocatorUtil.locate(VerifiableAuditedModel.class);
085    
086                    Collection<VerifiableAuditedModel> verifiableAuditedModels =
087                            verifiableAuditedModelsMap.values();
088    
089                    verify(
090                            verifiableAuditedModels.toArray(
091                                    new VerifiableAuditedModel[verifiableAuditedModels.size()]));
092            }
093    
094            protected Object[] getAuditedModelArray(
095                            String tableName, String pkColumnName, long primKey)
096                    throws Exception {
097    
098                    Connection con = null;
099                    PreparedStatement ps = null;
100                    ResultSet rs = null;
101    
102                    try {
103                            con = DataAccess.getUpgradeOptimizedConnection();
104    
105                            ps = con.prepareStatement(
106                                    "select companyId, userId, createDate, modifiedDate from " +
107                                            tableName + " where " + pkColumnName + " = ?");
108    
109                            ps.setLong(1, primKey);
110    
111                            rs = ps.executeQuery();
112    
113                            if (rs.next()) {
114                                    long companyId = rs.getLong("companyId");
115                                    long userId = rs.getLong("userId");
116                                    Timestamp createDate = rs.getTimestamp("createDate");
117                                    Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
118    
119                                    return new Object[] {
120                                            companyId, userId, getUserName(userId), createDate,
121                                            modifiedDate
122                                    };
123                            }
124    
125                            if (_log.isDebugEnabled()) {
126                                    _log.debug("Unable to find " + tableName + " " + primKey);
127                            }
128    
129                            return null;
130                    }
131                    finally {
132                            DataAccess.cleanUp(con, ps, rs);
133                    }
134            }
135    
136            protected Object[] getDefaultUserArray(Connection con, long companyId)
137                    throws Exception {
138    
139                    PreparedStatement ps = null;
140                    ResultSet rs = null;
141    
142                    try {
143                            ps = con.prepareStatement(
144                                    "select userId, firstName, middleName, lastName from User_" +
145                                            " where companyId = ? and defaultUser = ?");
146    
147                            ps.setLong(1, companyId);
148                            ps.setBoolean(2, true);
149    
150                            rs = ps.executeQuery();
151    
152                            if (rs.next()) {
153                                    long userId = rs.getLong("userId");
154                                    String firstName = rs.getString("firstName");
155                                    String middleName = rs.getString("middleName");
156                                    String lastName = rs.getString("lastName");
157    
158                                    FullNameGenerator fullNameGenerator =
159                                            FullNameGeneratorFactory.getInstance();
160    
161                                    String userName = fullNameGenerator.getFullName(
162                                            firstName, middleName, lastName);
163    
164                                    Timestamp createDate = new Timestamp(
165                                            System.currentTimeMillis());
166    
167                                    return new Object[] {
168                                            companyId, userId, userName, createDate, createDate
169                                    };
170                            }
171    
172                            return null;
173                    }
174                    finally {
175                            DataAccess.cleanUp(null, ps, rs);
176                    }
177            }
178    
179            protected String getUserName(long userId) throws Exception {
180                    Connection con = null;
181                    PreparedStatement ps = null;
182                    ResultSet rs = null;
183    
184                    try {
185                            con = DataAccess.getUpgradeOptimizedConnection();
186    
187                            ps = con.prepareStatement(
188                                    "select firstName, middleName, lastName from User_ where " +
189                                            "userId = ?");
190    
191                            ps.setLong(1, userId);
192    
193                            rs = ps.executeQuery();
194    
195                            if (rs.next()) {
196                                    String firstName = rs.getString("firstName");
197                                    String middleName = rs.getString("middleName");
198                                    String lastName = rs.getString("lastName");
199    
200                                    FullNameGenerator fullNameGenerator =
201                                            FullNameGeneratorFactory.getInstance();
202    
203                                    return fullNameGenerator.getFullName(
204                                            firstName, middleName, lastName);
205                            }
206    
207                            return StringPool.BLANK;
208                    }
209                    finally {
210                            DataAccess.cleanUp(con, ps, rs);
211                    }
212            }
213    
214            protected void verifyAuditedModel(
215                            String tableName, String primaryKeyColumnName, long primKey,
216                            Object[] auditedModelArray, boolean updateDates)
217                    throws Exception {
218    
219                    Connection con = null;
220                    PreparedStatement ps = null;
221    
222                    try {
223                            con = DataAccess.getUpgradeOptimizedConnection();
224    
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(con, ps);
278                    }
279            }
280    
281            protected void verifyAuditedModel(
282                            VerifiableAuditedModel verifiableAuditedModel)
283                    throws Exception {
284    
285                    Connection con = null;
286                    PreparedStatement ps = null;
287                    ResultSet rs = null;
288    
289                    try {
290                            con = DataAccess.getUpgradeOptimizedConnection();
291    
292                            StringBundler sb = new StringBundler(8);
293    
294                            sb.append("select ");
295                            sb.append(verifiableAuditedModel.getPrimaryKeyColumnName());
296                            sb.append(", companyId");
297    
298                            if (verifiableAuditedModel.getJoinByTableName() != null) {
299                                    sb.append(StringPool.COMMA_AND_SPACE);
300                                    sb.append(verifiableAuditedModel.getJoinByTableName());
301                            }
302    
303                            sb.append(" from ");
304                            sb.append(verifiableAuditedModel.getTableName());
305                            sb.append(" where userName is null order by companyId");
306    
307                            ps = con.prepareStatement(sb.toString());
308    
309                            rs = ps.executeQuery();
310    
311                            Object[] auditedModelArray = null;
312    
313                            long previousCompanyId = 0;
314    
315                            while (rs.next()) {
316                                    long companyId = rs.getLong("companyId");
317                                    long primKey = rs.getLong(
318                                            verifiableAuditedModel.getPrimaryKeyColumnName());
319    
320                                    if (verifiableAuditedModel.getJoinByTableName() != null) {
321                                            long relatedPrimKey = rs.getLong(
322                                                    verifiableAuditedModel.getJoinByTableName());
323    
324                                            auditedModelArray = getAuditedModelArray(
325                                                    verifiableAuditedModel.getRelatedModelName(),
326                                                    verifiableAuditedModel.getRelatedPKColumnName(),
327                                                    relatedPrimKey);
328                                    }
329                                    else if (previousCompanyId != companyId) {
330                                            auditedModelArray = getDefaultUserArray(con, companyId);
331    
332                                            previousCompanyId = companyId;
333                                    }
334    
335                                    if (auditedModelArray == null) {
336                                            continue;
337                                    }
338    
339                                    verifyAuditedModel(
340                                            verifiableAuditedModel.getTableName(),
341                                            verifiableAuditedModel.getPrimaryKeyColumnName(), primKey,
342                                            auditedModelArray, verifiableAuditedModel.isUpdateDates());
343                            }
344                    }
345                    finally {
346                            DataAccess.cleanUp(con, ps, rs);
347                    }
348            }
349    
350            private static final Log _log = LogFactoryUtil.getLog(
351                    VerifyAuditedModel.class);
352    
353    }