001
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.dao.shard.ShardUtil;
019 import com.liferay.portal.kernel.language.LanguageUtil;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.template.TemplateConstants;
023 import com.liferay.portal.kernel.upgrade.UpgradeProcess;
024 import com.liferay.portal.kernel.upgrade.util.UpgradeProcessUtil;
025 import com.liferay.portal.kernel.util.GetterUtil;
026 import com.liferay.portal.kernel.util.LocaleUtil;
027 import com.liferay.portal.kernel.util.LocalizationUtil;
028 import com.liferay.portal.kernel.util.PropsKeys;
029 import com.liferay.portal.kernel.util.PropsUtil;
030 import com.liferay.portal.kernel.util.StringBundler;
031 import com.liferay.portal.kernel.util.StringPool;
032 import com.liferay.portal.kernel.util.StringUtil;
033 import com.liferay.portal.kernel.util.Validator;
034 import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
035 import com.liferay.portal.kernel.xml.Document;
036 import com.liferay.portal.kernel.xml.DocumentException;
037 import com.liferay.portal.kernel.xml.Element;
038 import com.liferay.portal.kernel.xml.SAXReaderUtil;
039 import com.liferay.portal.model.Company;
040 import com.liferay.portal.model.ResourceConstants;
041 import com.liferay.portal.model.ResourcePermission;
042 import com.liferay.portal.model.RoleConstants;
043 import com.liferay.portal.security.permission.ActionKeys;
044 import com.liferay.portal.upgrade.v7_0_0.util.JournalArticleTable;
045 import com.liferay.portal.util.PortalUtil;
046 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
047 import com.liferay.portlet.dynamicdatamapping.model.DDMStructureConstants;
048 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
049 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
050 import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
051 import com.liferay.portlet.journal.model.JournalArticle;
052 import com.liferay.util.ContentUtil;
053
054 import java.sql.Connection;
055 import java.sql.PreparedStatement;
056 import java.sql.ResultSet;
057 import java.sql.SQLException;
058 import java.sql.Timestamp;
059
060 import java.util.ArrayList;
061 import java.util.HashMap;
062 import java.util.List;
063 import java.util.Locale;
064 import java.util.Map;
065
066
070 public class UpgradeJournal extends UpgradeProcess {
071
072 protected String addBasicWebContentStructureAndTemplate(long companyId)
073 throws Exception {
074
075 long groupId = getCompanyGroupId(companyId);
076
077 String defaultLanguageId = UpgradeProcessUtil.getDefaultLanguageId(
078 companyId);
079
080 Locale defaultLocale = LocaleUtil.fromLanguageId(defaultLanguageId);
081
082 List<Element> structureElements = getDDMStructures(defaultLocale);
083
084 Element structureElement = structureElements.get(0);
085
086 String name = structureElement.elementText("name");
087
088 String description = structureElement.elementText("description");
089
090 String localizedName = localize(groupId, name, defaultLanguageId);
091 String localizedDescription = localize(
092 groupId, description, defaultLanguageId);
093
094 Element structureElementRootElement = structureElement.element("root");
095
096 String xsd = structureElementRootElement.asXML();
097
098 if (hasDDMStructure(groupId, name) > 0) {
099 return name;
100 }
101
102 String ddmStructureUUID = PortalUUIDUtil.generate();
103
104 long ddmStructureId = addDDMStructure(
105 ddmStructureUUID, increment(), groupId, companyId, name,
106 localizedName, localizedDescription, xsd);
107
108 String ddmTemplateUUID = PortalUUIDUtil.generate();
109
110 Element templateElement = structureElement.element("template");
111
112 String fileName = templateElement.elementText("file-name");
113 boolean cacheable = GetterUtil.getBoolean(
114 templateElement.elementText("cacheable"));
115
116 addDDMTemplate(
117 ddmTemplateUUID, increment(), groupId, companyId, ddmStructureId,
118 name, localizedName, localizedDescription, getContent(fileName),
119 cacheable);
120
121 long stagingGroupId = getStagingGroupId(groupId);
122
123 if (stagingGroupId > 0) {
124 ddmStructureId = addDDMStructure(
125 ddmStructureUUID, increment(), stagingGroupId, companyId, name,
126 localizedName, localizedDescription, xsd);
127
128 addDDMTemplate(
129 ddmTemplateUUID, increment(), stagingGroupId, companyId,
130 ddmStructureId, name, localizedName, localizedDescription,
131 getContent(fileName), cacheable);
132 }
133
134 return name;
135 }
136
137 protected long addDDMStructure(
138 String uuid, long ddmStructureId, long groupId, long companyId,
139 String ddmStructureKey, String localizedName,
140 String localizedDescription, String xsd)
141 throws Exception {
142
143 Timestamp now = new Timestamp(System.currentTimeMillis());
144
145 Connection con = null;
146 PreparedStatement ps = null;
147
148 try {
149 con = DataAccess.getUpgradeOptimizedConnection();
150
151 StringBundler sb = new StringBundler(6);
152
153 sb.append("insert into DDMStructure (uuid_, structureId, ");
154 sb.append("groupId, companyId, userId, userName, createDate, ");
155 sb.append("modifiedDate, parentStructureId, classNameId, ");
156 sb.append("structureKey, name, description, definition, ");
157 sb.append("storageType, type_) values (?, ?, ?, ?, ?, ?, ?, ?, ");
158 sb.append("?, ?, ?, ?, ?, ?, ?, ?)");
159
160 String sql = sb.toString();
161
162 ps = con.prepareStatement(sql);
163
164 ps.setString(1, uuid);
165 ps.setLong(2, ddmStructureId);
166 ps.setLong(3, groupId);
167 ps.setLong(4, companyId);
168 ps.setLong(5, getDefaultUserId(companyId));
169 ps.setString(6, StringPool.BLANK);
170 ps.setTimestamp(7, now);
171 ps.setTimestamp(8, now);
172 ps.setLong(9, DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID);
173 ps.setLong(10, PortalUtil.getClassNameId(JournalArticle.class));
174 ps.setString(11, ddmStructureKey);
175 ps.setString(12, localizedName);
176 ps.setString(13, localizedDescription);
177 ps.setString(14, xsd);
178 ps.setString(15, "xml");
179 ps.setInt(16, DDMStructureConstants.TYPE_DEFAULT);
180
181 ps.executeUpdate();
182
183 Map<String, Long> bitwiseValues = getBitwiseValues(
184 DDMStructure.class.getName());
185
186 List<String> actionIds = new ArrayList<String>();
187
188 actionIds.add(ActionKeys.VIEW);
189
190 long bitwiseValue = getBitwiseValue(bitwiseValues, actionIds);
191
192 addResourcePermission(
193 companyId, DDMStructure.class.getName(), ddmStructureId,
194 getRoleId(companyId, RoleConstants.GUEST), bitwiseValue);
195 addResourcePermission(
196 companyId, DDMStructure.class.getName(), ddmStructureId,
197 getRoleId(companyId, RoleConstants.SITE_MEMBER), bitwiseValue);
198 }
199 catch (Exception e) {
200 _log.error("Unable to create the basic web content structure");
201
202 throw e;
203 }
204 finally {
205 DataAccess.cleanUp(con, ps);
206 }
207
208 return ddmStructureId;
209 }
210
211 protected long addDDMTemplate(
212 String uuid, long ddmTemplateId, long groupId, long companyId,
213 long ddmStructureId, String templateKey, String localizedName,
214 String localizedDescription, String script, boolean cacheable)
215 throws Exception {
216
217 Timestamp now = new Timestamp(System.currentTimeMillis());
218
219 Connection con = null;
220 PreparedStatement ps = null;
221
222 try {
223 con = DataAccess.getUpgradeOptimizedConnection();
224
225 StringBundler sb = new StringBundler(6);
226
227 sb.append("insert into DDMTemplate (uuid_, templateId, groupId, ");
228 sb.append("companyId, userId, userName, createDate, modifiedDate,");
229 sb.append("classNameId, classPK , templateKey, name, description,");
230 sb.append("type_, mode_, language, script, cacheable, smallImage,");
231 sb.append("smallImageId, smallImageURL) values (?, ?, ?, ?, ?, ?,");
232 sb.append("?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
233
234 String sql = sb.toString();
235
236 ps = con.prepareStatement(sql);
237
238 ps.setString(1, uuid);
239 ps.setLong(2, ddmTemplateId);
240 ps.setLong(3, groupId);
241 ps.setLong(4, companyId);
242 ps.setLong(5, getDefaultUserId(companyId));
243 ps.setString(6, StringPool.BLANK);
244 ps.setTimestamp(7, now);
245 ps.setTimestamp(8, now);
246 ps.setLong(9, PortalUtil.getClassNameId(DDMStructure.class));
247 ps.setLong(10, ddmStructureId);
248 ps.setString(11, templateKey);
249 ps.setString(12, localizedName);
250 ps.setString(13, localizedDescription);
251 ps.setString(14, DDMTemplateConstants.TEMPLATE_TYPE_DISPLAY);
252 ps.setString(15, DDMTemplateConstants.TEMPLATE_MODE_CREATE);
253 ps.setString(16, TemplateConstants.LANG_TYPE_FTL);
254 ps.setString(17, script);
255 ps.setBoolean(18, cacheable);
256 ps.setBoolean(19, false);
257 ps.setLong(20, 0);
258 ps.setString(21, StringPool.BLANK);
259
260 ps.executeUpdate();
261
262 Map<String, Long> bitwiseValues = getBitwiseValues(
263 DDMTemplate.class.getName());
264
265 List<String> actionIds = new ArrayList<String>();
266
267 actionIds.add(ActionKeys.VIEW);
268
269 long bitwiseValue = getBitwiseValue(bitwiseValues, actionIds);
270
271 addResourcePermission(
272 companyId, DDMTemplate.class.getName(), ddmTemplateId,
273 getRoleId(companyId, RoleConstants.GUEST), bitwiseValue);
274 addResourcePermission(
275 companyId, DDMTemplate.class.getName(), ddmTemplateId,
276 getRoleId(companyId, RoleConstants.SITE_MEMBER), bitwiseValue);
277 }
278 catch (Exception e) {
279 _log.error("Unable to create the basic web content template");
280
281 throw e;
282 }
283 finally {
284 DataAccess.cleanUp(con, ps);
285 }
286
287 return ddmTemplateId;
288 }
289
290 protected void addResourcePermission(
291 long companyId, String className, long primKey, long roleId,
292 long actionIds)
293 throws Exception {
294
295 Connection con = null;
296 PreparedStatement ps = null;
297
298 try {
299 long resourcePermissionId = increment(
300 ResourcePermission.class.getName());
301
302 con = DataAccess.getUpgradeOptimizedConnection();
303
304 StringBundler sb = new StringBundler(3);
305
306 sb.append("insert into ResourcePermission (resourcePermissionId, ");
307 sb.append("companyId, name, scope, primKey, roleId, ownerId, ");
308 sb.append("actionIds) values (?, ?, ?, ?, ?, ?, ?, ?)");
309
310 String sql = sb.toString();
311
312 ps = con.prepareStatement(sql);
313
314 ps.setLong(1, resourcePermissionId);
315 ps.setLong(2, companyId);
316 ps.setString(3, className);
317 ps.setInt(4, ResourceConstants.SCOPE_INDIVIDUAL);
318 ps.setLong(5, primKey);
319 ps.setLong(6, roleId);
320 ps.setLong(7, 0);
321 ps.setLong(8, actionIds);
322
323 ps.executeUpdate();
324 }
325 catch (Exception e) {
326 if (_log.isWarnEnabled()) {
327 _log.warn("Unable to add resource permission " + className, e);
328 }
329 }
330 finally {
331 DataAccess.cleanUp(con, ps);
332 }
333 }
334
335 protected String convertStaticContentToDynamic(String content)
336 throws Exception {
337
338 Document document = SAXReaderUtil.read(content);
339
340 Document newDocument = SAXReaderUtil.createDocument();
341
342 Element rootElement = document.getRootElement();
343
344 String availableLocales = rootElement.attributeValue(
345 "available-locales");
346 String defaultLocale = rootElement.attributeValue("default-locale");
347
348 Element newRootElement = SAXReaderUtil.createElement("root");
349
350 newRootElement.addAttribute("available-locales", availableLocales);
351 newRootElement.addAttribute("default-locale", defaultLocale);
352
353 newDocument.add(newRootElement);
354
355 Element dynamicElementElement = SAXReaderUtil.createElement(
356 "dynamic-element");
357
358 dynamicElementElement.addAttribute("name", "content");
359 dynamicElementElement.addAttribute("type", "text_area");
360 dynamicElementElement.addAttribute("index-type", "keyword");
361 dynamicElementElement.addAttribute("index", String.valueOf(0));
362
363 newRootElement.add(dynamicElementElement);
364
365 List<Element> staticContentElements = rootElement.elements(
366 "static-content");
367
368 for (Element staticContentElement : staticContentElements) {
369 String languageId = staticContentElement.attributeValue(
370 "language-id");
371 String text = staticContentElement.getText();
372
373 Element dynamicContentElement = SAXReaderUtil.createElement(
374 "dynamic-content");
375
376 dynamicContentElement.addAttribute("language-id", languageId);
377 dynamicContentElement.addCDATA(text);
378
379 dynamicElementElement.add(dynamicContentElement);
380 }
381
382 return DDMXMLUtil.formatXML(newDocument);
383 }
384
385 @Override
386 protected void doUpgrade() throws Exception {
387 updateBasicWebContentStructure();
388
389 try {
390 runSQL("alter_column_type JournalArticle description TEXT null");
391 }
392 catch (SQLException sqle) {
393 upgradeTable(
394 JournalArticleTable.TABLE_NAME,
395 JournalArticleTable.TABLE_COLUMNS,
396 JournalArticleTable.TABLE_SQL_CREATE,
397 JournalArticleTable.TABLE_SQL_ADD_INDEXES);
398 }
399 }
400
401 protected long getBitwiseValue(
402 Map<String, Long> bitwiseValues, List<String> actionIds) {
403
404 long bitwiseValue = 0;
405
406 for (String actionId : actionIds) {
407 Long actionIdBitwiseValue = bitwiseValues.get(actionId);
408
409 if (actionIdBitwiseValue == null) {
410 continue;
411 }
412
413 bitwiseValue |= actionIdBitwiseValue;
414 }
415
416 return bitwiseValue;
417 }
418
419 protected Map<String, Long> getBitwiseValues(String name) throws Exception {
420 Map<String, Long> bitwiseValues = _bitwiseValues.get(name);
421
422 if (bitwiseValues != null) {
423 return bitwiseValues;
424 }
425
426 Connection con = null;
427 PreparedStatement ps = null;
428 ResultSet rs = null;
429
430 String currentShardName = null;
431
432 try {
433 currentShardName = ShardUtil.setTargetSource(
434 PropsUtil.get(PropsKeys.SHARD_DEFAULT_NAME));
435
436 con = DataAccess.getUpgradeOptimizedConnection();
437
438 ps = con.prepareStatement(
439 "select actionId, bitwiseValue from ResourceAction " +
440 "where name = ?");
441
442 ps.setString(1, name);
443
444 rs = ps.executeQuery();
445
446 bitwiseValues = new HashMap<String, Long>();
447
448 while (rs.next()) {
449 String actionId = rs.getString("actionId");
450 long bitwiseValue = rs.getLong("bitwiseValue");
451
452 bitwiseValues.put(actionId, bitwiseValue);
453 }
454
455 _bitwiseValues.put(name, bitwiseValues);
456
457 return bitwiseValues;
458 }
459 finally {
460 if (Validator.isNotNull(currentShardName)) {
461 ShardUtil.setTargetSource(currentShardName);
462 }
463
464 DataAccess.cleanUp(con, ps, rs);
465 }
466 }
467
468 protected long getCompanyGroupId(long companyId) throws Exception {
469 Connection con = null;
470 PreparedStatement ps = null;
471 ResultSet rs = null;
472
473 try {
474 con = DataAccess.getUpgradeOptimizedConnection();
475
476 ps = con.prepareStatement(
477 "select groupId from Group_ where classNameId = ? and " +
478 "classPK = ?");
479
480 ps.setLong(1, PortalUtil.getClassNameId(Company.class.getName()));
481 ps.setLong(2, companyId);
482
483 rs = ps.executeQuery();
484
485 if (rs.next()) {
486 return rs.getLong("groupId");
487 }
488
489 return 0;
490 }
491 finally {
492 DataAccess.cleanUp(con, ps, rs);
493 }
494 }
495
496 protected String getContent(String fileName) {
497 return ContentUtil.get(
498 "com/liferay/portal/events/dependencies/" + fileName);
499 }
500
501 protected List<Element> getDDMStructures(Locale locale)
502 throws DocumentException {
503
504 String xml = getContent("basic-web-content-structure.xml");
505
506 xml = StringUtil.replace(xml, "[$LOCALE_DEFAULT$]", locale.toString());
507
508 Document document = SAXReaderUtil.read(xml);
509
510 Element rootElement = document.getRootElement();
511
512 return rootElement.elements("structure");
513 }
514
515 protected long getDefaultUserId(long companyId) throws Exception {
516 Connection con = null;
517 PreparedStatement ps = null;
518 ResultSet rs = null;
519
520 try {
521 con = DataAccess.getUpgradeOptimizedConnection();
522
523 ps = con.prepareStatement(
524 "select userId from User_ where companyId = ? and " +
525 "defaultUser = ?");
526
527 ps.setLong(1, companyId);
528 ps.setBoolean(2, true);
529
530 rs = ps.executeQuery();
531
532 if (rs.next()) {
533 return rs.getLong("userId");
534 }
535
536 return 0;
537 }
538 finally {
539 DataAccess.cleanUp(con, ps, rs);
540 }
541 }
542
543 protected long getRoleId(long companyId, String name) throws Exception {
544 String roleIdsKey = companyId + StringPool.POUND + name;
545
546 Long roleId = _roleIds.get(roleIdsKey);
547
548 if (roleId != null) {
549 return roleId;
550 }
551
552 Connection con = null;
553 PreparedStatement ps = null;
554 ResultSet rs = null;
555
556 try {
557 con = DataAccess.getUpgradeOptimizedConnection();
558
559 ps = con.prepareStatement(
560 "select roleId from Role_ where companyId = ? and name = ?");
561
562 ps.setLong(1, companyId);
563 ps.setString(2, name);
564
565 rs = ps.executeQuery();
566
567 if (rs.next()) {
568 roleId = rs.getLong("roleId");
569 }
570
571 _roleIds.put(roleIdsKey, roleId);
572
573 return roleId;
574 }
575 finally {
576 DataAccess.cleanUp(con, ps, rs);
577 }
578 }
579
580 protected long getStagingGroupId(long groupId) throws Exception {
581 Connection con = null;
582 PreparedStatement ps = null;
583 ResultSet rs = null;
584
585 try {
586 con = DataAccess.getUpgradeOptimizedConnection();
587
588 ps = con.prepareStatement(
589 "select groupId from Group_ where liveGroupId = ?");
590
591 ps.setLong(1, groupId);
592
593 rs = ps.executeQuery();
594
595 if (rs.next()) {
596 return rs.getLong("groupId");
597 }
598
599 return 0;
600 }
601 finally {
602 DataAccess.cleanUp(con, ps, rs);
603 }
604 }
605
606 protected int hasDDMStructure(long groupId, String ddmStructureKey)
607 throws Exception {
608
609 Connection con = null;
610 PreparedStatement ps = null;
611 ResultSet rs = null;
612
613 try {
614 con = DataAccess.getUpgradeOptimizedConnection();
615
616 ps = con.prepareStatement(
617 "select count(*) from DDMStructure where groupId = ? and " +
618 "classNameId = ? and structureKey = ?");
619
620 ps.setLong(1, groupId);
621 ps.setLong(
622 2, PortalUtil.getClassNameId(JournalArticle.class.getName()));
623 ps.setString(3, ddmStructureKey);
624
625 rs = ps.executeQuery();
626
627 if (rs.next()) {
628 int count = rs.getInt(1);
629
630 return count;
631 }
632
633 return 0;
634 }
635 finally {
636 DataAccess.cleanUp(con, ps, rs);
637 }
638 }
639
640 protected String localize(
641 long groupId, String key, String defaultLanguageId)
642 throws Exception {
643
644 Map<Locale, String> localizationMap = new HashMap<Locale, String>();
645
646 Locale[] locales = LanguageUtil.getAvailableLocales(groupId);
647
648 for (Locale locale : locales) {
649 localizationMap.put(locale, LanguageUtil.get(locale, key));
650 }
651
652 return LocalizationUtil.updateLocalization(
653 localizationMap, StringPool.BLANK, key, defaultLanguageId);
654 }
655
656 protected void updateBasicWebContentStructure() throws Exception {
657 Connection con = null;
658 PreparedStatement ps = null;
659 ResultSet rs = null;
660
661 try {
662 con = DataAccess.getUpgradeOptimizedConnection();
663
664 ps = con.prepareStatement("select companyId from Company");
665
666 rs = ps.executeQuery();
667
668 while (rs.next()) {
669 long companyId = rs.getLong("companyId");
670
671 updateJournalArticles(companyId);
672 }
673 }
674 finally {
675 DataAccess.cleanUp(con, ps, rs);
676 }
677 }
678
679 protected void updateJournalArticle(
680 long id_, String ddmStructureKey, String ddmTemplateKey,
681 String content)
682 throws Exception {
683
684 Connection con = null;
685 PreparedStatement ps = null;
686
687 try {
688 con = DataAccess.getUpgradeOptimizedConnection();
689
690 ps = con.prepareStatement(
691 "update JournalArticle set structureId = ?, templateId = ?, " +
692 "content = ? where id_ = ?");
693
694 ps.setString(1, ddmStructureKey);
695 ps.setString(2, ddmTemplateKey);
696 ps.setString(3, convertStaticContentToDynamic(content));
697 ps.setLong(4, id_);
698
699 ps.executeUpdate();
700 }
701 finally {
702 DataAccess.cleanUp(con, ps);
703 }
704 }
705
706 protected void updateJournalArticles(long companyId) throws Exception {
707 Connection con = null;
708 PreparedStatement ps = null;
709 ResultSet rs = null;
710
711 try {
712 con = DataAccess.getUpgradeOptimizedConnection();
713
714 ps = con.prepareStatement(
715 "select id_, content from JournalArticle where companyId = " +
716 companyId + " and structureId is NULL or structureId " +
717 "LIKE ''");
718
719 String name = addBasicWebContentStructureAndTemplate(companyId);
720
721 rs = ps.executeQuery();
722
723 while (rs.next()) {
724 long id_ = rs.getLong("id_");
725 String content = rs.getString("content");
726
727 updateJournalArticle(id_, name, name, content);
728 }
729 }
730 finally {
731 DataAccess.cleanUp(con, ps, rs);
732 }
733 }
734
735 private static Log _log = LogFactoryUtil.getLog(UpgradeJournal.class);
736
737 private Map<String, Map<String, Long>> _bitwiseValues =
738 new HashMap<String, Map<String, Long>>();
739 private Map<String, Long> _roleIds = new HashMap<String, Long>();
740
741 }