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