001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.lar;
016    
017    import com.liferay.portal.LARFileException;
018    import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
019    import com.liferay.portal.kernel.dao.orm.Disjunction;
020    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
021    import com.liferay.portal.kernel.dao.orm.Property;
022    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
023    import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil;
024    import com.liferay.portal.kernel.exception.PortalException;
025    import com.liferay.portal.kernel.exception.SystemException;
026    import com.liferay.portal.kernel.lar.DefaultConfigurationPortletDataHandler;
027    import com.liferay.portal.kernel.lar.ExportImportHelper;
028    import com.liferay.portal.kernel.lar.ExportImportHelperUtil;
029    import com.liferay.portal.kernel.lar.ExportImportPathUtil;
030    import com.liferay.portal.kernel.lar.ManifestSummary;
031    import com.liferay.portal.kernel.lar.MissingReference;
032    import com.liferay.portal.kernel.lar.MissingReferences;
033    import com.liferay.portal.kernel.lar.PortletDataContext;
034    import com.liferay.portal.kernel.lar.PortletDataContextFactoryUtil;
035    import com.liferay.portal.kernel.lar.PortletDataHandler;
036    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
037    import com.liferay.portal.kernel.lar.StagedModelDataHandler;
038    import com.liferay.portal.kernel.lar.StagedModelDataHandlerRegistryUtil;
039    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
040    import com.liferay.portal.kernel.lar.StagedModelType;
041    import com.liferay.portal.kernel.lar.UserIdStrategy;
042    import com.liferay.portal.kernel.log.Log;
043    import com.liferay.portal.kernel.log.LogFactoryUtil;
044    import com.liferay.portal.kernel.repository.model.FileEntry;
045    import com.liferay.portal.kernel.util.ArrayUtil;
046    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
047    import com.liferay.portal.kernel.util.CharPool;
048    import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
049    import com.liferay.portal.kernel.util.DateRange;
050    import com.liferay.portal.kernel.util.FileUtil;
051    import com.liferay.portal.kernel.util.GetterUtil;
052    import com.liferay.portal.kernel.util.HttpUtil;
053    import com.liferay.portal.kernel.util.LocaleUtil;
054    import com.liferay.portal.kernel.util.MapUtil;
055    import com.liferay.portal.kernel.util.ParamUtil;
056    import com.liferay.portal.kernel.util.StringBundler;
057    import com.liferay.portal.kernel.util.StringPool;
058    import com.liferay.portal.kernel.util.StringUtil;
059    import com.liferay.portal.kernel.util.TempFileUtil;
060    import com.liferay.portal.kernel.util.Time;
061    import com.liferay.portal.kernel.util.TimeZoneUtil;
062    import com.liferay.portal.kernel.util.Validator;
063    import com.liferay.portal.kernel.xml.Document;
064    import com.liferay.portal.kernel.xml.Element;
065    import com.liferay.portal.kernel.xml.ElementHandler;
066    import com.liferay.portal.kernel.xml.ElementProcessor;
067    import com.liferay.portal.kernel.zip.ZipReader;
068    import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
069    import com.liferay.portal.model.Group;
070    import com.liferay.portal.model.Layout;
071    import com.liferay.portal.model.LayoutSet;
072    import com.liferay.portal.model.Organization;
073    import com.liferay.portal.model.Portlet;
074    import com.liferay.portal.model.PortletConstants;
075    import com.liferay.portal.model.StagedModel;
076    import com.liferay.portal.model.SystemEventConstants;
077    import com.liferay.portal.model.User;
078    import com.liferay.portal.service.GroupLocalServiceUtil;
079    import com.liferay.portal.service.LayoutLocalServiceUtil;
080    import com.liferay.portal.service.LayoutServiceUtil;
081    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
082    import com.liferay.portal.service.OrganizationLocalServiceUtil;
083    import com.liferay.portal.service.PortletLocalServiceUtil;
084    import com.liferay.portal.service.UserLocalServiceUtil;
085    import com.liferay.portal.service.persistence.OrganizationUtil;
086    import com.liferay.portal.service.persistence.SystemEventActionableDynamicQuery;
087    import com.liferay.portal.theme.ThemeDisplay;
088    import com.liferay.portal.util.PortalUtil;
089    import com.liferay.portal.util.PortletKeys;
090    import com.liferay.portal.util.PropsValues;
091    import com.liferay.portal.util.WebKeys;
092    import com.liferay.portlet.PortletPreferencesFactoryUtil;
093    import com.liferay.portlet.asset.model.AssetCategory;
094    import com.liferay.portlet.asset.model.AssetVocabulary;
095    import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
096    import com.liferay.portlet.asset.service.AssetVocabularyLocalServiceUtil;
097    import com.liferay.portlet.asset.service.persistence.AssetCategoryUtil;
098    import com.liferay.portlet.asset.service.persistence.AssetVocabularyUtil;
099    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
100    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
101    import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
102    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
103    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
104    import com.liferay.portlet.documentlibrary.service.DLFileEntryTypeLocalServiceUtil;
105    import com.liferay.portlet.documentlibrary.service.persistence.DLFileEntryTypeUtil;
106    import com.liferay.portlet.documentlibrary.util.DLUtil;
107    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
108    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
109    import com.liferay.portlet.dynamicdatamapping.service.persistence.DDMStructureUtil;
110    import com.liferay.portlet.journal.model.JournalArticle;
111    
112    import java.io.File;
113    import java.io.InputStream;
114    import java.io.StringReader;
115    
116    import java.util.ArrayList;
117    import java.util.Calendar;
118    import java.util.Date;
119    import java.util.HashMap;
120    import java.util.List;
121    import java.util.Locale;
122    import java.util.Map;
123    import java.util.TimeZone;
124    import java.util.regex.Matcher;
125    import java.util.regex.Pattern;
126    
127    import javax.portlet.PortletPreferences;
128    import javax.portlet.PortletRequest;
129    
130    import org.apache.xerces.parsers.SAXParser;
131    
132    import org.xml.sax.InputSource;
133    
134    /**
135     * @author Zsolt Berentey
136     * @author Levente Hud??k
137     * @author Julio Camarero
138     */
139    public class ExportImportHelperImpl implements ExportImportHelper {
140    
141            @Override
142            public Calendar getCalendar(
143                    PortletRequest portletRequest, String paramPrefix,
144                    boolean timeZoneSensitive) {
145    
146                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
147                            WebKeys.THEME_DISPLAY);
148    
149                    int dateMonth = ParamUtil.getInteger(
150                            portletRequest, paramPrefix + "Month");
151                    int dateDay = ParamUtil.getInteger(portletRequest, paramPrefix + "Day");
152                    int dateYear = ParamUtil.getInteger(
153                            portletRequest, paramPrefix + "Year");
154                    int dateHour = ParamUtil.getInteger(
155                            portletRequest, paramPrefix + "Hour");
156                    int dateMinute = ParamUtil.getInteger(
157                            portletRequest, paramPrefix + "Minute");
158                    int dateAmPm = ParamUtil.getInteger(
159                            portletRequest, paramPrefix + "AmPm");
160    
161                    if (dateAmPm == Calendar.PM) {
162                            dateHour += 12;
163                    }
164    
165                    Locale locale = null;
166                    TimeZone timeZone = null;
167    
168                    if (timeZoneSensitive) {
169                            locale = themeDisplay.getLocale();
170                            timeZone = themeDisplay.getTimeZone();
171                    }
172                    else {
173                            locale = LocaleUtil.getDefault();
174                            timeZone = TimeZoneUtil.getTimeZone(StringPool.UTC);
175                    }
176    
177                    Calendar calendar = CalendarFactoryUtil.getCalendar(timeZone, locale);
178    
179                    calendar.set(Calendar.MONTH, dateMonth);
180                    calendar.set(Calendar.DATE, dateDay);
181                    calendar.set(Calendar.YEAR, dateYear);
182                    calendar.set(Calendar.HOUR_OF_DAY, dateHour);
183                    calendar.set(Calendar.MINUTE, dateMinute);
184                    calendar.set(Calendar.SECOND, 0);
185                    calendar.set(Calendar.MILLISECOND, 0);
186    
187                    return calendar;
188            }
189    
190            @Override
191            public DateRange getDateRange(
192                            PortletRequest portletRequest, long groupId, boolean privateLayout,
193                            long plid, String portletId)
194                    throws Exception {
195    
196                    Date startDate = null;
197                    Date endDate = null;
198    
199                    String range = ParamUtil.getString(portletRequest, "range");
200    
201                    if (range.equals("dateRange")) {
202                            Calendar startCalendar = getCalendar(
203                                    portletRequest, "startDate", true);
204    
205                            startDate = startCalendar.getTime();
206    
207                            Calendar endCalendar = getCalendar(portletRequest, "endDate", true);
208    
209                            endDate = endCalendar.getTime();
210                    }
211                    else if (range.equals("fromLastPublishDate")) {
212                            if (Validator.isNotNull(portletId) && (plid > 0)) {
213                                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
214    
215                                    PortletPreferences preferences =
216                                            PortletPreferencesFactoryUtil.getPortletSetup(
217                                                    layout, portletId, StringPool.BLANK);
218    
219                                    long lastPublishDate = GetterUtil.getLong(
220                                            preferences.getValue(
221                                                    "last-publish-date", StringPool.BLANK));
222    
223                                    if (lastPublishDate > 0) {
224                                            endDate = new Date();
225    
226                                            startDate = new Date(lastPublishDate);
227                                    }
228                            }
229                            else {
230                                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
231                                            groupId, privateLayout);
232    
233                                    long lastPublishDate = GetterUtil.getLong(
234                                            layoutSet.getSettingsProperty("last-publish-date"));
235    
236                                    if (lastPublishDate > 0) {
237                                            endDate = new Date();
238    
239                                            startDate = new Date(lastPublishDate);
240                                    }
241                            }
242                    }
243                    else if (range.equals("last")) {
244                            int rangeLast = ParamUtil.getInteger(portletRequest, "last");
245    
246                            Date now = new Date();
247    
248                            startDate = new Date(now.getTime() - (rangeLast * Time.HOUR));
249    
250                            endDate = now;
251                    }
252    
253                    return new DateRange(startDate, endDate);
254            }
255    
256            @Override
257            public Layout getExportableLayout(ThemeDisplay themeDisplay)
258                    throws PortalException, SystemException {
259    
260                    Layout layout = themeDisplay.getLayout();
261    
262                    if (!layout.isTypeControlPanel()) {
263                            return layout;
264                    }
265    
266                    Group scopeGroup = themeDisplay.getScopeGroup();
267    
268                    if (scopeGroup.isLayout()) {
269                            layout = LayoutLocalServiceUtil.getLayout(scopeGroup.getClassPK());
270                    }
271                    else if (!scopeGroup.isCompany()) {
272                            long defaultPlid = LayoutLocalServiceUtil.getDefaultPlid(
273                                    themeDisplay.getSiteGroupId());
274    
275                            if (defaultPlid > 0) {
276                                    layout = LayoutLocalServiceUtil.getLayout(defaultPlid);
277                            }
278                    }
279    
280                    return layout;
281            }
282    
283            @Override
284            public String getExportableRootPortletId(long companyId, String portletId)
285                    throws Exception {
286    
287                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
288                            companyId, portletId);
289    
290                    if (portlet == null) {
291                            return null;
292                    }
293    
294                    String portletDataHandlerClass = portlet.getPortletDataHandlerClass();
295    
296                    if (portletDataHandlerClass == null) {
297                            return null;
298                    }
299    
300                    return PortletConstants.getRootPortletId(portletId);
301            }
302    
303            @Override
304            public ManifestSummary getManifestSummary(
305                            long userId, long groupId, Map<String, String[]> parameterMap,
306                            File file)
307                    throws Exception {
308    
309                    final Group group = GroupLocalServiceUtil.getGroup(groupId);
310                    String userIdStrategy = MapUtil.getString(
311                            parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
312                    ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
313    
314                    PortletDataContext portletDataContext =
315                            PortletDataContextFactoryUtil.createImportPortletDataContext(
316                                    group.getCompanyId(), groupId, parameterMap,
317                                    getUserIdStrategy(userId, userIdStrategy), zipReader);
318    
319                    final ManifestSummary manifestSummary = new ManifestSummary();
320    
321                    SAXParser saxParser = new SAXParser();
322    
323                    ElementHandler elementHandler = new ElementHandler(
324                            new ManifestSummaryElementProcessor(group, manifestSummary),
325                            new String[] {"header", "portlet", "staged-model"});
326    
327                    saxParser.setContentHandler(elementHandler);
328    
329                    InputStream is = portletDataContext.getZipEntryAsInputStream(
330                            "/manifest.xml");
331    
332                    if (is == null) {
333                            throw new LARFileException("manifest.xml is not in the LAR");
334                    }
335    
336                    String manifestXMLContent = StringUtil.read(is);
337    
338                    saxParser.parse(new InputSource(new StringReader(manifestXMLContent)));
339    
340                    return manifestSummary;
341            }
342    
343            @Override
344            public ManifestSummary getManifestSummary(
345                            long userId, long groupId, Map<String, String[]> parameterMap,
346                            FileEntry fileEntry)
347                    throws Exception {
348    
349                    File file = DLFileEntryLocalServiceUtil.getFile(
350                            userId, fileEntry.getFileEntryId(), fileEntry.getVersion(), false);
351                    File newFile = null;
352                    boolean rename = false;
353    
354                    ManifestSummary manifestSummary = null;
355    
356                    try {
357                            String newFileName = StringUtil.replace(
358                                    file.getPath(), file.getName(), fileEntry.getTitle());
359    
360                            newFile = new File(newFileName);
361    
362                            rename = file.renameTo(newFile);
363    
364                            if (!rename) {
365                                    newFile = FileUtil.createTempFile(fileEntry.getExtension());
366    
367                                    FileUtil.copyFile(file, newFile);
368                            }
369    
370                            manifestSummary = getManifestSummary(
371                                    userId, groupId, parameterMap, newFile);
372    
373                    }
374                    finally {
375                            if (rename) {
376                                    newFile.renameTo(file);
377                            }
378                            else {
379                                    FileUtil.delete(newFile);
380                            }
381                    }
382    
383                    return manifestSummary;
384            }
385    
386            @Override
387            public long getModelDeletionCount(
388                            final PortletDataContext portletDataContext,
389                            final StagedModelType stagedModelType)
390                    throws PortalException, SystemException {
391    
392                    ActionableDynamicQuery actionableDynamicQuery =
393                            new SystemEventActionableDynamicQuery() {
394    
395                            protected void addCreateDateProperty(DynamicQuery dynamicQuery) {
396                                    if (!portletDataContext.hasDateRange()) {
397                                            return;
398                                    }
399    
400                                    Property createDateProperty = PropertyFactoryUtil.forName(
401                                            "createDate");
402    
403                                    Date startDate = portletDataContext.getStartDate();
404    
405                                    dynamicQuery.add(createDateProperty.ge(startDate));
406    
407                                    Date endDate = portletDataContext.getEndDate();
408    
409                                    dynamicQuery.add(createDateProperty.le(endDate));
410                            }
411    
412                            @Override
413                            protected void addCriteria(DynamicQuery dynamicQuery) {
414                                    Disjunction disjunction = RestrictionsFactoryUtil.disjunction();
415    
416                                    Property groupIdProperty = PropertyFactoryUtil.forName(
417                                            "groupId");
418    
419                                    disjunction.add(groupIdProperty.eq(0L));
420                                    disjunction.add(
421                                            groupIdProperty.eq(portletDataContext.getScopeGroupId()));
422    
423                                    dynamicQuery.add(disjunction);
424    
425                                    Property classNameIdProperty = PropertyFactoryUtil.forName(
426                                            "classNameId");
427    
428                                    dynamicQuery.add(
429                                            classNameIdProperty.eq(stagedModelType.getClassNameId()));
430    
431                                    Property referrerClassNameIdProperty =
432                                            PropertyFactoryUtil.forName("referrerClassNameId");
433    
434                                    dynamicQuery.add(
435                                            referrerClassNameIdProperty.eq(
436                                                    stagedModelType.getReferrerClassNameId()));
437    
438                                    Property typeProperty = PropertyFactoryUtil.forName("type");
439    
440                                    dynamicQuery.add(
441                                            typeProperty.eq(SystemEventConstants.TYPE_DELETE));
442    
443                                    addCreateDateProperty(dynamicQuery);
444                            }
445    
446                            @Override
447                            protected void performAction(Object object) {
448                            }
449    
450                    };
451    
452                    actionableDynamicQuery.setCompanyId(portletDataContext.getCompanyId());
453    
454                    return actionableDynamicQuery.performCount();
455            }
456    
457            @Override
458            public FileEntry getTempFileEntry(
459                            long groupId, long userId, String folderName)
460                    throws PortalException, SystemException {
461    
462                    String[] tempFileEntryNames = LayoutServiceUtil.getTempFileEntryNames(
463                            groupId, folderName);
464    
465                    if (tempFileEntryNames.length == 0) {
466                            return null;
467                    }
468    
469                    return TempFileUtil.getTempFile(
470                            groupId, userId, tempFileEntryNames[0], folderName);
471            }
472    
473            @Override
474            public String replaceExportContentReferences(
475                            PortletDataContext portletDataContext,
476                            StagedModel entityStagedModel, Element entityElement,
477                            String content, boolean exportReferencedContent)
478                    throws Exception {
479    
480                    content = ExportImportHelperUtil.replaceExportLayoutReferences(
481                            portletDataContext, content, exportReferencedContent);
482                    content = ExportImportHelperUtil.replaceExportLinksToLayouts(
483                            portletDataContext, entityStagedModel, entityElement, content,
484                            exportReferencedContent);
485    
486                    content = ExportImportHelperUtil.replaceExportDLReferences(
487                            portletDataContext, entityStagedModel, entityElement, content,
488                            exportReferencedContent);
489    
490                    Element groupElement = entityElement.getParent();
491    
492                    String groupElementName = groupElement.getName();
493    
494                    if (!groupElementName.equals(JournalArticle.class.getSimpleName())) {
495                            content = StringUtil.replace(
496                                    content, StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
497                    }
498    
499                    return content;
500            }
501    
502            @Override
503            public String replaceExportDLReferences(
504                            PortletDataContext portletDataContext,
505                            StagedModel entityStagedModel, Element entityElement,
506                            String content, boolean exportReferencedContent)
507                    throws Exception {
508    
509                    Group group = GroupLocalServiceUtil.getGroup(
510                            portletDataContext.getGroupId());
511    
512                    if (group.isStagingGroup()) {
513                            group = group.getLiveGroup();
514                    }
515    
516                    if (group.isStaged() && !group.isStagedRemotely() &&
517                            !group.isStagedPortlet(PortletKeys.DOCUMENT_LIBRARY)) {
518    
519                            return content;
520                    }
521    
522                    StringBuilder sb = new StringBuilder(content);
523    
524                    String contextPath = PortalUtil.getPathContext();
525    
526                    String[] patterns = {
527                            contextPath.concat("/c/document_library/get_file?"),
528                            contextPath.concat("/documents/"),
529                            contextPath.concat("/image/image_gallery?")
530                    };
531    
532                    int beginPos = -1;
533                    int endPos = content.length();
534    
535                    while (true) {
536                            beginPos = StringUtil.lastIndexOfAny(content, patterns, endPos);
537    
538                            if (beginPos == -1) {
539                                    break;
540                            }
541    
542                            Map<String, String[]> dlReferenceParameters =
543                                    getDLReferenceParameters(
544                                            portletDataContext, content,
545                                            beginPos + contextPath.length(), endPos);
546    
547                            FileEntry fileEntry = getFileEntry(
548                                    portletDataContext, dlReferenceParameters);
549    
550                            if (fileEntry == null) {
551                                    endPos = beginPos - 1;
552    
553                                    continue;
554                            }
555    
556                            endPos = MapUtil.getInteger(dlReferenceParameters, "endPos");
557    
558                            try {
559                                    if (exportReferencedContent) {
560                                            StagedModelDataHandlerUtil.exportStagedModel(
561                                                    portletDataContext, fileEntry);
562                                    }
563    
564                                    portletDataContext.addReferenceElement(
565                                            entityStagedModel, entityElement, fileEntry,
566                                            FileEntry.class,
567                                            PortletDataContext.REFERENCE_TYPE_DEPENDENCY,
568                                            !exportReferencedContent);
569    
570                                    String path = ExportImportPathUtil.getModelPath(
571                                            fileEntry.getGroupId(), FileEntry.class.getName(),
572                                            fileEntry.getFileEntryId());
573    
574                                    sb.replace(beginPos, endPos, "[$dl-reference=" + path + "$]");
575                            }
576                            catch (Exception e) {
577                                    if (_log.isDebugEnabled()) {
578                                            _log.debug(e, e);
579                                    }
580                                    else if (_log.isWarnEnabled()) {
581                                            _log.warn(e.getMessage());
582                                    }
583                            }
584    
585                            endPos = beginPos - 1;
586                    }
587    
588                    return sb.toString();
589            }
590    
591            @Override
592            public String replaceExportLayoutReferences(
593                            PortletDataContext portletDataContext, String content,
594                            boolean exportReferencedContent)
595                    throws Exception {
596    
597                    Group group = GroupLocalServiceUtil.getGroup(
598                            portletDataContext.getScopeGroupId());
599    
600                    StringBuilder sb = new StringBuilder(content);
601    
602                    String[] patterns = {"href=", "[["};
603    
604                    int beginPos = -1;
605                    int endPos = content.length();
606                    int offset = 0;
607    
608                    while (true) {
609                            if (beginPos > -1) {
610                                    endPos = beginPos - 1;
611                            }
612    
613                            beginPos = StringUtil.lastIndexOfAny(content, patterns, endPos);
614    
615                            if (beginPos == -1) {
616                                    break;
617                            }
618    
619                            if (content.startsWith("href=", beginPos)) {
620                                    offset = 5;
621    
622                                    char c = content.charAt(beginPos + offset);
623    
624                                    if ((c == CharPool.APOSTROPHE) || (c == CharPool.QUOTE)) {
625                                            offset++;
626                                    }
627                            }
628                            else if (content.charAt(beginPos) == CharPool.OPEN_BRACKET) {
629                                    offset = 2;
630                            }
631    
632                            endPos = StringUtil.indexOfAny(
633                                    content, _LAYOUT_REFERENCE_STOP_CHARS, beginPos + offset,
634                                    endPos);
635    
636                            if (endPos == -1) {
637                                    continue;
638                            }
639    
640                            String url = content.substring(beginPos + offset, endPos);
641    
642                            if (!url.startsWith(StringPool.SLASH)) {
643                                    continue;
644                            }
645    
646                            StringBundler urlSB = new StringBundler(5);
647    
648                            String pathContext = PortalUtil.getPathContext();
649    
650                            if (pathContext.length() > 1) {
651                                    if (!url.startsWith(pathContext)) {
652                                            continue;
653                                    }
654    
655                                    urlSB.append("@data_handler_path_context@");
656    
657                                    url = url.substring(pathContext.length());
658                            }
659    
660                            int pos = url.indexOf(StringPool.SLASH, 1);
661    
662                            if (!url.startsWith(StringPool.SLASH) || (pos == -1)) {
663                                    if (urlSB.length() > 0) {
664                                            urlSB.append(url);
665    
666                                            sb.replace(beginPos + offset, endPos, urlSB.toString());
667                                    }
668    
669                                    continue;
670                            }
671    
672                            String localePath = url.substring(0, pos);
673    
674                            Locale locale = LocaleUtil.fromLanguageId(
675                                    localePath.substring(1), true, false);
676    
677                            if (locale != null) {
678                                    String urlWithoutLocale = url.substring(localePath.length());
679    
680                                    if (urlWithoutLocale.startsWith(
681                                                    _PRIVATE_GROUP_SERVLET_MAPPING) ||
682                                            urlWithoutLocale.startsWith(
683                                                    _PRIVATE_USER_SERVLET_MAPPING) ||
684                                            urlWithoutLocale.startsWith(
685                                                    _PUBLIC_GROUP_SERVLET_MAPPING)) {
686    
687                                            urlSB.append(localePath);
688    
689                                            url = urlWithoutLocale;
690                                    }
691                            }
692    
693                            if (url.startsWith(_PRIVATE_GROUP_SERVLET_MAPPING)) {
694                                    urlSB.append("@data_handler_private_group_servlet_mapping@");
695    
696                                    url = url.substring(
697                                            _PRIVATE_GROUP_SERVLET_MAPPING.length() - 1);
698                            }
699                            else if (url.startsWith(_PRIVATE_USER_SERVLET_MAPPING)) {
700                                    urlSB.append("@data_handler_private_user_servlet_mapping@");
701    
702                                    url = url.substring(_PRIVATE_USER_SERVLET_MAPPING.length() - 1);
703                            }
704                            else if (url.startsWith(_PUBLIC_GROUP_SERVLET_MAPPING)) {
705                                    urlSB.append("@data_handler_public_servlet_mapping@");
706    
707                                    url = url.substring(_PUBLIC_GROUP_SERVLET_MAPPING.length() - 1);
708                            }
709                            else {
710                                    continue;
711                            }
712    
713                            String groupFriendlyURL = group.getFriendlyURL();
714    
715                            if (url.equals(groupFriendlyURL) ||
716                                    url.startsWith(groupFriendlyURL + StringPool.SLASH)) {
717    
718                                    urlSB.append("@data_handler_group_friendly_url@");
719    
720                                    url = url.substring(groupFriendlyURL.length());
721                            }
722    
723                            urlSB.append(url);
724    
725                            sb.replace(beginPos + offset, endPos, urlSB.toString());
726                    }
727    
728                    return sb.toString();
729            }
730    
731            @Override
732            public String replaceExportLinksToLayouts(
733                            PortletDataContext portletDataContext,
734                            StagedModel entityStagedModel, Element entityElement,
735                            String content, boolean exportReferencedContent)
736                    throws Exception {
737    
738                    List<String> oldLinksToLayout = new ArrayList<String>();
739                    List<String> newLinksToLayout = new ArrayList<String>();
740    
741                    Matcher matcher = _exportLinksToLayoutPattern.matcher(content);
742    
743                    while (matcher.find()) {
744                            long layoutId = GetterUtil.getLong(matcher.group(1));
745    
746                            String type = matcher.group(2);
747    
748                            boolean privateLayout = type.startsWith("private");
749    
750                            try {
751                                    Layout layout = LayoutLocalServiceUtil.getLayout(
752                                            portletDataContext.getScopeGroupId(), privateLayout,
753                                            layoutId);
754    
755                                    String oldLinkToLayout = matcher.group(0);
756    
757                                    StringBundler sb = new StringBundler(5);
758    
759                                    sb.append(type);
760                                    sb.append(StringPool.AT);
761                                    sb.append(layout.getUuid());
762                                    sb.append(StringPool.AT);
763                                    sb.append(layout.getFriendlyURL());
764    
765                                    String newLinkToLayout = StringUtil.replace(
766                                            oldLinkToLayout, type, sb.toString());
767    
768                                    oldLinksToLayout.add(oldLinkToLayout);
769                                    newLinksToLayout.add(newLinkToLayout);
770    
771                                    if (exportReferencedContent) {
772                                            StagedModelDataHandlerUtil.exportStagedModel(
773                                                    portletDataContext, layout);
774                                    }
775    
776                                    portletDataContext.addReferenceElement(
777                                            entityStagedModel, entityElement, layout, Layout.class,
778                                            PortletDataContext.REFERENCE_TYPE_DEPENDENCY,
779                                            !exportReferencedContent);
780                            }
781                            catch (Exception e) {
782                                    if (_log.isDebugEnabled() || _log.isWarnEnabled()) {
783                                            String message =
784                                                    "Unable to get layout with ID " + layoutId +
785                                                            " in group " + portletDataContext.getScopeGroupId();
786    
787                                            if (_log.isWarnEnabled()) {
788                                                    _log.warn(message);
789                                            }
790                                            else {
791                                                    _log.debug(message, e);
792                                            }
793                                    }
794                            }
795                    }
796    
797                    content = StringUtil.replace(
798                            content, ArrayUtil.toStringArray(oldLinksToLayout.toArray()),
799                            ArrayUtil.toStringArray(newLinksToLayout.toArray()));
800    
801                    return content;
802            }
803    
804            @Override
805            public String replaceImportContentReferences(
806                            PortletDataContext portletDataContext, Element entityElement,
807                            String content, boolean importReferencedContent)
808                    throws Exception {
809    
810                    content = ExportImportHelperUtil.replaceImportLayoutReferences(
811                            portletDataContext, content, importReferencedContent);
812                    content = ExportImportHelperUtil.replaceImportLinksToLayouts(
813                            portletDataContext, content, importReferencedContent);
814    
815                    content = ExportImportHelperUtil.replaceImportDLReferences(
816                            portletDataContext, entityElement, content,
817                            importReferencedContent);
818    
819                    return content;
820            }
821    
822            @Override
823            public String replaceImportDLReferences(
824                            PortletDataContext portletDataContext, Element entityElement,
825                            String content, boolean importReferencedContent)
826                    throws Exception {
827    
828                    List<Element> referenceDataElements =
829                            portletDataContext.getReferenceDataElements(
830                                    entityElement, FileEntry.class,
831                                    PortletDataContext.REFERENCE_TYPE_DEPENDENCY);
832    
833                    for (Element referenceDataElement : referenceDataElements) {
834                            String fileEntryUUID = referenceDataElement.attributeValue("uuid");
835    
836                            if (fileEntryUUID == null) {
837                                    continue;
838                            }
839    
840                            String path = referenceDataElement.attributeValue("path");
841    
842                            if (!content.contains("[$dl-reference=" + path + "$]")) {
843                                    continue;
844                            }
845    
846                            StagedModelDataHandlerUtil.importStagedModel(
847                                    portletDataContext, referenceDataElement);
848    
849                            FileEntry fileEntry = null;
850    
851                            try {
852                                    long groupId = portletDataContext.getScopeGroupId();
853    
854                                    long fileEntryGroupId = GetterUtil.getLong(
855                                            referenceDataElement.attributeValue("group-id"));
856    
857                                    if (fileEntryGroupId ==
858                                                    portletDataContext.getSourceCompanyGroupId()) {
859    
860                                            groupId = portletDataContext.getSourceCompanyGroupId();
861                                    }
862    
863                                    fileEntry = DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
864                                            fileEntryUUID, groupId);
865                            }
866                            catch (NoSuchFileEntryException nsfee) {
867                                    if (_log.isWarnEnabled()) {
868                                            _log.warn("Unable to reference " + path);
869                                    }
870    
871                                    continue;
872                            }
873    
874                            String url = DLUtil.getPreviewURL(
875                                    fileEntry, fileEntry.getFileVersion(), null, StringPool.BLANK,
876                                    false, false);
877    
878                            content = StringUtil.replace(
879                                    content, "[$dl-reference=" + path + "$]", url);
880                    }
881    
882                    return content;
883            }
884    
885            @Override
886            public String replaceImportLayoutReferences(
887                            PortletDataContext portletDataContext, String content,
888                            boolean importReferencedContent)
889                    throws Exception {
890    
891                    Group group = GroupLocalServiceUtil.getGroup(
892                            portletDataContext.getScopeGroupId());
893    
894                    content = StringUtil.replace(
895                            content, "@data_handler_group_friendly_url@",
896                            group.getFriendlyURL());
897    
898                    content = StringUtil.replace(
899                            content, "@data_handler_path_context@",
900                            PortalUtil.getPathContext());
901                    content = StringUtil.replace(
902                            content, "@data_handler_private_group_servlet_mapping@",
903                            PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING);
904                    content = StringUtil.replace(
905                            content, "@data_handler_private_user_servlet_mapping@",
906                            PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING);
907                    content = StringUtil.replace(
908                            content, "@data_handler_public_servlet_mapping@",
909                            PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING);
910    
911                    return content;
912            }
913    
914            @Override
915            public String replaceImportLinksToLayouts(
916                            PortletDataContext portletDataContext, String content,
917                            boolean importReferencedContent)
918                    throws Exception {
919    
920                    List<String> oldLinksToLayout = new ArrayList<String>();
921                    List<String> newLinksToLayout = new ArrayList<String>();
922    
923                    Matcher matcher = _importLinksToLayoutPattern.matcher(content);
924    
925                    while (matcher.find()) {
926                            long oldLayoutId = GetterUtil.getLong(matcher.group(1));
927    
928                            long newLayoutId = oldLayoutId;
929    
930                            String type = matcher.group(2);
931    
932                            boolean privateLayout = type.startsWith("private");
933    
934                            String layoutUuid = matcher.group(3);
935                            String friendlyURL = matcher.group(4);
936    
937                            try {
938                                    Layout layout =
939                                            LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
940                                                    layoutUuid, portletDataContext.getScopeGroupId(),
941                                                    privateLayout);
942    
943                                    if (layout == null) {
944                                            layout = LayoutLocalServiceUtil.fetchLayoutByFriendlyURL(
945                                                    portletDataContext.getScopeGroupId(), privateLayout,
946                                                    friendlyURL);
947                                    }
948    
949                                    if (layout == null) {
950                                            layout = LayoutLocalServiceUtil.fetchLayout(
951                                                    portletDataContext.getScopeGroupId(), privateLayout,
952                                                    oldLayoutId);
953                                    }
954    
955                                    if (layout == null) {
956                                            if (_log.isWarnEnabled()) {
957                                                    StringBundler sb = new StringBundler(9);
958    
959                                                    sb.append("Unable to get layout with UUID ");
960                                                    sb.append(layoutUuid);
961                                                    sb.append(", friendly URL ");
962                                                    sb.append(friendlyURL);
963                                                    sb.append(", or ");
964                                                    sb.append("layoutId ");
965                                                    sb.append(oldLayoutId);
966                                                    sb.append(" in group ");
967                                                    sb.append(portletDataContext.getScopeGroupId());
968    
969                                                    _log.warn(sb.toString());
970                                            }
971                                    }
972                                    else {
973                                            newLayoutId = layout.getLayoutId();
974                                    }
975                            }
976                            catch (SystemException se) {
977                                    if (_log.isDebugEnabled() || _log.isWarnEnabled()) {
978                                            String message =
979                                                    "Unable to get layout in group " +
980                                                            portletDataContext.getScopeGroupId();
981    
982                                            if (_log.isWarnEnabled()) {
983                                                    _log.warn(message);
984                                            }
985                                            else {
986                                                    _log.debug(message, se);
987                                            }
988                                    }
989                            }
990    
991                            String oldLinkToLayout = matcher.group(0);
992    
993                            StringBundler sb = new StringBundler(4);
994    
995                            sb.append(StringPool.AT);
996                            sb.append(layoutUuid);
997                            sb.append(StringPool.AT);
998                            sb.append(friendlyURL);
999    
1000                            String newLinkToLayout = StringUtil.replace(
1001                                    oldLinkToLayout,
1002                                    new String[] {sb.toString(), String.valueOf(oldLayoutId)},
1003                                    new String[] {StringPool.BLANK, String.valueOf(newLayoutId)});
1004    
1005                            oldLinksToLayout.add(oldLinkToLayout);
1006                            newLinksToLayout.add(newLinkToLayout);
1007                    }
1008    
1009                    content = StringUtil.replace(
1010                            content, ArrayUtil.toStringArray(oldLinksToLayout.toArray()),
1011                            ArrayUtil.toStringArray(newLinksToLayout.toArray()));
1012    
1013                    return content;
1014            }
1015    
1016            @Override
1017            public void updateExportPortletPreferencesClassPKs(
1018                            PortletDataContext portletDataContext, Portlet portlet,
1019                            PortletPreferences portletPreferences, String key, String className,
1020                            Element rootElement)
1021                    throws Exception {
1022    
1023                    String[] oldValues = portletPreferences.getValues(key, null);
1024    
1025                    if (oldValues == null) {
1026                            return;
1027                    }
1028    
1029                    String[] newValues = new String[oldValues.length];
1030    
1031                    for (int i = 0; i < oldValues.length; i++) {
1032                            String oldValue = oldValues[i];
1033    
1034                            String newValue = oldValue;
1035    
1036                            String[] primaryKeys = StringUtil.split(oldValue);
1037    
1038                            for (String primaryKey : primaryKeys) {
1039                                    if (!Validator.isNumber(primaryKey)) {
1040                                            break;
1041                                    }
1042    
1043                                    long primaryKeyLong = GetterUtil.getLong(primaryKey);
1044    
1045                                    String uuid = null;
1046    
1047                                    if (className.equals(AssetCategory.class.getName())) {
1048                                            AssetCategory assetCategory =
1049                                                    AssetCategoryLocalServiceUtil.fetchCategory(
1050                                                            primaryKeyLong);
1051    
1052                                            if (assetCategory != null) {
1053                                                    uuid = assetCategory.getUuid();
1054    
1055                                                    portletDataContext.addReferenceElement(
1056                                                            portlet, rootElement, assetCategory,
1057                                                            AssetCategory.class,
1058                                                            PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true);
1059                                            }
1060                                    }
1061                                    else if (className.equals(AssetVocabulary.class.getName())) {
1062                                            AssetVocabulary assetVocabulary =
1063                                                    AssetVocabularyLocalServiceUtil.fetchAssetVocabulary(
1064                                                            primaryKeyLong);
1065    
1066                                            if (assetVocabulary != null) {
1067                                                    uuid = assetVocabulary.getUuid();
1068    
1069                                                    portletDataContext.addReferenceElement(
1070                                                            portlet, rootElement, assetVocabulary,
1071                                                            AssetVocabulary.class,
1072                                                            PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true);
1073                                            }
1074                                    }
1075                                    else if (className.equals(DDMStructure.class.getName())) {
1076                                            DDMStructure ddmStructure =
1077                                                    DDMStructureLocalServiceUtil.fetchStructure(
1078                                                            primaryKeyLong);
1079    
1080                                            if (ddmStructure != null) {
1081                                                    uuid = ddmStructure.getUuid();
1082    
1083                                                    portletDataContext.addReferenceElement(
1084                                                            portlet, rootElement, ddmStructure,
1085                                                            DDMStructure.class,
1086                                                            PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true);
1087                                            }
1088                                    }
1089                                    else if (className.equals(DLFileEntryType.class.getName())) {
1090                                            DLFileEntryType dlFileEntryType =
1091                                                    DLFileEntryTypeLocalServiceUtil.fetchFileEntryType(
1092                                                            primaryKeyLong);
1093    
1094                                            if (dlFileEntryType != null) {
1095                                                    uuid = dlFileEntryType.getUuid();
1096    
1097                                                    portletDataContext.addReferenceElement(
1098                                                            portlet, rootElement, dlFileEntryType,
1099                                                            DLFileEntryType.class,
1100                                                            PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true);
1101                                            }
1102                                    }
1103                                    else if (className.equals(Organization.class.getName())) {
1104                                            Organization organization =
1105                                                    OrganizationLocalServiceUtil.fetchOrganization(
1106                                                            primaryKeyLong);
1107    
1108                                            if (organization != null) {
1109                                                    uuid = organization.getUuid();
1110    
1111                                                    portletDataContext.addReferenceElement(
1112                                                            portlet, rootElement, organization,
1113                                                            Organization.class,
1114                                                            PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true);
1115                                            }
1116                                    }
1117    
1118                                    if (Validator.isNull(uuid)) {
1119                                            if (_log.isWarnEnabled()) {
1120                                                    _log.warn(
1121                                                            "Unable to get UUID for class " + className +
1122                                                                    " with primary key " + primaryKeyLong);
1123                                            }
1124    
1125                                            continue;
1126                                    }
1127    
1128                                    newValue = StringUtil.replace(newValue, primaryKey, uuid);
1129                            }
1130    
1131                            newValues[i] = newValue;
1132                    }
1133    
1134                    portletPreferences.setValues(key, newValues);
1135            }
1136    
1137            @Override
1138            public void updateImportPortletPreferencesClassPKs(
1139                            PortletDataContext portletDataContext,
1140                            PortletPreferences portletPreferences, String key, Class<?> clazz,
1141                            long companyGroupId)
1142                    throws Exception {
1143    
1144                    String[] oldValues = portletPreferences.getValues(key, null);
1145    
1146                    if (oldValues == null) {
1147                            return;
1148                    }
1149    
1150                    Map<Long, Long> primaryKeys =
1151                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(clazz);
1152    
1153                    String[] newValues = new String[oldValues.length];
1154    
1155                    for (int i = 0; i < oldValues.length; i++) {
1156                            String oldValue = oldValues[i];
1157    
1158                            String newValue = oldValue;
1159    
1160                            String[] uuids = StringUtil.split(oldValue);
1161    
1162                            for (String uuid : uuids) {
1163                                    Long newPrimaryKey = null;
1164    
1165                                    if (Validator.isNumber(uuid)) {
1166                                            long oldPrimaryKey = GetterUtil.getLong(uuid);
1167    
1168                                            newPrimaryKey = MapUtil.getLong(
1169                                                    primaryKeys, oldPrimaryKey, oldPrimaryKey);
1170                                    }
1171                                    else {
1172                                            String className = clazz.getName();
1173    
1174                                            if (className.equals(AssetCategory.class.getName())) {
1175                                                    AssetCategory assetCategory =
1176                                                            AssetCategoryUtil.fetchByUUID_G(
1177                                                                    uuid, portletDataContext.getScopeGroupId());
1178    
1179                                                    if (assetCategory == null) {
1180                                                            assetCategory = AssetCategoryUtil.fetchByUUID_G(
1181                                                                    uuid, companyGroupId);
1182                                                    }
1183    
1184                                                    if (assetCategory != null) {
1185                                                            newPrimaryKey = assetCategory.getCategoryId();
1186                                                    }
1187                                            }
1188                                            else if (className.equals(
1189                                                                    AssetVocabulary.class.getName())) {
1190    
1191                                                    AssetVocabulary assetVocabulary =
1192                                                            AssetVocabularyUtil.fetchByUUID_G(
1193                                                                    uuid, portletDataContext.getScopeGroupId());
1194    
1195                                                    if (assetVocabulary == null) {
1196                                                            assetVocabulary = AssetVocabularyUtil.fetchByUUID_G(
1197                                                                    uuid, companyGroupId);
1198                                                    }
1199    
1200                                                    if (assetVocabulary != null) {
1201                                                            newPrimaryKey = assetVocabulary.getVocabularyId();
1202                                                    }
1203                                            }
1204                                            else if (className.equals(DDMStructure.class.getName())) {
1205                                                    DDMStructure ddmStructure =
1206                                                            DDMStructureUtil.fetchByUUID_G(
1207                                                                    uuid, portletDataContext.getScopeGroupId());
1208    
1209                                                    if (ddmStructure == null) {
1210                                                            ddmStructure = DDMStructureUtil.fetchByUUID_G(
1211                                                                    uuid, companyGroupId);
1212                                                    }
1213    
1214                                                    if (ddmStructure != null) {
1215                                                            newPrimaryKey = ddmStructure.getStructureId();
1216                                                    }
1217                                            }
1218                                            else if (className.equals(
1219                                                                    DLFileEntryType.class.getName())) {
1220    
1221                                                    DLFileEntryType dlFileEntryType =
1222                                                            DLFileEntryTypeUtil.fetchByUUID_G(
1223                                                                    uuid, portletDataContext.getScopeGroupId());
1224    
1225                                                    if (dlFileEntryType == null) {
1226                                                            dlFileEntryType = DLFileEntryTypeUtil.fetchByUUID_G(
1227                                                                    uuid, companyGroupId);
1228                                                    }
1229    
1230                                                    if (dlFileEntryType != null) {
1231                                                            newPrimaryKey =
1232                                                                    dlFileEntryType.getFileEntryTypeId();
1233                                                    }
1234                                            }
1235                                            else if (className.equals(Organization.class.getName())) {
1236                                                    Organization organization =
1237                                                            OrganizationUtil.fetchByUuid_C_First(
1238                                                                    uuid, portletDataContext.getCompanyId(), null);
1239    
1240                                                    if (organization != null) {
1241                                                            newPrimaryKey = organization.getOrganizationId();
1242                                                    }
1243                                            }
1244                                    }
1245    
1246                                    if (Validator.isNull(newPrimaryKey)) {
1247                                            if (_log.isWarnEnabled()) {
1248                                                    StringBundler sb = new StringBundler(8);
1249    
1250                                                    sb.append("Unable to get primary key for ");
1251                                                    sb.append(clazz);
1252                                                    sb.append(" with UUID ");
1253                                                    sb.append(uuid);
1254                                                    sb.append(" in company group ");
1255                                                    sb.append(companyGroupId);
1256                                                    sb.append(" or in group ");
1257                                                    sb.append(portletDataContext.getScopeGroupId());
1258    
1259                                                    _log.warn(sb.toString());
1260                                            }
1261                                    }
1262                                    else {
1263                                            newValue = StringUtil.replace(
1264                                                    newValue, uuid, newPrimaryKey.toString());
1265                                    }
1266                            }
1267    
1268                            newValues[i] = newValue;
1269                    }
1270    
1271                    portletPreferences.setValues(key, newValues);
1272            }
1273    
1274            @Override
1275            public MissingReferences validateMissingReferences(
1276                            long userId, long groupId, Map<String, String[]> parameterMap,
1277                            File file)
1278                    throws Exception {
1279    
1280                    final MissingReferences missingReferences = new MissingReferences();
1281    
1282                    Group group = GroupLocalServiceUtil.getGroup(groupId);
1283                    String userIdStrategy = MapUtil.getString(
1284                            parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
1285                    ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
1286    
1287                    final PortletDataContext portletDataContext =
1288                            PortletDataContextFactoryUtil.createImportPortletDataContext(
1289                                    group.getCompanyId(), groupId, parameterMap,
1290                                    getUserIdStrategy(userId, userIdStrategy), zipReader);
1291    
1292                    SAXParser saxParser = new SAXParser();
1293    
1294                    ElementHandler elementHandler = new ElementHandler(
1295                            new ElementProcessor() {
1296    
1297                                    @Override
1298                                    public void processElement(Element element) {
1299                                            MissingReference missingReference =
1300                                                    validateMissingReference(portletDataContext, element);
1301    
1302                                            if (missingReference != null) {
1303                                                    missingReferences.add(missingReference);
1304                                            }
1305                                    }
1306    
1307                            },
1308                            new String[] {"missing-reference"});
1309    
1310                    saxParser.setContentHandler(elementHandler);
1311    
1312                    saxParser.parse(
1313                            new InputSource(
1314                                    portletDataContext.getZipEntryAsInputStream("/manifest.xml")));
1315    
1316                    return missingReferences;
1317            }
1318    
1319            @Override
1320            public void writeManifestSummary(
1321                    Document document, ManifestSummary manifestSummary) {
1322    
1323                    Element rootElement = document.getRootElement();
1324    
1325                    Element manifestSummaryElement = rootElement.addElement(
1326                            "manifest-summary");
1327    
1328                    for (String manifestSummaryKey :
1329                                    manifestSummary.getManifestSummaryKeys()) {
1330    
1331                            Element element = manifestSummaryElement.addElement("staged-model");
1332    
1333                            element.addAttribute("manifest-summary-key", manifestSummaryKey);
1334    
1335                            long modelAdditionCount = manifestSummary.getModelAdditionCount(
1336                                    manifestSummaryKey);
1337    
1338                            if (modelAdditionCount > 0) {
1339                                    element.addAttribute(
1340                                            "addition-count", String.valueOf(modelAdditionCount));
1341                            }
1342    
1343                            long modelDeletionCount = manifestSummary.getModelDeletionCount(
1344                                    manifestSummaryKey);
1345    
1346                            if (modelDeletionCount > 0) {
1347                                    element.addAttribute(
1348                                            "deletion-count", String.valueOf(modelDeletionCount));
1349                            }
1350                    }
1351            }
1352    
1353            protected Map<String, String[]> getDLReferenceParameters(
1354                    PortletDataContext portletDataContext, String content, int beginPos,
1355                    int endPos) {
1356    
1357                    boolean legacyURL = true;
1358                    char[] stopChars = _DL_REFERENCE_LEGACY_STOP_CHARS;
1359    
1360                    if (content.startsWith("/documents/", beginPos)) {
1361                            legacyURL = false;
1362                            stopChars = _DL_REFERENCE_STOP_CHARS;
1363                    }
1364    
1365                    endPos = StringUtil.indexOfAny(content, stopChars, beginPos, endPos);
1366    
1367                    if (endPos == -1) {
1368                            return null;
1369                    }
1370    
1371                    Map<String, String[]> map = new HashMap<String, String[]>();
1372    
1373                    String dlReference = content.substring(beginPos, endPos);
1374    
1375                    while (dlReference.contains(StringPool.AMPERSAND_ENCODED)) {
1376                            dlReference = dlReference.replace(
1377                                    StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
1378                    }
1379    
1380                    if (!legacyURL) {
1381                            String[] pathArray = dlReference.split(StringPool.SLASH);
1382    
1383                            map.put("groupId", new String[] {pathArray[2]});
1384    
1385                            if (pathArray.length == 4) {
1386                                    map.put("uuid", new String[] {pathArray[3]});
1387                            }
1388                            else if (pathArray.length == 5) {
1389                                    map.put("folderId", new String[] {pathArray[3]});
1390                                    map.put(
1391                                            "title", new String[] {HttpUtil.decodeURL(pathArray[4])});
1392                            }
1393                            else if (pathArray.length > 5) {
1394                                    map.put("uuid", new String[] {pathArray[5]});
1395                            }
1396                    }
1397                    else {
1398                            dlReference = dlReference.substring(
1399                                    dlReference.indexOf(CharPool.QUESTION) + 1);
1400    
1401                            map = HttpUtil.parameterMapFromString(dlReference);
1402    
1403                            if (map.containsKey("img_id")) {
1404                                    map.put("image_id", map.get("img_id"));
1405                            }
1406                            else if (map.containsKey("i_id")) {
1407                                    map.put("image_id", map.get("i_id"));
1408                            }
1409                    }
1410    
1411                    map.put("endPos", new String[] {String.valueOf(endPos)});
1412    
1413                    String groupIdString = MapUtil.getString(map, "groupId");
1414    
1415                    if (groupIdString.equals("@group_id@")) {
1416                            groupIdString = String.valueOf(
1417                                    portletDataContext.getScopeGroupId());
1418    
1419                            map.put("groupId", new String[] {groupIdString});
1420                    }
1421    
1422                    return map;
1423            }
1424    
1425            protected FileEntry getFileEntry(
1426                    PortletDataContext portletDataContext, Map<String, String[]> map) {
1427    
1428                    if (map == null) {
1429                            return null;
1430                    }
1431    
1432                    FileEntry fileEntry = null;
1433    
1434                    try {
1435                            String uuid = MapUtil.getString(map, "uuid");
1436                            long groupId = MapUtil.getLong(map, "groupId");
1437    
1438                            if (Validator.isNotNull(uuid)) {
1439                                    fileEntry =
1440                                            DLAppLocalServiceUtil.getFileEntryByUuidAndGroupId(
1441                                                    uuid, groupId);
1442                            }
1443                            else {
1444                                    if (map.containsKey("folderId")) {
1445                                            long folderId = MapUtil.getLong(map, "folderId");
1446                                            String name = MapUtil.getString(map, "name");
1447                                            String title = MapUtil.getString(map, "title");
1448    
1449                                            if (Validator.isNotNull(title)) {
1450                                                    fileEntry = DLAppLocalServiceUtil.getFileEntry(
1451                                                            groupId, folderId, title);
1452                                            }
1453                                            else {
1454                                                    DLFileEntry dlFileEntry =
1455                                                            DLFileEntryLocalServiceUtil.fetchFileEntryByName(
1456                                                                    groupId, folderId, name);
1457    
1458                                                    if (dlFileEntry != null) {
1459                                                            fileEntry = DLAppLocalServiceUtil.getFileEntry(
1460                                                                    dlFileEntry.getFileEntryId());
1461                                                    }
1462                                            }
1463                                    }
1464                                    else if (map.containsKey("image_id")) {
1465                                            DLFileEntry dlFileEntry =
1466                                                    DLFileEntryLocalServiceUtil.fetchFileEntryByAnyImageId(
1467                                                            MapUtil.getLong(map, "image_id"));
1468    
1469                                            if (dlFileEntry != null) {
1470                                                    fileEntry = DLAppLocalServiceUtil.getFileEntry(
1471                                                            dlFileEntry.getFileEntryId());
1472                                            }
1473                                    }
1474                            }
1475                    }
1476                    catch (Exception e) {
1477                            if (_log.isDebugEnabled()) {
1478                                    _log.debug(e, e);
1479                            }
1480                            else if (_log.isWarnEnabled()) {
1481                                    _log.warn(e.getMessage());
1482                            }
1483                    }
1484    
1485                    return fileEntry;
1486            }
1487    
1488            protected UserIdStrategy getUserIdStrategy(
1489                            long userId, String userIdStrategy)
1490                    throws Exception {
1491    
1492                    User user = UserLocalServiceUtil.getUserById(userId);
1493    
1494                    if (UserIdStrategy.ALWAYS_CURRENT_USER_ID.equals(userIdStrategy)) {
1495                            return new AlwaysCurrentUserIdStrategy(user);
1496                    }
1497    
1498                    return new CurrentUserIdStrategy(user);
1499            }
1500    
1501            protected MissingReference validateMissingReference(
1502                    PortletDataContext portletDataContext, Element element) {
1503    
1504                    String className = element.attributeValue("class-name");
1505    
1506                    StagedModelDataHandler<?> stagedModelDataHandler =
1507                            StagedModelDataHandlerRegistryUtil.getStagedModelDataHandler(
1508                                    className);
1509    
1510                    if (!stagedModelDataHandler.validateReference(
1511                                    portletDataContext, element.getParent(), element)) {
1512    
1513                            return new MissingReference(element);
1514                    }
1515    
1516                    return null;
1517            }
1518    
1519            private static final char[] _DL_REFERENCE_LEGACY_STOP_CHARS = {
1520                    CharPool.APOSTROPHE, CharPool.CLOSE_BRACKET, CharPool.CLOSE_CURLY_BRACE,
1521                    CharPool.CLOSE_PARENTHESIS, CharPool.GREATER_THAN, CharPool.LESS_THAN,
1522                    CharPool.PIPE, CharPool.QUOTE, CharPool.SPACE
1523            };
1524    
1525            private static final char[] _DL_REFERENCE_STOP_CHARS = {
1526                    CharPool.APOSTROPHE, CharPool.CLOSE_BRACKET, CharPool.CLOSE_CURLY_BRACE,
1527                    CharPool.CLOSE_PARENTHESIS, CharPool.GREATER_THAN, CharPool.LESS_THAN,
1528                    CharPool.PIPE, CharPool.QUESTION, CharPool.QUOTE, CharPool.SPACE
1529            };
1530    
1531            private static final char[] _LAYOUT_REFERENCE_STOP_CHARS = {
1532                    CharPool.APOSTROPHE, CharPool.CLOSE_BRACKET, CharPool.CLOSE_CURLY_BRACE,
1533                    CharPool.CLOSE_PARENTHESIS, CharPool.GREATER_THAN, CharPool.LESS_THAN,
1534                    CharPool.PIPE, CharPool.QUESTION, CharPool.QUOTE, CharPool.SPACE
1535            };
1536    
1537            private static final String _PRIVATE_GROUP_SERVLET_MAPPING =
1538                    PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING +
1539                            StringPool.SLASH;
1540    
1541            private static final String _PRIVATE_USER_SERVLET_MAPPING =
1542                    PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING +
1543                            StringPool.SLASH;
1544    
1545            private static final String _PUBLIC_GROUP_SERVLET_MAPPING =
1546                    PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING +
1547                            StringPool.SLASH;
1548    
1549            private static Log _log = LogFactoryUtil.getLog(
1550                    ExportImportHelperImpl.class);
1551    
1552            private Pattern _exportLinksToLayoutPattern = Pattern.compile(
1553                    "\\[([0-9]+)@(public|private\\-[a-z]*)\\]");
1554            private Pattern _importLinksToLayoutPattern = Pattern.compile(
1555                    "\\[([0-9]+)@(public|private\\-[a-z]*)@(\\p{XDigit}{8}\\-" +
1556                    "(?:\\p{XDigit}{4}\\-){3}\\p{XDigit}{12})@([^\\]]*)\\]");
1557    
1558            private class ManifestSummaryElementProcessor implements ElementProcessor {
1559    
1560                    public ManifestSummaryElementProcessor(
1561                            Group group, ManifestSummary manifestSummary) {
1562    
1563                            _group = group;
1564                            _manifestSummary = manifestSummary;
1565                    }
1566    
1567                    @Override
1568                    public void processElement(Element element) {
1569                            String elementName = element.getName();
1570    
1571                            if (elementName.equals("header")) {
1572                                    String exportDateString = element.attributeValue("export-date");
1573    
1574                                    Date exportDate = GetterUtil.getDate(
1575                                            exportDateString,
1576                                            DateFormatFactoryUtil.getSimpleDateFormat(
1577                                                    Time.RFC822_FORMAT));
1578    
1579                                    _manifestSummary.setExportDate(exportDate);
1580                            }
1581                            else if (elementName.equals("portlet")) {
1582                                    String portletId = element.attributeValue("portlet-id");
1583    
1584                                    Portlet portlet = null;
1585    
1586                                    try {
1587                                            portlet = PortletLocalServiceUtil.getPortletById(
1588                                                    _group.getCompanyId(), portletId);
1589                                    }
1590                                    catch (Exception e) {
1591                                            return;
1592                                    }
1593    
1594                                    _manifestSummary.addConfigurationPortlet(
1595                                            portlet,
1596                                            StringUtil.split(
1597                                                    element.attributeValue("portlet-configuration")));
1598    
1599                                    PortletDataHandler portletDataHandler =
1600                                            portlet.getPortletDataHandlerInstance();
1601    
1602                                    if (!(portletDataHandler instanceof
1603                                                    DefaultConfigurationPortletDataHandler) &&
1604                                            GetterUtil.getBoolean(
1605                                                    element.attributeValue("portlet-data"))) {
1606    
1607                                            _manifestSummary.addDataPortlet(portlet);
1608                                    }
1609                            }
1610                            else if (elementName.equals("staged-model")) {
1611                                    String manifestSummaryKey = element.attributeValue(
1612                                            "manifest-summary-key");
1613    
1614                                    long modelAdditionCount = GetterUtil.getLong(
1615                                            element.attributeValue("addition-count"));
1616    
1617                                    _manifestSummary.addModelAdditionCount(
1618                                            manifestSummaryKey, modelAdditionCount);
1619    
1620                                    long modelDeletionCount = GetterUtil.getLong(
1621                                            element.attributeValue("deletion-count"));
1622    
1623                                    _manifestSummary.addModelDeletionCount(
1624                                            manifestSummaryKey, modelDeletionCount);
1625                            }
1626                    }
1627    
1628                    private Group _group;
1629                    private ManifestSummary _manifestSummary;
1630    
1631            }
1632    
1633    }