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.document.library.kernel.model.DLFileEntryType;
018    import com.liferay.document.library.kernel.model.DLFileEntryTypeConstants;
019    import com.liferay.document.library.kernel.util.DLUtil;
020    import com.liferay.portal.kernel.dao.jdbc.AutoBatchPreparedStatementUtil;
021    import com.liferay.portal.kernel.language.LanguageUtil;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.model.Company;
025    import com.liferay.portal.kernel.upgrade.UpgradeProcess;
026    import com.liferay.portal.kernel.upgrade.util.UpgradeProcessUtil;
027    import com.liferay.portal.kernel.util.FileUtil;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.LocaleUtil;
030    import com.liferay.portal.kernel.util.LocalizationUtil;
031    import com.liferay.portal.kernel.util.LoggingTimer;
032    import com.liferay.portal.kernel.util.PortalUtil;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.Validator;
035    import com.liferay.portal.repository.liferayrepository.LiferayRepository;
036    import com.liferay.portal.repository.portletrepository.PortletRepository;
037    import com.liferay.portal.upgrade.v7_0_0.util.DLFolderTable;
038    
039    import java.sql.PreparedStatement;
040    import java.sql.ResultSet;
041    
042    import java.util.HashMap;
043    import java.util.HashSet;
044    import java.util.Locale;
045    import java.util.Map;
046    import java.util.Set;
047    
048    /**
049     * @author Michael Young
050     */
051    public class UpgradeDocumentLibrary extends UpgradeProcess {
052    
053            protected void addClassName(long classNameId, String className)
054                    throws Exception {
055    
056                    try (PreparedStatement ps = connection.prepareStatement(
057                                    "insert into ClassName_ (mvccVersion, classNameId, value) " +
058                                            "values (?, ?, ?)")) {
059    
060                            ps.setLong(1, 0);
061                            ps.setLong(2, classNameId);
062                            ps.setString(3, className);
063    
064                            ps.executeUpdate();
065                    }
066            }
067    
068            protected void addDDMStructureLink(
069                            long ddmStructureLinkId, long classNameId, long classPK,
070                            long ddmStructureId)
071                    throws Exception {
072    
073                    try (PreparedStatement ps = connection.prepareStatement(
074                                    "insert into DDMStructureLink (structureLinkId, classNameId, " +
075                                            "classPK, structureId) values (?, ?, ?, ?)")) {
076    
077                            ps.setLong(1, ddmStructureLinkId);
078                            ps.setLong(2, classNameId);
079                            ps.setLong(3, classPK);
080                            ps.setLong(4, ddmStructureId);
081    
082                            ps.executeUpdate();
083                    }
084                    catch (Exception e) {
085                            _log.error(
086                                    "Unable to add dynamic data mapping structure link for file " +
087                                            "entry type " + classPK);
088    
089                            throw e;
090                    }
091            }
092    
093            @Override
094            protected void doUpgrade() throws Exception {
095    
096                    // DLFileEntry
097    
098                    updateFileEntryFileNames();
099    
100                    // DLFileEntryType
101    
102                    updateFileEntryTypeNamesAndDescriptions();
103    
104                    updateFileEntryTypeDDMStructureLinks();
105    
106                    // DLFileVersion
107    
108                    updateFileVersionFileNames();
109    
110                    // DLFolder
111    
112                    alter(
113                            DLFolderTable.class,
114                            new AlterColumnType("name", "VARCHAR(255) null"));
115    
116                    updateRepositoryClassNameIds();
117            }
118    
119            protected boolean hasFileEntry(
120                            long groupId, long folderId, long fileEntryId, String title,
121                            String fileName)
122                    throws Exception {
123    
124                    try (PreparedStatement ps = connection.prepareStatement(
125                                    "select count(*) from DLFileEntry where groupId = ? and " +
126                                            "folderId = ? and ((fileEntryId <> ? and title = ?) or " +
127                                                    "fileName = ?)")) {
128    
129                            ps.setLong(1, groupId);
130                            ps.setLong(2, folderId);
131                            ps.setLong(3, fileEntryId);
132                            ps.setString(4, title);
133                            ps.setString(5, fileName);
134    
135                            try (ResultSet rs = ps.executeQuery()) {
136                                    while (rs.next()) {
137                                            int count = rs.getInt(1);
138    
139                                            if (count > 0) {
140                                                    return true;
141                                            }
142                                    }
143    
144                                    return false;
145                            }
146                    }
147            }
148    
149            /**
150             * @deprecated As of 7.0.0, replaced by {@link #hasFileEntry(long, long,
151             *             long, String, String)}
152             */
153            @Deprecated
154            protected boolean hasFileEntry(long groupId, long folderId, String fileName)
155                    throws Exception {
156    
157                    throw new UnsupportedOperationException();
158            }
159    
160            protected void updateFileEntryFileNames() throws Exception {
161                    try (LoggingTimer loggingTimer = new LoggingTimer()) {
162                            runSQL("alter table DLFileEntry add fileName VARCHAR(255) null");
163    
164                            Set<String> generatedUniqueFileNames = new HashSet<>();
165                            Set<String> generatedUniqueTitles = new HashSet<>();
166    
167                            try (PreparedStatement ps1 = connection.prepareStatement(
168                                            "select fileEntryId, groupId, folderId, extension, title," +
169                                                    " version from DLFileEntry");
170                                    PreparedStatement ps2 =
171                                            AutoBatchPreparedStatementUtil.autoBatch(
172                                                    connection.prepareStatement(
173                                                            "update DLFileEntry set fileName = ?, title = ? " +
174                                                                    "where fileEntryId = ?"));
175                                    PreparedStatement ps3 =
176                                            AutoBatchPreparedStatementUtil.concurrentAutoBatch(
177                                                    connection,
178                                                    "update DLFileVersion set title = ? where " +
179                                                            "fileEntryId = " + "? and version = ?");
180                                    ResultSet rs = ps1.executeQuery()) {
181    
182                                    while (rs.next()) {
183                                            long fileEntryId = rs.getLong("fileEntryId");
184                                            long groupId = rs.getLong("groupId");
185                                            long folderId = rs.getLong("folderId");
186                                            String extension = GetterUtil.getString(
187                                                    rs.getString("extension"));
188                                            String title = GetterUtil.getString(rs.getString("title"));
189                                            String version = rs.getString("version");
190    
191                                            String uniqueFileName = DLUtil.getSanitizedFileName(
192                                                    title, extension);
193    
194                                            String titleExtension = StringPool.BLANK;
195                                            String titleWithoutExtension = title;
196    
197                                            if (title.endsWith(StringPool.PERIOD + extension)) {
198                                                    titleExtension = extension;
199                                                    titleWithoutExtension = FileUtil.stripExtension(title);
200                                            }
201    
202                                            boolean generatedUniqueFileName = false;
203                                            String uniqueTitle = title;
204    
205                                            for (int i = 1;; i++) {
206                                                    if (!generatedUniqueFileNames.contains(
207                                                                    uniqueFileName) &&
208                                                            !generatedUniqueTitles.contains(uniqueTitle) &&
209                                                            !hasFileEntry(
210                                                                    groupId, folderId, fileEntryId, uniqueTitle,
211                                                                    uniqueFileName)) {
212    
213                                                            break;
214                                                    }
215    
216                                                    generatedUniqueFileName = true;
217    
218                                                    uniqueTitle =
219                                                            titleWithoutExtension + StringPool.UNDERLINE +
220                                                                    String.valueOf(i);
221    
222                                                    if (Validator.isNotNull(titleExtension)) {
223                                                            uniqueTitle += StringPool.PERIOD.concat(
224                                                                    titleExtension);
225                                                    }
226    
227                                                    uniqueFileName = DLUtil.getSanitizedFileName(
228                                                            uniqueTitle, extension);
229                                            }
230    
231                                            if (generatedUniqueFileName) {
232                                                    generatedUniqueFileNames.add(uniqueFileName);
233                                                    generatedUniqueTitles.add(uniqueTitle);
234                                            }
235    
236                                            ps2.setString(1, uniqueFileName);
237    
238                                            if (Validator.isNotNull(uniqueTitle)) {
239                                                    ps2.setString(2, uniqueTitle);
240                                            }
241                                            else {
242                                                    ps2.setString(2, title);
243                                            }
244    
245                                            ps2.setLong(3, fileEntryId);
246    
247                                            ps2.addBatch();
248    
249                                            if (Validator.isNotNull(uniqueTitle)) {
250                                                    ps3.setString(1, uniqueTitle);
251                                                    ps3.setLong(2, fileEntryId);
252                                                    ps3.setString(3, version);
253    
254                                                    ps3.addBatch();
255                                            }
256                                    }
257    
258                                    ps2.executeBatch();
259    
260                                    ps3.executeBatch();
261                            }
262                    }
263            }
264    
265            protected void updateFileEntryTypeDDMStructureLinks() throws Exception {
266                    try (LoggingTimer loggingTimer = new LoggingTimer();
267                            PreparedStatement ps = connection.prepareStatement(
268                                    "select * from DLFileEntryTypes_DDMStructures");
269                            ResultSet rs = ps.executeQuery()) {
270    
271                            long classNameId = PortalUtil.getClassNameId(DLFileEntryType.class);
272    
273                            while (rs.next()) {
274                                    long structureId = rs.getLong("structureId");
275                                    long fileEntryTypeId = rs.getLong("fileEntryTypeId");
276    
277                                    addDDMStructureLink(
278                                            increment(), classNameId, fileEntryTypeId, structureId);
279                            }
280    
281                            runSQL("drop table DLFileEntryTypes_DDMStructures");
282                    }
283            }
284    
285            protected void updateFileEntryTypeNamesAndDescriptions() throws Exception {
286                    try (LoggingTimer loggingTimer = new LoggingTimer();
287                            PreparedStatement ps = connection.prepareStatement(
288                                    "select companyId, groupId from Group_ where classNameId = " +
289                                            "?")) {
290    
291                            long classNameId = PortalUtil.getClassNameId(Company.class);
292    
293                            ps.setLong(1, classNameId);
294    
295                            try (ResultSet rs = ps.executeQuery()) {
296                                    while (rs.next()) {
297                                            long companyId = rs.getLong(1);
298                                            long groupId = rs.getLong(2);
299    
300                                            updateFileEntryTypeNamesAndDescriptions(companyId, groupId);
301                                    }
302                            }
303                    }
304            }
305    
306            protected void updateFileEntryTypeNamesAndDescriptions(
307                            long companyId, long groupId)
308                    throws Exception {
309    
310                    Map<String, String> nameLanguageKeys = new HashMap<>();
311    
312                    nameLanguageKeys.put(
313                            DLFileEntryTypeConstants.NAME_CONTRACT,
314                            DLFileEntryTypeConstants.FILE_ENTRY_TYPE_KEY_CONTRACT);
315                    nameLanguageKeys.put(
316                            DLFileEntryTypeConstants.NAME_MARKETING_BANNER,
317                            DLFileEntryTypeConstants.FILE_ENTRY_TYPE_KEY_MARKETING_BANNER);
318                    nameLanguageKeys.put(
319                            DLFileEntryTypeConstants.NAME_ONLINE_TRAINING,
320                            DLFileEntryTypeConstants.FILE_ENTRY_TYPE_KEY_ONLINE_TRAINING);
321                    nameLanguageKeys.put(
322                            DLFileEntryTypeConstants.NAME_SALES_PRESENTATION,
323                            DLFileEntryTypeConstants.FILE_ENTRY_TYPE_KEY_SALES_PRESENTATION);
324    
325                    for (Map.Entry<String, String> nameAndKey :
326                                    nameLanguageKeys.entrySet()) {
327    
328                            String dlFileEntryTypeKey = nameAndKey.getValue();
329                            String nameLanguageKey = nameAndKey.getKey();
330    
331                            updateFileEntryTypeNamesAndDescriptions(
332                                    companyId, groupId, dlFileEntryTypeKey, nameLanguageKey);
333                    }
334            }
335    
336            protected void updateFileEntryTypeNamesAndDescriptions(
337                            long companyId, long groupId, String dlFileEntryTypeKey,
338                            String nameLanguageKey)
339                    throws Exception {
340    
341                    try (PreparedStatement ps = connection.prepareStatement(
342                                    "select fileEntryTypeId, name, description from " +
343                                            "DLFileEntryType where groupId = ? and fileEntryTypeKey " +
344                                                    "= ?")) {
345    
346                            ps.setLong(1, groupId);
347                            ps.setString(2, dlFileEntryTypeKey);
348    
349                            try (ResultSet rs = ps.executeQuery()) {
350                                    if (!rs.next()) {
351                                            return;
352                                    }
353    
354                                    long fileEntryTypeId = rs.getLong(1);
355                                    String name = rs.getString(2);
356                                    String description = rs.getString(3);
357    
358                                    if (rs.next()) {
359                                            throw new IllegalStateException(
360                                                    String.format(
361                                                            "Found more than one row in table DLFileEntryType" +
362                                                                    " with groupId %s and fileEntryTypeKey %s",
363                                                            groupId, dlFileEntryTypeKey));
364                                    }
365    
366                                    updateFileEntryTypeNamesAndDescriptions(
367                                            companyId, fileEntryTypeId, nameLanguageKey, name,
368                                            description);
369                            }
370                    }
371            }
372    
373            protected void updateFileEntryTypeNamesAndDescriptions(
374                            long companyId, long dlFileEntryTypeId, String nameLanguageKey,
375                            String nameXML, String descriptionXML)
376                    throws Exception {
377    
378                    boolean update = false;
379    
380                    Locale defaultLocale = LocaleUtil.fromLanguageId(
381                            UpgradeProcessUtil.getDefaultLanguageId(companyId));
382    
383                    String defaultValue = LanguageUtil.get(defaultLocale, nameLanguageKey);
384    
385                    Map<Locale, String> nameMap = LocalizationUtil.getLocalizationMap(
386                            nameXML);
387                    Map<Locale, String> descriptionMap =
388                            LocalizationUtil.getLocalizationMap(descriptionXML);
389    
390                    for (Locale locale : LanguageUtil.getSupportedLocales()) {
391                            String value = LanguageUtil.get(locale, nameLanguageKey);
392    
393                            if (!locale.equals(defaultLocale) && value.equals(defaultValue)) {
394                                    continue;
395                            }
396    
397                            String description = descriptionMap.get(locale);
398    
399                            if (description == null) {
400                                    descriptionMap.put(locale, value);
401    
402                                    update = true;
403                            }
404    
405                            String name = nameMap.get(locale);
406    
407                            if (name == null) {
408                                    nameMap.put(locale, value);
409    
410                                    update = true;
411                            }
412                    }
413    
414                    if (update) {
415                            updateFileEntryTypeNamesAndDescriptions(
416                                    dlFileEntryTypeId, nameXML, descriptionXML, nameMap,
417                                    descriptionMap, defaultLocale);
418                    }
419            }
420    
421            protected void updateFileEntryTypeNamesAndDescriptions(
422                            long fileEntryTypeId, String nameXML, String descriptionXML,
423                            Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
424                            Locale defaultLocale)
425                    throws Exception {
426    
427                    try (PreparedStatement ps = connection.prepareStatement(
428                                    "update DLFileEntryType set name = ?, description = ? where " +
429                                            "fileEntryTypeId = ?")) {
430    
431                            String languageId = LanguageUtil.getLanguageId(defaultLocale);
432    
433                            nameXML = LocalizationUtil.updateLocalization(
434                                    nameMap, nameXML, "Name", languageId);
435                            descriptionXML = LocalizationUtil.updateLocalization(
436                                    descriptionMap, descriptionXML, "Description", languageId);
437    
438                            ps.setString(1, nameXML);
439                            ps.setString(2, descriptionXML);
440                            ps.setLong(3, fileEntryTypeId);
441    
442                            int rowCount = ps.executeUpdate();
443    
444                            if (rowCount != 1) {
445                                    throw new IllegalStateException(
446                                            String.format(
447                                                    "Updated %s rows in table DLFileEntryType with " +
448                                                            "fileEntryTypeId %s",
449                                                    rowCount, fileEntryTypeId));
450                            }
451                    }
452            }
453    
454            protected void updateFileVersionFileName(
455                            long fileVersionId, String fileName)
456                    throws Exception {
457            }
458    
459            protected void updateFileVersionFileNames() throws Exception {
460                    try (LoggingTimer loggingTimer = new LoggingTimer()) {
461                            runSQL("alter table DLFileVersion add fileName VARCHAR(255) null");
462    
463                            try (PreparedStatement ps1 = connection.prepareStatement(
464                                            "select fileVersionId, extension, title from " +
465                                                    "DLFileVersion");
466                                    PreparedStatement ps2 =
467                                            AutoBatchPreparedStatementUtil.concurrentAutoBatch(
468                                                    connection,
469                                                    "update DLFileVersion set fileName = ? where " +
470                                                            "fileVersionId = ?");
471                                    ResultSet rs = ps1.executeQuery()) {
472    
473                                    while (rs.next()) {
474                                            long fileVersionId = rs.getLong("fileVersionId");
475                                            String extension = GetterUtil.getString(
476                                                    rs.getString("extension"));
477                                            String title = GetterUtil.getString(rs.getString("title"));
478    
479                                            String fileName = DLUtil.getSanitizedFileName(
480                                                    title, extension);
481    
482                                            ps2.setString(1, fileName);
483                                            ps2.setLong(2, fileVersionId);
484    
485                                            ps2.addBatch();
486                                    }
487    
488                                    ps2.executeBatch();
489                            }
490                    }
491            }
492    
493            protected void updateRepositoryClassNameIds() throws Exception {
494                    try (LoggingTimer loggingTimer = new LoggingTimer()) {
495                            long liferayRepositoryClassNameId = PortalUtil.getClassNameId(
496                                    LiferayRepository.class);
497                            long portletRepositoryClassNameId = PortalUtil.getClassNameId(
498                                    PortletRepository.class);
499    
500                            if (portletRepositoryClassNameId == 0) {
501                                    portletRepositoryClassNameId = increment();
502    
503                                    addClassName(
504                                            portletRepositoryClassNameId,
505                                            PortletRepository.class.getName());
506                            }
507    
508                            try (PreparedStatement ps = connection.prepareStatement(
509                                            "update Repository set classNameId = ? where classNameId " +
510                                                    "= ?")) {
511    
512                                    ps.setLong(1, portletRepositoryClassNameId);
513                                    ps.setLong(2, liferayRepositoryClassNameId);
514    
515                                    ps.executeUpdate();
516                            }
517                    }
518            }
519    
520            private static final Log _log = LogFactoryUtil.getLog(
521                    UpgradeDocumentLibrary.class);
522    
523    }