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