1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.journal.lar;
16  
17  import com.liferay.portal.NoSuchImageException;
18  import com.liferay.portal.kernel.dao.orm.QueryUtil;
19  import com.liferay.portal.kernel.exception.PortalException;
20  import com.liferay.portal.kernel.exception.SystemException;
21  import com.liferay.portal.kernel.lar.BasePortletDataHandler;
22  import com.liferay.portal.kernel.lar.PortletDataContext;
23  import com.liferay.portal.kernel.lar.PortletDataException;
24  import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
25  import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
26  import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
27  import com.liferay.portal.kernel.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
30  import com.liferay.portal.kernel.util.CharPool;
31  import com.liferay.portal.kernel.util.FileUtil;
32  import com.liferay.portal.kernel.util.GetterUtil;
33  import com.liferay.portal.kernel.util.MapUtil;
34  import com.liferay.portal.kernel.util.StringBundler;
35  import com.liferay.portal.kernel.util.StringPool;
36  import com.liferay.portal.kernel.util.StringUtil;
37  import com.liferay.portal.kernel.util.Validator;
38  import com.liferay.portal.kernel.workflow.WorkflowConstants;
39  import com.liferay.portal.kernel.xml.Document;
40  import com.liferay.portal.kernel.xml.Element;
41  import com.liferay.portal.kernel.xml.SAXReaderUtil;
42  import com.liferay.portal.model.Group;
43  import com.liferay.portal.model.Image;
44  import com.liferay.portal.model.User;
45  import com.liferay.portal.service.GroupLocalServiceUtil;
46  import com.liferay.portal.service.ServiceContext;
47  import com.liferay.portal.service.UserLocalServiceUtil;
48  import com.liferay.portal.service.persistence.ImageUtil;
49  import com.liferay.portal.util.PortletKeys;
50  import com.liferay.portal.util.PropsValues;
51  import com.liferay.portlet.documentlibrary.lar.DLPortletDataHandlerImpl;
52  import com.liferay.portlet.documentlibrary.model.DLFileEntry;
53  import com.liferay.portlet.documentlibrary.model.DLFileRank;
54  import com.liferay.portlet.documentlibrary.model.DLFolder;
55  import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
56  import com.liferay.portlet.imagegallery.lar.IGPortletDataHandlerImpl;
57  import com.liferay.portlet.imagegallery.model.IGFolder;
58  import com.liferay.portlet.imagegallery.model.IGImage;
59  import com.liferay.portlet.imagegallery.service.IGImageLocalServiceUtil;
60  import com.liferay.portlet.journal.model.JournalArticle;
61  import com.liferay.portlet.journal.model.JournalArticleConstants;
62  import com.liferay.portlet.journal.model.JournalArticleImage;
63  import com.liferay.portlet.journal.model.JournalFeed;
64  import com.liferay.portlet.journal.model.JournalStructure;
65  import com.liferay.portlet.journal.model.JournalTemplate;
66  import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
67  import com.liferay.portlet.journal.service.JournalFeedLocalServiceUtil;
68  import com.liferay.portlet.journal.service.JournalStructureLocalServiceUtil;
69  import com.liferay.portlet.journal.service.JournalTemplateLocalServiceUtil;
70  import com.liferay.portlet.journal.service.persistence.JournalArticleImageUtil;
71  import com.liferay.portlet.journal.service.persistence.JournalArticleUtil;
72  import com.liferay.portlet.journal.service.persistence.JournalFeedUtil;
73  import com.liferay.portlet.journal.service.persistence.JournalStructureUtil;
74  import com.liferay.portlet.journal.service.persistence.JournalTemplateUtil;
75  import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
76  
77  import java.io.File;
78  
79  import java.util.Calendar;
80  import java.util.Date;
81  import java.util.HashMap;
82  import java.util.List;
83  import java.util.Map;
84  
85  import javax.portlet.PortletPreferences;
86  
87  /**
88   * <a href="JournalPortletDataHandlerImpl.java.html"><b><i>View Source</i></b>
89   * </a>
90   *
91   * <p>
92   * Provides the Journal portlet export and import functionality, which is to
93   * clone all articles, structures, and templates associated with the layout's
94   * group. Upon import, new instances of the corresponding articles, structures,
95   * and templates are created or updated according to the DATA_MIRROW strategy
96   * The author of the newly created objects are determined by the
97   * JournalCreationStrategy class defined in <i>portal.properties</i>. That
98   * strategy also allows the text of the journal article to be modified prior to
99   * import.
100  * </p>
101  *
102  * <p>
103  * This <code>PortletDataHandler</code> differs from
104  * <code>JournalContentPortletDataHandlerImpl</code> in that it exports all
105  * articles owned by the group whether or not they are actually displayed in a
106  * portlet in the layout set.
107  * </p>
108  *
109  * @author Raymond Augé
110  * @author Joel Kozikowski
111  * @author Brian Wing Shun Chan
112  * @author Bruno Farache
113  * @author Karthik Sudarshan
114  * @author Wesley Gong
115  * @see    com.liferay.portal.kernel.lar.PortletDataHandler
116  * @see    com.liferay.portlet.journal.lar.JournalContentPortletDataHandlerImpl
117  * @see    com.liferay.portlet.journal.lar.JournalCreationStrategy
118  */
119 public class JournalPortletDataHandlerImpl extends BasePortletDataHandler {
120 
121     public static void exportArticle(
122             PortletDataContext context, Element articlesEl, Element dlFoldersEl,
123             Element dlFileEntriesEl, Element dlFileRanks, Element igFoldersEl,
124             Element igImagesEl, JournalArticle article)
125         throws PortalException, SystemException {
126 
127         if (!context.isWithinDateRange(article.getModifiedDate())) {
128             return;
129         }
130 
131         if (article.getStatus() != WorkflowConstants.STATUS_APPROVED) {
132             return;
133         }
134 
135         String path = getArticlePath(context, article);
136 
137         if (!context.isPathNotProcessed(path)) {
138             return;
139         }
140 
141         // Clone this article to make sure changes to its content are never
142         // persisted
143 
144         article = (JournalArticle)article.clone();
145 
146         Element articleEl = articlesEl.addElement("article");
147 
148         articleEl.addAttribute("path", path);
149 
150         Image smallImage = ImageUtil.fetchByPrimaryKey(
151             article.getSmallImageId());
152 
153         if (article.isSmallImage() && (smallImage != null)) {
154             String smallImagePath = getArticleSmallImagePath(context, article);
155 
156             articleEl.addAttribute("small-image-path", smallImagePath);
157 
158             article.setSmallImageType(smallImage.getType());
159 
160             context.addZipEntry(smallImagePath, smallImage.getTextObj());
161         }
162 
163         if (context.getBooleanParameter(_NAMESPACE, "images")) {
164             String imagePath = getArticleImagePath(context, article);
165 
166             articleEl.addAttribute("image-path", imagePath);
167 
168             List<JournalArticleImage> articleImages =
169                 JournalArticleImageUtil.findByG_A_V(
170                     article.getGroupId(), article.getArticleId(),
171                     article.getVersion());
172 
173             for (JournalArticleImage articleImage : articleImages) {
174                 try {
175                     Image image = ImageUtil.findByPrimaryKey(
176                         articleImage.getArticleImageId());
177 
178                     String articleImagePath = getArticleImagePath(
179                         context, article, articleImage, image);
180 
181                     if (!context.isPathNotProcessed(articleImagePath)) {
182                         continue;
183                     }
184 
185                     context.addZipEntry(articleImagePath, image.getTextObj());
186                 }
187                 catch (NoSuchImageException nsie) {
188                 }
189             }
190         }
191 
192         context.addPermissions(
193             JournalArticle.class, article.getResourcePrimKey());
194 
195         if (context.getBooleanParameter(_NAMESPACE, "categories")) {
196             context.addAssetCategories(
197                 JournalArticle.class, article.getResourcePrimKey());
198         }
199 
200         if (context.getBooleanParameter(_NAMESPACE, "comments")) {
201             context.addComments(
202                 JournalArticle.class, article.getResourcePrimKey());
203         }
204 
205         if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
206             context.addRatingsEntries(
207                 JournalArticle.class, article.getResourcePrimKey());
208         }
209 
210         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
211             context.addAssetTags(
212                 JournalArticle.class, article.getResourcePrimKey());
213         }
214 
215         if (context.getBooleanParameter(_NAMESPACE, "embedded-assets")) {
216             String content = article.getContent();
217 
218             content = exportDLFileEntries(
219                 context, dlFoldersEl, dlFileEntriesEl, dlFileRanks,
220                 article.getGroupId(), content);
221             content = exportIGImages(context, igFoldersEl, igImagesEl,
222                 article.getGroupId(), content);
223             content = exportLayoutFriendlyURLs(article.getGroupId(), content);
224 
225             article.setContent(content);
226         }
227 
228         article.setUserUuid(article.getUserUuid());
229         article.setStatusByUserUuid(article.getStatusByUserUuid());
230 
231         context.addZipEntry(path, article);
232     }
233 
234     public static void exportFeed(
235             PortletDataContext context, Element feedsEl, JournalFeed feed)
236         throws PortalException, SystemException {
237 
238         if (!context.isWithinDateRange(feed.getModifiedDate())) {
239             return;
240         }
241 
242         String path = getFeedPath(context, feed);
243 
244         if (!context.isPathNotProcessed(path)) {
245             return;
246         }
247 
248         Element feedEl = feedsEl.addElement("feed");
249 
250         feedEl.addAttribute("path", path);
251 
252         feed.setUserUuid(feed.getUserUuid());
253 
254         context.addPermissions(JournalFeed.class, feed.getId());
255 
256         context.addZipEntry(path, feed);
257     }
258 
259     public static String exportDLFileEntries(
260         PortletDataContext context, Element foldersEl, Element fileEntriesEl,
261         Element fileRanks, long entityGroupId, String content) {
262 
263         StringBuilder sb = new StringBuilder(content);
264 
265         int beginPos = content.length();
266 
267         while (true) {
268             beginPos = content.lastIndexOf("/get_file?", beginPos);
269 
270             if (beginPos == -1) {
271                 return sb.toString();
272             }
273 
274             int endPos1 = content.indexOf(StringPool.APOSTROPHE, beginPos);
275             int endPos2 = content.indexOf(StringPool.CLOSE_BRACKET, beginPos);
276             int endPos3 = content.indexOf(
277                 StringPool.CLOSE_PARENTHESIS, beginPos);
278             int endPos4 = content.indexOf(StringPool.LESS_THAN, beginPos);
279             int endPos5 = content.indexOf(StringPool.QUOTE, beginPos);
280             int endPos6 = content.indexOf(StringPool.SPACE, beginPos);
281 
282             int endPos = endPos1;
283 
284             if ((endPos == -1) || ((endPos2 != -1) && (endPos2 < endPos))) {
285                 endPos = endPos2;
286             }
287 
288             if ((endPos == -1) || ((endPos3 != -1) && (endPos3 < endPos))) {
289                 endPos = endPos3;
290             }
291 
292             if ((endPos == -1) || ((endPos4 != -1) && (endPos4 < endPos))) {
293                 endPos = endPos4;
294             }
295 
296             if ((endPos == -1) || ((endPos5 != -1) && (endPos5 < endPos))) {
297                 endPos = endPos5;
298             }
299 
300             if ((endPos == -1) || ((endPos6 != -1) && (endPos6 < endPos))) {
301                 endPos = endPos6;
302             }
303 
304             if ((beginPos == -1) || (endPos == -1)) {
305                 break;
306             }
307 
308             try {
309                 String oldParameters = content.substring(beginPos, endPos);
310 
311                 oldParameters = oldParameters.substring(
312                     oldParameters.indexOf(StringPool.QUESTION) + 1);
313 
314                 boolean hasEncodedAmpersands = false;
315 
316                 while (oldParameters.contains(StringPool.AMPERSAND_ENCODED)) {
317                     hasEncodedAmpersands = true;
318 
319                     oldParameters = oldParameters.replace(
320                         StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
321                 }
322 
323                 Map<String, String> map = MapUtil.toLinkedHashMap(
324                     oldParameters.split(StringPool.AMPERSAND),
325                     StringPool.EQUAL);
326 
327                 DLFileEntry fileEntry = null;
328 
329                 if (map.containsKey("uuid")) {
330                     String uuid = map.get("uuid");
331 
332                     String groupIdString = map.get("groupId");
333 
334                     long groupId = GetterUtil.getLong(groupIdString);
335 
336                     if (groupIdString.equals("@group_id@")) {
337                         groupId = entityGroupId;
338                     }
339 
340                     fileEntry = DLFileEntryLocalServiceUtil.
341                         getFileEntryByUuidAndGroupId(uuid, groupId);
342                 }
343                 else if (map.containsKey("folderId")) {
344                     long folderId = GetterUtil.getLong(map.get("folderId"));
345                     String name = map.get("name");
346 
347                     long groupId = context.getSourceGroupId();
348 
349                     fileEntry = DLFileEntryLocalServiceUtil.getFileEntry(
350                         groupId, folderId, name);
351                 }
352 
353                 if (fileEntry == null) {
354                     beginPos--;
355 
356                     continue;
357                 }
358 
359                 DLPortletDataHandlerImpl.exportFileEntry(
360                     context, foldersEl, fileEntriesEl, fileRanks, fileEntry);
361 
362                 String newParameters =
363                     "/get_file?uuid=" + fileEntry.getUuid() +
364                         "&groupId=@data_handler_group_id@";
365 
366                 if (hasEncodedAmpersands) {
367                     newParameters = newParameters.replace(
368                         StringPool.AMPERSAND, StringPool.AMPERSAND_ENCODED);
369                 }
370 
371                 sb.replace(beginPos, endPos, newParameters);
372             }
373             catch (Exception e) {
374                 if (_log.isWarnEnabled()) {
375                     _log.warn(e);
376                 }
377             }
378 
379             beginPos--;
380         }
381 
382         return sb.toString();
383     }
384 
385     public static String exportIGImages(
386         PortletDataContext context, Element foldersEl, Element imagesEl,
387         long entityGroupId, String content) {
388 
389         StringBuilder sb = new StringBuilder(content);
390 
391         int beginPos = content.length();
392 
393         while (true) {
394             beginPos = content.lastIndexOf("/image_gallery?", beginPos);
395 
396             if (beginPos == -1) {
397                 return sb.toString();
398             }
399 
400             int endPos1 = content.indexOf(StringPool.APOSTROPHE, beginPos);
401             int endPos2 = content.indexOf(StringPool.CLOSE_BRACKET, beginPos);
402             int endPos3 = content.indexOf(
403                 StringPool.CLOSE_PARENTHESIS, beginPos);
404             int endPos4 = content.indexOf(StringPool.LESS_THAN, beginPos);
405             int endPos5 = content.indexOf(StringPool.QUOTE, beginPos);
406             int endPos6 = content.indexOf(StringPool.SPACE, beginPos);
407 
408             int endPos = endPos1;
409 
410             if ((endPos == -1) || ((endPos2 != -1) && (endPos2 < endPos))) {
411                 endPos = endPos2;
412             }
413 
414             if ((endPos == -1) || ((endPos3 != -1) && (endPos3 < endPos))) {
415                 endPos = endPos3;
416             }
417 
418             if ((endPos == -1) || ((endPos4 != -1) && (endPos4 < endPos))) {
419                 endPos = endPos4;
420             }
421 
422             if ((endPos == -1) || ((endPos5 != -1) && (endPos5 < endPos))) {
423                 endPos = endPos5;
424             }
425 
426             if ((endPos == -1) || ((endPos6 != -1) && (endPos6 < endPos))) {
427                 endPos = endPos6;
428             }
429 
430             if ((beginPos == -1) || (endPos == -1)) {
431                 break;
432             }
433 
434             try {
435                 String oldParameters = content.substring(beginPos, endPos);
436 
437                 oldParameters = oldParameters.substring(
438                     oldParameters.indexOf(StringPool.QUESTION) + 1);
439 
440                 boolean hasEncodedAmpersands = false;
441 
442                 while (oldParameters.contains(StringPool.AMPERSAND_ENCODED)) {
443                     hasEncodedAmpersands = true;
444 
445                     oldParameters = oldParameters.replace(
446                         StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
447                 }
448 
449                 Map<String, String> map = MapUtil.toLinkedHashMap(
450                     oldParameters.split(StringPool.AMPERSAND),
451                     StringPool.EQUAL);
452 
453                 IGImage image = null;
454 
455                 if (map.containsKey("uuid")) {
456                     String uuid = map.get("uuid");
457 
458                     String groupIdString = map.get("groupId");
459 
460                     long groupId = GetterUtil.getLong(groupIdString);
461 
462                     if (groupIdString.equals("@group_id@")) {
463                         groupId = entityGroupId;
464                     }
465 
466                     image = IGImageLocalServiceUtil.getImageByUuidAndGroupId(
467                         uuid, groupId);
468                 }
469                 else if (map.containsKey("image_id") ||
470                          map.containsKey("img_id") ||
471                          map.containsKey("i_id")) {
472 
473                     long imageId = GetterUtil.getLong(map.get("image_id"));
474 
475                     if (imageId <= 0) {
476                         imageId = GetterUtil.getLong(map.get("img_id"));
477 
478                         if (imageId <= 0) {
479                             imageId = GetterUtil.getLong(map.get("i_id"));
480                         }
481                     }
482 
483                     try {
484                         image = IGImageLocalServiceUtil.getImageByLargeImageId(
485                             imageId);
486                     }
487                     catch (Exception e) {
488                         image = IGImageLocalServiceUtil.getImageBySmallImageId(
489                             imageId);
490                     }
491                 }
492 
493                 if (image == null) {
494                     beginPos--;
495 
496                     continue;
497                 }
498 
499                 IGPortletDataHandlerImpl.exportImage(
500                     context, foldersEl, imagesEl, image);
501 
502                 String timestamp = map.get("t");
503 
504                 if (timestamp == null) {
505                     timestamp = String.valueOf(System.currentTimeMillis());
506                 }
507 
508                 String newParameters =
509                     "/image_gallery?uuid=" + image.getUuid() +
510                         "&groupId=@data_handler_group_id@&t=" + timestamp;
511 
512                 if (hasEncodedAmpersands) {
513                     newParameters = newParameters.replace(
514                         StringPool.AMPERSAND, StringPool.AMPERSAND_ENCODED);
515                 }
516 
517                 sb.replace(beginPos, endPos, newParameters);
518             }
519             catch (Exception e) {
520                 if (_log.isWarnEnabled()) {
521                     _log.warn(e);
522                 }
523             }
524 
525             beginPos--;
526         }
527 
528         return sb.toString();
529     }
530 
531     public static String exportLayoutFriendlyURLs(
532         long entityGroupId, String content) {
533 
534         Group group = null;
535 
536         try {
537             group = GroupLocalServiceUtil.getGroup(entityGroupId);
538         }
539         catch (Exception e) {
540             if (_log.isWarnEnabled()) {
541                 _log.warn(e);
542             }
543 
544             return content;
545         }
546 
547         StringBuilder sb = new StringBuilder(content);
548 
549         String friendlyURLPrivateGroupPath =
550             PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
551         String friendlyURLPrivateUserPath =
552             PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
553         String friendlyURLPublicPath =
554             PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
555 
556         String href = "href=";
557 
558         int beginPos = content.length();
559 
560         while (true) {
561             int hrefLength = href.length();
562 
563             beginPos = content.lastIndexOf(href, beginPos);
564 
565             if (beginPos == -1) {
566                 break;
567             }
568 
569             char c = content.charAt(beginPos + hrefLength);
570 
571             if ((c == CharPool.APOSTROPHE) || (c == CharPool.QUOTE)) {
572                 hrefLength++;
573             }
574 
575             int endPos1 = content.indexOf(
576                 StringPool.APOSTROPHE, beginPos + hrefLength);
577             int endPos2 = content.indexOf(
578                 StringPool.CLOSE_BRACKET, beginPos + hrefLength);
579             int endPos3 = content.indexOf(
580                 StringPool.CLOSE_PARENTHESIS, beginPos + hrefLength);
581             int endPos4 = content.indexOf(
582                 StringPool.LESS_THAN, beginPos + hrefLength);
583             int endPos5 = content.indexOf(
584                 StringPool.QUOTE, beginPos + hrefLength);
585             int endPos6 = content.indexOf(
586                 StringPool.SPACE, beginPos + hrefLength);
587 
588             int endPos = endPos1;
589 
590             if ((endPos == -1) || ((endPos2 != -1) && (endPos2 < endPos))) {
591                 endPos = endPos2;
592             }
593 
594             if ((endPos == -1) || ((endPos3 != -1) && (endPos3 < endPos))) {
595                 endPos = endPos3;
596             }
597 
598             if ((endPos == -1) || ((endPos4 != -1) && (endPos4 < endPos))) {
599                 endPos = endPos4;
600             }
601 
602             if ((endPos == -1) || ((endPos5 != -1) && (endPos5 < endPos))) {
603                 endPos = endPos5;
604             }
605 
606             if ((endPos == -1) || ((endPos6 != -1) && (endPos6 < endPos))) {
607                 endPos = endPos6;
608             }
609 
610             if (endPos == -1) {
611                 beginPos--;
612 
613                 continue;
614             }
615 
616             String url = content.substring(beginPos + hrefLength, endPos);
617 
618             if (!url.startsWith(friendlyURLPrivateGroupPath) &&
619                 !url.startsWith(friendlyURLPrivateUserPath) &&
620                 !url.startsWith(friendlyURLPublicPath)) {
621 
622                 beginPos--;
623 
624                 continue;
625             }
626 
627             int beginGroupPos = content.indexOf(
628                 StringPool.SLASH, beginPos + hrefLength + 1);
629 
630             if (beginGroupPos == -1) {
631                 beginPos--;
632 
633                 continue;
634             }
635 
636             int endGroupPos = content.indexOf(
637                 StringPool.SLASH, beginGroupPos + 1);
638 
639             if (endGroupPos == -1) {
640                 beginPos--;
641 
642                 continue;
643             }
644 
645             String groupFriendlyURL = content.substring(
646                 beginGroupPos, endGroupPos);
647 
648             if (groupFriendlyURL.equals(group.getFriendlyURL())) {
649                 sb.replace(
650                     beginGroupPos, endGroupPos,
651                     "@data_handler_group_friendly_url@");
652             }
653 
654             beginPos--;
655         }
656 
657         return sb.toString();
658     }
659 
660     public static void exportStructure(
661             PortletDataContext context, Element structuresEl,
662             JournalStructure structure)
663         throws PortalException, SystemException {
664 
665         if (!context.isWithinDateRange(structure.getModifiedDate())) {
666             return;
667         }
668 
669         String path = getStructurePath(context, structure);
670 
671         if (!context.isPathNotProcessed(path)) {
672             return;
673         }
674 
675         Element structureEl = structuresEl.addElement("structure");
676 
677         structureEl.addAttribute("path", path);
678 
679         structure.setUserUuid(structure.getUserUuid());
680 
681         context.addPermissions(JournalStructure.class, structure.getId());
682 
683         context.addZipEntry(path, structure);
684     }
685 
686     public static void exportTemplate(
687             PortletDataContext context, Element templatesEl,
688             Element dlFoldersEl, Element dlFileEntriesEl, Element dlFileRanks,
689             Element igFoldersEl, Element igImagesEl, JournalTemplate template)
690         throws PortalException, SystemException {
691 
692         if (!context.isWithinDateRange(template.getModifiedDate())) {
693             return;
694         }
695 
696         String path = getTemplatePath(context, template);
697 
698         if (!context.isPathNotProcessed(path)) {
699             return;
700         }
701 
702         // Clone this template to make sure changes to its content are never
703         // persisted
704 
705         template = (JournalTemplate)template.clone();
706 
707         Element templateEl = templatesEl.addElement("template");
708 
709         templateEl.addAttribute("path", path);
710 
711         if (template.isSmallImage()) {
712             String smallImagePath = getTemplateSmallImagePath(
713                 context, template);
714 
715             templateEl.addAttribute("small-image-path", smallImagePath);
716 
717             Image smallImage = ImageUtil.fetchByPrimaryKey(
718                 template.getSmallImageId());
719 
720             template.setSmallImageType(smallImage.getType());
721 
722             context.addZipEntry(smallImagePath, smallImage.getTextObj());
723         }
724 
725         if (context.getBooleanParameter(_NAMESPACE, "embedded-assets")) {
726             String content = template.getXsl();
727 
728             content = exportDLFileEntries(
729                 context, dlFoldersEl, dlFileEntriesEl, dlFileRanks,
730                 template.getGroupId(), content);
731             content = exportIGImages(
732                 context, igFoldersEl, igImagesEl, template.getGroupId(),
733                 content);
734             content = exportLayoutFriendlyURLs(template.getGroupId(), content);
735 
736             content = StringUtil.replace(
737                 content, StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
738 
739             template.setXsl(content);
740         }
741 
742         template.setUserUuid(template.getUserUuid());
743 
744         context.addPermissions(JournalTemplate.class, template.getId());
745 
746         context.addZipEntry(path, template);
747     }
748 
749     public static void importArticle(
750             PortletDataContext context, Map<String, String> structureIds,
751             Map<String, String> templateIds, Map<String, String> articleIds,
752             Element articleEl)
753         throws Exception {
754 
755         String path = articleEl.attributeValue("path");
756 
757         if (!context.isPathNotProcessed(path)) {
758             return;
759         }
760 
761         JournalArticle article = (JournalArticle)context.getZipEntryAsObject(
762             path);
763 
764         long userId = context.getUserId(article.getUserUuid());
765 
766         User user = UserLocalServiceUtil.getUser(userId);
767 
768         long groupId = context.getGroupId();
769 
770         String articleId = article.getArticleId();
771         boolean autoArticleId = false;
772 
773         if ((Validator.isNumber(articleId)) ||
774             (JournalArticleUtil.fetchByG_A_V(
775                 groupId, articleId,
776                     JournalArticleConstants.DEFAULT_VERSION) != null)) {
777 
778             autoArticleId = true;
779         }
780 
781         String newArticleId = articleIds.get(articleId);
782 
783         if (Validator.isNotNull(newArticleId)) {
784 
785             // A sibling of a different version was already assigned a new
786             // article id
787 
788             articleId = newArticleId;
789             autoArticleId = false;
790         }
791 
792         String content = article.getContent();
793 
794         content = StringUtil.replace(
795             content, "@data_handler_group_id@", String.valueOf(groupId));
796 
797         Group group = GroupLocalServiceUtil.getGroup(groupId);
798 
799         content = StringUtil.replace(
800             content, "@data_handler_group_friendly_url@",
801             group.getFriendlyURL());
802 
803         article.setContent(content);
804 
805         String parentStructureId = MapUtil.getString(
806             structureIds, article.getStructureId(), article.getStructureId());
807         String parentTemplateId = MapUtil.getString(
808             templateIds, article.getTemplateId(), article.getTemplateId());
809 
810         Date displayDate = article.getDisplayDate();
811 
812         int displayDateMonth = 0;
813         int displayDateDay = 0;
814         int displayDateYear = 0;
815         int displayDateHour = 0;
816         int displayDateMinute = 0;
817 
818         if (displayDate != null) {
819             Calendar displayCal = CalendarFactoryUtil.getCalendar(
820                 user.getTimeZone());
821 
822             displayCal.setTime(displayDate);
823 
824             displayDateMonth = displayCal.get(Calendar.MONTH);
825             displayDateDay = displayCal.get(Calendar.DATE);
826             displayDateYear = displayCal.get(Calendar.YEAR);
827             displayDateHour = displayCal.get(Calendar.HOUR);
828             displayDateMinute = displayCal.get(Calendar.MINUTE);
829 
830             if (displayCal.get(Calendar.AM_PM) == Calendar.PM) {
831                 displayDateHour += 12;
832             }
833         }
834 
835         Date expirationDate = article.getExpirationDate();
836 
837         int expirationDateMonth = 0;
838         int expirationDateDay = 0;
839         int expirationDateYear = 0;
840         int expirationDateHour = 0;
841         int expirationDateMinute = 0;
842         boolean neverExpire = true;
843 
844         if (expirationDate != null) {
845             Calendar expirationCal = CalendarFactoryUtil.getCalendar(
846                 user.getTimeZone());
847 
848             expirationCal.setTime(expirationDate);
849 
850             expirationDateMonth = expirationCal.get(Calendar.MONTH);
851             expirationDateDay = expirationCal.get(Calendar.DATE);
852             expirationDateYear = expirationCal.get(Calendar.YEAR);
853             expirationDateHour = expirationCal.get(Calendar.HOUR);
854             expirationDateMinute = expirationCal.get(Calendar.MINUTE);
855             neverExpire = false;
856 
857             if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
858                 expirationDateHour += 12;
859             }
860         }
861 
862         Date reviewDate = article.getReviewDate();
863 
864         int reviewDateMonth = 0;
865         int reviewDateDay = 0;
866         int reviewDateYear = 0;
867         int reviewDateHour = 0;
868         int reviewDateMinute = 0;
869         boolean neverReview = true;
870 
871         if (reviewDate != null) {
872             Calendar reviewCal = CalendarFactoryUtil.getCalendar(
873                 user.getTimeZone());
874 
875             reviewCal.setTime(reviewDate);
876 
877             reviewDateMonth = reviewCal.get(Calendar.MONTH);
878             reviewDateDay = reviewCal.get(Calendar.DATE);
879             reviewDateYear = reviewCal.get(Calendar.YEAR);
880             reviewDateHour = reviewCal.get(Calendar.HOUR);
881             reviewDateMinute = reviewCal.get(Calendar.MINUTE);
882             neverReview = false;
883 
884             if (reviewCal.get(Calendar.AM_PM) == Calendar.PM) {
885                 reviewDateHour += 12;
886             }
887         }
888 
889         if (Validator.isNotNull(article.getStructureId())) {
890             JournalStructure structure = JournalStructureUtil.fetchByG_S(
891                 context.getGroupId(), article.getStructureId());
892 
893             if (structure == null) {
894                 if (_log.isWarnEnabled()) {
895                     _log.warn(
896                         "Structure " + article.getStructureId() + " is " +
897                             "missing for article " + article.getArticleId() +
898                                 ", skipping this article.");
899                 }
900 
901                 return;
902             }
903         }
904 
905         if (Validator.isNotNull(article.getTemplateId())) {
906             JournalTemplate template = JournalTemplateUtil.fetchByG_T(
907                 context.getGroupId(), article.getTemplateId());
908 
909             if (template == null) {
910                 if (_log.isWarnEnabled()) {
911                     _log.warn(
912                         "Template " + article.getTemplateId() + " is missing " +
913                             "for article " + article.getArticleId() +
914                                 ", skipping this article.");
915                 }
916 
917                 return;
918             }
919         }
920 
921         File smallFile = null;
922 
923         String smallImagePath = articleEl.attributeValue("small-image-path");
924 
925         if (article.isSmallImage() && Validator.isNotNull(smallImagePath)) {
926             byte[] bytes = context.getZipEntryAsByteArray(smallImagePath);
927 
928             smallFile = File.createTempFile(
929                 String.valueOf(article.getSmallImageId()),
930                 StringPool.PERIOD + article.getSmallImageType());
931 
932             FileUtil.write(smallFile, bytes);
933         }
934 
935         Map<String, byte[]> images = new HashMap<String, byte[]>();
936 
937         if (context.getBooleanParameter(_NAMESPACE, "images")) {
938             String imagePath = articleEl.attributeValue("image-path");
939 
940             List<String> imageFiles = context.getZipFolderEntries(imagePath);
941 
942             for (String imageFile : imageFiles) {
943                 String fileName = imageFile;
944 
945                 if (fileName.contains(StringPool.SLASH)) {
946                     fileName = fileName.substring(
947                         fileName.lastIndexOf(StringPool.SLASH) + 1);
948                 }
949 
950                 if (fileName.endsWith(".xml")) {
951                     continue;
952                 }
953 
954                 int pos = fileName.lastIndexOf(StringPool.PERIOD);
955 
956                 if (pos != -1) {
957                     fileName = fileName.substring(0, pos);
958                 }
959 
960                 images.put(fileName, context.getZipEntryAsByteArray(imageFile));
961             }
962         }
963 
964         String articleURL = null;
965 
966         long[] assetCategoryIds = null;
967         String[] assetTagNames = null;
968 
969         if (context.getBooleanParameter(_NAMESPACE, "categories")) {
970             assetCategoryIds = context.getAssetCategoryIds(
971                 JournalArticle.class, article.getResourcePrimKey());
972         }
973 
974         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
975             assetTagNames = context.getAssetTagNames(
976                 JournalArticle.class, article.getResourcePrimKey());
977         }
978 
979         JournalCreationStrategy creationStrategy =
980             JournalCreationStrategyFactory.getInstance();
981 
982         long authorId = creationStrategy.getAuthorUserId(context, article);
983 
984         if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
985             userId = authorId;
986         }
987 
988         String newContent = creationStrategy.getTransformedContent(
989             context, article);
990 
991         if (newContent != JournalCreationStrategy.ARTICLE_CONTENT_UNCHANGED) {
992             article.setContent(newContent);
993         }
994 
995         boolean addCommunityPermissions =
996             creationStrategy.addCommunityPermissions(context, article);
997         boolean addGuestPermissions = creationStrategy.addGuestPermissions(
998             context, article);
999 
1000        ServiceContext serviceContext = new ServiceContext();
1001
1002        serviceContext.setAddCommunityPermissions(addCommunityPermissions);
1003        serviceContext.setAddGuestPermissions(addGuestPermissions);
1004        serviceContext.setAssetCategoryIds(assetCategoryIds);
1005        serviceContext.setAssetTagNames(assetTagNames);
1006        serviceContext.setCreateDate(article.getCreateDate());
1007        serviceContext.setModifiedDate(article.getModifiedDate());
1008        serviceContext.setScopeGroupId(groupId);
1009
1010        if (article.getStatus() != WorkflowConstants.STATUS_APPROVED) {
1011            serviceContext.setWorkflowAction(
1012                WorkflowConstants.ACTION_SAVE_DRAFT);
1013        }
1014
1015        JournalArticle importedArticle = null;
1016
1017        if (context.getDataStrategy().equals(
1018                PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
1019
1020            JournalArticle existingArticle = JournalArticleUtil.fetchByUUID_G(
1021                article.getUuid(), groupId);
1022
1023            if (existingArticle == null) {
1024                importedArticle = JournalArticleLocalServiceUtil.addArticle(
1025                    article.getUuid(), userId, groupId, articleId,
1026                    autoArticleId, article.getVersion(), article.getTitle(),
1027                    article.getDescription(), article.getContent(),
1028                    article.getType(), parentStructureId, parentTemplateId,
1029                    displayDateMonth, displayDateDay, displayDateYear,
1030                    displayDateHour, displayDateMinute, expirationDateMonth,
1031                    expirationDateDay, expirationDateYear, expirationDateHour,
1032                    expirationDateMinute, neverExpire, reviewDateMonth,
1033                    reviewDateDay, reviewDateYear, reviewDateHour,
1034                    reviewDateMinute, neverReview, article.isIndexable(),
1035                    article.isSmallImage(), article.getSmallImageURL(),
1036                    smallFile, images, articleURL, serviceContext);
1037            }
1038            else {
1039                importedArticle = JournalArticleLocalServiceUtil.updateArticle(
1040                    userId, existingArticle.getGroupId(),
1041                    existingArticle.getArticleId(),
1042                    existingArticle.getVersion(), article.getTitle(),
1043                    article.getDescription(), article.getContent(),
1044                    article.getType(), parentStructureId, parentTemplateId,
1045                    displayDateMonth, displayDateDay, displayDateYear,
1046                    displayDateHour, displayDateMinute, expirationDateMonth,
1047                    expirationDateDay, expirationDateYear, expirationDateHour,
1048                    expirationDateMinute, neverExpire, reviewDateMonth,
1049                    reviewDateDay, reviewDateYear, reviewDateHour,
1050                    reviewDateMinute, neverReview, article.isIndexable(),
1051                    article.isSmallImage(), article.getSmallImageURL(),
1052                    smallFile, images, articleURL, serviceContext);
1053            }
1054        }
1055        else {
1056            importedArticle = JournalArticleLocalServiceUtil.addArticle(
1057                userId, groupId, articleId, autoArticleId, article.getVersion(),
1058                article.getTitle(), article.getDescription(),
1059                article.getContent(), article.getType(), parentStructureId,
1060                parentTemplateId, displayDateMonth, displayDateDay,
1061                displayDateYear, displayDateHour, displayDateMinute,
1062                expirationDateMonth, expirationDateDay, expirationDateYear,
1063                expirationDateHour, expirationDateMinute, neverExpire,
1064                reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
1065                reviewDateMinute, neverReview, article.isIndexable(),
1066                article.isSmallImage(), article.getSmallImageURL(), smallFile,
1067                images, articleURL, serviceContext);
1068        }
1069
1070        context.importPermissions(
1071            JournalArticle.class, article.getResourcePrimKey(),
1072            importedArticle.getResourcePrimKey());
1073
1074        if (context.getBooleanParameter(_NAMESPACE, "comments")) {
1075            context.importComments(
1076                JournalArticle.class, article.getResourcePrimKey(),
1077                importedArticle.getResourcePrimKey(), groupId);
1078        }
1079
1080        if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
1081            context.importRatingsEntries(
1082                JournalArticle.class, article.getResourcePrimKey(),
1083                importedArticle.getResourcePrimKey());
1084        }
1085
1086        articleIds.put(articleId, importedArticle.getArticleId());
1087
1088        if (!articleId.equals(importedArticle.getArticleId())) {
1089            if (_log.isWarnEnabled()) {
1090                _log.warn(
1091                    "An article with the ID " + articleId + " already " +
1092                        "exists. The new generated ID is " +
1093                            importedArticle.getArticleId());
1094            }
1095        }
1096    }
1097
1098    public static void importFeed(
1099            PortletDataContext context, Map<String, String> structureIds,
1100            Map<String, String> templateIds, Map<String, String> feedIds,
1101            Element feedEl)
1102        throws Exception {
1103
1104        String path = feedEl.attributeValue("path");
1105
1106        if (!context.isPathNotProcessed(path)) {
1107            return;
1108        }
1109
1110        JournalFeed feed = (JournalFeed)context.getZipEntryAsObject(path);
1111
1112        long userId = context.getUserId(feed.getUserUuid());
1113        long groupId = context.getGroupId();
1114
1115        String feedId = feed.getFeedId();
1116        boolean autoFeedId = false;
1117
1118        if ((Validator.isNumber(feedId)) ||
1119            (JournalFeedUtil.fetchByG_F(groupId, feedId) != null)) {
1120
1121            autoFeedId = true;
1122        }
1123
1124        String parentStructureId = MapUtil.getString(
1125            structureIds, feed.getStructureId(), feed.getStructureId());
1126        String parentTemplateId = MapUtil.getString(
1127            templateIds, feed.getTemplateId(), feed.getTemplateId());
1128        String parentRenderTemplateId = MapUtil.getString(
1129            templateIds, feed.getRendererTemplateId(),
1130            feed.getRendererTemplateId());
1131
1132        JournalCreationStrategy creationStrategy =
1133            JournalCreationStrategyFactory.getInstance();
1134
1135        long authorId = creationStrategy.getAuthorUserId(context, feed);
1136
1137        if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
1138            userId = authorId;
1139        }
1140
1141        boolean addCommunityPermissions =
1142            creationStrategy.addCommunityPermissions(context, feed);
1143        boolean addGuestPermissions = creationStrategy.addGuestPermissions(
1144            context, feed);
1145
1146        ServiceContext serviceContext = new ServiceContext();
1147
1148        serviceContext.setAddCommunityPermissions(addCommunityPermissions);
1149        serviceContext.setAddGuestPermissions(addGuestPermissions);
1150        serviceContext.setCreateDate(feed.getCreateDate());
1151        serviceContext.setModifiedDate(feed.getModifiedDate());
1152
1153        JournalFeed existingFeed = null;
1154
1155        if (context.getDataStrategy().equals(
1156                PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
1157
1158            existingFeed = JournalFeedUtil.fetchByUUID_G(
1159                feed.getUuid(), groupId);
1160
1161            if (existingFeed == null) {
1162                existingFeed = JournalFeedLocalServiceUtil.addFeed(
1163                    feed.getUuid(), userId, groupId, feedId, autoFeedId,
1164                    feed.getName(), feed.getDescription(), feed.getType(),
1165                    parentStructureId, parentTemplateId, parentRenderTemplateId,
1166                    feed.getDelta(), feed.getOrderByCol(),
1167                    feed.getOrderByType(), feed.getTargetLayoutFriendlyUrl(),
1168                    feed.getTargetPortletId(), feed.getContentField(),
1169                    feed.getFeedType(), feed.getFeedVersion(),
1170                    serviceContext);
1171            }
1172            else {
1173                existingFeed = JournalFeedLocalServiceUtil.updateFeed(
1174                    existingFeed.getGroupId(), existingFeed.getFeedId(),
1175                    feed.getName(), feed.getDescription(), feed.getType(),
1176                    parentStructureId, parentTemplateId, parentRenderTemplateId,
1177                    feed.getDelta(), feed.getOrderByCol(),
1178                    feed.getOrderByType(), feed.getTargetLayoutFriendlyUrl(),
1179                    feed.getTargetPortletId(), feed.getContentField(),
1180                    feed.getFeedType(), feed.getFeedVersion(), serviceContext);
1181            }
1182        }
1183        else {
1184            existingFeed = JournalFeedLocalServiceUtil.addFeed(
1185                userId, groupId, feedId, autoFeedId, feed.getName(),
1186                feed.getDescription(), feed.getType(), parentStructureId,
1187                parentTemplateId, parentRenderTemplateId, feed.getDelta(),
1188                feed.getOrderByCol(), feed.getOrderByType(),
1189                feed.getTargetLayoutFriendlyUrl(), feed.getTargetPortletId(),
1190                feed.getContentField(), feed.getFeedType(),
1191                feed.getFeedVersion(), serviceContext);
1192        }
1193
1194        feedIds.put(feedId, existingFeed.getFeedId());
1195
1196        context.importPermissions(
1197            JournalFeed.class, feed.getId(), existingFeed.getId());
1198
1199        if (!feedId.equals(existingFeed.getFeedId())) {
1200            if (_log.isWarnEnabled()) {
1201                _log.warn(
1202                    "A feed with the ID " + feedId + " already " +
1203                        "exists. The new generated ID is " +
1204                            existingFeed.getFeedId());
1205            }
1206        }
1207    }
1208
1209    public static void importStructure(
1210            PortletDataContext context, Map<String, String> structureIds,
1211            Element structureEl)
1212        throws Exception {
1213
1214        String path = structureEl.attributeValue("path");
1215
1216        importStructure(context, structureIds, path);
1217    }
1218
1219    protected static void importStructure(
1220            PortletDataContext context, Map<String, String> structureIds,
1221            String path)
1222        throws Exception {
1223
1224        if (!context.isPathNotProcessed(path)) {
1225            return;
1226        }
1227
1228        JournalStructure structure =
1229            (JournalStructure)context.getZipEntryAsObject(path);
1230
1231        long userId = context.getUserId(structure.getUserUuid());
1232        long groupId = context.getGroupId();
1233
1234        String structureId = structure.getStructureId();
1235        boolean autoStructureId = false;
1236
1237        if ((Validator.isNumber(structureId)) ||
1238            (JournalStructureUtil.fetchByG_S(groupId, structureId) != null)) {
1239
1240            autoStructureId = true;
1241        }
1242
1243        JournalCreationStrategy creationStrategy =
1244            JournalCreationStrategyFactory.getInstance();
1245
1246        long authorId = creationStrategy.getAuthorUserId(context, structure);
1247
1248        if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
1249            userId = authorId;
1250        }
1251
1252        boolean addCommunityPermissions =
1253            creationStrategy.addCommunityPermissions(context, structure);
1254        boolean addGuestPermissions = creationStrategy.addGuestPermissions(
1255            context, structure);
1256
1257        ServiceContext serviceContext = new ServiceContext();
1258
1259        serviceContext.setAddCommunityPermissions(addCommunityPermissions);
1260        serviceContext.setAddGuestPermissions(addGuestPermissions);
1261        serviceContext.setCreateDate(structure.getCreateDate());
1262        serviceContext.setModifiedDate(structure.getModifiedDate());
1263
1264        JournalStructure existingStructure = null;
1265
1266        if (context.getDataStrategy().equals(
1267                PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
1268
1269            existingStructure = JournalStructureUtil.fetchByUUID_G(
1270                structure.getUuid(), groupId);
1271
1272            if (existingStructure == null) {
1273                existingStructure =
1274                    JournalStructureLocalServiceUtil.addStructure(
1275                        structure.getUuid(), userId, groupId, structureId,
1276                        autoStructureId, structure.getParentStructureId(),
1277                        structure.getName(), structure.getDescription(),
1278                        structure.getXsd(), serviceContext);
1279            }
1280            else {
1281                existingStructure =
1282                    JournalStructureLocalServiceUtil.updateStructure(
1283                        existingStructure.getGroupId(),
1284                        existingStructure.getStructureId(),
1285                        structure.getParentStructureId(), structure.getName(),
1286                        structure.getDescription(), structure.getXsd(),
1287                        serviceContext);
1288            }
1289        }
1290        else {
1291            existingStructure = JournalStructureLocalServiceUtil.addStructure(
1292                userId, groupId, structureId, autoStructureId,
1293                structure.getParentStructureId(), structure.getName(),
1294                structure.getDescription(), structure.getXsd(), serviceContext);
1295        }
1296
1297        structureIds.put(structureId, existingStructure.getStructureId());
1298
1299        context.importPermissions(
1300            JournalStructure.class, structure.getId(),
1301            existingStructure.getId());
1302
1303        if (!structureId.equals(existingStructure.getStructureId())) {
1304            if (_log.isWarnEnabled()) {
1305                _log.warn(
1306                    "A structure with the ID " + structureId + " already " +
1307                        "exists. The new generated ID is " +
1308                            existingStructure.getStructureId());
1309            }
1310        }
1311    }
1312
1313    public static void importTemplate(
1314            PortletDataContext context, Map<String, String> structureIds,
1315            Map<String, String> templateIds, Element templateEl)
1316        throws Exception {
1317
1318        String path = templateEl.attributeValue("path");
1319
1320        importTemplate(
1321            context, structureIds, templateIds,
1322            templateEl.attributeValue("small-image-path"), path);
1323    }
1324
1325    protected static void importTemplate(
1326            PortletDataContext context, Map<String, String> structureIds,
1327            Map<String, String> templateIds, String smallImagePath, String path)
1328        throws Exception {
1329
1330        if (!context.isPathNotProcessed(path)) {
1331            return;
1332        }
1333
1334        JournalTemplate template = (JournalTemplate)context.getZipEntryAsObject(
1335            path);
1336
1337        long userId = context.getUserId(template.getUserUuid());
1338        long groupId = context.getGroupId();
1339
1340        String templateId = template.getTemplateId();
1341        boolean autoTemplateId = false;
1342
1343        if ((Validator.isNumber(templateId)) ||
1344            (JournalTemplateUtil.fetchByG_T(groupId, templateId) != null)) {
1345
1346            autoTemplateId = true;
1347        }
1348
1349        String parentStructureId = MapUtil.getString(
1350            structureIds, template.getStructureId(), template.getStructureId());
1351
1352        boolean formatXsl = false;
1353
1354        JournalCreationStrategy creationStrategy =
1355            JournalCreationStrategyFactory.getInstance();
1356
1357        long authorId = creationStrategy.getAuthorUserId(context, template);
1358
1359        if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
1360            userId = authorId;
1361        }
1362
1363        boolean addCommunityPermissions =
1364            creationStrategy.addCommunityPermissions(context, template);
1365        boolean addGuestPermissions = creationStrategy.addGuestPermissions(
1366            context, template);
1367
1368        ServiceContext serviceContext = new ServiceContext();
1369
1370        serviceContext.setAddCommunityPermissions(addCommunityPermissions);
1371        serviceContext.setAddGuestPermissions(addGuestPermissions);
1372        serviceContext.setCreateDate(template.getCreateDate());
1373        serviceContext.setModifiedDate(template.getModifiedDate());
1374
1375        File smallFile = null;
1376
1377        if (template.isSmallImage() && Validator.isNotNull(smallImagePath)) {
1378            if (smallImagePath.endsWith(StringPool.PERIOD)) {
1379                smallImagePath += template.getSmallImageType();
1380            }
1381
1382            byte[] bytes = context.getZipEntryAsByteArray(smallImagePath);
1383
1384            if (bytes != null) {
1385                smallFile = File.createTempFile(
1386                    String.valueOf(template.getSmallImageId()),
1387                    StringPool.PERIOD + template.getSmallImageType());
1388
1389                FileUtil.write(smallFile, bytes);
1390            }
1391        }
1392
1393        JournalTemplate existingTemplate = null;
1394
1395        if (context.getDataStrategy().equals(
1396                PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
1397
1398            existingTemplate = JournalTemplateUtil.fetchByUUID_G(
1399                template.getUuid(), groupId);
1400
1401            if (existingTemplate == null) {
1402                existingTemplate = JournalTemplateLocalServiceUtil.addTemplate(
1403                    template.getUuid(), userId, groupId, templateId,
1404                    autoTemplateId, parentStructureId, template.getName(),
1405                    template.getDescription(), template.getXsl(), formatXsl,
1406                    template.getLangType(), template.getCacheable(),
1407                    template.isSmallImage(), template.getSmallImageURL(),
1408                    smallFile, serviceContext);
1409            }
1410            else {
1411                existingTemplate =
1412                    JournalTemplateLocalServiceUtil.updateTemplate(
1413                        existingTemplate.getGroupId(),
1414                        existingTemplate.getTemplateId(),
1415                        existingTemplate.getStructureId(), template.getName(),
1416                        template.getDescription(), template.getXsl(), formatXsl,
1417                        template.getLangType(), template.getCacheable(),
1418                        template.isSmallImage(), template.getSmallImageURL(),
1419                        smallFile, serviceContext);
1420            }
1421        }
1422        else {
1423            existingTemplate = JournalTemplateLocalServiceUtil.addTemplate(
1424                userId, groupId, templateId, autoTemplateId, parentStructureId,
1425                template.getName(), template.getDescription(),
1426                template.getXsl(), formatXsl, template.getLangType(),
1427                template.getCacheable(), template.isSmallImage(),
1428                template.getSmallImageURL(), smallFile, serviceContext);
1429        }
1430
1431        templateIds.put(templateId, existingTemplate.getTemplateId());
1432
1433        context.importPermissions(
1434            JournalTemplate.class, template.getId(),
1435            existingTemplate.getId());
1436
1437        if (!templateId.equals(existingTemplate.getTemplateId())) {
1438            if (_log.isWarnEnabled()) {
1439                _log.warn(
1440                    "A template with the ID " + templateId + " already " +
1441                        "exists. The new generated ID is " +
1442                            existingTemplate.getTemplateId());
1443            }
1444        }
1445    }
1446
1447    public PortletPreferences deleteData(
1448            PortletDataContext context, String portletId,
1449            PortletPreferences preferences)
1450        throws PortletDataException {
1451
1452        try {
1453            if (!context.addPrimaryKey(
1454                    JournalPortletDataHandlerImpl.class, "deleteData")) {
1455
1456                JournalArticleLocalServiceUtil.deleteArticles(
1457                    context.getGroupId());
1458
1459                JournalTemplateLocalServiceUtil.deleteTemplates(
1460                    context.getGroupId());
1461
1462                JournalStructureLocalServiceUtil.deleteStructures(
1463                    context.getGroupId());
1464            }
1465
1466            return preferences;
1467        }
1468        catch (Exception e) {
1469            throw new PortletDataException(e);
1470        }
1471    }
1472
1473    public String exportData(
1474            PortletDataContext context, String portletId,
1475            PortletPreferences preferences)
1476        throws PortletDataException {
1477
1478        try {
1479            context.addPermissions(
1480                "com.liferay.portlet.journal", context.getGroupId());
1481
1482            Document doc = SAXReaderUtil.createDocument();
1483
1484            Element root = doc.addElement("journal-data");
1485
1486            root.addAttribute("group-id", String.valueOf(context.getGroupId()));
1487
1488            Element structuresEl = root.addElement("structures");
1489
1490            List<JournalStructure> structures =
1491                JournalStructureUtil.findByGroupId(context.getGroupId());
1492
1493            for (JournalStructure structure : structures) {
1494                exportStructure(context, structuresEl, structure);
1495            }
1496
1497            Element templatesEl = root.addElement("templates");
1498            Element dlFoldersEl = root.addElement("dl-folders");
1499            Element dlFilesEl = root.addElement("dl-file-entries");
1500            Element dlFileRanksEl = root.addElement("dl-file-ranks");
1501            Element igFoldersEl = root.addElement("ig-folders");
1502            Element igImagesEl = root.addElement("ig-images");
1503
1504            List<JournalTemplate> templates = JournalTemplateUtil.findByGroupId(
1505                context.getGroupId());
1506
1507            for (JournalTemplate template : templates) {
1508                exportTemplate(
1509                    context, templatesEl, dlFoldersEl, dlFilesEl, dlFileRanksEl,
1510                    igFoldersEl, igImagesEl, template);
1511            }
1512
1513            Element feedsEl = root.addElement("feeds");
1514
1515            List<JournalFeed> feeds = JournalFeedUtil.findByGroupId(
1516                context.getGroupId());
1517
1518            for (JournalFeed feed : feeds) {
1519                if (context.isWithinDateRange(feed.getModifiedDate())) {
1520                    exportFeed(context, feedsEl, feed);
1521                }
1522            }
1523
1524            Element articlesEl = root.addElement("articles");
1525
1526            if (context.getBooleanParameter(_NAMESPACE, "articles")) {
1527                List<JournalArticle> articles =
1528                    JournalArticleUtil.findByGroupId(
1529                        context.getGroupId(), QueryUtil.ALL_POS,
1530                        QueryUtil.ALL_POS, new ArticleIDComparator(true));
1531
1532                for (JournalArticle article : articles) {
1533                    exportArticle(
1534                        context, articlesEl, dlFoldersEl, dlFilesEl,
1535                        dlFileRanksEl, igFoldersEl, igImagesEl, article);
1536                }
1537            }
1538
1539            return doc.formattedString();
1540        }
1541        catch (Exception e) {
1542            throw new PortletDataException(e);
1543        }
1544    }
1545
1546    public PortletDataHandlerControl[] getExportControls() {
1547        return new PortletDataHandlerControl[] {
1548            _articles, _structuresTemplatesAndFeeds, _embeddedAssets, _images,
1549            _categories, _comments, _ratings, _tags
1550        };
1551    }
1552
1553    public PortletDataHandlerControl[] getImportControls() {
1554        return new PortletDataHandlerControl[] {
1555            _articles, _structuresTemplatesAndFeeds, _images, _categories,
1556            _comments, _ratings, _tags
1557        };
1558    }
1559
1560    public PortletPreferences importData(
1561            PortletDataContext context, String portletId,
1562            PortletPreferences preferences, String data)
1563        throws PortletDataException {
1564
1565        try {
1566            context.importPermissions(
1567                "com.liferay.portlet.journal", context.getSourceGroupId(),
1568                context.getGroupId());
1569
1570            Document doc = SAXReaderUtil.read(data);
1571
1572            Element root = doc.getRootElement();
1573
1574            List<Element> structureEls = root.element("structures").elements(
1575                "structure");
1576
1577            Map<String, String> structureIds =
1578                (Map<String, String>)context.getNewPrimaryKeysMap(
1579                    JournalStructure.class);
1580
1581            for (Element structureEl : structureEls) {
1582                importStructure(context, structureIds, structureEl);
1583            }
1584
1585            List<Element> templateEls = root.element("templates").elements(
1586                "template");
1587
1588            Map<String, String> templateIds =
1589                (Map<String, String>)context.getNewPrimaryKeysMap(
1590                    JournalTemplate.class);
1591
1592            for (Element templateEl : templateEls) {
1593                importTemplate(context, structureIds, templateIds, templateEl);
1594            }
1595
1596            List<Element> feedEls = root.element("feeds").elements("feed");
1597
1598            Map<String, String> feedIds =
1599                (Map<String, String>)context.getNewPrimaryKeysMap(
1600                    JournalFeed.class);
1601
1602            for (Element feedEl : feedEls) {
1603                importFeed(context, structureIds, templateIds, feedIds, feedEl);
1604            }
1605
1606            if (context.getBooleanParameter(_NAMESPACE, "articles")) {
1607                List<Element> articleEls = root.element("articles").elements(
1608                    "article");
1609
1610                Map<String, String> articleIds =
1611                    (Map<String, String>)context.getNewPrimaryKeysMap(
1612                        JournalArticle.class);
1613
1614                for (Element articleEl : articleEls) {
1615                    importArticle(
1616                        context, structureIds, templateIds, articleIds,
1617                        articleEl);
1618                }
1619            }
1620
1621            List<Element> dlFolderEls = root.element("dl-folders").elements(
1622                "folder");
1623
1624            Map<Long, Long> dlFolderPKs =
1625                (Map<Long, Long>)context.getNewPrimaryKeysMap(DLFolder.class);
1626
1627            for (Element folderEl : dlFolderEls) {
1628                String path = folderEl.attributeValue("path");
1629
1630                if (!context.isPathNotProcessed(path)) {
1631                    continue;
1632                }
1633
1634                DLFolder folder = (DLFolder)context.getZipEntryAsObject(path);
1635
1636                DLPortletDataHandlerImpl.importFolder(
1637                    context, dlFolderPKs, folder);
1638            }
1639
1640            List<Element> fileEntryEls = root.element(
1641                "dl-file-entries").elements("file-entry");
1642
1643            Map<String, String> fileEntryNames =
1644                (Map<String, String>)context.getNewPrimaryKeysMap(
1645                    DLFileEntry.class);
1646
1647            for (Element fileEntryEl : fileEntryEls) {
1648                String path = fileEntryEl.attributeValue("path");
1649
1650                if (!context.isPathNotProcessed(path)) {
1651                    continue;
1652                }
1653
1654                DLFileEntry fileEntry = null;
1655
1656                try {
1657                    fileEntry = (DLFileEntry)context.getZipEntryAsObject(path);
1658                }
1659                catch (Exception e) {
1660                    if (_log.isWarnEnabled()) {
1661                        _log.warn("No file entry found for path " + path);
1662                    }
1663
1664                    continue;
1665                }
1666
1667                String binPath = fileEntryEl.attributeValue("bin-path");
1668
1669                DLPortletDataHandlerImpl.importFileEntry(
1670                    context, dlFolderPKs, fileEntryNames, fileEntry, binPath);
1671            }
1672
1673            List<Element> fileRankEls = root.element("dl-file-ranks").elements(
1674                "file-rank");
1675
1676            for (Element fileRankEl : fileRankEls) {
1677                String path = fileRankEl.attributeValue("path");
1678
1679                if (!context.isPathNotProcessed(path)) {
1680                    continue;
1681                }
1682
1683                DLFileRank fileRank = (DLFileRank)context.getZipEntryAsObject(
1684                    path);
1685
1686                DLPortletDataHandlerImpl.importFileRank(
1687                    context, dlFolderPKs, fileEntryNames, fileRank);
1688            }
1689
1690            List<Element> igFolderEls = root.element("ig-folders").elements(
1691                "folder");
1692
1693            Map<Long, Long> igFolderPKs =
1694                (Map<Long, Long>)context.getNewPrimaryKeysMap(IGFolder.class);
1695
1696            for (Element folderEl : igFolderEls) {
1697                String path = folderEl.attributeValue("path");
1698
1699                if (!context.isPathNotProcessed(path)) {
1700                    continue;
1701                }
1702
1703                IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
1704
1705                IGPortletDataHandlerImpl.importFolder(
1706                    context, igFolderPKs, folder);
1707            }
1708
1709            List<Element> imageEls = root.element("ig-images").elements(
1710                "image");
1711
1712            for (Element imageEl : imageEls) {
1713                String path = imageEl.attributeValue("path");
1714
1715                if (!context.isPathNotProcessed(path)) {
1716                    continue;
1717                }
1718
1719                IGImage image = (IGImage)context.getZipEntryAsObject(path);
1720
1721                String binPath = imageEl.attributeValue("bin-path");
1722
1723                IGPortletDataHandlerImpl.importImage(
1724                    context, igFolderPKs, image, binPath);
1725            }
1726
1727            return preferences;
1728        }
1729        catch (Exception e) {
1730            throw new PortletDataException(e);
1731        }
1732    }
1733
1734    public boolean isAlwaysExportable() {
1735        return _ALWAYS_EXPORTABLE;
1736    }
1737
1738    public boolean isPublishToLiveByDefault() {
1739        return PropsValues.JOURNAL_PUBLISH_TO_LIVE_BY_DEFAULT;
1740    }
1741
1742    protected static String getArticlePath(
1743        PortletDataContext context, JournalArticle article) {
1744
1745        StringBundler sb = new StringBundler(8);
1746
1747        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1748        sb.append("/articles/");
1749        sb.append(article.getUuid());
1750        sb.append(StringPool.SLASH);
1751        sb.append(article.getVersion());
1752        sb.append(StringPool.SLASH);
1753        sb.append("article.xml");
1754
1755        return sb.toString();
1756    }
1757
1758    protected static String getArticleImagePath(
1759        PortletDataContext context, JournalArticle article) {
1760
1761        StringBundler sb = new StringBundler(6);
1762
1763        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1764        sb.append("/articles/");
1765        sb.append(article.getUuid());
1766        sb.append(StringPool.SLASH);
1767        sb.append(article.getVersion());
1768        sb.append(StringPool.SLASH);
1769
1770        return sb.toString();
1771    }
1772
1773    protected static String getArticleImagePath(
1774        PortletDataContext context, JournalArticle article,
1775        JournalArticleImage articleImage, Image image) {
1776
1777        StringBundler sb = new StringBundler(13);
1778
1779        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1780        sb.append("/articles/");
1781        sb.append(article.getUuid());
1782        sb.append(StringPool.SLASH);
1783        sb.append(article.getVersion());
1784        sb.append(StringPool.SLASH);
1785        sb.append(articleImage.getElInstanceId());
1786        sb.append(StringPool.UNDERLINE);
1787        sb.append(articleImage.getElName());
1788
1789        if (Validator.isNotNull(articleImage.getLanguageId())) {
1790            sb.append(StringPool.UNDERLINE);
1791            sb.append(articleImage.getLanguageId());
1792        }
1793
1794        sb.append(StringPool.PERIOD);
1795        sb.append(image.getType());
1796
1797        return sb.toString();
1798    }
1799
1800    protected static String getArticleSmallImagePath(
1801            PortletDataContext context, JournalArticle article)
1802        throws PortalException, SystemException {
1803
1804        StringBundler sb = new StringBundler(6);
1805
1806        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1807        sb.append("/articles/");
1808        sb.append(article.getUuid());
1809        sb.append("/thumbnail");
1810        sb.append(StringPool.PERIOD);
1811        sb.append(article.getSmallImageType());
1812
1813        return sb.toString();
1814    }
1815
1816    protected static String getFeedPath(
1817        PortletDataContext context, JournalFeed feed) {
1818
1819        StringBundler sb = new StringBundler(4);
1820
1821        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1822        sb.append("/feeds/");
1823        sb.append(feed.getUuid());
1824        sb.append(".xml");
1825
1826        return sb.toString();
1827    }
1828
1829    protected static String getTemplatePath(
1830        PortletDataContext context, JournalTemplate template) {
1831
1832        StringBundler sb = new StringBundler(4);
1833
1834        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1835        sb.append("/templates/");
1836        sb.append(template.getUuid());
1837        sb.append(".xml");
1838
1839        return sb.toString();
1840    }
1841
1842    protected static String getTemplateSmallImagePath(
1843            PortletDataContext context, JournalTemplate template)
1844        throws PortalException, SystemException {
1845
1846        StringBundler sb = new StringBundler(5);
1847
1848        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1849        sb.append("/templates/thumbnail-");
1850        sb.append(template.getUuid());
1851        sb.append(StringPool.PERIOD);
1852        sb.append(template.getSmallImageType());
1853
1854        return sb.toString();
1855    }
1856
1857    protected static String getStructurePath(
1858        PortletDataContext context, JournalStructure structure) {
1859
1860        StringBundler sb = new StringBundler(4);
1861
1862        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1863        sb.append("/structures/");
1864        sb.append(structure.getUuid());
1865        sb.append(".xml");
1866
1867        return sb.toString();
1868    }
1869
1870    private static final boolean _ALWAYS_EXPORTABLE = true;
1871
1872    private static final String _NAMESPACE = "journal";
1873
1874    private static Log _log = LogFactoryUtil.getLog(
1875        JournalPortletDataHandlerImpl.class);
1876
1877    private static PortletDataHandlerBoolean _categories =
1878        new PortletDataHandlerBoolean(_NAMESPACE, "categories");
1879
1880    private static PortletDataHandlerBoolean _comments =
1881        new PortletDataHandlerBoolean(_NAMESPACE, "comments");
1882
1883    private static PortletDataHandlerBoolean _embeddedAssets =
1884        new PortletDataHandlerBoolean(_NAMESPACE, "embedded-assets");
1885
1886    private static PortletDataHandlerBoolean _images =
1887        new PortletDataHandlerBoolean(_NAMESPACE, "images");
1888
1889    private static PortletDataHandlerBoolean _ratings =
1890        new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
1891
1892    private static PortletDataHandlerBoolean
1893        _structuresTemplatesAndFeeds = new PortletDataHandlerBoolean(
1894            _NAMESPACE, "structures-templates-and-feeds", true, true);
1895
1896    private static PortletDataHandlerBoolean _tags =
1897        new PortletDataHandlerBoolean(_NAMESPACE, "tags");
1898
1899    private static PortletDataHandlerBoolean _articles =
1900        new PortletDataHandlerBoolean(_NAMESPACE, "articles", true, false,
1901        new PortletDataHandlerControl[] {_images, _comments, _ratings, _tags});
1902
1903}