001
014
015 package com.liferay.portlet.journal.lar;
016
017 import com.liferay.portal.NoSuchImageException;
018 import com.liferay.portal.kernel.dao.orm.QueryUtil;
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.exception.SystemException;
021 import com.liferay.portal.kernel.lar.BasePortletDataHandler;
022 import com.liferay.portal.kernel.lar.PortletDataContext;
023 import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
024 import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
025 import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
026 import com.liferay.portal.kernel.log.Log;
027 import com.liferay.portal.kernel.log.LogFactoryUtil;
028 import com.liferay.portal.kernel.repository.model.FileEntry;
029 import com.liferay.portal.kernel.util.ArrayUtil;
030 import com.liferay.portal.kernel.util.CalendarFactoryUtil;
031 import com.liferay.portal.kernel.util.CharPool;
032 import com.liferay.portal.kernel.util.FileUtil;
033 import com.liferay.portal.kernel.util.GetterUtil;
034 import com.liferay.portal.kernel.util.LocaleUtil;
035 import com.liferay.portal.kernel.util.LocalizationUtil;
036 import com.liferay.portal.kernel.util.MapUtil;
037 import com.liferay.portal.kernel.util.StringBundler;
038 import com.liferay.portal.kernel.util.StringPool;
039 import com.liferay.portal.kernel.util.StringUtil;
040 import com.liferay.portal.kernel.util.Validator;
041 import com.liferay.portal.kernel.workflow.WorkflowConstants;
042 import com.liferay.portal.kernel.xml.Document;
043 import com.liferay.portal.kernel.xml.Element;
044 import com.liferay.portal.kernel.xml.SAXReaderUtil;
045 import com.liferay.portal.model.Group;
046 import com.liferay.portal.model.Image;
047 import com.liferay.portal.model.Layout;
048 import com.liferay.portal.model.RepositoryEntry;
049 import com.liferay.portal.model.User;
050 import com.liferay.portal.service.GroupLocalServiceUtil;
051 import com.liferay.portal.service.ServiceContext;
052 import com.liferay.portal.service.UserLocalServiceUtil;
053 import com.liferay.portal.service.persistence.ImageUtil;
054 import com.liferay.portal.service.persistence.LayoutUtil;
055 import com.liferay.portal.util.PortalUtil;
056 import com.liferay.portal.util.PortletKeys;
057 import com.liferay.portal.util.PropsValues;
058 import com.liferay.portlet.documentlibrary.lar.DLPortletDataHandler;
059 import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
060 import com.liferay.portlet.documentlibrary.util.DLUtil;
061 import com.liferay.portlet.dynamicdatamapping.lar.DDMPortletDataHandler;
062 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
063 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
064 import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
065 import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
066 import com.liferay.portlet.dynamicdatamapping.service.persistence.DDMStructureUtil;
067 import com.liferay.portlet.dynamicdatamapping.service.persistence.DDMTemplateUtil;
068 import com.liferay.portlet.journal.ArticleContentException;
069 import com.liferay.portlet.journal.FeedTargetLayoutFriendlyUrlException;
070 import com.liferay.portlet.journal.NoSuchArticleException;
071 import com.liferay.portlet.journal.model.JournalArticle;
072 import com.liferay.portlet.journal.model.JournalArticleConstants;
073 import com.liferay.portlet.journal.model.JournalArticleImage;
074 import com.liferay.portlet.journal.model.JournalArticleResource;
075 import com.liferay.portlet.journal.model.JournalFeed;
076 import com.liferay.portlet.journal.model.JournalFolder;
077 import com.liferay.portlet.journal.model.JournalFolderConstants;
078 import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
079 import com.liferay.portlet.journal.service.JournalFeedLocalServiceUtil;
080 import com.liferay.portlet.journal.service.JournalFolderLocalServiceUtil;
081 import com.liferay.portlet.journal.service.persistence.JournalArticleImageUtil;
082 import com.liferay.portlet.journal.service.persistence.JournalArticleResourceUtil;
083 import com.liferay.portlet.journal.service.persistence.JournalArticleUtil;
084 import com.liferay.portlet.journal.service.persistence.JournalFeedUtil;
085 import com.liferay.portlet.journal.service.persistence.JournalFolderUtil;
086 import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
087 import com.liferay.portlet.journal.util.comparator.StructurePKComparator;
088
089 import java.io.File;
090
091 import java.util.ArrayList;
092 import java.util.Calendar;
093 import java.util.Collections;
094 import java.util.Date;
095 import java.util.HashMap;
096 import java.util.List;
097 import java.util.Locale;
098 import java.util.Map;
099 import java.util.regex.Matcher;
100 import java.util.regex.Pattern;
101
102 import javax.portlet.PortletPreferences;
103
104
134 public class JournalPortletDataHandler extends BasePortletDataHandler {
135
136 public static final String NAMESPACE = "journal";
137
138 public static void exportArticle(
139 PortletDataContext portletDataContext, Element articlesElement,
140 Element ddmStructuresElement, Element ddmTemplatesElement,
141 Element dlFileEntryTypesElement, Element dlFoldersElement,
142 Element dlFileEntriesElement, Element dlFileRanksElement,
143 Element dlRepositoriesElement, Element dlRepositoryEntriesElement,
144 JournalArticle article, boolean checkDateRange)
145 throws Exception {
146
147 if (checkDateRange &&
148 !portletDataContext.isWithinDateRange(article.getModifiedDate())) {
149
150 return;
151 }
152
153 if ((article.getStatus() != WorkflowConstants.STATUS_APPROVED) &&
154 (article.getStatus() != WorkflowConstants.STATUS_EXPIRED)) {
155
156 return;
157 }
158
159 String path = getArticlePath(portletDataContext, article);
160
161 if (!portletDataContext.isPathNotProcessed(path)) {
162 return;
163 }
164
165
166
167
168 article = (JournalArticle)article.clone();
169
170 Element articleElement = (Element)articlesElement.selectSingleNode(
171 "
172
173 if (articleElement == null) {
174 articleElement = articlesElement.addElement("article");
175 }
176
177 articleElement.addAttribute(
178 "article-resource-uuid", article.getArticleResourceUuid());
179
180 if (Validator.isNotNull(article.getStructureId())) {
181 DDMStructure ddmStructure =
182 DDMStructureLocalServiceUtil.getStructure(
183 article.getGroupId(),
184 PortalUtil.getClassNameId(JournalArticle.class),
185 article.getStructureId(), true);
186
187 articleElement.addAttribute(
188 "ddm-structure-uuid", ddmStructure.getUuid());
189
190 StagedModelDataHandlerUtil.exportStagedModel(
191 portletDataContext, ddmStructuresElement, ddmStructure);
192 }
193
194 if (Validator.isNotNull(article.getTemplateId())) {
195 DDMTemplate ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
196 article.getGroupId(),
197 PortalUtil.getClassNameId(DDMStructure.class),
198 article.getTemplateId(), true);
199
200 articleElement.addAttribute(
201 "ddm-template-uuid", ddmTemplate.getUuid());
202
203 StagedModelDataHandlerUtil.exportStagedModel(
204 portletDataContext,
205 new Element[] {
206 ddmTemplatesElement, dlFileEntryTypesElement,
207 dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
208 dlRepositoriesElement, dlRepositoryEntriesElement
209 },
210 ddmTemplate);
211 }
212
213 if (article.isSmallImage()) {
214 Image smallImage = ImageUtil.fetchByPrimaryKey(
215 article.getSmallImageId());
216
217 if (Validator.isNotNull(article.getSmallImageURL())) {
218 String smallImageURL =
219 DDMPortletDataHandler.exportReferencedContent(
220 portletDataContext, dlFileEntryTypesElement,
221 dlFoldersElement, dlFileEntriesElement,
222 dlFileRanksElement, dlRepositoriesElement,
223 dlRepositoryEntriesElement, articleElement,
224 article.getSmallImageURL().concat(StringPool.SPACE));
225
226 article.setSmallImageURL(smallImageURL);
227 }
228 else if (smallImage != null) {
229 String smallImagePath = getArticleSmallImagePath(
230 portletDataContext, article);
231
232 articleElement.addAttribute("small-image-path", smallImagePath);
233
234 article.setSmallImageType(smallImage.getType());
235
236 portletDataContext.addZipEntry(
237 smallImagePath, smallImage.getTextObj());
238 }
239 }
240
241 if (portletDataContext.getBooleanParameter(NAMESPACE, "images")) {
242 String imagePath = getArticleImagePath(portletDataContext, article);
243
244 articleElement.addAttribute("image-path", imagePath);
245
246 List<JournalArticleImage> articleImages =
247 JournalArticleImageUtil.findByG_A_V(
248 article.getGroupId(), article.getArticleId(),
249 article.getVersion());
250
251 for (JournalArticleImage articleImage : articleImages) {
252 Image image = null;
253
254 try {
255 image = ImageUtil.findByPrimaryKey(
256 articleImage.getArticleImageId());
257 }
258 catch (NoSuchImageException nsie) {
259 continue;
260 }
261
262 if (image.getTextObj() == null) {
263 continue;
264 }
265
266 String articleImagePath = getArticleImagePath(
267 portletDataContext, article, articleImage, image);
268
269 if (!portletDataContext.isPathNotProcessed(articleImagePath)) {
270 continue;
271 }
272
273 portletDataContext.addZipEntry(
274 articleImagePath, image.getTextObj());
275 }
276 }
277
278 article.setStatusByUserUuid(article.getStatusByUserUuid());
279
280 if (portletDataContext.getBooleanParameter(
281 NAMESPACE, "embedded-assets")) {
282
283 String content = DDMPortletDataHandler.exportReferencedContent(
284 portletDataContext, dlFileEntryTypesElement, dlFoldersElement,
285 dlFileEntriesElement, dlFileRanksElement, dlRepositoriesElement,
286 dlRepositoryEntriesElement, articleElement,
287 article.getContent());
288
289 article.setContent(content);
290 }
291
292 portletDataContext.addClassedModel(
293 articleElement, path, article, NAMESPACE);
294 }
295
296 public static String getArticlePath(
297 PortletDataContext portletDataContext, JournalArticle article)
298 throws Exception {
299
300 StringBundler sb = new StringBundler(8);
301
302 sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
303 sb.append("/articles/");
304 sb.append(article.getArticleResourceUuid());
305 sb.append(StringPool.SLASH);
306 sb.append(article.getVersion());
307 sb.append(StringPool.SLASH);
308 sb.append("article.xml");
309
310 return sb.toString();
311 }
312
313 public static void importArticle(
314 PortletDataContext portletDataContext, Element articleElement)
315 throws Exception {
316
317 String path = articleElement.attributeValue("path");
318
319 if (!portletDataContext.isPathNotProcessed(path)) {
320 return;
321 }
322
323 JournalArticle article =
324 (JournalArticle)portletDataContext.getZipEntryAsObject(
325 articleElement, path);
326
327 prepareLanguagesForImport(article);
328
329 long userId = portletDataContext.getUserId(article.getUserUuid());
330
331 JournalCreationStrategy creationStrategy =
332 JournalCreationStrategyFactory.getInstance();
333
334 long authorId = creationStrategy.getAuthorUserId(
335 portletDataContext, article);
336
337 if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
338 userId = authorId;
339 }
340
341 User user = UserLocalServiceUtil.getUser(userId);
342
343 Map<Long, Long> folderIds =
344 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
345 JournalFolder.class);
346
347 long folderId = MapUtil.getLong(
348 folderIds, article.getFolderId(), article.getFolderId());
349
350 if ((folderId != JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) &&
351 (folderId == article.getFolderId())) {
352
353 String folderPath = getImportFolderPath(
354 portletDataContext, folderId);
355
356 JournalFolder folder =
357 (JournalFolder)portletDataContext.getZipEntryAsObject(
358 folderPath);
359
360 importFolder(portletDataContext, folderPath, folder);
361
362 folderId = MapUtil.getLong(
363 folderIds, article.getFolderId(), article.getFolderId());
364 }
365
366 String articleId = article.getArticleId();
367 boolean autoArticleId = false;
368
369 if (Validator.isNumber(articleId) ||
370 (JournalArticleUtil.fetchByG_A_V(
371 portletDataContext.getScopeGroupId(), articleId,
372 JournalArticleConstants.VERSION_DEFAULT) != null)) {
373
374 autoArticleId = true;
375 }
376
377 Map<String, String> articleIds =
378 (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
379 JournalArticle.class + ".articleId");
380
381 String newArticleId = articleIds.get(articleId);
382
383 if (Validator.isNotNull(newArticleId)) {
384
385
386
387
388 articleId = newArticleId;
389 autoArticleId = false;
390 }
391
392 String content = article.getContent();
393
394 content = importReferencedContent(
395 portletDataContext, articleElement, content);
396
397 article.setContent(content);
398
399 String newContent = creationStrategy.getTransformedContent(
400 portletDataContext, article);
401
402 if (newContent != JournalCreationStrategy.ARTICLE_CONTENT_UNCHANGED) {
403 article.setContent(newContent);
404 }
405
406 Map<String, String> ddmStructureKeys =
407 (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
408 DDMStructure.class);
409
410 String parentDDMStructureKey = MapUtil.getString(
411 ddmStructureKeys, article.getStructureId(),
412 article.getStructureId());
413
414 Map<String, String> ddmTemplateKeys =
415 (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
416 DDMTemplate.class);
417
418 String parentDDMTemplateKey = MapUtil.getString(
419 ddmTemplateKeys, article.getTemplateId(), article.getTemplateId());
420
421 Date displayDate = article.getDisplayDate();
422
423 int displayDateMonth = 0;
424 int displayDateDay = 0;
425 int displayDateYear = 0;
426 int displayDateHour = 0;
427 int displayDateMinute = 0;
428
429 if (displayDate != null) {
430 Calendar displayCal = CalendarFactoryUtil.getCalendar(
431 user.getTimeZone());
432
433 displayCal.setTime(displayDate);
434
435 displayDateMonth = displayCal.get(Calendar.MONTH);
436 displayDateDay = displayCal.get(Calendar.DATE);
437 displayDateYear = displayCal.get(Calendar.YEAR);
438 displayDateHour = displayCal.get(Calendar.HOUR);
439 displayDateMinute = displayCal.get(Calendar.MINUTE);
440
441 if (displayCal.get(Calendar.AM_PM) == Calendar.PM) {
442 displayDateHour += 12;
443 }
444 }
445
446 Date expirationDate = article.getExpirationDate();
447
448 int expirationDateMonth = 0;
449 int expirationDateDay = 0;
450 int expirationDateYear = 0;
451 int expirationDateHour = 0;
452 int expirationDateMinute = 0;
453 boolean neverExpire = true;
454
455 if (expirationDate != null) {
456 Calendar expirationCal = CalendarFactoryUtil.getCalendar(
457 user.getTimeZone());
458
459 expirationCal.setTime(expirationDate);
460
461 expirationDateMonth = expirationCal.get(Calendar.MONTH);
462 expirationDateDay = expirationCal.get(Calendar.DATE);
463 expirationDateYear = expirationCal.get(Calendar.YEAR);
464 expirationDateHour = expirationCal.get(Calendar.HOUR);
465 expirationDateMinute = expirationCal.get(Calendar.MINUTE);
466 neverExpire = false;
467
468 if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
469 expirationDateHour += 12;
470 }
471 }
472
473 Date reviewDate = article.getReviewDate();
474
475 int reviewDateMonth = 0;
476 int reviewDateDay = 0;
477 int reviewDateYear = 0;
478 int reviewDateHour = 0;
479 int reviewDateMinute = 0;
480 boolean neverReview = true;
481
482 if (reviewDate != null) {
483 Calendar reviewCal = CalendarFactoryUtil.getCalendar(
484 user.getTimeZone());
485
486 reviewCal.setTime(reviewDate);
487
488 reviewDateMonth = reviewCal.get(Calendar.MONTH);
489 reviewDateDay = reviewCal.get(Calendar.DATE);
490 reviewDateYear = reviewCal.get(Calendar.YEAR);
491 reviewDateHour = reviewCal.get(Calendar.HOUR);
492 reviewDateMinute = reviewCal.get(Calendar.MINUTE);
493 neverReview = false;
494
495 if (reviewCal.get(Calendar.AM_PM) == Calendar.PM) {
496 reviewDateHour += 12;
497 }
498 }
499
500 long ddmStructureId = 0;
501
502 if (Validator.isNotNull(article.getStructureId())) {
503 String ddmStructureUuid = articleElement.attributeValue(
504 "ddm-structure-uuid");
505
506 DDMStructure existingDDMStructure = DDMStructureUtil.fetchByUUID_G(
507 ddmStructureUuid, portletDataContext.getScopeGroupId());
508
509 if (existingDDMStructure == null) {
510 Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
511 portletDataContext.getCompanyId());
512
513 long companyGroupId = companyGroup.getGroupId();
514
515 existingDDMStructure = DDMStructureUtil.fetchByUUID_G(
516 ddmStructureUuid, companyGroupId);
517 }
518
519 if (existingDDMStructure == null) {
520 String newStructureId = ddmStructureKeys.get(
521 article.getStructureId());
522
523 if (Validator.isNotNull(newStructureId)) {
524 existingDDMStructure = DDMStructureUtil.fetchByG_C_S(
525 portletDataContext.getScopeGroupId(),
526 PortalUtil.getClassNameId(JournalArticle.class),
527 String.valueOf(newStructureId));
528 }
529
530 if (existingDDMStructure == null) {
531 if (_log.isWarnEnabled()) {
532 StringBundler sb = new StringBundler();
533
534 sb.append("Structure ");
535 sb.append(article.getStructureId());
536 sb.append(" is missing for article ");
537 sb.append(article.getArticleId());
538 sb.append(", skipping this article.");
539
540 _log.warn(sb.toString());
541 }
542
543 return;
544 }
545 }
546
547 ddmStructureId = existingDDMStructure.getStructureId();
548
549 parentDDMStructureKey = existingDDMStructure.getStructureKey();
550 }
551
552 if (Validator.isNotNull(article.getTemplateId())) {
553 String ddmTemplateUuid = articleElement.attributeValue(
554 "ddm-template-uuid");
555
556 DDMTemplate existingDDMTemplate = DDMTemplateUtil.fetchByUUID_G(
557 ddmTemplateUuid, portletDataContext.getScopeGroupId());
558
559 if (existingDDMTemplate == null) {
560 Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
561 portletDataContext.getCompanyId());
562
563 long companyGroupId = companyGroup.getGroupId();
564
565 existingDDMTemplate = DDMTemplateUtil.fetchByUUID_G(
566 ddmTemplateUuid, companyGroupId);
567 }
568
569 if (existingDDMTemplate == null) {
570 String newTemplateId = ddmTemplateKeys.get(
571 article.getTemplateId());
572
573 if (Validator.isNotNull(newTemplateId)) {
574 existingDDMTemplate = DDMTemplateUtil.fetchByG_C_T(
575 portletDataContext.getScopeGroupId(),
576 PortalUtil.getClassNameId(DDMStructure.class),
577 newTemplateId);
578 }
579
580 if (existingDDMTemplate == null) {
581 if (_log.isWarnEnabled()) {
582 StringBundler sb = new StringBundler();
583
584 sb.append("Template ");
585 sb.append(article.getTemplateId());
586 sb.append(" is missing for article ");
587 sb.append(article.getArticleId());
588 sb.append(", skipping this article.");
589
590 _log.warn(sb.toString());
591 }
592
593 return;
594 }
595 }
596
597 parentDDMTemplateKey = existingDDMTemplate.getTemplateKey();
598 }
599
600 File smallFile = null;
601
602 if (article.isSmallImage()) {
603 String smallImagePath = articleElement.attributeValue(
604 "small-image-path");
605
606 if (Validator.isNotNull(article.getSmallImageURL())) {
607 String smallImageURL = importReferencedContent(
608 portletDataContext, articleElement,
609 article.getSmallImageURL());
610
611 article.setSmallImageURL(smallImageURL);
612 }
613 else if (Validator.isNotNull(smallImagePath)) {
614 byte[] bytes = portletDataContext.getZipEntryAsByteArray(
615 smallImagePath);
616
617 if (bytes != null) {
618 smallFile = FileUtil.createTempFile(
619 article.getSmallImageType());
620
621 FileUtil.write(smallFile, bytes);
622 }
623 }
624 }
625
626 Map<String, byte[]> images = new HashMap<String, byte[]>();
627
628 String imagePath = articleElement.attributeValue("image-path");
629
630 if (portletDataContext.getBooleanParameter(NAMESPACE, "images") &&
631 Validator.isNotNull(imagePath)) {
632
633 List<String> imageFiles = portletDataContext.getZipFolderEntries(
634 imagePath);
635
636 for (String imageFile : imageFiles) {
637 String fileName = imageFile;
638
639 if (fileName.contains(StringPool.SLASH)) {
640 fileName = fileName.substring(
641 fileName.lastIndexOf(CharPool.SLASH) + 1);
642 }
643
644 if (fileName.endsWith(".xml")) {
645 continue;
646 }
647
648 int pos = fileName.lastIndexOf(CharPool.PERIOD);
649
650 if (pos != -1) {
651 fileName = fileName.substring(0, pos);
652 }
653
654 images.put(
655 fileName,
656 portletDataContext.getZipEntryAsByteArray(imageFile));
657 }
658 }
659
660 String articleURL = null;
661
662 boolean addGroupPermissions = creationStrategy.addGroupPermissions(
663 portletDataContext, article);
664 boolean addGuestPermissions = creationStrategy.addGuestPermissions(
665 portletDataContext, article);
666
667 ServiceContext serviceContext = portletDataContext.createServiceContext(
668 articleElement, article, NAMESPACE);
669
670 serviceContext.setAddGroupPermissions(addGroupPermissions);
671 serviceContext.setAddGuestPermissions(addGuestPermissions);
672
673 if (article.getStatus() != WorkflowConstants.STATUS_APPROVED) {
674 serviceContext.setWorkflowAction(
675 WorkflowConstants.ACTION_SAVE_DRAFT);
676 }
677
678 JournalArticle importedArticle = null;
679
680 String articleResourceUuid = articleElement.attributeValue(
681 "article-resource-uuid");
682
683 if (portletDataContext.isDataStrategyMirror()) {
684 JournalArticleResource articleResource =
685 JournalArticleResourceUtil.fetchByUUID_G(
686 articleResourceUuid, portletDataContext.getScopeGroupId());
687
688 if (articleResource == null) {
689 Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
690 portletDataContext.getCompanyId());
691
692 long companyGroupId = companyGroup.getGroupId();
693
694 articleResource = JournalArticleResourceUtil.fetchByUUID_G(
695 articleResourceUuid, companyGroupId);
696 }
697
698 serviceContext.setUuid(articleResourceUuid);
699 serviceContext.setAttribute("urlTitle", article.getUrlTitle());
700
701 JournalArticle existingArticle = null;
702
703 if (articleResource != null) {
704 try {
705 existingArticle =
706 JournalArticleLocalServiceUtil.getLatestArticle(
707 articleResource.getResourcePrimKey(),
708 WorkflowConstants.STATUS_ANY, false);
709 }
710 catch (NoSuchArticleException nsae) {
711 }
712 }
713
714 if (existingArticle == null) {
715 existingArticle = JournalArticleUtil.fetchByG_A_V(
716 portletDataContext.getScopeGroupId(), newArticleId,
717 article.getVersion());
718 }
719
720 if (existingArticle == null) {
721 importedArticle = JournalArticleLocalServiceUtil.addArticle(
722 userId, portletDataContext.getScopeGroupId(), folderId,
723 article.getClassNameId(), ddmStructureId, articleId,
724 autoArticleId, article.getVersion(), article.getTitleMap(),
725 article.getDescriptionMap(), article.getContent(),
726 article.getType(), parentDDMStructureKey,
727 parentDDMTemplateKey, article.getLayoutUuid(),
728 displayDateMonth, displayDateDay, displayDateYear,
729 displayDateHour, displayDateMinute, expirationDateMonth,
730 expirationDateDay, expirationDateYear, expirationDateHour,
731 expirationDateMinute, neverExpire, reviewDateMonth,
732 reviewDateDay, reviewDateYear, reviewDateHour,
733 reviewDateMinute, neverReview, article.isIndexable(),
734 article.isSmallImage(), article.getSmallImageURL(),
735 smallFile, images, articleURL, serviceContext);
736 }
737 else {
738 importedArticle = JournalArticleLocalServiceUtil.updateArticle(
739 userId, existingArticle.getGroupId(), folderId,
740 existingArticle.getArticleId(), article.getVersion(),
741 article.getTitleMap(), article.getDescriptionMap(),
742 article.getContent(), article.getType(),
743 parentDDMStructureKey, parentDDMTemplateKey,
744 article.getLayoutUuid(), displayDateMonth, displayDateDay,
745 displayDateYear, displayDateHour, displayDateMinute,
746 expirationDateMonth, expirationDateDay, expirationDateYear,
747 expirationDateHour, expirationDateMinute, neverExpire,
748 reviewDateMonth, reviewDateDay, reviewDateYear,
749 reviewDateHour, reviewDateMinute, neverReview,
750 article.isIndexable(), article.isSmallImage(),
751 article.getSmallImageURL(), smallFile, images, articleURL,
752 serviceContext);
753 }
754 }
755 else {
756 importedArticle = JournalArticleLocalServiceUtil.addArticle(
757 userId, portletDataContext.getScopeGroupId(), folderId,
758 article.getClassNameId(), ddmStructureId, articleId,
759 autoArticleId, article.getVersion(), article.getTitleMap(),
760 article.getDescriptionMap(), article.getContent(),
761 article.getType(), parentDDMStructureKey, parentDDMTemplateKey,
762 article.getLayoutUuid(), displayDateMonth, displayDateDay,
763 displayDateYear, displayDateHour, displayDateMinute,
764 expirationDateMonth, expirationDateDay, expirationDateYear,
765 expirationDateHour, expirationDateMinute, neverExpire,
766 reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
767 reviewDateMinute, neverReview, article.isIndexable(),
768 article.isSmallImage(), article.getSmallImageURL(), smallFile,
769 images, articleURL, serviceContext);
770 }
771
772 if (smallFile != null) {
773 smallFile.delete();
774 }
775
776 portletDataContext.importClassedModel(
777 article, importedArticle, NAMESPACE);
778
779 if (Validator.isNull(newArticleId)) {
780 articleIds.put(
781 article.getArticleId(), importedArticle.getArticleId());
782 }
783
784 if (!articleId.equals(importedArticle.getArticleId())) {
785 if (_log.isWarnEnabled()) {
786 _log.warn(
787 "An article with the ID " + articleId + " already " +
788 "exists. The new generated ID is " +
789 importedArticle.getArticleId());
790 }
791 }
792 }
793
794 public static void importFeed(
795 PortletDataContext portletDataContext, Element feedElement)
796 throws Exception {
797
798 String path = feedElement.attributeValue("path");
799
800 if (!portletDataContext.isPathNotProcessed(path)) {
801 return;
802 }
803
804 JournalFeed feed = (JournalFeed)portletDataContext.getZipEntryAsObject(
805 path);
806
807 long userId = portletDataContext.getUserId(feed.getUserUuid());
808
809 JournalCreationStrategy creationStrategy =
810 JournalCreationStrategyFactory.getInstance();
811
812 long authorId = creationStrategy.getAuthorUserId(
813 portletDataContext, feed);
814
815 if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
816 userId = authorId;
817 }
818
819 Group group = GroupLocalServiceUtil.getGroup(
820 portletDataContext.getScopeGroupId());
821
822 String newGroupFriendlyURL = group.getFriendlyURL().substring(1);
823
824 String[] friendlyUrlParts = StringUtil.split(
825 feed.getTargetLayoutFriendlyUrl(), '/');
826
827 String oldGroupFriendlyURL = friendlyUrlParts[2];
828
829 if (oldGroupFriendlyURL.equals("@data_handler_group_friendly_url@")) {
830 feed.setTargetLayoutFriendlyUrl(
831 StringUtil.replace(
832 feed.getTargetLayoutFriendlyUrl(),
833 "@data_handler_group_friendly_url@", newGroupFriendlyURL));
834 }
835
836 String feedId = feed.getFeedId();
837 boolean autoFeedId = false;
838
839 if (Validator.isNumber(feedId) ||
840 (JournalFeedUtil.fetchByG_F(
841 portletDataContext.getScopeGroupId(), feedId) != null)) {
842
843 autoFeedId = true;
844 }
845
846 Map<String, String> ddmStructureKeys =
847 (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
848 DDMStructure.class + ".structureKey");
849
850 String parentDDMStructureKey = MapUtil.getString(
851 ddmStructureKeys, feed.getStructureId(), feed.getStructureId());
852
853 Map<String, String> ddmTemplateKeys =
854 (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
855 DDMTemplate.class + ".templateKey");
856
857 String parentDDMTemplateKey = MapUtil.getString(
858 ddmTemplateKeys, feed.getTemplateId(), feed.getTemplateId());
859 String parentRenderDDMTemplateKey = MapUtil.getString(
860 ddmTemplateKeys, feed.getRendererTemplateId(),
861 feed.getRendererTemplateId());
862
863 boolean addGroupPermissions = creationStrategy.addGroupPermissions(
864 portletDataContext, feed);
865 boolean addGuestPermissions = creationStrategy.addGuestPermissions(
866 portletDataContext, feed);
867
868 ServiceContext serviceContext = portletDataContext.createServiceContext(
869 feedElement, feed, NAMESPACE);
870
871 serviceContext.setAddGroupPermissions(addGroupPermissions);
872 serviceContext.setAddGuestPermissions(addGuestPermissions);
873
874 JournalFeed importedFeed = null;
875
876 try {
877 if (portletDataContext.isDataStrategyMirror()) {
878 JournalFeed existingFeed = JournalFeedUtil.fetchByUUID_G(
879 feed.getUuid(), portletDataContext.getScopeGroupId());
880
881 if (existingFeed == null) {
882 serviceContext.setUuid(feed.getUuid());
883
884 importedFeed = JournalFeedLocalServiceUtil.addFeed(
885 userId, portletDataContext.getScopeGroupId(), feedId,
886 autoFeedId, feed.getName(), feed.getDescription(),
887 feed.getType(), parentDDMStructureKey,
888 parentDDMTemplateKey, parentRenderDDMTemplateKey,
889 feed.getDelta(), feed.getOrderByCol(),
890 feed.getOrderByType(),
891 feed.getTargetLayoutFriendlyUrl(),
892 feed.getTargetPortletId(), feed.getContentField(),
893 feed.getFeedFormat(), feed.getFeedVersion(),
894 serviceContext);
895 }
896 else {
897 importedFeed = JournalFeedLocalServiceUtil.updateFeed(
898 existingFeed.getGroupId(), existingFeed.getFeedId(),
899 feed.getName(), feed.getDescription(), feed.getType(),
900 parentDDMStructureKey, parentDDMTemplateKey,
901 parentRenderDDMTemplateKey, feed.getDelta(),
902 feed.getOrderByCol(), feed.getOrderByType(),
903 feed.getTargetLayoutFriendlyUrl(),
904 feed.getTargetPortletId(), feed.getContentField(),
905 feed.getFeedFormat(), feed.getFeedVersion(),
906 serviceContext);
907 }
908 }
909 else {
910 importedFeed = JournalFeedLocalServiceUtil.addFeed(
911 userId, portletDataContext.getScopeGroupId(), feedId,
912 autoFeedId, feed.getName(), feed.getDescription(),
913 feed.getType(), parentDDMStructureKey, parentDDMTemplateKey,
914 parentRenderDDMTemplateKey, feed.getDelta(),
915 feed.getOrderByCol(), feed.getOrderByType(),
916 feed.getTargetLayoutFriendlyUrl(),
917 feed.getTargetPortletId(), feed.getContentField(),
918 feed.getFeedFormat(), feed.getFeedVersion(),
919 serviceContext);
920 }
921
922 portletDataContext.importClassedModel(
923 feed, importedFeed, NAMESPACE);
924
925 if (!feedId.equals(importedFeed.getFeedId())) {
926 if (_log.isWarnEnabled()) {
927 StringBundler sb = new StringBundler(5);
928
929 sb.append("A feed with the ID ");
930 sb.append(feedId);
931 sb.append(" already exists. The new generated ID is ");
932 sb.append(importedFeed.getFeedId());
933 sb.append(".");
934
935 _log.warn(sb.toString());
936 }
937 }
938 }
939 catch (FeedTargetLayoutFriendlyUrlException ftlfurle) {
940 if (_log.isWarnEnabled()) {
941 StringBundler sb = new StringBundler(6);
942
943 sb.append("A feed with the ID ");
944 sb.append(feedId);
945 sb.append(" cannot be imported because layout with friendly ");
946 sb.append("URL ");
947 sb.append(feed.getTargetLayoutFriendlyUrl());
948 sb.append(" does not exist");
949
950 _log.warn(sb.toString());
951 }
952 }
953 }
954
955 public static String importReferencedContent(
956 PortletDataContext portletDataContext, Element parentElement,
957 String content)
958 throws Exception {
959
960 content = importDLFileEntries(
961 portletDataContext, parentElement, content);
962 content = importLayoutFriendlyURLs(portletDataContext, content);
963 content = importLinksToLayout(portletDataContext, content);
964
965 return content;
966 }
967
968 public static void importReferencedData(
969 PortletDataContext portletDataContext, Element entityElement)
970 throws Exception {
971
972 Element dlRepositoriesElement = entityElement.element(
973 "dl-repositories");
974
975 List<Element> dlRepositoryElements = Collections.emptyList();
976
977 if (dlRepositoriesElement != null) {
978 dlRepositoryElements = dlRepositoriesElement.elements("repository");
979 }
980
981 for (Element repositoryElement : dlRepositoryElements) {
982 DLPortletDataHandler.importRepository(
983 portletDataContext, repositoryElement);
984 }
985
986 Element dlRepositoryEntriesElement = entityElement.element(
987 "dl-repository-entries");
988
989 List<Element> dlRepositoryEntryElements = Collections.emptyList();
990
991 if (dlRepositoryEntriesElement != null) {
992 dlRepositoryEntryElements = dlRepositoryEntriesElement.elements(
993 "repository-entry");
994 }
995
996 for (Element repositoryEntryElement : dlRepositoryEntryElements) {
997 DLPortletDataHandler.importRepositoryEntry(
998 portletDataContext, repositoryEntryElement);
999 }
1000
1001 Element dlFoldersElement = entityElement.element("dl-folders");
1002
1003 List<Element> dlFolderElements = Collections.emptyList();
1004
1005 if (dlFoldersElement != null) {
1006 dlFolderElements = dlFoldersElement.elements("folder");
1007 }
1008
1009 for (Element folderElement : dlFolderElements) {
1010 DLPortletDataHandler.importFolder(
1011 portletDataContext, folderElement);
1012 }
1013
1014 Element dlFileEntriesElement = entityElement.element("dl-file-entries");
1015
1016 List<Element> dlFileEntryElements = Collections.emptyList();
1017
1018 if (dlFileEntriesElement != null) {
1019 dlFileEntryElements = dlFileEntriesElement.elements("file-entry");
1020 }
1021
1022 for (Element fileEntryElement : dlFileEntryElements) {
1023 DLPortletDataHandler.importFileEntry(
1024 portletDataContext, fileEntryElement);
1025 }
1026
1027 Element dlFileRanksElement = entityElement.element("dl-file-ranks");
1028
1029 List<Element> dlFileRankElements = Collections.emptyList();
1030
1031 if (dlFileRanksElement != null) {
1032 dlFileRankElements = dlFileRanksElement.elements("file-rank");
1033 }
1034
1035 for (Element fileRankElement : dlFileRankElements) {
1036 DLPortletDataHandler.importFileRank(
1037 portletDataContext, fileRankElement);
1038 }
1039 }
1040
1041 public JournalPortletDataHandler() {
1042 setAlwaysExportable(true);
1043 setDataLocalized(true);
1044 setExportControls(
1045 new PortletDataHandlerBoolean(NAMESPACE, "web-content"),
1046 new PortletDataHandlerBoolean(
1047 NAMESPACE, "structures-templates-and-feeds", true, true),
1048 new PortletDataHandlerBoolean(NAMESPACE, "embedded-assets"),
1049 new PortletDataHandlerBoolean(
1050 NAMESPACE, "version-history",
1051 PropsValues.JOURNAL_PUBLISH_VERSION_HISTORY_BY_DEFAULT));
1052 setExportMetadataControls(
1053 new PortletDataHandlerBoolean(
1054 NAMESPACE, "web-content", true,
1055 new PortletDataHandlerControl[] {
1056 new PortletDataHandlerBoolean(NAMESPACE, "images"),
1057 new PortletDataHandlerBoolean(NAMESPACE, "categories"),
1058 new PortletDataHandlerBoolean(NAMESPACE, "comments"),
1059 new PortletDataHandlerBoolean(NAMESPACE, "ratings"),
1060 new PortletDataHandlerBoolean(NAMESPACE, "tags")
1061 }));
1062 setImportControls(getExportControls()[0], getExportControls()[1]);
1063 setPublishToLiveByDefault(
1064 PropsValues.JOURNAL_PUBLISH_TO_LIVE_BY_DEFAULT);
1065 }
1066
1067 protected static void exportFeed(
1068 PortletDataContext portletDataContext, Element feedsElement,
1069 JournalFeed feed)
1070 throws Exception {
1071
1072 if (!portletDataContext.isWithinDateRange(feed.getModifiedDate())) {
1073 return;
1074 }
1075
1076 String path = getFeedPath(portletDataContext, feed);
1077
1078 if (!portletDataContext.isPathNotProcessed(path)) {
1079 return;
1080 }
1081
1082 feed = (JournalFeed)feed.clone();
1083
1084 Element feedElement = feedsElement.addElement("feed");
1085
1086 Group group = GroupLocalServiceUtil.getGroup(
1087 portletDataContext.getScopeGroupId());
1088
1089 String newGroupFriendlyURL = group.getFriendlyURL().substring(1);
1090
1091 String[] friendlyUrlParts = StringUtil.split(
1092 feed.getTargetLayoutFriendlyUrl(), '/');
1093
1094 String oldGroupFriendlyURL = friendlyUrlParts[2];
1095
1096 if (newGroupFriendlyURL.equals(oldGroupFriendlyURL)) {
1097 String targetLayoutFriendlyUrl = StringUtil.replaceFirst(
1098 feed.getTargetLayoutFriendlyUrl(),
1099 StringPool.SLASH + newGroupFriendlyURL + StringPool.SLASH,
1100 "/@data_handler_group_friendly_url@/");
1101
1102 feed.setTargetLayoutFriendlyUrl(targetLayoutFriendlyUrl);
1103 }
1104
1105 portletDataContext.addClassedModel(feedElement, path, feed, NAMESPACE);
1106 }
1107
1108 protected static void exportFolder(
1109 PortletDataContext portletDataContext, Element foldersElement,
1110 Element articlesElement, Element ddmStructuresElement,
1111 Element ddmTemplatesElement, Element dlFileEntryTypesElement,
1112 Element dlFoldersElement, Element dlFileEntriesElement,
1113 Element dlFileRanksElement, Element dlRepositoriesElement,
1114 Element dlRepositoryEntriesElement, JournalFolder folder,
1115 boolean checkDateRange)
1116 throws Exception {
1117
1118 if (checkDateRange &&
1119 !portletDataContext.isWithinDateRange(folder.getModifiedDate())) {
1120
1121 return;
1122 }
1123
1124 exportParentFolder(
1125 portletDataContext, foldersElement, folder.getParentFolderId());
1126
1127 String path = getFolderPath(portletDataContext, folder);
1128
1129 if (portletDataContext.isPathNotProcessed(path)) {
1130 Element folderElement = foldersElement.addElement("folder");
1131
1132 portletDataContext.addClassedModel(
1133 folderElement, path, folder, NAMESPACE);
1134 }
1135
1136 List<JournalArticle> articles = JournalArticleUtil.findByG_F(
1137 folder.getGroupId(), folder.getFolderId());
1138
1139 for (JournalArticle article : articles) {
1140 exportArticle(
1141 portletDataContext, articlesElement, ddmStructuresElement,
1142 ddmTemplatesElement, dlFileEntryTypesElement, dlFoldersElement,
1143 dlFileEntriesElement, dlFileRanksElement, dlRepositoriesElement,
1144 dlRepositoryEntriesElement, article, true);
1145 }
1146 }
1147
1148 protected static void exportParentFolder(
1149 PortletDataContext portletDataContext, Element foldersElement,
1150 long folderId)
1151 throws Exception {
1152
1153 if (folderId == JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1154 return;
1155 }
1156
1157 JournalFolder folder = JournalFolderUtil.findByPrimaryKey(folderId);
1158
1159 exportParentFolder(
1160 portletDataContext, foldersElement, folder.getParentFolderId());
1161
1162 String path = getFolderPath(portletDataContext, folder);
1163
1164 if (portletDataContext.isPathNotProcessed(path)) {
1165 Element folderElement = foldersElement.addElement("folder");
1166
1167 portletDataContext.addClassedModel(
1168 folderElement, path, folder, NAMESPACE);
1169 }
1170 }
1171
1172 protected static String getArticleImagePath(
1173 PortletDataContext portletDataContext, JournalArticle article)
1174 throws Exception {
1175
1176 StringBundler sb = new StringBundler(6);
1177
1178 sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
1179 sb.append("/articles/");
1180 sb.append(article.getArticleResourceUuid());
1181 sb.append(StringPool.SLASH);
1182 sb.append(article.getVersion());
1183 sb.append(StringPool.SLASH);
1184
1185 return sb.toString();
1186 }
1187
1188 protected static String getArticleImagePath(
1189 PortletDataContext portletDataContext, JournalArticle article,
1190 JournalArticleImage articleImage, Image image)
1191 throws Exception {
1192
1193 StringBundler sb = new StringBundler(12);
1194
1195 sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
1196 sb.append("/articles/");
1197 sb.append(article.getArticleResourceUuid());
1198 sb.append(StringPool.SLASH);
1199 sb.append(article.getVersion());
1200 sb.append(StringPool.SLASH);
1201 sb.append(articleImage.getElInstanceId());
1202 sb.append(StringPool.UNDERLINE);
1203 sb.append(articleImage.getElName());
1204
1205 if (Validator.isNotNull(articleImage.getLanguageId())) {
1206 sb.append(articleImage.getLanguageId());
1207 }
1208
1209 sb.append(StringPool.PERIOD);
1210 sb.append(image.getType());
1211
1212 return sb.toString();
1213 }
1214
1215 protected static String getArticleSmallImagePath(
1216 PortletDataContext portletDataContext, JournalArticle article)
1217 throws Exception {
1218
1219 StringBundler sb = new StringBundler(6);
1220
1221 sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
1222 sb.append("/articles/");
1223 sb.append(article.getArticleResourceUuid());
1224 sb.append("/thumbnail");
1225 sb.append(StringPool.PERIOD);
1226 sb.append(article.getSmallImageType());
1227
1228 return sb.toString();
1229 }
1230
1231 protected static String getDDMStructurePath(
1232 PortletDataContext portletDataContext, String uuid) {
1233
1234 StringBundler sb = new StringBundler(4);
1235
1236 sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
1237 sb.append("/ddm-structures/");
1238 sb.append(uuid);
1239 sb.append(".xml");
1240
1241 return sb.toString();
1242 }
1243
1244 protected static String getDDMTemplatePath(
1245 PortletDataContext portletDataContext, DDMTemplate ddmTemplate) {
1246
1247 StringBundler sb = new StringBundler(4);
1248
1249 sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
1250 sb.append("/ddm-templates/");
1251 sb.append(ddmTemplate.getUuid());
1252 sb.append(".xml");
1253
1254 return sb.toString();
1255 }
1256
1257 protected static String getFeedPath(
1258 PortletDataContext portletDataContext, JournalFeed feed) {
1259
1260 StringBundler sb = new StringBundler(4);
1261
1262 sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
1263 sb.append("/feeds/");
1264 sb.append(feed.getUuid());
1265 sb.append(".xml");
1266
1267 return sb.toString();
1268 }
1269
1270 protected static String getFolderPath(
1271 PortletDataContext portletDataContext, JournalFolder folder) {
1272
1273 StringBundler sb = new StringBundler(4);
1274
1275 sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
1276 sb.append("/folders/");
1277 sb.append(folder.getFolderId());
1278 sb.append(".xml");
1279
1280 return sb.toString();
1281 }
1282
1283 protected static String getImportFolderPath(
1284 PortletDataContext portletDataContext, long folderId) {
1285
1286 StringBundler sb = new StringBundler(4);
1287
1288 sb.append(portletDataContext.getSourcePortletPath(PortletKeys.JOURNAL));
1289 sb.append("/folders/");
1290 sb.append(folderId);
1291 sb.append(".xml");
1292
1293 return sb.toString();
1294 }
1295
1296 protected static String importDLFileEntries(
1297 PortletDataContext portletDataContext, Element parentElement,
1298 String content)
1299 throws Exception {
1300
1301 List<Element> dlReferenceElements = parentElement.elements(
1302 "dl-reference");
1303
1304 for (Element dlReferenceElement : dlReferenceElements) {
1305 String dlReferencePath = dlReferenceElement.attributeValue("path");
1306
1307 String fileEntryUUID = null;
1308
1309 try {
1310 Object zipEntryObject = portletDataContext.getZipEntryAsObject(
1311 dlReferencePath);
1312
1313 if (zipEntryObject == null) {
1314 if (_log.isWarnEnabled()) {
1315 _log.warn("Unable to reference " + dlReferencePath);
1316 }
1317
1318 continue;
1319 }
1320
1321 boolean defaultRepository = GetterUtil.getBoolean(
1322 dlReferenceElement.attributeValue("default-repository"));
1323
1324 if (defaultRepository) {
1325 FileEntry fileEntry = (FileEntry)zipEntryObject;
1326
1327 fileEntryUUID = fileEntry.getUuid();
1328 }
1329 else {
1330 RepositoryEntry repositoryEntry =
1331 (RepositoryEntry)zipEntryObject;
1332
1333 fileEntryUUID = repositoryEntry.getUuid();
1334 }
1335 }
1336 catch (Exception e) {
1337 if (_log.isDebugEnabled()) {
1338 _log.debug(e, e);
1339 }
1340 else if (_log.isWarnEnabled()) {
1341 _log.warn(e.getMessage());
1342 }
1343 }
1344
1345 if (fileEntryUUID == null) {
1346 continue;
1347 }
1348
1349 FileEntry fileEntry =
1350 DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
1351 fileEntryUUID, portletDataContext.getScopeGroupId());
1352
1353 if (fileEntry == null) {
1354 continue;
1355 }
1356
1357 String dlReference = "[$dl-reference=" + dlReferencePath + "$]";
1358
1359 String url = DLUtil.getPreviewURL(
1360 fileEntry, fileEntry.getFileVersion(), null, StringPool.BLANK,
1361 false, false);
1362
1363 content = StringUtil.replace(content, dlReference, url);
1364 }
1365
1366 return content;
1367 }
1368
1369 protected static void importFolder(
1370 PortletDataContext portletDataContext, Element folderElement)
1371 throws Exception {
1372
1373 String path = folderElement.attributeValue("path");
1374
1375 if (!portletDataContext.isPathNotProcessed(path)) {
1376 return;
1377 }
1378
1379 JournalFolder folder =
1380 (JournalFolder)portletDataContext.getZipEntryAsObject(path);
1381
1382 importFolder(portletDataContext, path, folder);
1383 }
1384
1385 protected static void importFolder(
1386 PortletDataContext portletDataContext, String folderPath,
1387 JournalFolder folder)
1388 throws Exception {
1389
1390 long userId = portletDataContext.getUserId(folder.getUserUuid());
1391
1392 Map<Long, Long> folderIds =
1393 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
1394 JournalFolder.class);
1395
1396 long parentFolderId = MapUtil.getLong(
1397 folderIds, folder.getParentFolderId(), folder.getParentFolderId());
1398
1399 if ((parentFolderId !=
1400 JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) &&
1401 (parentFolderId == folder.getParentFolderId())) {
1402
1403 String path = getImportFolderPath(
1404 portletDataContext, parentFolderId);
1405
1406 JournalFolder parentFolder =
1407 (JournalFolder)portletDataContext.getZipEntryAsObject(path);
1408
1409 importFolder(portletDataContext, path, parentFolder);
1410
1411 parentFolderId = MapUtil.getLong(
1412 folderIds, folder.getParentFolderId(),
1413 folder.getParentFolderId());
1414 }
1415
1416 ServiceContext serviceContext = portletDataContext.createServiceContext(
1417 folderPath, folder, NAMESPACE);
1418
1419 JournalFolder importedFolder = null;
1420
1421 long groupId = portletDataContext.getScopeGroupId();
1422
1423 if (portletDataContext.isDataStrategyMirror()) {
1424 JournalFolder existingFolder = JournalFolderUtil.fetchByUUID_G(
1425 folder.getUuid(), groupId);
1426
1427 if (existingFolder == null) {
1428 serviceContext.setUuid(folder.getUuid());
1429
1430 importedFolder = JournalFolderLocalServiceUtil.addFolder(
1431 userId, groupId, parentFolderId, folder.getName(),
1432 folder.getDescription(), serviceContext);
1433 }
1434 else {
1435 importedFolder = JournalFolderLocalServiceUtil.updateFolder(
1436 userId, existingFolder.getFolderId(), parentFolderId,
1437 folder.getName(), folder.getDescription(), false,
1438 serviceContext);
1439 }
1440 }
1441 else {
1442 importedFolder = JournalFolderLocalServiceUtil.addFolder(
1443 userId, groupId, parentFolderId, folder.getName(),
1444 folder.getDescription(), serviceContext);
1445 }
1446
1447 portletDataContext.importClassedModel(
1448 folder, importedFolder, NAMESPACE);
1449 }
1450
1451 protected static String importLayoutFriendlyURLs(
1452 PortletDataContext portletDataContext, String content)
1453 throws Exception {
1454
1455 String privateGroupServletMapping =
1456 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
1457 String privateUserServletMapping =
1458 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
1459 String publicServletMapping =
1460 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
1461
1462 String portalContextPath = PortalUtil.getPathContext();
1463
1464 if (Validator.isNotNull(portalContextPath)) {
1465 privateGroupServletMapping = portalContextPath.concat(
1466 privateGroupServletMapping);
1467 privateUserServletMapping = portalContextPath.concat(
1468 privateUserServletMapping);
1469 publicServletMapping = portalContextPath.concat(
1470 publicServletMapping);
1471 }
1472
1473 content = StringUtil.replace(
1474 content, "@data_handler_private_group_servlet_mapping@",
1475 privateGroupServletMapping);
1476 content = StringUtil.replace(
1477 content, "@data_handler_private_user_servlet_mapping@",
1478 privateUserServletMapping);
1479 content = StringUtil.replace(
1480 content, "@data_handler_public_servlet_mapping@",
1481 publicServletMapping);
1482
1483 Group group = GroupLocalServiceUtil.getGroup(
1484 portletDataContext.getScopeGroupId());
1485
1486 content = StringUtil.replace(
1487 content, "@data_handler_group_friendly_url@",
1488 group.getFriendlyURL());
1489
1490 return content;
1491 }
1492
1493 protected static String importLinksToLayout(
1494 PortletDataContext portletDataContext, String content)
1495 throws Exception {
1496
1497 List<String> oldLinksToLayout = new ArrayList<String>();
1498 List<String> newLinksToLayout = new ArrayList<String>();
1499
1500 Matcher matcher = _importLinksToLayoutPattern.matcher(content);
1501
1502 while (matcher.find()) {
1503 long oldLayoutId = GetterUtil.getLong(matcher.group(1));
1504
1505 long newLayoutId = oldLayoutId;
1506
1507 String type = matcher.group(2);
1508
1509 boolean privateLayout = type.startsWith("private");
1510
1511 String layoutUuid = matcher.group(3);
1512
1513 String friendlyURL = matcher.group(4);
1514
1515 try {
1516 Layout layout = LayoutUtil.fetchByUUID_G_P(
1517 layoutUuid, portletDataContext.getScopeGroupId(),
1518 privateLayout);
1519
1520 if (layout == null) {
1521 layout = LayoutUtil.fetchByG_P_F(
1522 portletDataContext.getScopeGroupId(), privateLayout,
1523 friendlyURL);
1524 }
1525
1526 if (layout == null) {
1527 layout = LayoutUtil.fetchByG_P_L(
1528 portletDataContext.getScopeGroupId(), privateLayout,
1529 oldLayoutId);
1530 }
1531
1532 if (layout == null) {
1533 if (_log.isWarnEnabled()) {
1534 StringBundler sb = new StringBundler(9);
1535
1536 sb.append("Unable to get layout with UUID ");
1537 sb.append(layoutUuid);
1538 sb.append(", friendly URL ");
1539 sb.append(friendlyURL);
1540 sb.append(", or ");
1541 sb.append("layoutId ");
1542 sb.append(oldLayoutId);
1543 sb.append(" in group ");
1544 sb.append(portletDataContext.getScopeGroupId());
1545
1546 _log.warn(sb.toString());
1547 }
1548 }
1549 else {
1550 newLayoutId = layout.getLayoutId();
1551 }
1552 }
1553 catch (SystemException se) {
1554 if (_log.isWarnEnabled()) {
1555 _log.warn(
1556 "Unable to get layout in group " +
1557 portletDataContext.getScopeGroupId(), se);
1558 }
1559 }
1560
1561 String oldLinkToLayout = matcher.group(0);
1562
1563 StringBundler sb = new StringBundler(4);
1564
1565 sb.append(StringPool.AT);
1566 sb.append(layoutUuid);
1567 sb.append(StringPool.AT);
1568 sb.append(friendlyURL);
1569
1570 String newLinkToLayout = StringUtil.replace(
1571 oldLinkToLayout,
1572 new String[] {sb.toString(), String.valueOf(oldLayoutId)},
1573 new String[] {StringPool.BLANK, String.valueOf(newLayoutId)});
1574
1575 oldLinksToLayout.add(oldLinkToLayout);
1576 newLinksToLayout.add(newLinkToLayout);
1577 }
1578
1579 content = StringUtil.replace(
1580 content, ArrayUtil.toStringArray(oldLinksToLayout.toArray()),
1581 ArrayUtil.toStringArray(newLinksToLayout.toArray()));
1582
1583 return content;
1584 }
1585
1586 protected static void prepareLanguagesForImport(JournalArticle article)
1587 throws PortalException {
1588
1589 Locale articleDefaultLocale = LocaleUtil.fromLanguageId(
1590 article.getDefaultLocale());
1591
1592 Locale[] articleAvailableLocales = LocaleUtil.fromLanguageIds(
1593 article.getAvailableLocales());
1594
1595 Locale defaultImportLocale = LocalizationUtil.getDefaultImportLocale(
1596 JournalArticle.class.getName(), article.getPrimaryKey(),
1597 articleDefaultLocale, articleAvailableLocales);
1598
1599 article.prepareLocalizedFieldsForImport(defaultImportLocale);
1600 }
1601
1602 @Override
1603 protected PortletPreferences doDeleteData(
1604 PortletDataContext portletDataContext, String portletId,
1605 PortletPreferences portletPreferences)
1606 throws Exception {
1607
1608 if (portletDataContext.addPrimaryKey(
1609 JournalPortletDataHandler.class, "deleteData")) {
1610
1611 return portletPreferences;
1612 }
1613
1614 JournalArticleLocalServiceUtil.deleteArticles(
1615 portletDataContext.getScopeGroupId());
1616
1617 DDMTemplateLocalServiceUtil.deleteTemplates(
1618 portletDataContext.getScopeGroupId());
1619
1620 DDMStructureLocalServiceUtil.deleteStructures(
1621 portletDataContext.getScopeGroupId());
1622
1623 return portletPreferences;
1624 }
1625
1626 @Override
1627 protected String doExportData(
1628 PortletDataContext portletDataContext, String portletId,
1629 PortletPreferences portletPreferences)
1630 throws Exception {
1631
1632 portletDataContext.addPermissions(
1633 "com.liferay.portlet.journal",
1634 portletDataContext.getScopeGroupId());
1635
1636 Element rootElement = addExportRootElement();
1637
1638 rootElement.addAttribute(
1639 "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
1640
1641 Element ddmStructuresElement = rootElement.addElement("ddm-structures");
1642
1643 List<DDMStructure> ddmStructures = DDMStructureUtil.findByG_C(
1644 portletDataContext.getScopeGroupId(),
1645 PortalUtil.getClassNameId(JournalArticle.class), QueryUtil.ALL_POS,
1646 QueryUtil.ALL_POS, new StructurePKComparator(true));
1647
1648 List<DDMTemplate> ddmTemplates = new ArrayList<DDMTemplate>();
1649
1650 for (DDMStructure ddmStructure : ddmStructures) {
1651 if (portletDataContext.isWithinDateRange(
1652 ddmStructure.getModifiedDate())) {
1653
1654 StagedModelDataHandlerUtil.exportStagedModel(
1655 portletDataContext, ddmStructuresElement, ddmStructure);
1656 }
1657
1658 ddmTemplates.addAll(ddmStructure.getTemplates());
1659 }
1660
1661 Element ddmTemplatesElement = rootElement.addElement("ddm-templates");
1662 Element dlFileEntryTypesElement = rootElement.addElement(
1663 "dl-file-entry-types");
1664 Element dlFoldersElement = rootElement.addElement("dl-folders");
1665 Element dlFilesElement = rootElement.addElement("dl-file-entries");
1666 Element dlFileRanksElement = rootElement.addElement("dl-file-ranks");
1667 Element dlRepositoriesElement = rootElement.addElement(
1668 "dl-repositories");
1669 Element dlRepositoryEntriesElement = rootElement.addElement(
1670 "dl-repository-entries");
1671
1672 for (DDMTemplate ddmTemplate : ddmTemplates) {
1673 if (portletDataContext.isWithinDateRange(
1674 ddmTemplate.getModifiedDate())) {
1675
1676 StagedModelDataHandlerUtil.exportStagedModel(
1677 portletDataContext, ddmTemplatesElement, ddmTemplate);
1678 }
1679 }
1680
1681 Element feedsElement = rootElement.addElement("feeds");
1682
1683 List<JournalFeed> feeds = JournalFeedUtil.findByGroupId(
1684 portletDataContext.getScopeGroupId());
1685
1686 for (JournalFeed feed : feeds) {
1687 if (portletDataContext.isWithinDateRange(feed.getModifiedDate())) {
1688 exportFeed(portletDataContext, feedsElement, feed);
1689 }
1690 }
1691
1692 Element foldersElement = rootElement.addElement("folders");
1693 Element articlesElement = rootElement.addElement("articles");
1694
1695 if (portletDataContext.getBooleanParameter(NAMESPACE, "web-content")) {
1696 List<JournalFolder> folders = JournalFolderUtil.findByGroupId(
1697 portletDataContext.getScopeGroupId());
1698
1699 for (JournalFolder folder : folders) {
1700 exportFolder(
1701 portletDataContext, foldersElement, articlesElement,
1702 ddmStructuresElement, ddmTemplatesElement,
1703 dlFileEntryTypesElement, dlFoldersElement, dlFilesElement,
1704 dlFileRanksElement, dlRepositoriesElement,
1705 dlRepositoryEntriesElement, folder, true);
1706 }
1707
1708 List<JournalArticle> articles = JournalArticleUtil.findByG_F(
1709 portletDataContext.getScopeGroupId(),
1710 JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID,
1711 QueryUtil.ALL_POS, QueryUtil.ALL_POS,
1712 new ArticleIDComparator(true));
1713
1714 for (JournalArticle article : articles) {
1715 if (portletDataContext.getBooleanParameter(
1716 NAMESPACE, "version-history") ||
1717 JournalArticleLocalServiceUtil.isLatestVersion(
1718 article.getGroupId(), article.getArticleId(),
1719 article.getVersion(),
1720 WorkflowConstants.STATUS_APPROVED)) {
1721
1722 exportArticle(
1723 portletDataContext, articlesElement,
1724 ddmStructuresElement, ddmTemplatesElement,
1725 dlFileEntryTypesElement, dlFoldersElement,
1726 dlFilesElement, dlFileRanksElement,
1727 dlRepositoriesElement, dlRepositoryEntriesElement,
1728 article, true);
1729 }
1730 }
1731 }
1732
1733 return rootElement.formattedString();
1734 }
1735
1736 @Override
1737 protected PortletPreferences doImportData(
1738 PortletDataContext portletDataContext, String portletId,
1739 PortletPreferences portletPreferences, String data)
1740 throws Exception {
1741
1742 portletDataContext.importPermissions(
1743 "com.liferay.portlet.journal",
1744 portletDataContext.getSourceGroupId(),
1745 portletDataContext.getScopeGroupId());
1746
1747 Document document = SAXReaderUtil.read(data);
1748
1749 Element rootElement = document.getRootElement();
1750
1751 importReferencedData(portletDataContext, rootElement);
1752
1753 Element ddmStructuresElement = rootElement.element("ddm-structures");
1754
1755 List<Element> ddmStructureElements = ddmStructuresElement.elements(
1756 "structure");
1757
1758 for (Element ddmStructureElement : ddmStructureElements) {
1759 StagedModelDataHandlerUtil.importStagedModel(
1760 portletDataContext, ddmStructureElement);
1761 }
1762
1763 Element ddmTemplatesElement = rootElement.element("ddm-templates");
1764
1765 List<Element> ddmTemplateElements = ddmTemplatesElement.elements(
1766 "template");
1767
1768 for (Element ddmTemplateElement : ddmTemplateElements) {
1769 StagedModelDataHandlerUtil.importStagedModel(
1770 portletDataContext, ddmTemplateElement);
1771 }
1772
1773 Element feedsElement = rootElement.element("feeds");
1774
1775 List<Element> feedElements = feedsElement.elements("feed");
1776
1777 for (Element feedElement : feedElements) {
1778 importFeed(portletDataContext, feedElement);
1779 }
1780
1781 if (portletDataContext.getBooleanParameter(NAMESPACE, "web-content")) {
1782 Element foldersElement = rootElement.element("folders");
1783
1784 List<Element> folderElements = foldersElement.elements("folder");
1785
1786 for (Element folderElement : folderElements) {
1787 importFolder(portletDataContext, folderElement);
1788 }
1789
1790 Element articlesElement = rootElement.element("articles");
1791
1792 List<Element> articleElements = articlesElement.elements("article");
1793
1794 for (Element articleElement : articleElements) {
1795 try {
1796 importArticle(portletDataContext, articleElement);
1797 }
1798 catch (ArticleContentException ace) {
1799 if (_log.isWarnEnabled()) {
1800 String path = articleElement.attributeValue("path");
1801
1802 _log.warn(
1803 "Skipping article with path " + path +
1804 " because of invalid content");
1805 }
1806 }
1807 }
1808 }
1809
1810 return portletPreferences;
1811 }
1812
1813 private static Log _log = LogFactoryUtil.getLog(
1814 JournalPortletDataHandler.class);
1815
1816 private static Pattern _importLinksToLayoutPattern = Pattern.compile(
1817 "\\[([0-9]+)@(public|private\\-[a-z]*)@(\\p{XDigit}{8}\\-" +
1818 "(?:\\p{XDigit}{4}\\-){3}\\p{XDigit}{12})@([^\\]]*)\\]");
1819
1820 }