001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.journal.lar;
016    
017    import com.liferay.portal.NoSuchImageException;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.lar.BasePortletDataHandler;
022    import com.liferay.portal.kernel.lar.PortletDataContext;
023    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
024    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.repository.model.FileEntry;
028    import com.liferay.portal.kernel.util.ArrayUtil;
029    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
030    import com.liferay.portal.kernel.util.CharPool;
031    import com.liferay.portal.kernel.util.FileUtil;
032    import com.liferay.portal.kernel.util.GetterUtil;
033    import com.liferay.portal.kernel.util.HttpUtil;
034    import com.liferay.portal.kernel.util.LocaleUtil;
035    import com.liferay.portal.kernel.util.LocalizationUtil;
036    import com.liferay.portal.kernel.util.MapUtil;
037    import com.liferay.portal.kernel.util.StringBundler;
038    import com.liferay.portal.kernel.util.StringPool;
039    import com.liferay.portal.kernel.util.StringUtil;
040    import com.liferay.portal.kernel.util.Validator;
041    import com.liferay.portal.kernel.workflow.WorkflowConstants;
042    import com.liferay.portal.kernel.xml.Document;
043    import com.liferay.portal.kernel.xml.Element;
044    import com.liferay.portal.kernel.xml.SAXReaderUtil;
045    import com.liferay.portal.model.Group;
046    import com.liferay.portal.model.Image;
047    import com.liferay.portal.model.Layout;
048    import com.liferay.portal.model.RepositoryEntry;
049    import com.liferay.portal.model.User;
050    import com.liferay.portal.service.GroupLocalServiceUtil;
051    import com.liferay.portal.service.LayoutLocalServiceUtil;
052    import com.liferay.portal.service.ServiceContext;
053    import com.liferay.portal.service.UserLocalServiceUtil;
054    import com.liferay.portal.service.persistence.ImageUtil;
055    import com.liferay.portal.service.persistence.LayoutUtil;
056    import com.liferay.portal.util.PortletKeys;
057    import com.liferay.portal.util.PropsValues;
058    import com.liferay.portlet.documentlibrary.lar.DLPortletDataHandlerImpl;
059    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
060    import com.liferay.portlet.documentlibrary.util.DLUtil;
061    import com.liferay.portlet.journal.ArticleContentException;
062    import com.liferay.portlet.journal.FeedTargetLayoutFriendlyUrlException;
063    import com.liferay.portlet.journal.NoSuchArticleException;
064    import com.liferay.portlet.journal.NoSuchStructureException;
065    import com.liferay.portlet.journal.model.JournalArticle;
066    import com.liferay.portlet.journal.model.JournalArticleConstants;
067    import com.liferay.portlet.journal.model.JournalArticleImage;
068    import com.liferay.portlet.journal.model.JournalArticleResource;
069    import com.liferay.portlet.journal.model.JournalFeed;
070    import com.liferay.portlet.journal.model.JournalStructure;
071    import com.liferay.portlet.journal.model.JournalTemplate;
072    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
073    import com.liferay.portlet.journal.service.JournalFeedLocalServiceUtil;
074    import com.liferay.portlet.journal.service.JournalStructureLocalServiceUtil;
075    import com.liferay.portlet.journal.service.JournalTemplateLocalServiceUtil;
076    import com.liferay.portlet.journal.service.persistence.JournalArticleImageUtil;
077    import com.liferay.portlet.journal.service.persistence.JournalArticleResourceUtil;
078    import com.liferay.portlet.journal.service.persistence.JournalArticleUtil;
079    import com.liferay.portlet.journal.service.persistence.JournalFeedUtil;
080    import com.liferay.portlet.journal.service.persistence.JournalStructureUtil;
081    import com.liferay.portlet.journal.service.persistence.JournalTemplateUtil;
082    import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
083    import com.liferay.portlet.journal.util.comparator.StructurePKComparator;
084    
085    import java.io.File;
086    
087    import java.util.ArrayList;
088    import java.util.Calendar;
089    import java.util.Collections;
090    import java.util.Date;
091    import java.util.HashMap;
092    import java.util.List;
093    import java.util.Locale;
094    import java.util.Map;
095    import java.util.regex.Matcher;
096    import java.util.regex.Pattern;
097    
098    import javax.portlet.PortletPreferences;
099    
100    /**
101     * <p>
102     * Provides the Journal portlet export and import functionality, which is to
103     * clone all articles, structures, and templates associated with the layout's
104     * group. Upon import, new instances of the corresponding articles, structures,
105     * and templates are created or updated according to the DATA_MIRROW strategy
106     * The author of the newly created objects are determined by the
107     * JournalCreationStrategy class defined in <i>portal.properties</i>. That
108     * strategy also allows the text of the journal article to be modified prior to
109     * import.
110     * </p>
111     *
112     * <p>
113     * This <code>PortletDataHandler</code> differs from
114     * <code>JournalContentPortletDataHandlerImpl</code> in that it exports all
115     * articles owned by the group whether or not they are actually displayed in a
116     * portlet in the layout set.
117     * </p>
118     *
119     * @author Raymond Augé
120     * @author Joel Kozikowski
121     * @author Brian Wing Shun Chan
122     * @author Bruno Farache
123     * @author Karthik Sudarshan
124     * @author Wesley Gong
125     * @author Hugo Huijser
126     * @see    com.liferay.portal.kernel.lar.PortletDataHandler
127     * @see    com.liferay.portlet.journal.lar.JournalContentPortletDataHandlerImpl
128     * @see    com.liferay.portlet.journal.lar.JournalCreationStrategy
129     */
130    public class JournalPortletDataHandlerImpl extends BasePortletDataHandler {
131    
132            public static void exportArticle(
133                            PortletDataContext portletDataContext, Element articlesElement,
134                            Element structuresElement, Element templatesElement,
135                            Element dlFileEntryTypesElement, Element dlFoldersElement,
136                            Element dlFileEntriesElement, Element dlFileRanksElement,
137                            Element dlRepositoriesElement, Element dlRepositoryEntriesElement,
138                            JournalArticle article, String preferenceTemplateId,
139                            boolean checkDateRange)
140                    throws Exception {
141    
142                    if (checkDateRange &&
143                            !portletDataContext.isWithinDateRange(article.getModifiedDate())) {
144    
145                            return;
146                    }
147    
148                    if ((article.getStatus() != WorkflowConstants.STATUS_APPROVED) &&
149                            (article.getStatus() != WorkflowConstants.STATUS_EXPIRED)) {
150    
151                            return;
152                    }
153    
154                    String path = getArticlePath(portletDataContext, article);
155    
156                    if (!portletDataContext.isPathNotProcessed(path)) {
157                            return;
158                    }
159    
160                    // Clone this article to make sure changes to its content are never
161                    // persisted
162    
163                    article = (JournalArticle)article.clone();
164    
165                    Element articleElement = (Element)articlesElement.selectSingleNode(
166                            "//article[@path='".concat(path).concat("']"));
167    
168                    if (articleElement == null) {
169                            articleElement = articlesElement.addElement("article");
170                    }
171    
172                    articleElement.addAttribute(
173                            "article-resource-uuid", article.getArticleResourceUuid());
174    
175                    if (Validator.isNotNull(article.getStructureId())) {
176                            JournalStructure structure =
177                                    JournalStructureLocalServiceUtil.getStructure(
178                                            article.getGroupId(), article.getStructureId(), true);
179    
180                            articleElement.addAttribute("structure-uuid", structure.getUuid());
181    
182                            exportStructure(portletDataContext, structuresElement, structure);
183                    }
184    
185                    String templateId = article.getTemplateId();
186    
187                    if (Validator.isNotNull(preferenceTemplateId)) {
188                            templateId = preferenceTemplateId;
189                    }
190    
191                    if (Validator.isNotNull(templateId)) {
192                            JournalTemplate template =
193                                    JournalTemplateLocalServiceUtil.getTemplate(
194                                            article.getGroupId(), templateId, true);
195    
196                            articleElement.addAttribute("template-uuid", template.getUuid());
197    
198                            exportTemplate(
199                                    portletDataContext, templatesElement, dlFileEntryTypesElement,
200                                    dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
201                                    dlRepositoriesElement, dlRepositoryEntriesElement, template);
202                    }
203    
204                    Image smallImage = ImageUtil.fetchByPrimaryKey(
205                            article.getSmallImageId());
206    
207                    if (article.isSmallImage() && (smallImage != null)) {
208                            String smallImagePath = getArticleSmallImagePath(
209                                    portletDataContext, article);
210    
211                            articleElement.addAttribute("small-image-path", smallImagePath);
212    
213                            article.setSmallImageType(smallImage.getType());
214    
215                            portletDataContext.addZipEntry(
216                                    smallImagePath, smallImage.getTextObj());
217                    }
218    
219                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "images")) {
220                            String imagePath = getArticleImagePath(portletDataContext, article);
221    
222                            articleElement.addAttribute("image-path", imagePath);
223    
224                            List<JournalArticleImage> articleImages =
225                                    JournalArticleImageUtil.findByG_A_V(
226                                            article.getGroupId(), article.getArticleId(),
227                                            article.getVersion());
228    
229                            for (JournalArticleImage articleImage : articleImages) {
230                                    Image image = null;
231    
232                                    try {
233                                            image = ImageUtil.findByPrimaryKey(
234                                                    articleImage.getArticleImageId());
235                                    }
236                                    catch (NoSuchImageException nsie) {
237                                            continue;
238                                    }
239    
240                                    if (image.getTextObj() == null) {
241                                            continue;
242                                    }
243    
244                                    String articleImagePath = getArticleImagePath(
245                                            portletDataContext, article, articleImage, image);
246    
247                                    if (!portletDataContext.isPathNotProcessed(articleImagePath)) {
248                                            continue;
249                                    }
250    
251                                    portletDataContext.addZipEntry(
252                                            articleImagePath, image.getTextObj());
253                            }
254                    }
255    
256                    article.setStatusByUserUuid(article.getStatusByUserUuid());
257    
258                    if (portletDataContext.getBooleanParameter(
259                                    _NAMESPACE, "embedded-assets")) {
260    
261                            String content = exportReferencedContent(
262                                    portletDataContext, dlFileEntryTypesElement, dlFoldersElement,
263                                    dlFileEntriesElement, dlFileRanksElement, dlRepositoriesElement,
264                                    dlRepositoryEntriesElement, articleElement,
265                                    article.getContent());
266    
267                            article.setContent(content);
268                    }
269    
270                    portletDataContext.addClassedModel(
271                            articleElement, path, article, _NAMESPACE);
272            }
273    
274            public static String exportReferencedContent(
275                            PortletDataContext portletDataContext,
276                            Element dlFileEntryTypesElement, Element dlFoldersElement,
277                            Element dlFileEntriesElement, Element dlFileRanksElement,
278                            Element dlRepositoriesElement, Element dlRepositoryEntriesElement,
279                            Element entityElement, String content)
280                    throws Exception {
281    
282                    content = exportDLFileEntries(
283                            portletDataContext, dlFileEntryTypesElement, dlFoldersElement,
284                            dlFileEntriesElement, dlFileRanksElement, dlRepositoriesElement,
285                            dlRepositoryEntriesElement, entityElement, content, false);
286                    content = exportLayoutFriendlyURLs(portletDataContext, content);
287                    content = exportLinksToLayout(portletDataContext, content);
288    
289                    String entityElementName = entityElement.getName();
290    
291                    if (!entityElementName.equals("article")) {
292                            content = StringUtil.replace(
293                                    content, StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
294                    }
295    
296                    return content;
297            }
298    
299            public static String getArticlePath(
300                            PortletDataContext portletDataContext, JournalArticle article)
301                    throws Exception {
302    
303                    StringBundler sb = new StringBundler(8);
304    
305                    sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
306                    sb.append("/articles/");
307                    sb.append(article.getArticleResourceUuid());
308                    sb.append(StringPool.SLASH);
309                    sb.append(article.getVersion());
310                    sb.append(StringPool.SLASH);
311                    sb.append("article.xml");
312    
313                    return sb.toString();
314            }
315    
316            public static PortletDataHandlerControl[] getMetadataControls() {
317                    return _metadataControls;
318            }
319    
320            public static void importArticle(
321                            PortletDataContext portletDataContext, Element articleElement)
322                    throws Exception {
323    
324                    String path = articleElement.attributeValue("path");
325    
326                    if (!portletDataContext.isPathNotProcessed(path)) {
327                            return;
328                    }
329    
330                    JournalArticle article =
331                            (JournalArticle)portletDataContext.getZipEntryAsObject(path);
332    
333                    prepareLanguagesForImport(article);
334    
335                    long userId = portletDataContext.getUserId(article.getUserUuid());
336    
337                    JournalCreationStrategy creationStrategy =
338                            JournalCreationStrategyFactory.getInstance();
339    
340                    long authorId = creationStrategy.getAuthorUserId(
341                            portletDataContext, article);
342    
343                    if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
344                            userId = authorId;
345                    }
346    
347                    User user = UserLocalServiceUtil.getUser(userId);
348    
349                    String articleId = article.getArticleId();
350                    boolean autoArticleId = false;
351    
352                    if (Validator.isNumber(articleId) ||
353                            (JournalArticleUtil.fetchByG_A_V(
354                                    portletDataContext.getScopeGroupId(), articleId,
355                                    JournalArticleConstants.VERSION_DEFAULT) != null)) {
356    
357                            autoArticleId = true;
358                    }
359    
360                    Map<String, String> articleIds =
361                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
362                                    JournalArticle.class + ".articleId");
363    
364                    String newArticleId = articleIds.get(articleId);
365    
366                    if (Validator.isNotNull(newArticleId)) {
367    
368                            // A sibling of a different version was already assigned a new
369                            // article id
370    
371                            articleId = newArticleId;
372                            autoArticleId = false;
373                    }
374    
375                    String content = article.getContent();
376    
377                    content = importDLFileEntries(
378                            portletDataContext, articleElement, content);
379    
380                    Group group = GroupLocalServiceUtil.getGroup(
381                            portletDataContext.getScopeGroupId());
382    
383                    content = StringUtil.replace(
384                            content, "@data_handler_group_friendly_url@",
385                            group.getFriendlyURL());
386    
387                    content = importLinksToLayout(portletDataContext, content);
388    
389                    article.setContent(content);
390    
391                    String newContent = creationStrategy.getTransformedContent(
392                            portletDataContext, article);
393    
394                    if (newContent != JournalCreationStrategy.ARTICLE_CONTENT_UNCHANGED) {
395                            article.setContent(newContent);
396                    }
397    
398                    Map<String, String> structureIds =
399                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
400                                    JournalStructure.class);
401    
402                    String parentStructureId = MapUtil.getString(
403                            structureIds, article.getStructureId(), article.getStructureId());
404    
405                    Map<String, String> templateIds =
406                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
407                                    JournalTemplate.class);
408    
409                    String parentTemplateId = MapUtil.getString(
410                            templateIds, article.getTemplateId(), article.getTemplateId());
411    
412                    Date displayDate = article.getDisplayDate();
413    
414                    int displayDateMonth = 0;
415                    int displayDateDay = 0;
416                    int displayDateYear = 0;
417                    int displayDateHour = 0;
418                    int displayDateMinute = 0;
419    
420                    if (displayDate != null) {
421                            Calendar displayCal = CalendarFactoryUtil.getCalendar(
422                                    user.getTimeZone());
423    
424                            displayCal.setTime(displayDate);
425    
426                            displayDateMonth = displayCal.get(Calendar.MONTH);
427                            displayDateDay = displayCal.get(Calendar.DATE);
428                            displayDateYear = displayCal.get(Calendar.YEAR);
429                            displayDateHour = displayCal.get(Calendar.HOUR);
430                            displayDateMinute = displayCal.get(Calendar.MINUTE);
431    
432                            if (displayCal.get(Calendar.AM_PM) == Calendar.PM) {
433                                    displayDateHour += 12;
434                            }
435                    }
436    
437                    Date expirationDate = article.getExpirationDate();
438    
439                    int expirationDateMonth = 0;
440                    int expirationDateDay = 0;
441                    int expirationDateYear = 0;
442                    int expirationDateHour = 0;
443                    int expirationDateMinute = 0;
444                    boolean neverExpire = true;
445    
446                    if (expirationDate != null) {
447                            Calendar expirationCal = CalendarFactoryUtil.getCalendar(
448                                    user.getTimeZone());
449    
450                            expirationCal.setTime(expirationDate);
451    
452                            expirationDateMonth = expirationCal.get(Calendar.MONTH);
453                            expirationDateDay = expirationCal.get(Calendar.DATE);
454                            expirationDateYear = expirationCal.get(Calendar.YEAR);
455                            expirationDateHour = expirationCal.get(Calendar.HOUR);
456                            expirationDateMinute = expirationCal.get(Calendar.MINUTE);
457                            neverExpire = false;
458    
459                            if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
460                                    expirationDateHour += 12;
461                            }
462                    }
463    
464                    Date reviewDate = article.getReviewDate();
465    
466                    int reviewDateMonth = 0;
467                    int reviewDateDay = 0;
468                    int reviewDateYear = 0;
469                    int reviewDateHour = 0;
470                    int reviewDateMinute = 0;
471                    boolean neverReview = true;
472    
473                    if (reviewDate != null) {
474                            Calendar reviewCal = CalendarFactoryUtil.getCalendar(
475                                    user.getTimeZone());
476    
477                            reviewCal.setTime(reviewDate);
478    
479                            reviewDateMonth = reviewCal.get(Calendar.MONTH);
480                            reviewDateDay = reviewCal.get(Calendar.DATE);
481                            reviewDateYear = reviewCal.get(Calendar.YEAR);
482                            reviewDateHour = reviewCal.get(Calendar.HOUR);
483                            reviewDateMinute = reviewCal.get(Calendar.MINUTE);
484                            neverReview = false;
485    
486                            if (reviewCal.get(Calendar.AM_PM) == Calendar.PM) {
487                                    reviewDateHour += 12;
488                            }
489                    }
490    
491                    long structurePrimaryKey = 0;
492    
493                    if (Validator.isNotNull(article.getStructureId())) {
494                            String structureUuid = articleElement.attributeValue(
495                                    "structure-uuid");
496    
497                            JournalStructure existingStructure =
498                                    JournalStructureUtil.fetchByUUID_G(
499                                            structureUuid, portletDataContext.getScopeGroupId());
500    
501                            if (existingStructure == null) {
502                                    Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
503                                            portletDataContext.getCompanyId());
504    
505                                    long companyGroupId = companyGroup.getGroupId();
506    
507                                    existingStructure = JournalStructureUtil.fetchByUUID_G(
508                                            structureUuid, companyGroupId);
509                            }
510    
511                            if (existingStructure == null) {
512                                    String newStructureId = structureIds.get(
513                                            article.getStructureId());
514    
515                                    if (Validator.isNotNull(newStructureId)) {
516                                            existingStructure = JournalStructureUtil.fetchByG_S(
517                                                    portletDataContext.getScopeGroupId(),
518                                                    String.valueOf(newStructureId));
519                                    }
520    
521                                    if (existingStructure == null) {
522                                            if (_log.isWarnEnabled()) {
523                                                    StringBundler sb = new StringBundler();
524    
525                                                    sb.append("Structure ");
526                                                    sb.append(article.getStructureId());
527                                                    sb.append(" is missing for article ");
528                                                    sb.append(article.getArticleId());
529                                                    sb.append(", skipping this article.");
530    
531                                                    _log.warn(sb.toString());
532                                            }
533    
534                                            return;
535                                    }
536                            }
537    
538                            structurePrimaryKey = existingStructure.getPrimaryKey();
539    
540                            parentStructureId = existingStructure.getStructureId();
541                    }
542    
543                    if (Validator.isNotNull(article.getTemplateId())) {
544                            String templateUuid = articleElement.attributeValue(
545                                    "template-uuid");
546    
547                            JournalTemplate existingTemplate =
548                                    JournalTemplateUtil.fetchByUUID_G(
549                                            templateUuid, portletDataContext.getScopeGroupId());
550    
551                            if (existingTemplate == null) {
552                                    Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
553                                            portletDataContext.getCompanyId());
554    
555                                    long companyGroupId = companyGroup.getGroupId();
556    
557                                    existingTemplate = JournalTemplateUtil.fetchByUUID_G(
558                                            templateUuid, companyGroupId);
559                            }
560    
561                            if (existingTemplate == null) {
562                                    String newTemplateId = templateIds.get(article.getTemplateId());
563    
564                                    if (Validator.isNotNull(newTemplateId)) {
565                                            existingTemplate = JournalTemplateUtil.fetchByG_T(
566                                                    portletDataContext.getScopeGroupId(), newTemplateId);
567                                    }
568    
569                                    if (existingTemplate == null) {
570                                            if (_log.isWarnEnabled()) {
571                                                    StringBundler sb = new StringBundler();
572    
573                                                    sb.append("Template ");
574                                                    sb.append(article.getTemplateId());
575                                                    sb.append(" is missing for article ");
576                                                    sb.append(article.getArticleId());
577                                                    sb.append(", skipping this article.");
578    
579                                                    _log.warn(sb.toString());
580                                            }
581    
582                                            return;
583                                    }
584                            }
585    
586                            parentTemplateId = existingTemplate.getTemplateId();
587                    }
588    
589                    File smallFile = null;
590    
591                    String smallImagePath = articleElement.attributeValue(
592                            "small-image-path");
593    
594                    if (article.isSmallImage() && Validator.isNotNull(smallImagePath)) {
595                            byte[] bytes = portletDataContext.getZipEntryAsByteArray(
596                                    smallImagePath);
597    
598                            smallFile = FileUtil.createTempFile(article.getSmallImageType());
599    
600                            FileUtil.write(smallFile, bytes);
601                    }
602    
603                    Map<String, byte[]> images = new HashMap<String, byte[]>();
604    
605                    String imagePath = articleElement.attributeValue("image-path");
606    
607                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "images") &&
608                            Validator.isNotNull(imagePath)) {
609    
610                            List<String> imageFiles = portletDataContext.getZipFolderEntries(
611                                    imagePath);
612    
613                            for (String imageFile : imageFiles) {
614                                    String fileName = imageFile;
615    
616                                    if (fileName.contains(StringPool.SLASH)) {
617                                            fileName = fileName.substring(
618                                                    fileName.lastIndexOf(CharPool.SLASH) + 1);
619                                    }
620    
621                                    if (fileName.endsWith(".xml")) {
622                                            continue;
623                                    }
624    
625                                    int pos = fileName.lastIndexOf(CharPool.PERIOD);
626    
627                                    if (pos != -1) {
628                                            fileName = fileName.substring(0, pos);
629                                    }
630    
631                                    images.put(
632                                            fileName,
633                                            portletDataContext.getZipEntryAsByteArray(imageFile));
634                            }
635                    }
636    
637                    String articleURL = null;
638    
639                    boolean addGroupPermissions = creationStrategy.addGroupPermissions(
640                            portletDataContext, article);
641                    boolean addGuestPermissions = creationStrategy.addGuestPermissions(
642                            portletDataContext, article);
643    
644                    ServiceContext serviceContext = portletDataContext.createServiceContext(
645                            articleElement, article, _NAMESPACE);
646    
647                    serviceContext.setAddGroupPermissions(addGroupPermissions);
648                    serviceContext.setAddGuestPermissions(addGuestPermissions);
649                    serviceContext.setAttribute("imported", Boolean.TRUE.toString());
650    
651                    if (article.getStatus() != WorkflowConstants.STATUS_APPROVED) {
652                            serviceContext.setWorkflowAction(
653                                    WorkflowConstants.ACTION_SAVE_DRAFT);
654                    }
655    
656                    JournalArticle importedArticle = null;
657    
658                    String articleResourceUuid = articleElement.attributeValue(
659                            "article-resource-uuid");
660    
661                    if (portletDataContext.isDataStrategyMirror()) {
662                            JournalArticleResource articleResource =
663                                    JournalArticleResourceUtil.fetchByUUID_G(
664                                            articleResourceUuid, portletDataContext.getScopeGroupId());
665    
666                            if (articleResource == null) {
667                                    Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
668                                            portletDataContext.getCompanyId());
669    
670                                    long companyGroupId = companyGroup.getGroupId();
671    
672                                    articleResource = JournalArticleResourceUtil.fetchByUUID_G(
673                                            articleResourceUuid, companyGroupId);
674                            }
675    
676                            serviceContext.setUuid(articleResourceUuid);
677    
678                            JournalArticle existingArticle = null;
679    
680                            if (articleResource != null) {
681                                    try {
682                                            existingArticle =
683                                                    JournalArticleLocalServiceUtil.getLatestArticle(
684                                                            articleResource.getResourcePrimKey(),
685                                                            WorkflowConstants.STATUS_ANY, false);
686                                    }
687                                    catch (NoSuchArticleException nsae) {
688                                    }
689                            }
690    
691                            if (existingArticle == null) {
692                                    existingArticle = JournalArticleUtil.fetchByG_A_V(
693                                            portletDataContext.getScopeGroupId(), newArticleId,
694                                            article.getVersion());
695                            }
696    
697                            if (existingArticle == null) {
698                                    importedArticle = JournalArticleLocalServiceUtil.addArticle(
699                                            userId, portletDataContext.getScopeGroupId(),
700                                            article.getClassNameId(), structurePrimaryKey, articleId,
701                                            autoArticleId, article.getVersion(), article.getTitleMap(),
702                                            article.getDescriptionMap(), article.getContent(),
703                                            article.getType(), parentStructureId, parentTemplateId,
704                                            article.getLayoutUuid(), displayDateMonth, displayDateDay,
705                                            displayDateYear, displayDateHour, displayDateMinute,
706                                            expirationDateMonth, expirationDateDay, expirationDateYear,
707                                            expirationDateHour, expirationDateMinute, neverExpire,
708                                            reviewDateMonth, reviewDateDay, reviewDateYear,
709                                            reviewDateHour, reviewDateMinute, neverReview,
710                                            article.isIndexable(), article.isSmallImage(),
711                                            article.getSmallImageURL(), smallFile, images, articleURL,
712                                            serviceContext);
713                            }
714                            else {
715                                    importedArticle = JournalArticleLocalServiceUtil.updateArticle(
716                                            userId, existingArticle.getGroupId(),
717                                            existingArticle.getArticleId(),
718                                            existingArticle.getVersion(), article.getTitleMap(),
719                                            article.getDescriptionMap(), article.getContent(),
720                                            article.getType(), parentStructureId, parentTemplateId,
721                                            article.getLayoutUuid(), displayDateMonth, displayDateDay,
722                                            displayDateYear, displayDateHour, displayDateMinute,
723                                            expirationDateMonth, expirationDateDay, expirationDateYear,
724                                            expirationDateHour, expirationDateMinute, neverExpire,
725                                            reviewDateMonth, reviewDateDay, reviewDateYear,
726                                            reviewDateHour, reviewDateMinute, neverReview,
727                                            article.isIndexable(), article.isSmallImage(),
728                                            article.getSmallImageURL(), smallFile, images, articleURL,
729                                            serviceContext);
730                            }
731                    }
732                    else {
733                            importedArticle = JournalArticleLocalServiceUtil.addArticle(
734                                    userId, portletDataContext.getScopeGroupId(),
735                                    article.getClassNameId(), structurePrimaryKey, articleId,
736                                    autoArticleId, article.getVersion(), article.getTitleMap(),
737                                    article.getDescriptionMap(), article.getContent(),
738                                    article.getType(), parentStructureId, parentTemplateId,
739                                    article.getLayoutUuid(), displayDateMonth, displayDateDay,
740                                    displayDateYear, displayDateHour, displayDateMinute,
741                                    expirationDateMonth, expirationDateDay, expirationDateYear,
742                                    expirationDateHour, expirationDateMinute, neverExpire,
743                                    reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
744                                    reviewDateMinute, neverReview, article.isIndexable(),
745                                    article.isSmallImage(), article.getSmallImageURL(), smallFile,
746                                    images, articleURL, serviceContext);
747                    }
748    
749                    if (smallFile != null) {
750                            smallFile.delete();
751                    }
752    
753                    portletDataContext.importClassedModel(
754                            article, importedArticle, _NAMESPACE);
755    
756                    if (Validator.isNull(newArticleId)) {
757                            articleIds.put(
758                                    article.getArticleId(), importedArticle.getArticleId());
759                    }
760    
761                    Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
762                            portletDataContext.getCompanyId());
763    
764                    if (importedArticle.getGroupId() == companyGroup.getGroupId()) {
765                            portletDataContext.addCompanyReference(
766                                    JournalArticle.class, articleId);
767                    }
768    
769                    if (!articleId.equals(importedArticle.getArticleId())) {
770                            if (_log.isWarnEnabled()) {
771                                    _log.warn(
772                                            "An article with the ID " + articleId + " already " +
773                                                    "exists. The new generated ID is " +
774                                                            importedArticle.getArticleId());
775                            }
776                    }
777            }
778    
779            public static void importFeed(
780                            PortletDataContext portletDataContext, Element feedElement)
781                    throws Exception {
782    
783                    String path = feedElement.attributeValue("path");
784    
785                    if (!portletDataContext.isPathNotProcessed(path)) {
786                            return;
787                    }
788    
789                    JournalFeed feed = (JournalFeed)portletDataContext.getZipEntryAsObject(
790                            path);
791    
792                    long userId = portletDataContext.getUserId(feed.getUserUuid());
793    
794                    JournalCreationStrategy creationStrategy =
795                            JournalCreationStrategyFactory.getInstance();
796    
797                    long authorId = creationStrategy.getAuthorUserId(
798                            portletDataContext, feed);
799    
800                    if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
801                            userId = authorId;
802                    }
803    
804                    Group group = GroupLocalServiceUtil.getGroup(
805                            portletDataContext.getScopeGroupId());
806    
807                    String newGroupFriendlyURL = group.getFriendlyURL().substring(1);
808    
809                    String[] friendlyUrlParts = StringUtil.split(
810                            feed.getTargetLayoutFriendlyUrl(), '/');
811    
812                    String oldGroupFriendlyURL = friendlyUrlParts[2];
813    
814                    if (oldGroupFriendlyURL.equals("@data_handler_group_friendly_url@")) {
815                            feed.setTargetLayoutFriendlyUrl(
816                                    StringUtil.replace(
817                                            feed.getTargetLayoutFriendlyUrl(),
818                                            "@data_handler_group_friendly_url@", newGroupFriendlyURL));
819                    }
820    
821                    String feedId = feed.getFeedId();
822                    boolean autoFeedId = false;
823    
824                    if (Validator.isNumber(feedId) ||
825                            (JournalFeedUtil.fetchByG_F(
826                                    portletDataContext.getScopeGroupId(), feedId) != null)) {
827    
828                            autoFeedId = true;
829                    }
830    
831                    Map<String, String> structureIds =
832                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
833                                    JournalStructure.class + ".structureId");
834    
835                    String parentStructureId = MapUtil.getString(
836                            structureIds, feed.getStructureId(), feed.getStructureId());
837    
838                    Map<String, String> templateIds =
839                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
840                                    JournalTemplate.class + ".templateId");
841    
842                    String parentTemplateId = MapUtil.getString(
843                            templateIds, feed.getTemplateId(), feed.getTemplateId());
844                    String parentRenderTemplateId = MapUtil.getString(
845                            templateIds, feed.getRendererTemplateId(),
846                            feed.getRendererTemplateId());
847    
848                    boolean addGroupPermissions = creationStrategy.addGroupPermissions(
849                            portletDataContext, feed);
850                    boolean addGuestPermissions = creationStrategy.addGuestPermissions(
851                            portletDataContext, feed);
852    
853                    ServiceContext serviceContext = portletDataContext.createServiceContext(
854                            feedElement, feed, _NAMESPACE);
855    
856                    serviceContext.setAddGroupPermissions(addGroupPermissions);
857                    serviceContext.setAddGuestPermissions(addGuestPermissions);
858    
859                    JournalFeed importedFeed = null;
860    
861                    try {
862                            if (portletDataContext.isDataStrategyMirror()) {
863                                    JournalFeed existingFeed = JournalFeedUtil.fetchByUUID_G(
864                                            feed.getUuid(), portletDataContext.getScopeGroupId());
865    
866                                    if (existingFeed == null) {
867                                            serviceContext.setUuid(feed.getUuid());
868    
869                                            importedFeed = JournalFeedLocalServiceUtil.addFeed(
870                                                    userId, portletDataContext.getScopeGroupId(), feedId,
871                                                    autoFeedId, feed.getName(), feed.getDescription(),
872                                                    feed.getType(), parentStructureId, parentTemplateId,
873                                                    parentRenderTemplateId, feed.getDelta(),
874                                                    feed.getOrderByCol(), feed.getOrderByType(),
875                                                    feed.getTargetLayoutFriendlyUrl(),
876                                                    feed.getTargetPortletId(), feed.getContentField(),
877                                                    feed.getFeedType(), feed.getFeedVersion(),
878                                                    serviceContext);
879                                    }
880                                    else {
881                                            importedFeed = JournalFeedLocalServiceUtil.updateFeed(
882                                                    existingFeed.getGroupId(), existingFeed.getFeedId(),
883                                                    feed.getName(), feed.getDescription(), feed.getType(),
884                                                    parentStructureId, parentTemplateId,
885                                                    parentRenderTemplateId, feed.getDelta(),
886                                                    feed.getOrderByCol(), feed.getOrderByType(),
887                                                    feed.getTargetLayoutFriendlyUrl(),
888                                                    feed.getTargetPortletId(), feed.getContentField(),
889                                                    feed.getFeedType(), feed.getFeedVersion(),
890                                                    serviceContext);
891                                    }
892                            }
893                            else {
894                                    importedFeed = JournalFeedLocalServiceUtil.addFeed(
895                                            userId, portletDataContext.getScopeGroupId(), feedId,
896                                            autoFeedId, feed.getName(), feed.getDescription(),
897                                            feed.getType(), parentStructureId, parentTemplateId,
898                                            parentRenderTemplateId, feed.getDelta(),
899                                            feed.getOrderByCol(), feed.getOrderByType(),
900                                            feed.getTargetLayoutFriendlyUrl(),
901                                            feed.getTargetPortletId(), feed.getContentField(),
902                                            feed.getFeedType(), feed.getFeedVersion(), serviceContext);
903                            }
904    
905                            portletDataContext.importClassedModel(
906                                    feed, importedFeed, _NAMESPACE);
907    
908                            if (!feedId.equals(importedFeed.getFeedId())) {
909                                    if (_log.isWarnEnabled()) {
910                                            StringBundler sb = new StringBundler(5);
911    
912                                            sb.append("A feed with the ID ");
913                                            sb.append(feedId);
914                                            sb.append(" already exists. The new generated ID is ");
915                                            sb.append(importedFeed.getFeedId());
916                                            sb.append(".");
917    
918                                            _log.warn(sb.toString());
919                                    }
920                            }
921                    }
922                    catch (FeedTargetLayoutFriendlyUrlException ftlfurle) {
923                            if (_log.isWarnEnabled()) {
924                                    StringBundler sb = new StringBundler(6);
925    
926                                    sb.append("A feed with the ID ");
927                                    sb.append(feedId);
928                                    sb.append(" cannot be imported because layout with friendly ");
929                                    sb.append("URL ");
930                                    sb.append(feed.getTargetLayoutFriendlyUrl());
931                                    sb.append(" does not exist");
932    
933                                    _log.warn(sb.toString());
934                            }
935                    }
936            }
937    
938            public static String importReferencedContent(
939                            PortletDataContext portletDataContext, Element parentElement,
940                            String content)
941                    throws Exception {
942    
943                    content = importDLFileEntries(
944                            portletDataContext, parentElement, content);
945    
946                    Group group = GroupLocalServiceUtil.getGroup(
947                            portletDataContext.getScopeGroupId());
948    
949                    content = StringUtil.replace(
950                            content, "@data_handler_group_friendly_url@",
951                            group.getFriendlyURL());
952    
953                    content = importLinksToLayout(portletDataContext, content);
954    
955                    return content;
956            }
957    
958            public static void importReferencedData(
959                            PortletDataContext portletDataContext, Element entityElement)
960                    throws Exception {
961    
962                    Element dlRepositoriesElement = entityElement.element(
963                            "dl-repositories");
964    
965                    List<Element> dlRepositoryElements = Collections.emptyList();
966    
967                    if (dlRepositoriesElement != null) {
968                            dlRepositoryElements = dlRepositoriesElement.elements("repository");
969                    }
970    
971                    for (Element repositoryElement : dlRepositoryElements) {
972                            DLPortletDataHandlerImpl.importRepository(
973                                    portletDataContext, repositoryElement);
974                    }
975    
976                    Element dlRepositoryEntriesElement = entityElement.element(
977                            "dl-repository-entries");
978    
979                    List<Element> dlRepositoryEntryElements = Collections.emptyList();
980    
981                    if (dlRepositoryEntriesElement != null) {
982                            dlRepositoryEntryElements = dlRepositoryEntriesElement.elements(
983                                    "repository-entry");
984                    }
985    
986                    for (Element repositoryEntryElement : dlRepositoryEntryElements) {
987                            DLPortletDataHandlerImpl.importRepositoryEntry(
988                                    portletDataContext, repositoryEntryElement);
989                    }
990    
991                    Element dlFoldersElement = entityElement.element("dl-folders");
992    
993                    List<Element> dlFolderElements = Collections.emptyList();
994    
995                    if (dlFoldersElement != null) {
996                            dlFolderElements = dlFoldersElement.elements("folder");
997                    }
998    
999                    for (Element folderElement : dlFolderElements) {
1000                            DLPortletDataHandlerImpl.importFolder(
1001                                    portletDataContext, folderElement);
1002                    }
1003    
1004                    Element dlFileEntriesElement = entityElement.element("dl-file-entries");
1005    
1006                    List<Element> dlFileEntryElements = Collections.emptyList();
1007    
1008                    if (dlFileEntriesElement != null) {
1009                            dlFileEntryElements = dlFileEntriesElement.elements("file-entry");
1010                    }
1011    
1012                    for (Element fileEntryElement : dlFileEntryElements) {
1013                            DLPortletDataHandlerImpl.importFileEntry(
1014                                    portletDataContext, fileEntryElement);
1015                    }
1016    
1017                    Element dlFileRanksElement = entityElement.element("dl-file-ranks");
1018    
1019                    List<Element> dlFileRankElements = Collections.emptyList();
1020    
1021                    if (dlFileRanksElement != null) {
1022                            dlFileRankElements = dlFileRanksElement.elements("file-rank");
1023                    }
1024    
1025                    for (Element fileRankElement : dlFileRankElements) {
1026                            DLPortletDataHandlerImpl.importFileRank(
1027                                    portletDataContext, fileRankElement);
1028                    }
1029            }
1030    
1031            public static void importStructure(
1032                            PortletDataContext portletDataContext, Element structureElement)
1033                    throws Exception {
1034    
1035                    String path = structureElement.attributeValue("path");
1036    
1037                    if (!portletDataContext.isPathNotProcessed(path)) {
1038                            return;
1039                    }
1040    
1041                    JournalStructure structure =
1042                            (JournalStructure)portletDataContext.getZipEntryAsObject(path);
1043    
1044                    long userId = portletDataContext.getUserId(structure.getUserUuid());
1045    
1046                    JournalCreationStrategy creationStrategy =
1047                            JournalCreationStrategyFactory.getInstance();
1048    
1049                    long authorId = creationStrategy.getAuthorUserId(
1050                            portletDataContext, structure);
1051    
1052                    if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
1053                            userId = authorId;
1054                    }
1055    
1056                    String structureId = structure.getStructureId();
1057                    boolean autoStructureId = false;
1058    
1059                    if (Validator.isNumber(structureId) ||
1060                            (JournalStructureUtil.fetchByG_S(
1061                                    portletDataContext.getScopeGroupId(), structureId) != null)) {
1062    
1063                            autoStructureId = true;
1064                    }
1065    
1066                    Map<String, String> structureIds =
1067                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
1068                                    JournalStructure.class + ".structureId");
1069    
1070                    String parentStructureId = MapUtil.getString(
1071                            structureIds, structure.getParentStructureId(),
1072                            structure.getParentStructureId());
1073    
1074                    Document document = structureElement.getDocument();
1075    
1076                    Element rootElement = document.getRootElement();
1077    
1078                    Element parentStructureElement = (Element)rootElement.selectSingleNode(
1079                            "./structures/structure[@structure-id='" + parentStructureId +
1080                                    "']");
1081    
1082                    String parentStructureUuid = GetterUtil.getString(
1083                            structureElement.attributeValue("parent-structure-uuid"));
1084    
1085                    if ((parentStructureElement != null) &&
1086                            Validator.isNotNull(parentStructureId)) {
1087    
1088                            importStructure(portletDataContext, parentStructureElement);
1089    
1090                            parentStructureId = structureIds.get(parentStructureId);
1091                    }
1092                    else if (Validator.isNotNull(parentStructureUuid)) {
1093                            JournalStructure parentStructure =
1094                                    JournalStructureLocalServiceUtil.
1095                                            getJournalStructureByUuidAndGroupId(
1096                                                    parentStructureUuid, portletDataContext.getGroupId());
1097    
1098                            parentStructureId = parentStructure.getStructureId();
1099                    }
1100    
1101                    boolean addGroupPermissions = creationStrategy.addGroupPermissions(
1102                            portletDataContext, structure);
1103                    boolean addGuestPermissions = creationStrategy.addGuestPermissions(
1104                            portletDataContext, structure);
1105    
1106                    ServiceContext serviceContext = portletDataContext.createServiceContext(
1107                            structureElement, structure, _NAMESPACE);
1108    
1109                    serviceContext.setAddGroupPermissions(addGroupPermissions);
1110                    serviceContext.setAddGuestPermissions(addGuestPermissions);
1111    
1112                    JournalStructure importedStructure = null;
1113    
1114                    if (portletDataContext.isDataStrategyMirror()) {
1115                            JournalStructure existingStructure =
1116                                    JournalStructureUtil.fetchByUUID_G(
1117                                            structure.getUuid(), portletDataContext.getScopeGroupId());
1118    
1119                            if (existingStructure == null) {
1120                                    Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
1121                                            portletDataContext.getCompanyId());
1122    
1123                                    long companyGroupId = companyGroup.getGroupId();
1124    
1125                                    existingStructure = JournalStructureUtil.fetchByUUID_G(
1126                                            structure.getUuid(), companyGroupId);
1127                            }
1128    
1129                            if (existingStructure == null) {
1130                                    serviceContext.setUuid(structure.getUuid());
1131    
1132                                    importedStructure =
1133                                            JournalStructureLocalServiceUtil.addStructure(
1134                                                    userId, portletDataContext.getScopeGroupId(),
1135                                                    structureId, autoStructureId, parentStructureId,
1136                                                    structure.getNameMap(), structure.getDescriptionMap(),
1137                                                    structure.getXsd(), serviceContext);
1138                            }
1139                            else {
1140                                    importedStructure =
1141                                            JournalStructureLocalServiceUtil.updateStructure(
1142                                                    existingStructure.getGroupId(),
1143                                                    existingStructure.getStructureId(), parentStructureId,
1144                                                    structure.getNameMap(), structure.getDescriptionMap(),
1145                                                    structure.getXsd(), serviceContext);
1146                            }
1147                    }
1148                    else {
1149                            importedStructure = JournalStructureLocalServiceUtil.addStructure(
1150                                    userId, portletDataContext.getScopeGroupId(), structureId,
1151                                    autoStructureId, parentStructureId, structure.getNameMap(),
1152                                    structure.getDescriptionMap(), structure.getXsd(),
1153                                    serviceContext);
1154                    }
1155    
1156                    portletDataContext.importClassedModel(
1157                            structure, importedStructure, _NAMESPACE);
1158    
1159                    structureIds.put(structureId, importedStructure.getStructureId());
1160    
1161                    if (!structureId.equals(importedStructure.getStructureId())) {
1162                            if (_log.isWarnEnabled()) {
1163                                    _log.warn(
1164                                            "A structure with the ID " + structureId + " already " +
1165                                                    "exists. The new generated ID is " +
1166                                                            importedStructure.getStructureId());
1167                            }
1168                    }
1169            }
1170    
1171            public static void importTemplate(
1172                            PortletDataContext portletDataContext, Element templateElement)
1173                    throws Exception {
1174    
1175                    String path = templateElement.attributeValue("path");
1176    
1177                    if (!portletDataContext.isPathNotProcessed(path)) {
1178                            return;
1179                    }
1180    
1181                    JournalTemplate template =
1182                            (JournalTemplate)portletDataContext.getZipEntryAsObject(path);
1183    
1184                    long userId = portletDataContext.getUserId(template.getUserUuid());
1185    
1186                    JournalCreationStrategy creationStrategy =
1187                            JournalCreationStrategyFactory.getInstance();
1188    
1189                    long authorId = creationStrategy.getAuthorUserId(
1190                            portletDataContext, template);
1191    
1192                    if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
1193                            userId = authorId;
1194                    }
1195    
1196                    String templateId = template.getTemplateId();
1197                    boolean autoTemplateId = false;
1198    
1199                    if (Validator.isNumber(templateId) ||
1200                            (JournalTemplateUtil.fetchByG_T(
1201                                    portletDataContext.getScopeGroupId(), templateId) != null)) {
1202    
1203                            autoTemplateId = true;
1204                    }
1205    
1206                    Map<String, String> structureIds =
1207                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
1208                                    JournalStructure.class + ".structureId");
1209    
1210                    String parentStructureId = MapUtil.getString(
1211                            structureIds, template.getStructureId(), template.getStructureId());
1212    
1213                    String xsl = template.getXsl();
1214    
1215                    xsl = importDLFileEntries(portletDataContext, templateElement, xsl);
1216    
1217                    Group group = GroupLocalServiceUtil.getGroup(
1218                            portletDataContext.getScopeGroupId());
1219    
1220                    xsl = StringUtil.replace(
1221                            xsl, "@data_handler_group_friendly_url@", group.getFriendlyURL());
1222    
1223                    template.setXsl(xsl);
1224    
1225                    boolean formatXsl = false;
1226    
1227                    boolean addGroupPermissions = creationStrategy.addGroupPermissions(
1228                            portletDataContext, template);
1229                    boolean addGuestPermissions = creationStrategy.addGuestPermissions(
1230                            portletDataContext, template);
1231    
1232                    ServiceContext serviceContext = portletDataContext.createServiceContext(
1233                            templateElement, template, _NAMESPACE);
1234    
1235                    serviceContext.setAddGroupPermissions(addGroupPermissions);
1236                    serviceContext.setAddGuestPermissions(addGuestPermissions);
1237    
1238                    File smallFile = null;
1239    
1240                    String smallImagePath = templateElement.attributeValue(
1241                            "small-image-path");
1242    
1243                    if (template.isSmallImage() && Validator.isNotNull(smallImagePath)) {
1244                            if (smallImagePath.endsWith(StringPool.PERIOD)) {
1245                                    smallImagePath += template.getSmallImageType();
1246                            }
1247    
1248                            byte[] bytes = portletDataContext.getZipEntryAsByteArray(
1249                                    smallImagePath);
1250    
1251                            if (bytes != null) {
1252                                    smallFile = FileUtil.createTempFile(
1253                                            template.getSmallImageType());
1254    
1255                                    FileUtil.write(smallFile, bytes);
1256                            }
1257                    }
1258    
1259                    JournalTemplate importedTemplate = null;
1260    
1261                    if (portletDataContext.isDataStrategyMirror()) {
1262                            JournalTemplate existingTemplate =
1263                                    JournalTemplateUtil.fetchByUUID_G(
1264                                            template.getUuid(), portletDataContext.getScopeGroupId());
1265    
1266                            if (existingTemplate == null) {
1267                                    Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
1268                                            portletDataContext.getCompanyId());
1269    
1270                                    long companyGroupId = companyGroup.getGroupId();
1271    
1272                                    existingTemplate = JournalTemplateUtil.fetchByUUID_G(
1273                                            template.getUuid(), companyGroupId);
1274                            }
1275    
1276                            if (existingTemplate == null) {
1277                                    serviceContext.setUuid(template.getUuid());
1278    
1279                                    importedTemplate = JournalTemplateLocalServiceUtil.addTemplate(
1280                                            userId, portletDataContext.getScopeGroupId(), templateId,
1281                                            autoTemplateId, parentStructureId, template.getNameMap(),
1282                                            template.getDescriptionMap(), template.getXsl(), formatXsl,
1283                                            template.getLangType(), template.getCacheable(),
1284                                            template.isSmallImage(), template.getSmallImageURL(),
1285                                            smallFile, serviceContext);
1286                            }
1287                            else {
1288                                    String structureId = existingTemplate.getStructureId();
1289    
1290                                    if (Validator.isNull(structureId) &&
1291                                            Validator.isNotNull(template.getStructureId())) {
1292    
1293                                            JournalStructure structure =
1294                                                    JournalStructureUtil.fetchByG_S(
1295                                                            template.getGroupId(), template.getStructureId());
1296    
1297                                            if (structure == null) {
1298                                                    structureId = template.getStructureId();
1299                                            }
1300                                            else {
1301                                                    JournalStructure existingStructure =
1302                                                            JournalStructureUtil.findByUUID_G(
1303                                                                    structure.getUuid(),
1304                                                                    portletDataContext.getScopeGroupId());
1305    
1306                                                    structureId = existingStructure.getStructureId();
1307                                            }
1308                                    }
1309    
1310                                    importedTemplate =
1311                                            JournalTemplateLocalServiceUtil.updateTemplate(
1312                                                    existingTemplate.getGroupId(),
1313                                                    existingTemplate.getTemplateId(), structureId,
1314                                                    template.getNameMap(), template.getDescriptionMap(),
1315                                                    template.getXsl(), formatXsl, template.getLangType(),
1316                                                    template.getCacheable(), template.isSmallImage(),
1317                                                    template.getSmallImageURL(), smallFile, serviceContext);
1318                            }
1319                    }
1320                    else {
1321                            importedTemplate = JournalTemplateLocalServiceUtil.addTemplate(
1322                                    userId, portletDataContext.getScopeGroupId(), templateId,
1323                                    autoTemplateId, parentStructureId, template.getNameMap(),
1324                                    template.getDescriptionMap(), template.getXsl(), formatXsl,
1325                                    template.getLangType(), template.getCacheable(),
1326                                    template.isSmallImage(), template.getSmallImageURL(), smallFile,
1327                                    serviceContext);
1328                    }
1329    
1330                    if (smallFile != null) {
1331                            smallFile.delete();
1332                    }
1333    
1334                    portletDataContext.importClassedModel(
1335                            template, importedTemplate, _NAMESPACE);
1336    
1337                    Map<String, String> templateIds =
1338                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
1339                                    JournalTemplate.class + ".templateId");
1340    
1341                    templateIds.put(
1342                            template.getTemplateId(), importedTemplate.getTemplateId());
1343    
1344                    if (!templateId.equals(importedTemplate.getTemplateId())) {
1345                            if (_log.isWarnEnabled()) {
1346                                    _log.warn(
1347                                            "A template with the ID " + templateId + " already " +
1348                                                    "exists. The new generated ID is " +
1349                                                            importedTemplate.getTemplateId());
1350                            }
1351                    }
1352            }
1353    
1354            @Override
1355            public PortletDataHandlerControl[] getExportControls() {
1356                    return new PortletDataHandlerControl[] {
1357                            _articles, _structuresTemplatesAndFeeds, _embeddedAssets
1358                    };
1359            }
1360    
1361            @Override
1362            public PortletDataHandlerControl[] getExportMetadataControls() {
1363                    return new PortletDataHandlerControl[] {
1364                            new PortletDataHandlerBoolean(
1365                                    _NAMESPACE, "web-content", true, _metadataControls)
1366                    };
1367            }
1368    
1369            @Override
1370            public PortletDataHandlerControl[] getImportControls() {
1371                    return new PortletDataHandlerControl[] {
1372                            _articles, _structuresTemplatesAndFeeds
1373                    };
1374            }
1375    
1376            @Override
1377            public PortletDataHandlerControl[] getImportMetadataControls() {
1378                    return new PortletDataHandlerControl[] {
1379                            new PortletDataHandlerBoolean(
1380                                    _NAMESPACE, "web-content", true, _metadataControls)
1381                    };
1382            }
1383    
1384            @Override
1385            public boolean isAlwaysExportable() {
1386                    return _ALWAYS_EXPORTABLE;
1387            }
1388    
1389            @Override
1390            public boolean isDataLocalized() {
1391                    return _DATA_LOCALIZED;
1392            }
1393    
1394            @Override
1395            public boolean isPublishToLiveByDefault() {
1396                    return PropsValues.JOURNAL_PUBLISH_TO_LIVE_BY_DEFAULT;
1397            }
1398    
1399            protected static String exportDLFileEntries(
1400                            PortletDataContext portletDataContext,
1401                            Element dlFileEntryTypesElement, Element dlFoldersElement,
1402                            Element dlFileEntriesElement, Element dlFileRanksElement,
1403                            Element dlRepositoriesElement, Element dlRepositoryEntriesElement,
1404                            Element entityElement, String content, boolean checkDateRange)
1405                    throws Exception {
1406    
1407                    Group group = GroupLocalServiceUtil.getGroup(
1408                            portletDataContext.getGroupId());
1409    
1410                    if (group.isStagingGroup()) {
1411                            group = group.getLiveGroup();
1412                    }
1413    
1414                    if (group.isStaged() && !group.isStagedRemotely() &&
1415                            !group.isStagedPortlet(PortletKeys.DOCUMENT_LIBRARY)) {
1416    
1417                            return content;
1418                    }
1419    
1420                    StringBuilder sb = new StringBuilder(content);
1421    
1422                    int beginPos = content.length();
1423                    int currentLocation = -1;
1424    
1425                    while (true) {
1426                            currentLocation = content.lastIndexOf(
1427                                    "/c/document_library/get_file?", beginPos);
1428    
1429                            if (currentLocation == -1) {
1430                                    currentLocation = content.lastIndexOf("/documents/", beginPos);
1431                            }
1432    
1433                            if (currentLocation == -1) {
1434                                    return sb.toString();
1435                            }
1436    
1437                            beginPos = currentLocation;
1438    
1439                            int endPos1 = content.indexOf(CharPool.APOSTROPHE, beginPos);
1440                            int endPos2 = content.indexOf(CharPool.CLOSE_BRACKET, beginPos);
1441                            int endPos3 = content.indexOf(CharPool.CLOSE_CURLY_BRACE, beginPos);
1442                            int endPos4 = content.indexOf(CharPool.CLOSE_PARENTHESIS, beginPos);
1443                            int endPos5 = content.indexOf(CharPool.LESS_THAN, beginPos);
1444                            int endPos6 = content.indexOf(CharPool.QUESTION, beginPos);
1445                            int endPos7 = content.indexOf(CharPool.QUOTE, beginPos);
1446                            int endPos8 = content.indexOf(CharPool.SPACE, beginPos);
1447    
1448                            int endPos = endPos1;
1449    
1450                            if ((endPos == -1) || ((endPos2 != -1) && (endPos2 < endPos))) {
1451                                    endPos = endPos2;
1452                            }
1453    
1454                            if ((endPos == -1) || ((endPos3 != -1) && (endPos3 < endPos))) {
1455                                    endPos = endPos3;
1456                            }
1457    
1458                            if ((endPos == -1) || ((endPos4 != -1) && (endPos4 < endPos))) {
1459                                    endPos = endPos4;
1460                            }
1461    
1462                            if ((endPos == -1) || ((endPos5 != -1) && (endPos5 < endPos))) {
1463                                    endPos = endPos5;
1464                            }
1465    
1466                            if ((endPos == -1) || ((endPos6 != -1) && (endPos6 < endPos))) {
1467                                    endPos = endPos6;
1468                            }
1469    
1470                            if ((endPos == -1) || ((endPos7 != -1) && (endPos7 < endPos))) {
1471                                    endPos = endPos7;
1472                            }
1473    
1474                            if ((endPos == -1) || ((endPos8 != -1) && (endPos8 < endPos))) {
1475                                    endPos = endPos8;
1476                            }
1477    
1478                            if ((beginPos == -1) || (endPos == -1)) {
1479                                    break;
1480                            }
1481    
1482                            try {
1483                                    String oldParameters = content.substring(beginPos, endPos);
1484    
1485                                    while (oldParameters.contains(StringPool.AMPERSAND_ENCODED)) {
1486                                            oldParameters = oldParameters.replace(
1487                                                    StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
1488                                    }
1489    
1490                                    Map<String, String[]> map = new HashMap<String, String[]>();
1491    
1492                                    if (oldParameters.startsWith("/documents/")) {
1493                                            String[] pathArray = oldParameters.split(StringPool.SLASH);
1494    
1495                                            map.put("groupId", new String[] {pathArray[2]});
1496    
1497                                            if (pathArray.length == 4) {
1498                                                    map.put("uuid", new String[] {pathArray[3]});
1499                                            }
1500                                            else if (pathArray.length == 5) {
1501                                                    map.put("folderId", new String[] {pathArray[3]});
1502    
1503                                                    String name = HttpUtil.decodeURL(pathArray[4]);
1504    
1505                                                    int pos = name.indexOf(StringPool.QUESTION);
1506    
1507                                                    if (pos != -1) {
1508                                                            name = name.substring(0, pos);
1509                                                    }
1510    
1511                                                    map.put("name", new String[] {name});
1512                                            }
1513                                            else if (pathArray.length > 5) {
1514                                                    String uuid = pathArray[5];
1515    
1516                                                    int pos = uuid.indexOf(StringPool.QUESTION);
1517    
1518                                                    if (pos != -1) {
1519                                                            uuid = uuid.substring(0, pos);
1520                                                    }
1521    
1522                                                    map.put("uuid", new String[] {uuid});
1523                                            }
1524                                    }
1525                                    else {
1526                                            oldParameters = oldParameters.substring(
1527                                                    oldParameters.indexOf(CharPool.QUESTION) + 1);
1528    
1529                                            map = HttpUtil.parameterMapFromString(oldParameters);
1530                                    }
1531    
1532                                    FileEntry fileEntry = null;
1533    
1534                                    String uuid = MapUtil.getString(map, "uuid");
1535    
1536                                    if (Validator.isNotNull(uuid)) {
1537                                            String groupIdString = MapUtil.getString(map, "groupId");
1538    
1539                                            long groupId = GetterUtil.getLong(groupIdString);
1540    
1541                                            if (groupIdString.equals("@group_id@")) {
1542                                                    groupId = portletDataContext.getScopeGroupId();
1543                                            }
1544    
1545                                            fileEntry =
1546                                                    DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
1547                                                            uuid, groupId);
1548                                    }
1549                                    else {
1550                                            String folderIdString = MapUtil.getString(map, "folderId");
1551    
1552                                            if (Validator.isNotNull(folderIdString)) {
1553                                                    long folderId = GetterUtil.getLong(folderIdString);
1554                                                    String name = MapUtil.getString(map, "name");
1555    
1556                                                    String groupIdString = MapUtil.getString(
1557                                                            map, "groupId");
1558    
1559                                                    long groupId = GetterUtil.getLong(groupIdString);
1560    
1561                                                    if (groupIdString.equals("@group_id@")) {
1562                                                            groupId = portletDataContext.getScopeGroupId();
1563                                                    }
1564    
1565                                                    fileEntry = DLAppLocalServiceUtil.getFileEntry(
1566                                                            groupId, folderId, name);
1567                                            }
1568                                    }
1569    
1570                                    if (fileEntry == null) {
1571                                            beginPos--;
1572    
1573                                            continue;
1574                                    }
1575    
1576                                    DLPortletDataHandlerImpl.exportFileEntry(
1577                                            portletDataContext, dlFileEntryTypesElement,
1578                                            dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
1579                                            dlRepositoriesElement, dlRepositoryEntriesElement,
1580                                            fileEntry, checkDateRange);
1581    
1582                                    Element dlReferenceElement = entityElement.addElement(
1583                                            "dl-reference");
1584    
1585                                    dlReferenceElement.addAttribute(
1586                                            "default-repository",
1587                                            String.valueOf(fileEntry.isDefaultRepository()));
1588    
1589                                    String path = null;
1590    
1591                                    if (fileEntry.isDefaultRepository()) {
1592                                            path = DLPortletDataHandlerImpl.getFileEntryPath(
1593                                                    portletDataContext, fileEntry);
1594    
1595                                    }
1596                                    else {
1597                                            path = DLPortletDataHandlerImpl.getRepositoryEntryPath(
1598                                                    portletDataContext, fileEntry.getFileEntryId());
1599                                    }
1600    
1601                                    dlReferenceElement.addAttribute("path", path);
1602    
1603                                    String dlReference = "[$dl-reference=" + path + "$]";
1604    
1605                                    sb.replace(beginPos, endPos, dlReference);
1606                            }
1607                            catch (Exception e) {
1608                                    if (_log.isDebugEnabled()) {
1609                                            _log.debug(e, e);
1610                                    }
1611                                    else if (_log.isWarnEnabled()) {
1612                                            _log.warn(e.getMessage());
1613                                    }
1614                            }
1615    
1616                            beginPos--;
1617                    }
1618    
1619                    return sb.toString();
1620            }
1621    
1622            protected static void exportFeed(
1623                            PortletDataContext portletDataContext, Element feedsElement,
1624                            JournalFeed feed)
1625                    throws Exception {
1626    
1627                    if (!portletDataContext.isWithinDateRange(feed.getModifiedDate())) {
1628                            return;
1629                    }
1630    
1631                    String path = getFeedPath(portletDataContext, feed);
1632    
1633                    if (!portletDataContext.isPathNotProcessed(path)) {
1634                            return;
1635                    }
1636    
1637                    feed = (JournalFeed)feed.clone();
1638    
1639                    Element feedElement = feedsElement.addElement("feed");
1640    
1641                    Group group = GroupLocalServiceUtil.getGroup(
1642                            portletDataContext.getScopeGroupId());
1643    
1644                    String newGroupFriendlyURL = group.getFriendlyURL().substring(1);
1645    
1646                    String[] friendlyUrlParts = StringUtil.split(
1647                            feed.getTargetLayoutFriendlyUrl(), '/');
1648    
1649                    String oldGroupFriendlyURL = friendlyUrlParts[2];
1650    
1651                    if (newGroupFriendlyURL.equals(oldGroupFriendlyURL)) {
1652                            String targetLayoutFriendlyUrl = StringUtil.replaceFirst(
1653                                    feed.getTargetLayoutFriendlyUrl(),
1654                                    StringPool.SLASH + newGroupFriendlyURL + StringPool.SLASH,
1655                                    "/@data_handler_group_friendly_url@/");
1656    
1657                            feed.setTargetLayoutFriendlyUrl(targetLayoutFriendlyUrl);
1658                    }
1659    
1660                    portletDataContext.addClassedModel(feedElement, path, feed, _NAMESPACE);
1661            }
1662    
1663            protected static String exportLayoutFriendlyURLs(
1664                    PortletDataContext portletDataContext, String content) {
1665    
1666                    Group group = null;
1667    
1668                    try {
1669                            group = GroupLocalServiceUtil.getGroup(
1670                                    portletDataContext.getScopeGroupId());
1671                    }
1672                    catch (Exception e) {
1673                            if (_log.isWarnEnabled()) {
1674                                    _log.warn(e);
1675                            }
1676    
1677                            return content;
1678                    }
1679    
1680                    StringBuilder sb = new StringBuilder(content);
1681    
1682                    String friendlyURLPrivateGroupPath =
1683                            PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
1684                    String friendlyURLPrivateUserPath =
1685                            PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
1686                    String friendlyURLPublicPath =
1687                            PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
1688    
1689                    String href = "href=";
1690    
1691                    int beginPos = content.length();
1692    
1693                    while (true) {
1694                            int hrefLength = href.length();
1695    
1696                            beginPos = content.lastIndexOf(href, beginPos);
1697    
1698                            if (beginPos == -1) {
1699                                    break;
1700                            }
1701    
1702                            char c = content.charAt(beginPos + hrefLength);
1703    
1704                            if ((c == CharPool.APOSTROPHE) || (c == CharPool.QUOTE)) {
1705                                    hrefLength++;
1706                            }
1707    
1708                            int endPos1 = content.indexOf(
1709                                    CharPool.APOSTROPHE, beginPos + hrefLength);
1710                            int endPos2 = content.indexOf(
1711                                    CharPool.CLOSE_BRACKET, beginPos + hrefLength);
1712                            int endPos3 = content.indexOf(
1713                                    CharPool.CLOSE_CURLY_BRACE, beginPos + hrefLength);
1714                            int endPos4 = content.indexOf(
1715                                    CharPool.CLOSE_PARENTHESIS, beginPos + hrefLength);
1716                            int endPos5 = content.indexOf(
1717                                    CharPool.LESS_THAN, beginPos + hrefLength);
1718                            int endPos6 = content.indexOf(
1719                                    CharPool.QUESTION, beginPos + hrefLength);
1720                            int endPos7 = content.indexOf(
1721                                    CharPool.QUOTE, beginPos + hrefLength);
1722                            int endPos8 = content.indexOf(
1723                                    CharPool.SPACE, beginPos + hrefLength);
1724    
1725                            int endPos = endPos1;
1726    
1727                            if ((endPos == -1) || ((endPos2 != -1) && (endPos2 < endPos))) {
1728                                    endPos = endPos2;
1729                            }
1730    
1731                            if ((endPos == -1) || ((endPos3 != -1) && (endPos3 < endPos))) {
1732                                    endPos = endPos3;
1733                            }
1734    
1735                            if ((endPos == -1) || ((endPos4 != -1) && (endPos4 < endPos))) {
1736                                    endPos = endPos4;
1737                            }
1738    
1739                            if ((endPos == -1) || ((endPos5 != -1) && (endPos5 < endPos))) {
1740                                    endPos = endPos5;
1741                            }
1742    
1743                            if ((endPos == -1) || ((endPos6 != -1) && (endPos6 < endPos))) {
1744                                    endPos = endPos6;
1745                            }
1746    
1747                            if ((endPos == -1) || ((endPos7 != -1) && (endPos7 < endPos))) {
1748                                    endPos = endPos7;
1749                            }
1750    
1751                            if ((endPos == -1) || ((endPos8 != -1) && (endPos8 < endPos))) {
1752                                    endPos = endPos8;
1753                            }
1754    
1755                            if (endPos == -1) {
1756                                    beginPos--;
1757    
1758                                    continue;
1759                            }
1760    
1761                            String url = content.substring(beginPos + hrefLength, endPos);
1762    
1763                            if (!url.startsWith(friendlyURLPrivateGroupPath) &&
1764                                    !url.startsWith(friendlyURLPrivateUserPath) &&
1765                                    !url.startsWith(friendlyURLPublicPath)) {
1766    
1767                                    beginPos--;
1768    
1769                                    continue;
1770                            }
1771    
1772                            int beginGroupPos = content.indexOf(
1773                                    CharPool.SLASH, beginPos + hrefLength + 1);
1774    
1775                            if (beginGroupPos == -1) {
1776                                    beginPos--;
1777    
1778                                    continue;
1779                            }
1780    
1781                            int endGroupPos = content.indexOf(
1782                                    CharPool.SLASH, beginGroupPos + 1);
1783    
1784                            if (endGroupPos == -1) {
1785                                    beginPos--;
1786    
1787                                    continue;
1788                            }
1789    
1790                            String groupFriendlyURL = content.substring(
1791                                    beginGroupPos, endGroupPos);
1792    
1793                            if (groupFriendlyURL.equals(group.getFriendlyURL())) {
1794                                    sb.replace(
1795                                            beginGroupPos, endGroupPos,
1796                                            "@data_handler_group_friendly_url@");
1797                            }
1798    
1799                            beginPos--;
1800                    }
1801    
1802                    return sb.toString();
1803            }
1804    
1805            protected static String exportLinksToLayout(
1806                            PortletDataContext portletDataContext, String content)
1807                    throws Exception {
1808    
1809                    List<String> oldLinksToLayout = new ArrayList<String>();
1810                    List<String> newLinksToLayout = new ArrayList<String>();
1811    
1812                    Matcher matcher = _exportLinksToLayoutPattern.matcher(content);
1813    
1814                    while (matcher.find()) {
1815                            long layoutId = GetterUtil.getLong(matcher.group(1));
1816    
1817                            String type = matcher.group(2);
1818    
1819                            boolean privateLayout = type.startsWith("private");
1820    
1821                            try {
1822                                    Layout layout = LayoutLocalServiceUtil.getLayout(
1823                                            portletDataContext.getScopeGroupId(), privateLayout,
1824                                            layoutId);
1825    
1826                                    String oldLinkToLayout = matcher.group(0);
1827    
1828                                    StringBundler sb = new StringBundler(5);
1829    
1830                                    sb.append(type);
1831                                    sb.append(StringPool.AT);
1832                                    sb.append(layout.getUuid());
1833                                    sb.append(StringPool.AT);
1834                                    sb.append(layout.getFriendlyURL());
1835    
1836                                    String newLinkToLayout = StringUtil.replace(
1837                                            oldLinkToLayout, type, sb.toString());
1838    
1839                                    oldLinksToLayout.add(oldLinkToLayout);
1840                                    newLinksToLayout.add(newLinkToLayout);
1841                            }
1842                            catch (Exception e) {
1843                                    if (_log.isDebugEnabled() || _log.isWarnEnabled()) {
1844                                            String message =
1845                                                    "Unable to get layout with ID " + layoutId +
1846                                                            " in group " + portletDataContext.getScopeGroupId();
1847    
1848                                            if (_log.isWarnEnabled()) {
1849                                                    _log.warn(message);
1850                                            }
1851                                            else {
1852                                                    _log.debug(message, e);
1853                                            }
1854                                    }
1855                            }
1856                    }
1857    
1858                    content = StringUtil.replace(
1859                            content, ArrayUtil.toStringArray(oldLinksToLayout.toArray()),
1860                            ArrayUtil.toStringArray(newLinksToLayout.toArray()));
1861    
1862                    return content;
1863            }
1864    
1865            protected static void exportStructure(
1866                            PortletDataContext portletDataContext, Element structuresElement,
1867                            JournalStructure structure)
1868                    throws Exception {
1869    
1870                    String path = getStructurePath(portletDataContext, structure);
1871    
1872                    if (!portletDataContext.isPathNotProcessed(path)) {
1873                            return;
1874                    }
1875    
1876                    Element structureElement = structuresElement.addElement("structure");
1877    
1878                    String parentStructureId = structure.getParentStructureId();
1879    
1880                    if (Validator.isNotNull(parentStructureId)) {
1881                            try {
1882                                    JournalStructure parentStructure =
1883                                            JournalStructureLocalServiceUtil.getStructure(
1884                                                    structure.getGroupId(), parentStructureId, true);
1885    
1886                                    structureElement.addAttribute(
1887                                            "parent-structure-uuid", parentStructure.getUuid());
1888    
1889                                    exportStructure(
1890                                            portletDataContext, structuresElement, parentStructure);
1891                            }
1892                            catch (NoSuchStructureException nsse) {
1893                            }
1894                    }
1895    
1896                    portletDataContext.addClassedModel(
1897                            structureElement, path, structure, _NAMESPACE);
1898            }
1899    
1900            protected static void exportTemplate(
1901                            PortletDataContext portletDataContext, Element templatesElement,
1902                            Element dlFileEntryTypesElement, Element dlFoldersElement,
1903                            Element dlFileEntriesElement, Element dlFileRanksElement,
1904                            Element dlRepositoriesElement, Element dlRepositoryEntriesElement,
1905                            JournalTemplate template)
1906                    throws Exception {
1907    
1908                    String path = getTemplatePath(portletDataContext, template);
1909    
1910                    if (!portletDataContext.isPathNotProcessed(path)) {
1911                            return;
1912                    }
1913    
1914                    // Clone this template to make sure changes to its content are never
1915                    // persisted
1916    
1917                    template = (JournalTemplate)template.clone();
1918    
1919                    Element templateElement = templatesElement.addElement("template");
1920    
1921                    if (template.isSmallImage()) {
1922                            String smallImagePath = getTemplateSmallImagePath(
1923                                    portletDataContext, template);
1924    
1925                            templateElement.addAttribute("small-image-path", smallImagePath);
1926    
1927                            Image smallImage = ImageUtil.fetchByPrimaryKey(
1928                                    template.getSmallImageId());
1929    
1930                            template.setSmallImageType(smallImage.getType());
1931    
1932                            portletDataContext.addZipEntry(
1933                                    smallImagePath, smallImage.getTextObj());
1934                    }
1935    
1936                    if (portletDataContext.getBooleanParameter(
1937                                    _NAMESPACE, "embedded-assets")) {
1938    
1939                            String content = exportReferencedContent(
1940                                    portletDataContext, dlFileEntryTypesElement, dlFoldersElement,
1941                                    dlFileEntriesElement, dlFileRanksElement, dlRepositoriesElement,
1942                                    dlRepositoryEntriesElement, templateElement, template.getXsl());
1943    
1944                            template.setXsl(content);
1945                    }
1946    
1947                    portletDataContext.addClassedModel(
1948                            templateElement, path, template, _NAMESPACE);
1949            }
1950    
1951            protected static String getArticleImagePath(
1952                            PortletDataContext portletDataContext, JournalArticle article)
1953                    throws Exception {
1954    
1955                    StringBundler sb = new StringBundler(6);
1956    
1957                    sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
1958                    sb.append("/articles/");
1959                    sb.append(article.getArticleResourceUuid());
1960                    sb.append(StringPool.SLASH);
1961                    sb.append(article.getVersion());
1962                    sb.append(StringPool.SLASH);
1963    
1964                    return sb.toString();
1965            }
1966    
1967            protected static String getArticleImagePath(
1968                            PortletDataContext portletDataContext, JournalArticle article,
1969                            JournalArticleImage articleImage, Image image)
1970                    throws Exception {
1971    
1972                    StringBundler sb = new StringBundler(13);
1973    
1974                    sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
1975                    sb.append("/articles/");
1976                    sb.append(article.getArticleResourceUuid());
1977                    sb.append(StringPool.SLASH);
1978                    sb.append(article.getVersion());
1979                    sb.append(StringPool.SLASH);
1980                    sb.append(articleImage.getElInstanceId());
1981                    sb.append(StringPool.UNDERLINE);
1982                    sb.append(articleImage.getElName());
1983    
1984                    if (Validator.isNotNull(articleImage.getLanguageId())) {
1985                            sb.append(StringPool.UNDERLINE);
1986                            sb.append(articleImage.getLanguageId());
1987                    }
1988    
1989                    sb.append(StringPool.PERIOD);
1990                    sb.append(image.getType());
1991    
1992                    return sb.toString();
1993            }
1994    
1995            protected static String getArticleSmallImagePath(
1996                            PortletDataContext portletDataContext, JournalArticle article)
1997                    throws Exception {
1998    
1999                    StringBundler sb = new StringBundler(6);
2000    
2001                    sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
2002                    sb.append("/articles/");
2003                    sb.append(article.getArticleResourceUuid());
2004                    sb.append("/thumbnail");
2005                    sb.append(StringPool.PERIOD);
2006                    sb.append(article.getSmallImageType());
2007    
2008                    return sb.toString();
2009            }
2010    
2011            protected static String getFeedPath(
2012                    PortletDataContext portletDataContext, JournalFeed feed) {
2013    
2014                    StringBundler sb = new StringBundler(4);
2015    
2016                    sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
2017                    sb.append("/feeds/");
2018                    sb.append(feed.getUuid());
2019                    sb.append(".xml");
2020    
2021                    return sb.toString();
2022            }
2023    
2024            protected static String getStructurePath(
2025                    PortletDataContext portletDataContext, JournalStructure structure) {
2026    
2027                    StringBundler sb = new StringBundler(4);
2028    
2029                    sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
2030                    sb.append("/structures/");
2031                    sb.append(structure.getUuid());
2032                    sb.append(".xml");
2033    
2034                    return sb.toString();
2035            }
2036    
2037            protected static String getTemplatePath(
2038                    PortletDataContext portletDataContext, JournalTemplate template) {
2039    
2040                    StringBundler sb = new StringBundler(4);
2041    
2042                    sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
2043                    sb.append("/templates/");
2044                    sb.append(template.getUuid());
2045                    sb.append(".xml");
2046    
2047                    return sb.toString();
2048            }
2049    
2050            protected static String getTemplateSmallImagePath(
2051                            PortletDataContext portletDataContext, JournalTemplate template)
2052                    throws Exception {
2053    
2054                    StringBundler sb = new StringBundler(5);
2055    
2056                    sb.append(portletDataContext.getPortletPath(PortletKeys.JOURNAL));
2057                    sb.append("/templates/thumbnail-");
2058                    sb.append(template.getUuid());
2059                    sb.append(StringPool.PERIOD);
2060                    sb.append(template.getSmallImageType());
2061    
2062                    return sb.toString();
2063            }
2064    
2065            protected static String importDLFileEntries(
2066                            PortletDataContext portletDataContext, Element parentElement,
2067                            String content)
2068                    throws Exception {
2069    
2070                    List<Element> dlReferenceElements = parentElement.elements(
2071                            "dl-reference");
2072    
2073                    for (Element dlReferenceElement : dlReferenceElements) {
2074                            String dlReferencePath = dlReferenceElement.attributeValue("path");
2075    
2076                            String fileEntryUUID = null;
2077    
2078                            try {
2079                                    Object zipEntryObject = portletDataContext.getZipEntryAsObject(
2080                                            dlReferencePath);
2081    
2082                                    if (zipEntryObject == null) {
2083                                            if (_log.isWarnEnabled()) {
2084                                                    _log.warn("Unable to reference " + dlReferencePath);
2085                                            }
2086    
2087                                            continue;
2088                                    }
2089    
2090                                    boolean defaultRepository = GetterUtil.getBoolean(
2091                                            dlReferenceElement.attributeValue("default-repository"));
2092    
2093                                    if (defaultRepository) {
2094                                            FileEntry fileEntry = (FileEntry)zipEntryObject;
2095    
2096                                            fileEntryUUID = fileEntry.getUuid();
2097                                    }
2098                                    else {
2099                                            RepositoryEntry repositoryEntry =
2100                                                    (RepositoryEntry)zipEntryObject;
2101    
2102                                            fileEntryUUID = repositoryEntry.getUuid();
2103                                    }
2104                            }
2105                            catch (Exception e) {
2106                                    if (_log.isDebugEnabled()) {
2107                                            _log.debug(e, e);
2108                                    }
2109                                    else if (_log.isWarnEnabled()) {
2110                                            _log.warn(e.getMessage());
2111                                    }
2112                            }
2113    
2114                            if (fileEntryUUID == null) {
2115                                    continue;
2116                            }
2117    
2118                            FileEntry fileEntry =
2119                                    DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
2120                                            fileEntryUUID, portletDataContext.getGroupId());
2121    
2122                            if (fileEntry == null) {
2123                                    continue;
2124                            }
2125    
2126                            String dlReference = "[$dl-reference=" + dlReferencePath + "$]";
2127    
2128                            String url = DLUtil.getPreviewURL(
2129                                    fileEntry, fileEntry.getFileVersion(), null, StringPool.BLANK,
2130                                    false, false);
2131    
2132                            content = StringUtil.replace(content, dlReference, url);
2133                    }
2134    
2135                    return content;
2136            }
2137    
2138            protected static String importLinksToLayout(
2139                            PortletDataContext portletDataContext, String content)
2140                    throws Exception {
2141    
2142                    List<String> oldLinksToLayout = new ArrayList<String>();
2143                    List<String> newLinksToLayout = new ArrayList<String>();
2144    
2145                    Matcher matcher = _importLinksToLayoutPattern.matcher(content);
2146    
2147                    while (matcher.find()) {
2148                            long oldLayoutId = GetterUtil.getLong(matcher.group(1));
2149    
2150                            long newLayoutId = oldLayoutId;
2151    
2152                            String type = matcher.group(2);
2153    
2154                            boolean privateLayout = type.startsWith("private");
2155    
2156                            String layoutUuid = matcher.group(3);
2157    
2158                            String friendlyURL = matcher.group(4);
2159    
2160                            try {
2161                                    Layout layout = LayoutUtil.fetchByUUID_G(
2162                                            layoutUuid, portletDataContext.getScopeGroupId());
2163    
2164                                    if (layout == null) {
2165                                            layout = LayoutUtil.fetchByG_P_F(
2166                                                    portletDataContext.getScopeGroupId(), privateLayout,
2167                                                    friendlyURL);
2168                                    }
2169    
2170                                    if (layout == null) {
2171                                            layout = LayoutUtil.fetchByG_P_L(
2172                                                    portletDataContext.getScopeGroupId(), privateLayout,
2173                                                    oldLayoutId);
2174                                    }
2175    
2176                                    if (layout == null) {
2177                                            if (_log.isWarnEnabled()) {
2178                                                    StringBundler sb = new StringBundler(9);
2179    
2180                                                    sb.append("Unable to get layout with UUID ");
2181                                                    sb.append(layoutUuid);
2182                                                    sb.append(", friendly URL ");
2183                                                    sb.append(friendlyURL);
2184                                                    sb.append(", or ");
2185                                                    sb.append("layoutId ");
2186                                                    sb.append(oldLayoutId);
2187                                                    sb.append(" in group ");
2188                                                    sb.append(portletDataContext.getScopeGroupId());
2189    
2190                                                    _log.warn(sb.toString());
2191                                            }
2192                                    }
2193                                    else {
2194                                            newLayoutId = layout.getLayoutId();
2195                                    }
2196                            }
2197                            catch (SystemException se) {
2198                                    if (_log.isWarnEnabled()) {
2199                                            _log.warn(
2200                                                    "Unable to get layout in group " +
2201                                                            portletDataContext.getScopeGroupId(), se);
2202                                    }
2203                            }
2204    
2205                            String oldLinkToLayout = matcher.group(0);
2206    
2207                            StringBundler sb = new StringBundler(4);
2208    
2209                            sb.append(StringPool.AT);
2210                            sb.append(layoutUuid);
2211                            sb.append(StringPool.AT);
2212                            sb.append(friendlyURL);
2213    
2214                            String newLinkToLayout = StringUtil.replace(
2215                                    oldLinkToLayout,
2216                                    new String[] {sb.toString(), String.valueOf(oldLayoutId)},
2217                                    new String[] {StringPool.BLANK, String.valueOf(newLayoutId)});
2218    
2219                            oldLinksToLayout.add(oldLinkToLayout);
2220                            newLinksToLayout.add(newLinkToLayout);
2221                    }
2222    
2223                    content = StringUtil.replace(
2224                            content, ArrayUtil.toStringArray(oldLinksToLayout.toArray()),
2225                            ArrayUtil.toStringArray(newLinksToLayout.toArray()));
2226    
2227                    return content;
2228            }
2229    
2230            protected static void prepareLanguagesForImport(JournalArticle article)
2231                    throws PortalException {
2232    
2233                    Locale articleDefaultLocale = LocaleUtil.fromLanguageId(
2234                            article.getDefaultLocale());
2235    
2236                    Locale[] articleAvailableLocales = LocaleUtil.fromLanguageIds(
2237                            article.getAvailableLocales());
2238    
2239                    Locale defaultImportLocale = LocalizationUtil.getDefaultImportLocale(
2240                            JournalArticle.class.getName(), article.getPrimaryKey(),
2241                            articleDefaultLocale, articleAvailableLocales);
2242    
2243                    article.prepareLocalizedFieldsForImport(defaultImportLocale);
2244            }
2245    
2246            @Override
2247            protected PortletPreferences doDeleteData(
2248                            PortletDataContext portletDataContext, String portletId,
2249                            PortletPreferences portletPreferences)
2250                    throws Exception {
2251    
2252                    if (!portletDataContext.addPrimaryKey(
2253                                    JournalPortletDataHandlerImpl.class, "deleteData")) {
2254    
2255                            JournalArticleLocalServiceUtil.deleteArticles(
2256                                    portletDataContext.getScopeGroupId());
2257    
2258                            JournalTemplateLocalServiceUtil.deleteTemplates(
2259                                    portletDataContext.getScopeGroupId());
2260    
2261                            JournalStructureLocalServiceUtil.deleteStructures(
2262                                    portletDataContext.getScopeGroupId());
2263                    }
2264    
2265                    return portletPreferences;
2266            }
2267    
2268            @Override
2269            protected String doExportData(
2270                            PortletDataContext portletDataContext, String portletId,
2271                            PortletPreferences portletPreferences)
2272                    throws Exception {
2273    
2274                    portletDataContext.addPermissions(
2275                            "com.liferay.portlet.journal",
2276                            portletDataContext.getScopeGroupId());
2277    
2278                    Document document = SAXReaderUtil.createDocument();
2279    
2280                    Element rootElement = document.addElement("journal-data");
2281    
2282                    rootElement.addAttribute(
2283                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
2284    
2285                    Element structuresElement = rootElement.addElement("structures");
2286    
2287                    List<JournalStructure> structures = JournalStructureUtil.findByGroupId(
2288                            portletDataContext.getScopeGroupId(), QueryUtil.ALL_POS,
2289                            QueryUtil.ALL_POS, new StructurePKComparator(true));
2290    
2291                    for (JournalStructure structure : structures) {
2292                            if (portletDataContext.isWithinDateRange(
2293                                            structure.getModifiedDate())) {
2294    
2295                                    exportStructure(
2296                                            portletDataContext, structuresElement, structure);
2297                            }
2298                    }
2299    
2300                    Element templatesElement = rootElement.addElement("templates");
2301                    Element dlFileEntryTypesElement = rootElement.addElement(
2302                            "dl-file-entry-types");
2303                    Element dlFoldersElement = rootElement.addElement("dl-folders");
2304                    Element dlFilesElement = rootElement.addElement("dl-file-entries");
2305                    Element dlFileRanksElement = rootElement.addElement("dl-file-ranks");
2306                    Element dlRepositoriesElement = rootElement.addElement(
2307                            "dl-repositories");
2308                    Element dlRepositoryEntriesElement = rootElement.addElement(
2309                            "dl-repository-entries");
2310    
2311                    List<JournalTemplate> templates = JournalTemplateUtil.findByGroupId(
2312                            portletDataContext.getScopeGroupId());
2313    
2314                    for (JournalTemplate template : templates) {
2315                            if (portletDataContext.isWithinDateRange(
2316                                            template.getModifiedDate())) {
2317    
2318                                    exportTemplate(
2319                                            portletDataContext, templatesElement,
2320                                            dlFileEntryTypesElement, dlFoldersElement, dlFilesElement,
2321                                            dlFileRanksElement, dlRepositoriesElement,
2322                                            dlRepositoryEntriesElement, template);
2323                            }
2324                    }
2325    
2326                    Element feedsElement = rootElement.addElement("feeds");
2327    
2328                    List<JournalFeed> feeds = JournalFeedUtil.findByGroupId(
2329                            portletDataContext.getScopeGroupId());
2330    
2331                    for (JournalFeed feed : feeds) {
2332                            if (portletDataContext.isWithinDateRange(feed.getModifiedDate())) {
2333                                    exportFeed(portletDataContext, feedsElement, feed);
2334                            }
2335                    }
2336    
2337                    Element articlesElement = rootElement.addElement("articles");
2338    
2339                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "web-content")) {
2340                            List<JournalArticle> articles = JournalArticleUtil.findByGroupId(
2341                                    portletDataContext.getScopeGroupId(), QueryUtil.ALL_POS,
2342                                    QueryUtil.ALL_POS, new ArticleIDComparator(true));
2343    
2344                            for (JournalArticle article : articles) {
2345                                    exportArticle(
2346                                            portletDataContext, articlesElement, structuresElement,
2347                                            templatesElement, dlFileEntryTypesElement, dlFoldersElement,
2348                                            dlFilesElement, dlFileRanksElement, dlRepositoriesElement,
2349                                            dlRepositoryEntriesElement, article, null, true);
2350                            }
2351                    }
2352    
2353                    return document.formattedString();
2354            }
2355    
2356            @Override
2357            protected PortletPreferences doImportData(
2358                            PortletDataContext portletDataContext, String portletId,
2359                            PortletPreferences portletPreferences, String data)
2360                    throws Exception {
2361    
2362                    portletDataContext.importPermissions(
2363                            "com.liferay.portlet.journal",
2364                            portletDataContext.getSourceGroupId(),
2365                            portletDataContext.getScopeGroupId());
2366    
2367                    Document document = SAXReaderUtil.read(data);
2368    
2369                    Element rootElement = document.getRootElement();
2370    
2371                    importReferencedData(portletDataContext, rootElement);
2372    
2373                    Element structuresElement = rootElement.element("structures");
2374    
2375                    List<Element> structureElements = structuresElement.elements(
2376                            "structure");
2377    
2378                    for (Element structureElement : structureElements) {
2379                            importStructure(portletDataContext, structureElement);
2380                    }
2381    
2382                    Element templatesElement = rootElement.element("templates");
2383    
2384                    List<Element> templateElements = templatesElement.elements("template");
2385    
2386                    for (Element templateElement : templateElements) {
2387                            importTemplate(portletDataContext, templateElement);
2388                    }
2389    
2390                    Element feedsElement = rootElement.element("feeds");
2391    
2392                    List<Element> feedElements = feedsElement.elements("feed");
2393    
2394                    for (Element feedElement : feedElements) {
2395                            importFeed(portletDataContext, feedElement);
2396                    }
2397    
2398                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "web-content")) {
2399                            Element articlesElement = rootElement.element("articles");
2400    
2401                            List<Element> articleElements = articlesElement.elements("article");
2402    
2403                            for (Element articleElement : articleElements) {
2404                                    try {
2405                                            importArticle(portletDataContext, articleElement);
2406                                    }
2407                                    catch (ArticleContentException ace) {
2408                                            if (_log.isWarnEnabled()) {
2409                                                    String path = articleElement.attributeValue("path");
2410    
2411                                                    _log.warn(
2412                                                            "Skipping article with path " + path +
2413                                                                    " because of invalid content");
2414                                            }
2415                                    }
2416                            }
2417                    }
2418    
2419                    return portletPreferences;
2420            }
2421    
2422            private static final boolean _ALWAYS_EXPORTABLE = true;
2423    
2424            private static final boolean _DATA_LOCALIZED = true;
2425    
2426            private static final String _NAMESPACE = "journal";
2427    
2428            private static Log _log = LogFactoryUtil.getLog(
2429                    JournalPortletDataHandlerImpl.class);
2430    
2431            private static PortletDataHandlerBoolean _articles =
2432                    new PortletDataHandlerBoolean(_NAMESPACE, "web-content", true, false);
2433    
2434            private static PortletDataHandlerBoolean _embeddedAssets =
2435                    new PortletDataHandlerBoolean(_NAMESPACE, "embedded-assets");
2436    
2437            private static Pattern _exportLinksToLayoutPattern = Pattern.compile(
2438                    "\\[([0-9]+)@(public|private\\-[a-z]*)\\]");
2439    
2440            private static Pattern _importLinksToLayoutPattern = Pattern.compile(
2441                    "\\[([0-9]+)@(public|private\\-[a-z]*)@(\\p{XDigit}{8}\\-" +
2442                    "(?:\\p{XDigit}{4}\\-){3}\\p{XDigit}{12})@([^\\]]*)\\]");
2443    
2444            private static PortletDataHandlerControl[] _metadataControls =
2445                    new PortletDataHandlerControl[] {
2446                            new PortletDataHandlerBoolean(_NAMESPACE, "images"),
2447                            new PortletDataHandlerBoolean(_NAMESPACE, "categories"),
2448                            new PortletDataHandlerBoolean(_NAMESPACE, "comments"),
2449                            new PortletDataHandlerBoolean(_NAMESPACE, "ratings"),
2450                            new PortletDataHandlerBoolean(_NAMESPACE, "tags")
2451                    };
2452    
2453            private static PortletDataHandlerBoolean
2454                    _structuresTemplatesAndFeeds = new PortletDataHandlerBoolean(
2455                            _NAMESPACE, "structures-templates-and-feeds", true, true);
2456    
2457    }