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