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