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.portal.kernel.dao.jdbc.DataAccess;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.template.TemplateConstants;
021    import com.liferay.portal.kernel.upgrade.util.UpgradeProcessUtil;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.LocaleUtil;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
028    import com.liferay.portal.kernel.xml.Document;
029    import com.liferay.portal.kernel.xml.DocumentException;
030    import com.liferay.portal.kernel.xml.Element;
031    import com.liferay.portal.kernel.xml.SAXReaderUtil;
032    import com.liferay.portal.model.RoleConstants;
033    import com.liferay.portal.security.permission.ActionKeys;
034    import com.liferay.portal.upgrade.v7_0_0.util.JournalArticleTable;
035    import com.liferay.portal.util.PortalUtil;
036    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
037    import com.liferay.portlet.dynamicdatamapping.model.DDMStructureConstants;
038    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
039    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
040    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
041    import com.liferay.portlet.journal.model.JournalArticle;
042    import com.liferay.util.ContentUtil;
043    
044    import java.sql.Connection;
045    import java.sql.PreparedStatement;
046    import java.sql.ResultSet;
047    import java.sql.SQLException;
048    import java.sql.Timestamp;
049    
050    import java.util.ArrayList;
051    import java.util.List;
052    import java.util.Locale;
053    import java.util.Map;
054    
055    /**
056     * @author Gergely Mathe
057     * @author Eudaldo Alonso
058     */
059    public class UpgradeJournal extends UpgradeBaseJournal {
060    
061            protected String addBasicWebContentStructureAndTemplate(long companyId)
062                    throws Exception {
063    
064                    long groupId = getCompanyGroupId(companyId);
065    
066                    String defaultLanguageId = UpgradeProcessUtil.getDefaultLanguageId(
067                            companyId);
068    
069                    Locale defaultLocale = LocaleUtil.fromLanguageId(defaultLanguageId);
070    
071                    List<Element> structureElements = getDDMStructures(defaultLocale);
072    
073                    Element structureElement = structureElements.get(0);
074    
075                    String name = structureElement.elementText("name");
076    
077                    String description = structureElement.elementText("description");
078    
079                    String localizedName = localize(groupId, name, defaultLanguageId);
080                    String localizedDescription = localize(
081                            groupId, description, defaultLanguageId);
082    
083                    Element structureElementRootElement = structureElement.element("root");
084    
085                    String xsd = structureElementRootElement.asXML();
086    
087                    if (hasDDMStructure(groupId, name) > 0) {
088                            return name;
089                    }
090    
091                    String ddmStructureUUID = PortalUUIDUtil.generate();
092    
093                    long ddmStructureId = addDDMStructure(
094                            ddmStructureUUID, increment(), groupId, companyId, name,
095                            localizedName, localizedDescription, xsd);
096    
097                    String ddmTemplateUUID = PortalUUIDUtil.generate();
098    
099                    Element templateElement = structureElement.element("template");
100    
101                    String fileName = templateElement.elementText("file-name");
102                    boolean cacheable = GetterUtil.getBoolean(
103                            templateElement.elementText("cacheable"));
104    
105                    addDDMTemplate(
106                            ddmTemplateUUID, increment(), groupId, companyId, ddmStructureId,
107                            name, localizedName, localizedDescription, getContent(fileName),
108                            cacheable);
109    
110                    long stagingGroupId = getStagingGroupId(groupId);
111    
112                    if (stagingGroupId > 0) {
113                            ddmStructureId = addDDMStructure(
114                                    ddmStructureUUID, increment(), stagingGroupId, companyId, name,
115                                    localizedName, localizedDescription, xsd);
116    
117                            addDDMTemplate(
118                                    ddmTemplateUUID, increment(), stagingGroupId, companyId,
119                                    ddmStructureId, name, localizedName, localizedDescription,
120                                    getContent(fileName), cacheable);
121                    }
122    
123                    return name;
124            }
125    
126            protected long addDDMStructure(
127                            String uuid, long ddmStructureId, long groupId, long companyId,
128                            String ddmStructureKey, String localizedName,
129                            String localizedDescription, String xsd)
130                    throws Exception {
131    
132                    Timestamp now = new Timestamp(System.currentTimeMillis());
133    
134                    Connection con = null;
135                    PreparedStatement ps = null;
136    
137                    try {
138                            con = DataAccess.getUpgradeOptimizedConnection();
139    
140                            StringBundler sb = new StringBundler(6);
141    
142                            sb.append("insert into DDMStructure (uuid_, structureId, ");
143                            sb.append("groupId, companyId, userId, userName, createDate, ");
144                            sb.append("modifiedDate, parentStructureId, classNameId, ");
145                            sb.append("structureKey, version, name, description, definition, ");
146                            sb.append("storageType, type_) values (?, ?, ?, ?, ?, ?, ?, ?, ");
147                            sb.append("?, ?, ?, ?, ?, ?, ?, ?, ?)");
148    
149                            String sql = sb.toString();
150    
151                            ps = con.prepareStatement(sql);
152    
153                            ps.setString(1, uuid);
154                            ps.setLong(2, ddmStructureId);
155                            ps.setLong(3, groupId);
156                            ps.setLong(4, companyId);
157                            ps.setLong(5, getDefaultUserId(companyId));
158                            ps.setString(6, StringPool.BLANK);
159                            ps.setTimestamp(7, now);
160                            ps.setTimestamp(8, now);
161                            ps.setLong(9, DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID);
162                            ps.setLong(10, PortalUtil.getClassNameId(JournalArticle.class));
163                            ps.setString(11, ddmStructureKey);
164                            ps.setString(12, DDMStructureConstants.VERSION_DEFAULT);
165                            ps.setString(13, localizedName);
166                            ps.setString(14, localizedDescription);
167                            ps.setString(15, xsd);
168                            ps.setString(16, "xml");
169                            ps.setInt(17, DDMStructureConstants.TYPE_DEFAULT);
170    
171                            ps.executeUpdate();
172    
173                            addStructureVersion(
174                                    increment(), groupId, companyId, getDefaultUserId(companyId),
175                                    StringPool.BLANK, now, ddmStructureId, localizedName,
176                                    localizedDescription, xsd, "xml",
177                                    DDMStructureConstants.TYPE_DEFAULT);
178    
179                            Map<String, Long> bitwiseValues = getBitwiseValues(
180                                    DDMStructure.class.getName());
181    
182                            List<String> actionIds = new ArrayList<String>();
183    
184                            actionIds.add(ActionKeys.VIEW);
185    
186                            long bitwiseValue = getBitwiseValue(bitwiseValues, actionIds);
187    
188                            addResourcePermission(
189                                    companyId, DDMStructure.class.getName(), ddmStructureId,
190                                    getRoleId(companyId, RoleConstants.GUEST), bitwiseValue);
191                            addResourcePermission(
192                                    companyId, DDMStructure.class.getName(), ddmStructureId,
193                                    getRoleId(companyId, RoleConstants.SITE_MEMBER), bitwiseValue);
194                    }
195                    catch (Exception e) {
196                            _log.error("Unable to create the basic web content structure");
197    
198                            throw e;
199                    }
200                    finally {
201                            DataAccess.cleanUp(con, ps);
202                    }
203    
204                    return ddmStructureId;
205            }
206    
207            protected long addDDMTemplate(
208                            String uuid, long ddmTemplateId, long groupId, long companyId,
209                            long ddmStructureId, String templateKey, String localizedName,
210                            String localizedDescription, String script, boolean cacheable)
211                    throws Exception {
212    
213                    Timestamp now = new Timestamp(System.currentTimeMillis());
214    
215                    Connection con = null;
216                    PreparedStatement ps = null;
217    
218                    try {
219                            con = DataAccess.getUpgradeOptimizedConnection();
220    
221                            StringBundler sb = new StringBundler(7);
222    
223                            sb.append("insert into DDMTemplate (uuid_, templateId, groupId, ");
224                            sb.append("companyId, userId, userName, createDate, modifiedDate,");
225                            sb.append("classNameId, classPK, templateKey, version, name, ");
226                            sb.append("description, type_, mode_, language, script, ");
227                            sb.append("cacheable, smallImage, smallImageId, smallImageURL) ");
228                            sb.append("values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ");
229                            sb.append("?, ?, ?, ?, ?, ?, ?)");
230    
231                            String sql = sb.toString();
232    
233                            ps = con.prepareStatement(sql);
234    
235                            ps.setString(1, uuid);
236                            ps.setLong(2, ddmTemplateId);
237                            ps.setLong(3, groupId);
238                            ps.setLong(4, companyId);
239                            ps.setLong(5, getDefaultUserId(companyId));
240                            ps.setString(6, StringPool.BLANK);
241                            ps.setTimestamp(7, now);
242                            ps.setTimestamp(8, now);
243                            ps.setLong(9, PortalUtil.getClassNameId(DDMStructure.class));
244                            ps.setLong(10, ddmStructureId);
245                            ps.setString(11, templateKey);
246                            ps.setString(12, DDMTemplateConstants.VERSION_DEFAULT);
247                            ps.setString(13, localizedName);
248                            ps.setString(14, localizedDescription);
249                            ps.setString(15, DDMTemplateConstants.TEMPLATE_TYPE_DISPLAY);
250                            ps.setString(16, DDMTemplateConstants.TEMPLATE_MODE_CREATE);
251                            ps.setString(17, TemplateConstants.LANG_TYPE_FTL);
252                            ps.setString(18, script);
253                            ps.setBoolean(19, cacheable);
254                            ps.setBoolean(20, false);
255                            ps.setLong(21, 0);
256                            ps.setString(22, StringPool.BLANK);
257    
258                            ps.executeUpdate();
259    
260                            addTemplateVersion(
261                                    increment(), groupId, companyId, getDefaultUserId(companyId),
262                                    StringPool.BLANK, now, ddmTemplateId, localizedName,
263                                    localizedDescription, TemplateConstants.LANG_TYPE_FTL, script);
264    
265                            Map<String, Long> bitwiseValues = getBitwiseValues(
266                                    DDMTemplate.class.getName());
267    
268                            List<String> actionIds = new ArrayList<String>();
269    
270                            actionIds.add(ActionKeys.VIEW);
271    
272                            long bitwiseValue = getBitwiseValue(bitwiseValues, actionIds);
273    
274                            addResourcePermission(
275                                    companyId, DDMTemplate.class.getName(), ddmTemplateId,
276                                    getRoleId(companyId, RoleConstants.GUEST), bitwiseValue);
277                            addResourcePermission(
278                                    companyId, DDMTemplate.class.getName(), ddmTemplateId,
279                                    getRoleId(companyId, RoleConstants.SITE_MEMBER), bitwiseValue);
280                    }
281                    catch (Exception e) {
282                            _log.error("Unable to create the basic web content template");
283    
284                            throw e;
285                    }
286                    finally {
287                            DataAccess.cleanUp(con, ps);
288                    }
289    
290                    return ddmTemplateId;
291            }
292    
293            protected String convertStaticContentToDynamic(String content)
294                    throws Exception {
295    
296                    Document document = SAXReaderUtil.read(content);
297    
298                    Document newDocument = SAXReaderUtil.createDocument();
299    
300                    Element rootElement = document.getRootElement();
301    
302                    String availableLocales = rootElement.attributeValue(
303                            "available-locales");
304                    String defaultLocale = rootElement.attributeValue("default-locale");
305    
306                    Element newRootElement = SAXReaderUtil.createElement("root");
307    
308                    newRootElement.addAttribute("available-locales", availableLocales);
309                    newRootElement.addAttribute("default-locale", defaultLocale);
310    
311                    newDocument.add(newRootElement);
312    
313                    Element dynamicElementElement = SAXReaderUtil.createElement(
314                            "dynamic-element");
315    
316                    dynamicElementElement.addAttribute("name", "content");
317                    dynamicElementElement.addAttribute("type", "text_area");
318                    dynamicElementElement.addAttribute("index-type", "keyword");
319                    dynamicElementElement.addAttribute("index", String.valueOf(0));
320    
321                    newRootElement.add(dynamicElementElement);
322    
323                    List<Element> staticContentElements = rootElement.elements(
324                            "static-content");
325    
326                    for (Element staticContentElement : staticContentElements) {
327                            String languageId = staticContentElement.attributeValue(
328                                    "language-id");
329                            String text = staticContentElement.getText();
330    
331                            Element dynamicContentElement = SAXReaderUtil.createElement(
332                                    "dynamic-content");
333    
334                            dynamicContentElement.addAttribute("language-id", languageId);
335                            dynamicContentElement.addCDATA(text);
336    
337                            dynamicElementElement.add(dynamicContentElement);
338                    }
339    
340                    return DDMXMLUtil.formatXML(newDocument);
341            }
342    
343            @Override
344            protected void doUpgrade() throws Exception {
345                    try {
346                            runSQL(
347                                    "alter_column_name JournalArticle structureId " +
348                                            "DDMStructureKey VARCHAR(75) null");
349    
350                            runSQL(
351                                    "alter_column_name JournalArticle templateId DDMTemplateKey " +
352                                            "VARCHAR(75) null");
353    
354                            runSQL("alter_column_type JournalArticle description TEXT null");
355    
356                            runSQL(
357                                    "alter_column_name JournalFeed structureId DDMStructureKey " +
358                                            "TEXT null");
359    
360                            runSQL(
361                                    "alter_column_name JournalFeed templateId DDMTemplateKey " +
362                                            "TEXT null");
363    
364                            runSQL(
365                                    "alter_column_name JournalFeed rendererTemplateId " +
366                                            "DDMRendererTemplateKey TEXT null");
367                    }
368                    catch (SQLException sqle) {
369                            upgradeTable(
370                                    JournalArticleTable.TABLE_NAME,
371                                    JournalArticleTable.TABLE_COLUMNS,
372                                    JournalArticleTable.TABLE_SQL_CREATE,
373                                    JournalArticleTable.TABLE_SQL_ADD_INDEXES);
374                    }
375    
376                    updateBasicWebContentStructure();
377            }
378    
379            protected String getContent(String fileName) {
380                    return ContentUtil.get(
381                            "com/liferay/portal/events/dependencies/" + fileName);
382            }
383    
384            protected List<Element> getDDMStructures(Locale locale)
385                    throws DocumentException {
386    
387                    String xml = getContent("basic-web-content-structure.xml");
388    
389                    xml = StringUtil.replace(xml, "[$LOCALE_DEFAULT$]", locale.toString());
390    
391                    Document document = SAXReaderUtil.read(xml);
392    
393                    Element rootElement = document.getRootElement();
394    
395                    return rootElement.elements("structure");
396            }
397    
398            protected long getStagingGroupId(long groupId) throws Exception {
399                    Connection con = null;
400                    PreparedStatement ps = null;
401                    ResultSet rs = null;
402    
403                    try {
404                            con = DataAccess.getUpgradeOptimizedConnection();
405    
406                            ps = con.prepareStatement(
407                                    "select groupId from Group_ where liveGroupId = ?");
408    
409                            ps.setLong(1, groupId);
410    
411                            rs = ps.executeQuery();
412    
413                            if (rs.next()) {
414                                    return rs.getLong("groupId");
415                            }
416    
417                            return 0;
418                    }
419                    finally {
420                            DataAccess.cleanUp(con, ps, rs);
421                    }
422            }
423    
424            protected int hasDDMStructure(long groupId, String ddmStructureKey)
425                    throws Exception {
426    
427                    Connection con = null;
428                    PreparedStatement ps = null;
429                    ResultSet rs = null;
430    
431                    try {
432                            con = DataAccess.getUpgradeOptimizedConnection();
433    
434                            ps = con.prepareStatement(
435                                    "select count(*) from DDMStructure where groupId = ? and " +
436                                            "classNameId = ? and structureKey = ?");
437    
438                            ps.setLong(1, groupId);
439                            ps.setLong(
440                                    2, PortalUtil.getClassNameId(JournalArticle.class.getName()));
441                            ps.setString(3, ddmStructureKey);
442    
443                            rs = ps.executeQuery();
444    
445                            if (rs.next()) {
446                                    int count = rs.getInt(1);
447    
448                                    return count;
449                            }
450    
451                            return 0;
452                    }
453                    finally {
454                            DataAccess.cleanUp(con, ps, rs);
455                    }
456            }
457    
458            protected void updateBasicWebContentStructure() throws Exception {
459                    Connection con = null;
460                    PreparedStatement ps = null;
461                    ResultSet rs = null;
462    
463                    try {
464                            con = DataAccess.getUpgradeOptimizedConnection();
465    
466                            ps = con.prepareStatement("select companyId from Company");
467    
468                            rs = ps.executeQuery();
469    
470                            while (rs.next()) {
471                                    long companyId = rs.getLong("companyId");
472    
473                                    updateJournalArticles(companyId);
474                            }
475                    }
476                    finally {
477                            DataAccess.cleanUp(con, ps, rs);
478                    }
479            }
480    
481            protected void updateJournalArticle(
482                            long id_, String ddmStructureKey, String ddmTemplateKey,
483                            String content)
484                    throws Exception {
485    
486                    Connection con = null;
487                    PreparedStatement ps = null;
488    
489                    try {
490                            con = DataAccess.getUpgradeOptimizedConnection();
491    
492                            ps = con.prepareStatement(
493                                    "update JournalArticle set ddmStructureKey = ?, " +
494                                            "ddmTemplateKey = ?, content = ? where id_ = ?");
495    
496                            ps.setString(1, ddmStructureKey);
497                            ps.setString(2, ddmTemplateKey);
498                            ps.setString(3, convertStaticContentToDynamic(content));
499                            ps.setLong(4, id_);
500    
501                            ps.executeUpdate();
502                    }
503                    finally {
504                            DataAccess.cleanUp(con, ps);
505                    }
506            }
507    
508            protected void updateJournalArticles(long companyId) throws Exception {
509                    Connection con = null;
510                    PreparedStatement ps = null;
511                    ResultSet rs = null;
512    
513                    try {
514                            con = DataAccess.getUpgradeOptimizedConnection();
515    
516                            ps = con.prepareStatement(
517                                    "select id_, content from JournalArticle where companyId = " +
518                                            companyId + " and ddmStructureKey is null or " +
519                                                    "ddmStructureKey like ''");
520    
521                            String name = addBasicWebContentStructureAndTemplate(companyId);
522    
523                            rs = ps.executeQuery();
524    
525                            while (rs.next()) {
526                                    long id_ = rs.getLong("id_");
527                                    String content = rs.getString("content");
528    
529                                    updateJournalArticle(id_, name, name, content);
530                            }
531                    }
532                    finally {
533                            DataAccess.cleanUp(con, ps, rs);
534                    }
535            }
536    
537            private static final Log _log = LogFactoryUtil.getLog(UpgradeJournal.class);
538    
539    }