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.upgrade.v7_0_0;
016    
017    import com.liferay.blogs.kernel.model.BlogsEntry;
018    import com.liferay.document.library.kernel.model.DLFileEntry;
019    import com.liferay.document.library.kernel.model.DLFileEntryType;
020    import com.liferay.document.library.kernel.model.DLFolder;
021    import com.liferay.message.boards.kernel.model.MBCategory;
022    import com.liferay.message.boards.kernel.model.MBThread;
023    import com.liferay.portal.kernel.dao.jdbc.AutoBatchPreparedStatementUtil;
024    import com.liferay.portal.kernel.log.Log;
025    import com.liferay.portal.kernel.log.LogFactoryUtil;
026    import com.liferay.portal.kernel.model.Layout;
027    import com.liferay.portal.kernel.model.PortletPreferences;
028    import com.liferay.portal.kernel.model.WorkflowInstanceLink;
029    import com.liferay.portal.kernel.repository.model.Folder;
030    import com.liferay.portal.kernel.upgrade.UpgradeProcess;
031    import com.liferay.portal.kernel.util.ArrayUtil;
032    import com.liferay.portal.kernel.util.LoggingTimer;
033    import com.liferay.portal.kernel.util.PortalUtil;
034    import com.liferay.portal.kernel.util.StringBundler;
035    import com.liferay.portal.kernel.util.StringUtil;
036    
037    import java.sql.PreparedStatement;
038    import java.sql.ResultSet;
039    
040    import java.util.HashMap;
041    import java.util.Map;
042    
043    /**
044     * @author Eduardo Garcia
045     * @author Roberto D??az
046     * @author Iv??n Zaera
047     */
048    public class UpgradeSubscription extends UpgradeProcess {
049    
050            protected void addClassName(long classNameId, String className)
051                    throws Exception {
052    
053                    try (PreparedStatement ps = connection.prepareStatement(
054                                    "insert into ClassName_ (mvccVersion, classNameId, value) " +
055                                            "values (?, ?, ?)")) {
056    
057                            ps.setLong(1, 0);
058                            ps.setLong(2, classNameId);
059                            ps.setString(3, className);
060    
061                            ps.executeUpdate();
062                    }
063            }
064    
065            protected void deleteOrphanedSubscriptions() throws Exception {
066                    try (LoggingTimer loggingTimer = new LoggingTimer()) {
067                            long classNameId = PortalUtil.getClassNameId(
068                                    PortletPreferences.class.getName());
069    
070                            runSQL(
071                                    "delete from Subscription where classNameId = " + classNameId +
072                                            " and classPK not in (select portletPreferencesId from " +
073                                                    " PortletPreferences)");
074                    }
075            }
076    
077            @Override
078            protected void doUpgrade() throws Exception {
079                    deleteOrphanedSubscriptions();
080    
081                    updateSubscriptionClassNames(
082                            Folder.class.getName(), DLFolder.class.getName());
083                    updateSubscriptionClassNames(
084                            "com.liferay.portlet.journal.model.JournalArticle",
085                            "com.liferay.portlet.journal.model.JournalFolder");
086    
087                    updateSubscriptionGroupIds();
088            }
089    
090            protected long getClassNameId(String className) throws Exception {
091                    long classNameId = PortalUtil.getClassNameId(className);
092    
093                    if (classNameId != 0) {
094                            return classNameId;
095                    }
096    
097                    classNameId = increment();
098    
099                    addClassName(classNameId, className);
100    
101                    return classNameId;
102            }
103    
104            protected long getGroupId(long classNameId, long classPK) throws Exception {
105                    String className = PortalUtil.getClassName(classNameId);
106    
107                    String[] groupIdSQLParts = StringUtil.split(
108                            _getGroupIdSQLPartsMap.get(className));
109    
110                    if (ArrayUtil.isEmpty(groupIdSQLParts)) {
111                            if (_log.isWarnEnabled()) {
112                                    _log.warn(
113                                            "Unable to determine the group ID for the class name " +
114                                                    className);
115                            }
116    
117                            return 0;
118                    }
119    
120                    String sql =
121                            "select " + groupIdSQLParts[1] + " from " + groupIdSQLParts[0] +
122                                    " where " + groupIdSQLParts[2] + " = ?";
123    
124                    try (PreparedStatement ps = connection.prepareStatement(sql)) {
125                            ps.setLong(1, classPK);
126    
127                            try (ResultSet rs = ps.executeQuery()) {
128                                    if (rs.next()) {
129                                            return rs.getLong("groupId");
130                                    }
131                            }
132                    }
133    
134                    return 0;
135            }
136    
137            protected boolean hasGroup(long groupId) throws Exception {
138                    try (PreparedStatement ps = connection.prepareStatement(
139                                    "select count(*) from Group_ where groupId = ?")) {
140    
141                            ps.setLong(1, groupId);
142    
143                            try (ResultSet rs = ps.executeQuery()) {
144                                    if (rs.next()) {
145                                            int count = rs.getInt(1);
146    
147                                            if (count > 0) {
148                                                    return true;
149                                            }
150                                    }
151                            }
152    
153                            return false;
154                    }
155            }
156    
157            protected void updateSubscriptionClassNames(
158                            String oldClassName, String newClassName)
159                    throws Exception {
160    
161                    try (LoggingTimer loggingTimer = new LoggingTimer(oldClassName)) {
162                            StringBundler sb = new StringBundler(4);
163    
164                            sb.append("update Subscription set classNameId = ");
165                            sb.append(getClassNameId(newClassName));
166                            sb.append(" where classNameId = ");
167                            sb.append(PortalUtil.getClassNameId(oldClassName));
168    
169                            runSQL(sb.toString());
170                    }
171            }
172    
173            /**
174             * @deprecated As of 7.0.0, with no direct replacement
175             */
176            @Deprecated
177            protected void updateSubscriptionGroupId(
178                            long subscriptionId, long classNameId, long classPK)
179                    throws Exception {
180            }
181    
182            protected void updateSubscriptionGroupIds() throws Exception {
183                    try (LoggingTimer loggingTimer = new LoggingTimer();
184                            PreparedStatement ps1 = connection.prepareStatement(
185                                    "select subscriptionId, classNameId, classPK from " +
186                                            "Subscription");
187                            PreparedStatement ps2 =
188                                    AutoBatchPreparedStatementUtil.concurrentAutoBatch(
189                                            connection,
190                                            "update Subscription set groupId = ? where " +
191                                                    "subscriptionId = ?");
192                            ResultSet rs = ps1.executeQuery()) {
193    
194                            while (rs.next()) {
195                                    long subscriptionId = rs.getLong("subscriptionId");
196                                    long classNameId = rs.getLong("classNameId");
197                                    long classPK = rs.getLong("classPK");
198    
199                                    long groupId = getGroupId(classNameId, classPK);
200    
201                                    if ((groupId == 0) && hasGroup(classPK)) {
202                                            groupId = classPK;
203                                    }
204    
205                                    if (groupId != 0) {
206                                            ps2.setLong(1, groupId);
207                                            ps2.setLong(2, subscriptionId);
208    
209                                            ps2.addBatch();
210                                    }
211                            }
212    
213                            ps2.executeBatch();
214                    }
215            }
216    
217            private static final Log _log = LogFactoryUtil.getLog(
218                    UpgradeSubscription.class);
219    
220            private static final Map<String, String> _getGroupIdSQLPartsMap =
221                    new HashMap<>();
222    
223            static {
224                    _getGroupIdSQLPartsMap.put(
225                            BlogsEntry.class.getName(), "BlogsEntry,groupId,entryId");
226                    _getGroupIdSQLPartsMap.put(
227                            DLFileEntry.class.getName(), "DLFileEntry,groupId,fileEntryId");
228                    _getGroupIdSQLPartsMap.put(
229                            DLFileEntryType.class.getName(),
230                            "DLFileEntryType,groupId,fileEntryTypeId");
231                    _getGroupIdSQLPartsMap.put(
232                            DLFolder.class.getName(), "DLFolder,groupId,folderId");
233                    _getGroupIdSQLPartsMap.put(
234                            Layout.class.getName(), "Layout,groupId,plid");
235                    _getGroupIdSQLPartsMap.put(
236                            MBCategory.class.getName(), "MBCategory,groupId,categoryId");
237                    _getGroupIdSQLPartsMap.put(
238                            MBThread.class.getName(), "MBThread,groupId,threadId");
239                    _getGroupIdSQLPartsMap.put(
240                            WorkflowInstanceLink.class.getName(),
241                            "WorkflowInstanceLink,groupId,workflowInstanceId");
242                    _getGroupIdSQLPartsMap.put(
243                            "com.liferay.bookmarks.model.BookmarksEntry",
244                            "BookmarksEntry,groupId,entryId");
245                    _getGroupIdSQLPartsMap.put(
246                            "com.liferay.bookmarks.model.BookmarksFolder",
247                            "BookmarksFolder,groupId,folderId");
248                    _getGroupIdSQLPartsMap.put(
249                            "com.liferay.dynamic.data.mapping.kernel.DDMStructure",
250                            "DDMStructure,groupId,structureId");
251                    _getGroupIdSQLPartsMap.put(
252                            "com.liferay.journal.model.JournalFolder",
253                            "JournalFolder,groupId,folderId");
254                    _getGroupIdSQLPartsMap.put(
255                            "com.liferay.wiki.model.WikiNode", "WikiNode,groupId,nodeId");
256                    _getGroupIdSQLPartsMap.put(
257                            "com.liferay.wiki.model.WikiPage",
258                            "WikiPage,groupId,resourcePrimKey");
259            }
260    
261    }