001    /**
002     * Copyright (c) 2000-2013 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.concurrent.ThrowableAwareRunnable;
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.GetterUtil;
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    
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.List;
034    
035    /**
036     * @author Michael C. Han
037     * @author Shinn Lok
038     */
039    public class VerifyAuditedModel extends VerifyProcess {
040    
041            @Override
042            protected void doVerify() throws Exception {
043                    List<String> pendingModels = new ArrayList<String>();
044    
045                    for (String[] model : _MODELS) {
046                            pendingModels.add(model[0]);
047                    }
048    
049                    List<VerifyAuditedModelRunnable> verifyAuditedModelRunnables =
050                            new ArrayList<VerifyAuditedModelRunnable>(_MODELS.length);
051    
052                    while (!pendingModels.isEmpty()) {
053                            int count = pendingModels.size();
054    
055                            for (String[] model : _MODELS) {
056                                    if (pendingModels.contains(model[3]) ||
057                                            !pendingModels.contains(model[0])) {
058    
059                                            continue;
060                                    }
061    
062                                    VerifyAuditedModelRunnable verifyAuditedModelRunnable =
063                                            new VerifyAuditedModelRunnable(
064                                                    model[0], model[1], model[2], model[3], model[4],
065                                                    GetterUtil.getBoolean(model[5]));
066    
067                                    verifyAuditedModelRunnables.add(verifyAuditedModelRunnable);
068    
069                                    pendingModels.remove(model[0]);
070                            }
071    
072                            if (pendingModels.size() == count) {
073                                    throw new VerifyException(
074                                            "Circular dependency detected " + pendingModels);
075                            }
076                    }
077    
078                    doVerify(verifyAuditedModelRunnables);
079            }
080    
081            protected Object[] getDefaultUserArray(Connection con, long companyId)
082                    throws Exception {
083    
084                    PreparedStatement ps = null;
085                    ResultSet rs = null;
086    
087                    try {
088                            ps = con.prepareStatement(
089                                    "select userId, firstName, middleName, lastName from User_" +
090                                            " where companyId = ? and defaultUser = ?");
091    
092                            ps.setLong(1, companyId);
093                            ps.setBoolean(2, true);
094    
095                            rs = ps.executeQuery();
096    
097                            if (rs.next()) {
098                                    long userId = rs.getLong("userId");
099                                    String firstName = rs.getString("firstName");
100                                    String middleName = rs.getString("middleName");
101                                    String lastName = rs.getString("lastName");
102    
103                                    FullNameGenerator fullNameGenerator =
104                                            FullNameGeneratorFactory.getInstance();
105    
106                                    String userName = fullNameGenerator.getFullName(
107                                            firstName, middleName, lastName);
108    
109                                    Timestamp createDate = new Timestamp(
110                                            System.currentTimeMillis());
111    
112                                    return new Object[] {
113                                            companyId, userId, userName, createDate, createDate
114                                    };
115                            }
116    
117                            return null;
118                    }
119                    finally {
120                            DataAccess.cleanUp(null, ps, rs);
121                    }
122            }
123    
124            protected Object[] getModelArray(
125                            String modelName, String pkColumnName, long primKey)
126                    throws Exception {
127    
128                    Connection con = null;
129                    PreparedStatement ps = null;
130                    ResultSet rs = null;
131    
132                    try {
133                            con = DataAccess.getUpgradeOptimizedConnection();
134    
135                            ps = con.prepareStatement(
136                                    "select companyId, userId, createDate, modifiedDate from " +
137                                            modelName + " where " + pkColumnName + " = ?");
138    
139                            ps.setLong(1, primKey);
140    
141                            rs = ps.executeQuery();
142    
143                            if (rs.next()) {
144                                    long companyId = rs.getLong("companyId");
145                                    long userId = rs.getLong("userId");
146                                    Timestamp createDate = rs.getTimestamp("createDate");
147                                    Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
148    
149                                    return new Object[] {
150                                            companyId, userId, getUserName(userId), createDate,
151                                            modifiedDate
152                                    };
153                            }
154    
155                            if (_log.isDebugEnabled()) {
156                                    _log.debug(
157                                            "Unable to find " + modelName + StringPool.SPACE + primKey);
158                            }
159    
160                            return null;
161                    }
162                    finally {
163                            DataAccess.cleanUp(con, ps, rs);
164                    }
165            }
166    
167            protected String getUserName(long userId) throws Exception {
168                    Connection con = null;
169                    PreparedStatement ps = null;
170                    ResultSet rs = null;
171    
172                    try {
173                            con = DataAccess.getUpgradeOptimizedConnection();
174    
175                            ps = con.prepareStatement(
176                                    "select firstName, middleName, lastName from User_ where " +
177                                            "userId = ?");
178    
179                            ps.setLong(1, userId);
180    
181                            rs = ps.executeQuery();
182    
183                            if (rs.next()) {
184                                    String firstName = rs.getString("firstName");
185                                    String middleName = rs.getString("middleName");
186                                    String lastName = rs.getString("lastName");
187    
188                                    FullNameGenerator fullNameGenerator =
189                                            FullNameGeneratorFactory.getInstance();
190    
191                                    return fullNameGenerator.getFullName(
192                                            firstName, middleName, lastName);
193                            }
194    
195                            return StringPool.BLANK;
196                    }
197                    finally {
198                            DataAccess.cleanUp(con, ps, rs);
199                    }
200            }
201    
202            protected void verifyModel(
203                            String modelName, String pkColumnName, long primKey,
204                            Object[] modelArray, boolean updateDates)
205                    throws Exception {
206    
207                    Connection con = null;
208                    PreparedStatement ps = null;
209    
210                    try {
211                            con = DataAccess.getUpgradeOptimizedConnection();
212    
213                            long companyId = (Long)modelArray[0];
214    
215                            if (modelArray[2] == null) {
216                                    modelArray = getDefaultUserArray(con, companyId);
217    
218                                    if (modelArray == null) {
219                                            return;
220                                    }
221                            }
222    
223                            long userId = (Long)modelArray[1];
224                            String userName = (String)modelArray[2];
225                            Timestamp createDate = (Timestamp)modelArray[3];
226                            Timestamp modifiedDate = (Timestamp)modelArray[4];
227    
228                            StringBundler sb = new StringBundler(7);
229    
230                            sb.append("update ");
231                            sb.append(modelName);
232                            sb.append(" set companyId = ?, userId = ?, userName = ?");
233    
234                            if (updateDates) {
235                                    sb.append(", createDate = ?, modifiedDate = ?");
236                            }
237    
238                            sb.append(" where ");
239                            sb.append(pkColumnName);
240                            sb.append(" = ?");
241    
242                            ps = con.prepareStatement(sb.toString());
243    
244                            ps.setLong(1, companyId);
245                            ps.setLong(2, userId);
246                            ps.setString(3, userName);
247    
248                            if (updateDates) {
249                                    ps.setTimestamp(4, createDate);
250                                    ps.setTimestamp(5, modifiedDate);
251                                    ps.setLong(6, primKey);
252                            }
253                            else {
254                                    ps.setLong(4, primKey);
255                            }
256    
257                            ps.executeUpdate();
258                    }
259                    catch (Exception e) {
260                            if (_log.isWarnEnabled()) {
261                                    _log.warn("Unable to verify model " + modelName, e);
262                            }
263                    }
264                    finally {
265                            DataAccess.cleanUp(con, ps);
266                    }
267            }
268    
269            protected void verifyModel(
270                            String modelName, String pkColumnName, String joinByColumnName,
271                            String relatedModelName, String relatedPKColumnName,
272                            boolean updateDates)
273                    throws Exception {
274    
275                    Connection con = null;
276                    PreparedStatement ps = null;
277                    ResultSet rs = null;
278    
279                    try {
280                            con = DataAccess.getUpgradeOptimizedConnection();
281    
282                            StringBundler sb = new StringBundler(8);
283    
284                            sb.append("select ");
285                            sb.append(pkColumnName);
286                            sb.append(", companyId");
287    
288                            if (joinByColumnName != null) {
289                                    sb.append(StringPool.COMMA_AND_SPACE);
290                                    sb.append(joinByColumnName);
291                            }
292    
293                            sb.append(" from ");
294                            sb.append(modelName);
295                            sb.append(" where userName is null order by companyId");
296    
297                            ps = con.prepareStatement(sb.toString());
298    
299                            rs = ps.executeQuery();
300    
301                            Object[] modelArray = null;
302    
303                            long previousCompanyId = 0;
304    
305                            while (rs.next()) {
306                                    long companyId = rs.getLong("companyId");
307                                    long primKey = rs.getLong(pkColumnName);
308    
309                                    if (joinByColumnName != null) {
310                                            long relatedPrimKey = rs.getLong(joinByColumnName);
311    
312                                            modelArray = getModelArray(
313                                                    relatedModelName, relatedPKColumnName, relatedPrimKey);
314                                    }
315                                    else if (previousCompanyId != companyId) {
316                                            modelArray = getDefaultUserArray(con, companyId);
317    
318                                            previousCompanyId = companyId;
319                                    }
320    
321                                    if (modelArray == null) {
322                                            continue;
323                                    }
324    
325                                    verifyModel(
326                                            modelName, pkColumnName, primKey, modelArray, updateDates);
327                            }
328                    }
329                    finally {
330                            DataAccess.cleanUp(con, ps, rs);
331                    }
332            }
333    
334            private static final String[][] _MODELS = new String[][] {
335                    new String[] {
336                            "Layout", "plid", null, null, null, "false"
337                    },
338                    new String[] {
339                            "LayoutPrototype", "layoutPrototypeId", null, null, null, "true"
340                    },
341                    new String[] {
342                            "LayoutSetPrototype", "layoutSetPrototypeId", null, null, null,
343                            "false"
344                    },
345                    new String[] {
346                            "MBDiscussion", "discussionId", "threadId", "MBThread", "threadId",
347                            "true"
348                    },
349                    new String[] {
350                            "MBThread", "threadId", "rootMessageId", "MBMessage", "messageId",
351                            "true"
352                    },
353                    new String[] {
354                            "MBThreadFlag", "threadFlagId", "userId", "User_", "userId", "true",
355                    },
356                    new String[] {
357                            "Organization_", "organizationId", null, null, null, "true"
358                    },
359                    new String[] {
360                            "PollsChoice", "choiceId", "questionId", "PollsQuestion",
361                            "questionId", "true"
362                    },
363                    new String[] {
364                            "PollsVote", "voteId", "questionId", "PollsQuestion", "questionId",
365                            "true"
366                    },
367                    new String[] {
368                            "RepositoryEntry", "repositoryEntryId", "repositoryId",
369                            "Repository", "repositoryId", "true"
370                    },
371                    new String[] {
372                            "Role_", "roleId", null, null, null, "true"
373                    },
374                    new String[] {
375                            "UserGroup", "userGroupId", null, null, null, "true"
376                    }
377            };
378    
379            private static Log _log = LogFactoryUtil.getLog(VerifyAuditedModel.class);
380    
381            private class VerifyAuditedModelRunnable extends ThrowableAwareRunnable {
382    
383                    private VerifyAuditedModelRunnable(
384                            String modelName, String pkColumnName, String joinByColumnName,
385                            String relatedModelName, String relatedPKColumnName,
386                            boolean updateDates) {
387    
388                            _modelName = modelName;
389                            _pkColumnName = pkColumnName;
390                            _joinByColumnName = joinByColumnName;
391                            _relatedModelName = relatedModelName;
392                            _relatedPKColumnName = relatedPKColumnName;
393                            _updateDates = updateDates;
394                    }
395    
396                    @Override
397                    protected void doRun() throws Exception {
398                            verifyModel(
399                                    _modelName, _pkColumnName, _joinByColumnName, _relatedModelName,
400                                    _relatedPKColumnName, _updateDates);
401                    }
402    
403                    private final String _joinByColumnName;
404                    private final String _modelName;
405                    private final String _pkColumnName;
406                    private final String _relatedModelName;
407                    private final String _relatedPKColumnName;
408                    private final boolean _updateDates;
409    
410            }
411    
412    }