001    /**
002     * Copyright (c) 2000-present 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.LayoutImportException;
018    import com.liferay.portal.NoSuchPortletPreferencesException;
019    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskThreadLocal;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.exception.SystemException;
022    import com.liferay.portal.kernel.language.LanguageUtil;
023    import com.liferay.portal.kernel.lar.ExportImportDateUtil;
024    import com.liferay.portal.kernel.lar.ExportImportHelperUtil;
025    import com.liferay.portal.kernel.lar.ExportImportPathUtil;
026    import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
027    import com.liferay.portal.kernel.lar.ManifestSummary;
028    import com.liferay.portal.kernel.lar.PortletDataContext;
029    import com.liferay.portal.kernel.lar.PortletDataContextFactoryUtil;
030    import com.liferay.portal.kernel.lar.PortletDataException;
031    import com.liferay.portal.kernel.lar.PortletDataHandler;
032    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
033    import com.liferay.portal.kernel.lar.PortletDataHandlerStatusMessageSenderUtil;
034    import com.liferay.portal.kernel.lar.lifecycle.ExportImportLifecycleConstants;
035    import com.liferay.portal.kernel.lar.lifecycle.ExportImportLifecycleManager;
036    import com.liferay.portal.kernel.log.Log;
037    import com.liferay.portal.kernel.log.LogFactoryUtil;
038    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
039    import com.liferay.portal.kernel.util.CharPool;
040    import com.liferay.portal.kernel.util.DateRange;
041    import com.liferay.portal.kernel.util.GetterUtil;
042    import com.liferay.portal.kernel.util.MapUtil;
043    import com.liferay.portal.kernel.util.ReleaseInfo;
044    import com.liferay.portal.kernel.util.StringBundler;
045    import com.liferay.portal.kernel.util.StringPool;
046    import com.liferay.portal.kernel.util.StringUtil;
047    import com.liferay.portal.kernel.util.Time;
048    import com.liferay.portal.kernel.util.UnicodeProperties;
049    import com.liferay.portal.kernel.util.Validator;
050    import com.liferay.portal.kernel.xml.Document;
051    import com.liferay.portal.kernel.xml.Element;
052    import com.liferay.portal.kernel.xml.Node;
053    import com.liferay.portal.kernel.xml.SAXReaderUtil;
054    import com.liferay.portal.kernel.zip.ZipWriter;
055    import com.liferay.portal.kernel.zip.ZipWriterFactoryUtil;
056    import com.liferay.portal.model.Group;
057    import com.liferay.portal.model.Layout;
058    import com.liferay.portal.model.LayoutConstants;
059    import com.liferay.portal.model.LayoutTypePortlet;
060    import com.liferay.portal.model.Lock;
061    import com.liferay.portal.model.Portlet;
062    import com.liferay.portal.model.PortletConstants;
063    import com.liferay.portal.model.PortletItem;
064    import com.liferay.portal.model.PortletPreferences;
065    import com.liferay.portal.model.User;
066    import com.liferay.portal.model.impl.LayoutImpl;
067    import com.liferay.portal.service.GroupLocalServiceUtil;
068    import com.liferay.portal.service.LayoutLocalServiceUtil;
069    import com.liferay.portal.service.PortletItemLocalServiceUtil;
070    import com.liferay.portal.service.PortletLocalServiceUtil;
071    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
072    import com.liferay.portal.service.ServiceContext;
073    import com.liferay.portal.service.ServiceContextThreadLocal;
074    import com.liferay.portal.service.UserLocalServiceUtil;
075    import com.liferay.portal.util.PortalUtil;
076    import com.liferay.portal.util.PortletKeys;
077    import com.liferay.portlet.PortletPreferencesFactoryUtil;
078    import com.liferay.portlet.asset.model.AssetEntry;
079    import com.liferay.portlet.asset.model.AssetLink;
080    import com.liferay.portlet.asset.model.AssetTag;
081    import com.liferay.portlet.asset.model.AssetTagProperty;
082    import com.liferay.portlet.asset.service.AssetEntryLocalServiceUtil;
083    import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
084    import com.liferay.portlet.asset.service.AssetTagPropertyLocalServiceUtil;
085    import com.liferay.portlet.expando.model.ExpandoColumn;
086    import com.liferay.util.xml.DocUtil;
087    
088    import java.io.File;
089    import java.io.IOException;
090    
091    import java.util.Date;
092    import java.util.List;
093    import java.util.Map;
094    import java.util.Map.Entry;
095    import java.util.concurrent.Callable;
096    
097    import org.apache.commons.lang.time.StopWatch;
098    
099    /**
100     * @author Brian Wing Shun Chan
101     * @author Joel Kozikowski
102     * @author Charles May
103     * @author Raymond Aug??
104     * @author Jorge Ferrer
105     * @author Bruno Farache
106     * @author Zsigmond Rab
107     * @author Douglas Wong
108     * @author Mate Thurzo
109     */
110    public class PortletExporter {
111    
112            public static PortletExporter getInstance() {
113                    return _instance;
114            }
115    
116            public void exportPortletData(
117                            PortletDataContext portletDataContext, Portlet portlet,
118                            Layout layout,
119                            javax.portlet.PortletPreferences jxPortletPreferences,
120                            Element parentElement)
121                    throws Exception {
122    
123                    if (portlet == null) {
124                            return;
125                    }
126    
127                    PortletDataHandler portletDataHandler =
128                            portlet.getPortletDataHandlerInstance();
129    
130                    if ((portletDataHandler == null) ||
131                            portletDataHandler.isDataPortletInstanceLevel()) {
132    
133                            return;
134                    }
135    
136                    String portletId = portlet.getPortletId();
137    
138                    Group liveGroup = layout.getGroup();
139    
140                    if (liveGroup.isStagingGroup()) {
141                            liveGroup = liveGroup.getLiveGroup();
142                    }
143    
144                    boolean staged = liveGroup.isStagedPortlet(portlet.getRootPortletId());
145    
146                    if (!staged && ExportImportThreadLocal.isLayoutExportInProcess()) {
147                            if (_log.isDebugEnabled()) {
148                                    _log.debug(
149                                            "Not exporting data for " + portletId +
150                                                    " because it is configured not to be staged");
151                            }
152    
153                            return;
154                    }
155    
156                    if (_log.isDebugEnabled()) {
157                            _log.debug("Exporting data for " + portletId);
158                    }
159    
160                    StringBundler sb = new StringBundler(4);
161    
162                    sb.append(
163                            ExportImportPathUtil.getPortletPath(portletDataContext, portletId));
164                    sb.append(StringPool.SLASH);
165    
166                    if (portlet.isPreferencesUniquePerLayout()) {
167                            sb.append(layout.getPlid());
168                    }
169                    else {
170                            sb.append(portletDataContext.getScopeGroupId());
171                    }
172    
173                    sb.append("/portlet-data.xml");
174    
175                    String path = sb.toString();
176    
177                    if (portletDataContext.hasPrimaryKey(String.class, path)) {
178                            return;
179                    }
180    
181                    Date originalStartDate = portletDataContext.getStartDate();
182    
183                    Date portletLastPublishDate = ExportImportDateUtil.getLastPublishDate(
184                            portletDataContext, jxPortletPreferences);
185    
186                    portletDataContext.setStartDate(portletLastPublishDate);
187    
188                    long groupId = portletDataContext.getGroupId();
189    
190                    portletDataContext.setGroupId(portletDataContext.getScopeGroupId());
191    
192                    portletDataContext.clearScopedPrimaryKeys();
193    
194                    String data = null;
195    
196                    try {
197                            data = portletDataHandler.exportData(
198                                    portletDataContext, portletId, jxPortletPreferences);
199                    }
200                    catch (PortletDataException pde) {
201                            throw pde;
202                    }
203                    catch (Exception e) {
204                            throw new SystemException(e);
205                    }
206                    finally {
207                            portletDataContext.setGroupId(groupId);
208                            portletDataContext.setStartDate(originalStartDate);
209                    }
210    
211                    if (Validator.isNull(data)) {
212                            if (_log.isDebugEnabled()) {
213                                    _log.debug(
214                                            "Not exporting data for " + portletId +
215                                                    " because null data was returned");
216                            }
217    
218                            return;
219                    }
220    
221                    Element portletDataElement = parentElement.addElement("portlet-data");
222    
223                    portletDataElement.addAttribute("path", path);
224    
225                    portletDataContext.addZipEntry(path, data);
226    
227                    boolean updateLastPublishDate = MapUtil.getBoolean(
228                            portletDataContext.getParameterMap(),
229                            PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE);
230    
231                    if (updateLastPublishDate) {
232                            DateRange adjustedDateRange = new DateRange(
233                                    portletLastPublishDate, portletDataContext.getEndDate());
234    
235                            TransactionCommitCallbackRegistryUtil.registerCallback(
236                                    new UpdatePortletLastPublishDateCallable(
237                                            adjustedDateRange, portletDataContext.getEndDate(),
238                                            portletDataContext.getGroupId(), layout.getPlid(),
239                                            portletId));
240                    }
241            }
242    
243            public File exportPortletInfoAsFile(
244                            long plid, long groupId, String portletId,
245                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
246                    throws Exception {
247    
248                    PortletDataContext portletDataContext = null;
249    
250                    try {
251                            ExportImportThreadLocal.setPortletExportInProcess(true);
252    
253                            portletDataContext = getPortletDataContext(
254                                    plid, groupId, portletId, parameterMap, startDate, endDate);
255    
256                            ExportImportLifecycleManager.fireExportImportLifecycleEvent(
257                                    ExportImportLifecycleConstants.EVENT_PORTLET_EXPORT_STARTED,
258                                    PortletDataContextFactoryUtil.clonePortletDataContext(
259                                            portletDataContext));
260    
261                            File file = doExportPortletInfoAsFile(portletDataContext);
262    
263                            ExportImportLifecycleManager.fireExportImportLifecycleEvent(
264                                    ExportImportLifecycleConstants.EVENT_PORTLET_EXPORT_SUCCEEDED,
265                                    PortletDataContextFactoryUtil.clonePortletDataContext(
266                                            portletDataContext));
267    
268                            return file;
269                    }
270                    catch (Throwable t) {
271                            ExportImportLifecycleManager.fireExportImportLifecycleEvent(
272                                    ExportImportLifecycleConstants.EVENT_PORTLET_EXPORT_FAILED,
273                                    PortletDataContextFactoryUtil.clonePortletDataContext(
274                                            portletDataContext),
275                                    t);
276    
277                            throw t;
278                    }
279                    finally {
280                            ExportImportThreadLocal.setPortletExportInProcess(false);
281                    }
282            }
283    
284            protected File doExportPortletInfoAsFile(
285                            PortletDataContext portletDataContext)
286                    throws Exception {
287    
288                    boolean exportPermissions = MapUtil.getBoolean(
289                            portletDataContext.getParameterMap(),
290                            PortletDataHandlerKeys.PERMISSIONS);
291    
292                    if (_log.isDebugEnabled()) {
293                            _log.debug("Export permissions " + exportPermissions);
294                    }
295    
296                    StopWatch stopWatch = new StopWatch();
297    
298                    stopWatch.start();
299    
300                    Layout layout = LayoutLocalServiceUtil.getLayout(
301                            portletDataContext.getPlid());
302    
303                    if (!layout.isTypeControlPanel() && !layout.isTypePanel() &&
304                            !layout.isTypePortlet()) {
305    
306                            throw new LayoutImportException(
307                                    "Layout type " + layout.getType() + " is not valid");
308                    }
309    
310                    ServiceContext serviceContext =
311                            ServiceContextThreadLocal.getServiceContext();
312    
313                    if (serviceContext == null) {
314                            serviceContext = new ServiceContext();
315    
316                            serviceContext.setCompanyId(layout.getCompanyId());
317                            serviceContext.setSignedIn(false);
318    
319                            long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
320                                    layout.getCompanyId());
321    
322                            serviceContext.setUserId(defaultUserId);
323    
324                            ServiceContextThreadLocal.pushServiceContext(serviceContext);
325                    }
326    
327                    long layoutSetBranchId = MapUtil.getLong(
328                            portletDataContext.getParameterMap(), "layoutSetBranchId");
329    
330                    serviceContext.setAttribute("layoutSetBranchId", layoutSetBranchId);
331    
332                    long scopeGroupId = portletDataContext.getGroupId();
333    
334                    javax.portlet.PortletPreferences jxPortletPreferences =
335                            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
336                                    layout, portletDataContext.getPortletId());
337    
338                    String scopeType = GetterUtil.getString(
339                            jxPortletPreferences.getValue("lfrScopeType", null));
340                    String scopeLayoutUuid = GetterUtil.getString(
341                            jxPortletPreferences.getValue("lfrScopeLayoutUuid", null));
342    
343                    if (Validator.isNotNull(scopeType)) {
344                            Group scopeGroup = null;
345    
346                            if (scopeType.equals("company")) {
347                                    scopeGroup = GroupLocalServiceUtil.getCompanyGroup(
348                                            layout.getCompanyId());
349                            }
350                            else if (Validator.isNotNull(scopeLayoutUuid)) {
351                                    scopeGroup = layout.getScopeGroup();
352                            }
353    
354                            if (scopeGroup != null) {
355                                    scopeGroupId = scopeGroup.getGroupId();
356                            }
357                    }
358    
359                    portletDataContext.setScopeType(scopeType);
360                    portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);
361    
362                    Document document = SAXReaderUtil.createDocument();
363    
364                    Element rootElement = document.addElement("root");
365    
366                    portletDataContext.setExportDataRootElement(rootElement);
367    
368                    Element headerElement = rootElement.addElement("header");
369    
370                    headerElement.addAttribute(
371                            "available-locales",
372                            StringUtil.merge(
373                                    LanguageUtil.getAvailableLocales(
374                                            PortalUtil.getSiteGroupId(
375                                                    portletDataContext.getScopeGroupId()))));
376                    headerElement.addAttribute(
377                            "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
378                    headerElement.addAttribute("export-date", Time.getRFC822());
379    
380                    if (portletDataContext.hasDateRange()) {
381                            headerElement.addAttribute(
382                                    "start-date",
383                                    String.valueOf(portletDataContext.getStartDate()));
384                            headerElement.addAttribute(
385                                    "end-date", String.valueOf(portletDataContext.getEndDate()));
386                    }
387    
388                    headerElement.addAttribute("type", "portlet");
389                    headerElement.addAttribute(
390                            "company-id", String.valueOf(portletDataContext.getCompanyId()));
391                    headerElement.addAttribute(
392                            "company-group-id",
393                            String.valueOf(portletDataContext.getCompanyGroupId()));
394                    headerElement.addAttribute("group-id", String.valueOf(scopeGroupId));
395                    headerElement.addAttribute(
396                            "user-personal-site-group-id",
397                            String.valueOf(portletDataContext.getUserPersonalSiteGroupId()));
398                    headerElement.addAttribute(
399                            "private-layout", String.valueOf(layout.isPrivateLayout()));
400                    headerElement.addAttribute(
401                            "root-portlet-id", portletDataContext.getRootPortletId());
402    
403                    Element missingReferencesElement = rootElement.addElement(
404                            "missing-references");
405    
406                    portletDataContext.setMissingReferencesElement(
407                            missingReferencesElement);
408    
409                    Map<String, Boolean> exportPortletControlsMap =
410                            ExportImportHelperUtil.getExportPortletControlsMap(
411                                    layout.getCompanyId(), portletDataContext.getPortletId(),
412                                    portletDataContext.getParameterMap());
413    
414                    exportPortlet(
415                            portletDataContext, layout, rootElement, exportPermissions,
416                            exportPortletControlsMap.get(
417                                    PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
418                            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA),
419                            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP),
420                            exportPortletControlsMap.get(
421                                    PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));
422                    exportService(
423                            portletDataContext, rootElement,
424                            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP));
425    
426                    exportAssetLinks(portletDataContext);
427                    exportAssetTags(portletDataContext);
428                    exportExpandoTables(portletDataContext);
429                    exportLocks(portletDataContext);
430    
431                    _deletionSystemEventExporter.exportDeletionSystemEvents(
432                            portletDataContext);
433    
434                    if (exportPermissions) {
435                            _permissionExporter.exportPortletDataPermissions(
436                                    portletDataContext);
437                    }
438    
439                    ExportImportHelperUtil.writeManifestSummary(
440                            document, portletDataContext.getManifestSummary());
441    
442                    if (_log.isInfoEnabled()) {
443                            _log.info("Exporting portlet took " + stopWatch.getTime() + " ms");
444                    }
445    
446                    try {
447                            portletDataContext.addZipEntry(
448                                    "/manifest.xml", document.formattedString());
449                    }
450                    catch (IOException ioe) {
451                            throw new SystemException(ioe);
452                    }
453    
454                    ZipWriter zipWriter = portletDataContext.getZipWriter();
455    
456                    return zipWriter.getFile();
457            }
458    
459            protected void exportAssetLinks(PortletDataContext portletDataContext)
460                    throws Exception {
461    
462                    Document document = SAXReaderUtil.createDocument();
463    
464                    Element rootElement = document.addElement("links");
465    
466                    Map<String, List<AssetLink>> assetLinksMap =
467                            portletDataContext.getAssetLinksMap();
468    
469                    for (Entry<String, List<AssetLink>> entry : assetLinksMap.entrySet()) {
470                            String[] assetLinkNameParts = StringUtil.split(
471                                    entry.getKey(), CharPool.POUND);
472    
473                            List<AssetLink> assetLinks = entry.getValue();
474    
475                            String sourceAssetEntryUuid = assetLinkNameParts[0];
476    
477                            Element assetElement = rootElement.addElement("asset-link-group");
478    
479                            assetElement.addAttribute("source-uuid", sourceAssetEntryUuid);
480    
481                            for (AssetLink assetLink : assetLinks) {
482                                    String path = getAssetLinkPath(
483                                            portletDataContext, assetLink.getLinkId());
484    
485                                    if (portletDataContext.hasPrimaryKey(String.class, path)) {
486                                            return;
487                                    }
488    
489                                    Element assetLinkElement = assetElement.addElement(
490                                            "asset-link");
491    
492                                    assetLinkElement.addAttribute("path", path);
493    
494                                    AssetEntry targetAssetEntry =
495                                            AssetEntryLocalServiceUtil.fetchAssetEntry(
496                                                    assetLink.getEntryId2());
497    
498                                    assetLinkElement.addAttribute(
499                                            "target-uuid", targetAssetEntry.getClassUuid());
500    
501                                    portletDataContext.addZipEntry(path, assetLink);
502                            }
503                    }
504    
505                    portletDataContext.addZipEntry(
506                            ExportImportPathUtil.getRootPath(portletDataContext) + "/links.xml",
507                            document.formattedString());
508            }
509    
510            protected void exportAssetTag(
511                            PortletDataContext portletDataContext, AssetTag assetTag,
512                            Element assetTagsElement)
513                    throws PortalException {
514    
515                    String path = getAssetTagPath(portletDataContext, assetTag.getTagId());
516    
517                    if (portletDataContext.hasPrimaryKey(String.class, path)) {
518                            return;
519                    }
520    
521                    Element assetTagElement = assetTagsElement.addElement("tag");
522    
523                    assetTagElement.addAttribute("path", path);
524    
525                    assetTag.setUserUuid(assetTag.getUserUuid());
526    
527                    portletDataContext.addZipEntry(path, assetTag);
528    
529                    List<AssetTagProperty> assetTagProperties =
530                            AssetTagPropertyLocalServiceUtil.getTagProperties(
531                                    assetTag.getTagId());
532    
533                    for (AssetTagProperty assetTagProperty : assetTagProperties) {
534                            Element propertyElement = assetTagElement.addElement("property");
535    
536                            propertyElement.addAttribute("key", assetTagProperty.getKey());
537                            propertyElement.addAttribute("value", assetTagProperty.getValue());
538                    }
539    
540                    portletDataContext.addPermissions(AssetTag.class, assetTag.getTagId());
541            }
542    
543            protected void exportAssetTags(PortletDataContext portletDataContext)
544                    throws Exception {
545    
546                    Document document = SAXReaderUtil.createDocument();
547    
548                    Element rootElement = document.addElement("tags");
549    
550                    Map<String, String[]> assetTagNamesMap =
551                            portletDataContext.getAssetTagNamesMap();
552    
553                    if (assetTagNamesMap.isEmpty()) {
554                            return;
555                    }
556    
557                    for (Map.Entry<String, String[]> entry : assetTagNamesMap.entrySet()) {
558                            String[] assetTagNameParts = StringUtil.split(
559                                    entry.getKey(), CharPool.POUND);
560    
561                            String className = assetTagNameParts[0];
562                            String classPK = assetTagNameParts[1];
563    
564                            Element assetElement = rootElement.addElement("asset");
565    
566                            assetElement.addAttribute("class-name", className);
567                            assetElement.addAttribute("class-pk", classPK);
568                            assetElement.addAttribute(
569                                    "tags", StringUtil.merge(entry.getValue()));
570    
571                            List<AssetTag> assetTags = AssetTagLocalServiceUtil.getTags(
572                                    className, GetterUtil.getLong(classPK));
573    
574                            for (AssetTag assetTag : assetTags) {
575                                    exportAssetTag(portletDataContext, assetTag, rootElement);
576                            }
577                    }
578    
579                    portletDataContext.addZipEntry(
580                            ExportImportPathUtil.getRootPath(portletDataContext) + "/tags.xml",
581                            document.formattedString());
582            }
583    
584            protected void exportExpandoTables(PortletDataContext portletDataContext)
585                    throws Exception {
586    
587                    Document document = SAXReaderUtil.createDocument();
588    
589                    Element rootElement = document.addElement("expando-tables");
590    
591                    Map<String, List<ExpandoColumn>> expandoColumnsMap =
592                            portletDataContext.getExpandoColumns();
593    
594                    for (Map.Entry<String, List<ExpandoColumn>> entry :
595                                    expandoColumnsMap.entrySet()) {
596    
597                            String className = entry.getKey();
598    
599                            Element expandoTableElement = rootElement.addElement(
600                                    "expando-table");
601    
602                            expandoTableElement.addAttribute("class-name", className);
603    
604                            List<ExpandoColumn> expandoColumns = entry.getValue();
605    
606                            for (ExpandoColumn expandoColumn : expandoColumns) {
607                                    Element expandoColumnElement = expandoTableElement.addElement(
608                                            "expando-column");
609    
610                                    expandoColumnElement.addAttribute(
611                                            "column-id", String.valueOf(expandoColumn.getColumnId()));
612                                    expandoColumnElement.addAttribute(
613                                            "name", expandoColumn.getName());
614                                    expandoColumnElement.addAttribute(
615                                            "type", String.valueOf(expandoColumn.getType()));
616    
617                                    DocUtil.add(
618                                            expandoColumnElement, "default-data",
619                                            expandoColumn.getDefaultData());
620    
621                                    Element typeSettingsElement = expandoColumnElement.addElement(
622                                            "type-settings");
623    
624                                    UnicodeProperties typeSettingsProperties =
625                                            expandoColumn.getTypeSettingsProperties();
626    
627                                    typeSettingsElement.addCDATA(typeSettingsProperties.toString());
628                            }
629                    }
630    
631                    portletDataContext.addZipEntry(
632                            ExportImportPathUtil.getRootPath(portletDataContext) +
633                                    "/expando-tables.xml",
634                            document.formattedString());
635            }
636    
637            protected void exportLocks(PortletDataContext portletDataContext)
638                    throws Exception {
639    
640                    Document document = SAXReaderUtil.createDocument();
641    
642                    Element rootElement = document.addElement("locks");
643    
644                    Map<String, Lock> locksMap = portletDataContext.getLocks();
645    
646                    for (Map.Entry<String, Lock> entry : locksMap.entrySet()) {
647                            Lock lock = entry.getValue();
648    
649                            String entryKey = entry.getKey();
650    
651                            int pos = entryKey.indexOf(CharPool.POUND);
652    
653                            String className = entryKey.substring(0, pos);
654                            String key = entryKey.substring(pos + 1);
655    
656                            String path = getLockPath(portletDataContext, className, key, lock);
657    
658                            Element assetElement = rootElement.addElement("asset");
659    
660                            assetElement.addAttribute("path", path);
661                            assetElement.addAttribute("class-name", className);
662                            assetElement.addAttribute("key", key);
663    
664                            portletDataContext.addZipEntry(path, lock);
665                    }
666    
667                    portletDataContext.addZipEntry(
668                            ExportImportPathUtil.getRootPath(portletDataContext) + "/locks.xml",
669                            document.formattedString());
670            }
671    
672            protected void exportPortlet(
673                            PortletDataContext portletDataContext, Layout layout,
674                            Element parentElement, boolean exportPermissions,
675                            boolean exportPortletArchivedSetups, boolean exportPortletData,
676                            boolean exportPortletSetup, boolean exportPortletUserPreferences)
677                    throws Exception {
678    
679                    long plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
680                    long layoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
681    
682                    if (layout != null) {
683                            plid = layout.getPlid();
684                            layoutId = layout.getLayoutId();
685                    }
686    
687                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
688                            portletDataContext.getCompanyId(),
689                            portletDataContext.getPortletId());
690    
691                    if (portlet == null) {
692                            if (_log.isDebugEnabled()) {
693                                    _log.debug(
694                                            "Do not export portlet " +
695                                                    portletDataContext.getPortletId() +
696                                                            " because the portlet does not exist");
697                            }
698    
699                            return;
700                    }
701    
702                    if (!portlet.isInstanceable() &&
703                            !portlet.isPreferencesUniquePerLayout() &&
704                            portletDataContext.hasNotUniquePerLayout(
705                                    portletDataContext.getPortletId())) {
706    
707                            return;
708                    }
709    
710                    if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
711                            PortletDataContext clonedPortletDataContext =
712                                    PortletDataContextFactoryUtil.clonePortletDataContext(
713                                            portletDataContext);
714    
715                            ManifestSummary manifestSummary =
716                                    clonedPortletDataContext.getManifestSummary();
717    
718                            manifestSummary.resetCounters();
719    
720                            PortletDataHandler portletDataHandler =
721                                    portlet.getPortletDataHandlerInstance();
722    
723                            portletDataHandler.prepareManifestSummary(clonedPortletDataContext);
724    
725                            PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
726                                    "portlet", portletDataContext.getPortletId(), manifestSummary);
727                    }
728    
729                    Document document = SAXReaderUtil.createDocument();
730    
731                    Element portletElement = document.addElement("portlet");
732    
733                    portletElement.addAttribute(
734                            "portlet-id", portletDataContext.getPortletId());
735                    portletElement.addAttribute(
736                            "root-portlet-id", portletDataContext.getRootPortletId());
737                    portletElement.addAttribute("old-plid", String.valueOf(plid));
738                    portletElement.addAttribute(
739                            "scope-group-id",
740                            String.valueOf(portletDataContext.getScopeGroupId()));
741                    portletElement.addAttribute(
742                            "scope-layout-type", portletDataContext.getScopeType());
743                    portletElement.addAttribute(
744                            "scope-layout-uuid", portletDataContext.getScopeLayoutUuid());
745                    portletElement.addAttribute(
746                            "private-layout", String.valueOf(layout.isPrivateLayout()));
747    
748                    // Data
749    
750                    if (exportPortletData) {
751                            javax.portlet.PortletPreferences jxPortletPreferences =
752                                    PortletPreferencesFactoryUtil.getStrictPortletSetup(
753                                            layout, portletDataContext.getPortletId());
754    
755                            if (!portlet.isPreferencesUniquePerLayout()) {
756                                    StringBundler sb = new StringBundler(5);
757    
758                                    sb.append(portletDataContext.getPortletId());
759                                    sb.append(StringPool.AT);
760                                    sb.append(portletDataContext.getScopeType());
761                                    sb.append(StringPool.AT);
762                                    sb.append(portletDataContext.getScopeLayoutUuid());
763    
764                                    String dataKey = sb.toString();
765    
766                                    if (!portletDataContext.hasNotUniquePerLayout(dataKey)) {
767                                            portletDataContext.putNotUniquePerLayout(dataKey);
768    
769                                            exportPortletData(
770                                                    portletDataContext, portlet, layout,
771                                                    jxPortletPreferences, portletElement);
772                                    }
773                            }
774                            else {
775                                    exportPortletData(
776                                            portletDataContext, portlet, layout, jxPortletPreferences,
777                                            portletElement);
778                            }
779                    }
780    
781                    // Portlet preferences
782    
783                    if (exportPortletSetup) {
784    
785                            // Company
786    
787                            exportPortletPreferences(
788                                    portletDataContext, portletDataContext.getCompanyId(),
789                                    PortletKeys.PREFS_OWNER_TYPE_COMPANY, false, layout, plid,
790                                    portlet.getRootPortletId(), portletElement);
791    
792                            // Group
793    
794                            exportPortletPreferences(
795                                    portletDataContext, portletDataContext.getScopeGroupId(),
796                                    PortletKeys.PREFS_OWNER_TYPE_GROUP, false, layout,
797                                    PortletKeys.PREFS_PLID_SHARED, portlet.getRootPortletId(),
798                                    portletElement);
799    
800                            // Layout
801    
802                            exportPortletPreferences(
803                                    portletDataContext, PortletKeys.PREFS_OWNER_ID_DEFAULT,
804                                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, false, layout, plid,
805                                    portletDataContext.getPortletId(), portletElement);
806                    }
807    
808                    // Portlet user preferences
809    
810                    if (exportPortletUserPreferences) {
811                            List<PortletPreferences> portletPreferencesList =
812                                    PortletPreferencesLocalServiceUtil.getPortletPreferences(
813                                            PortletKeys.PREFS_OWNER_TYPE_USER, plid,
814                                            portletDataContext.getPortletId());
815    
816                            for (PortletPreferences portletPreferences :
817                                            portletPreferencesList) {
818    
819                                    boolean defaultUser = false;
820    
821                                    if (portletPreferences.getOwnerId() ==
822                                                    PortletKeys.PREFS_OWNER_ID_DEFAULT) {
823    
824                                            defaultUser = true;
825                                    }
826    
827                                    exportPortletPreferences(
828                                            portletDataContext, portletPreferences.getOwnerId(),
829                                            PortletKeys.PREFS_OWNER_TYPE_USER, defaultUser, layout,
830                                            plid, portletDataContext.getPortletId(), portletElement);
831                            }
832    
833                            try {
834                                    PortletPreferences groupPortletPreferences =
835                                            PortletPreferencesLocalServiceUtil.getPortletPreferences(
836                                                    portletDataContext.getScopeGroupId(),
837                                                    PortletKeys.PREFS_OWNER_TYPE_GROUP,
838                                                    PortletKeys.PREFS_PLID_SHARED,
839                                                    portlet.getRootPortletId());
840    
841                                    exportPortletPreference(
842                                            portletDataContext, portletDataContext.getScopeGroupId(),
843                                            PortletKeys.PREFS_OWNER_TYPE_GROUP, false,
844                                            groupPortletPreferences, portlet.getRootPortletId(),
845                                            PortletKeys.PREFS_PLID_SHARED, portletElement);
846                            }
847                            catch (NoSuchPortletPreferencesException nsppe) {
848                            }
849                    }
850    
851                    // Archived setups
852    
853                    if (exportPortletArchivedSetups) {
854                            List<PortletItem> portletItems =
855                                    PortletItemLocalServiceUtil.getPortletItems(
856                                            portletDataContext.getGroupId(),
857                                            portletDataContext.getRootPortletId(),
858                                            PortletPreferences.class.getName());
859    
860                            for (PortletItem portletItem : portletItems) {
861                                    exportPortletPreferences(
862                                            portletDataContext, portletItem.getPortletItemId(),
863                                            PortletKeys.PREFS_OWNER_TYPE_ARCHIVED, false, null, plid,
864                                            portletItem.getPortletId(), portletElement);
865                            }
866                    }
867    
868                    // Permissions
869    
870                    if (exportPermissions) {
871                            _permissionExporter.exportPortletPermissions(
872                                    portletDataContext, portletDataContext.getPortletId(), layout,
873                                    portletElement);
874                    }
875    
876                    // Zip
877    
878                    StringBundler pathSB = new StringBundler(4);
879    
880                    pathSB.append(ExportImportPathUtil.getPortletPath(portletDataContext));
881                    pathSB.append(StringPool.SLASH);
882                    pathSB.append(plid);
883                    pathSB.append("/portlet.xml");
884    
885                    String path = pathSB.toString();
886    
887                    Element element = parentElement.addElement("portlet");
888    
889                    element.addAttribute("portlet-id", portletDataContext.getPortletId());
890                    element.addAttribute("layout-id", String.valueOf(layoutId));
891                    element.addAttribute("path", path);
892                    element.addAttribute("portlet-data", String.valueOf(exportPortletData));
893    
894                    StringBundler configurationOptionsSB = new StringBundler(6);
895    
896                    if (exportPortletSetup) {
897                            configurationOptionsSB.append("setup");
898                            configurationOptionsSB.append(StringPool.COMMA);
899                    }
900    
901                    if (exportPortletArchivedSetups) {
902                            configurationOptionsSB.append("archived-setups");
903                            configurationOptionsSB.append(StringPool.COMMA);
904                    }
905    
906                    if (exportPortletUserPreferences) {
907                            configurationOptionsSB.append("user-preferences");
908                            configurationOptionsSB.append(StringPool.COMMA);
909                    }
910    
911                    if (configurationOptionsSB.index() > 0) {
912                            configurationOptionsSB.setIndex(configurationOptionsSB.index() -1);
913                    }
914    
915                    element.addAttribute(
916                            "portlet-configuration", configurationOptionsSB.toString());
917    
918                    try {
919                            portletDataContext.addZipEntry(path, document.formattedString());
920                    }
921                    catch (IOException ioe) {
922                            if (_log.isWarnEnabled()) {
923                                    _log.warn(ioe.getMessage());
924                            }
925                    }
926            }
927    
928            protected void exportPortletPreference(
929                            PortletDataContext portletDataContext, long ownerId, int ownerType,
930                            boolean defaultUser, PortletPreferences portletPreferences,
931                            String portletId, long plid, Element parentElement)
932                    throws Exception {
933    
934                    String preferencesXML = portletPreferences.getPreferences();
935    
936                    if (Validator.isNull(preferencesXML)) {
937                            preferencesXML = PortletConstants.DEFAULT_PREFERENCES;
938                    }
939    
940                    javax.portlet.PortletPreferences jxPortletPreferences =
941                            PortletPreferencesFactoryUtil.fromDefaultXML(preferencesXML);
942    
943                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
944                            portletDataContext.getCompanyId(), portletId);
945    
946                    Element portletPreferencesElement = parentElement.addElement(
947                            "portlet-preferences");
948    
949                    if ((portlet != null) &&
950                            (portlet.getPortletDataHandlerInstance() != null)) {
951    
952                            Element exportDataRootElement =
953                                    portletDataContext.getExportDataRootElement();
954    
955                            try {
956                                    portletDataContext.clearScopedPrimaryKeys();
957    
958                                    Element preferenceDataElement =
959                                            portletPreferencesElement.addElement("preference-data");
960    
961                                    portletDataContext.setExportDataRootElement(
962                                            preferenceDataElement);
963    
964                                    PortletDataHandler portletDataHandler =
965                                            portlet.getPortletDataHandlerInstance();
966    
967                                    jxPortletPreferences =
968                                            portletDataHandler.processExportPortletPreferences(
969                                                    portletDataContext, portletId, jxPortletPreferences);
970                            }
971                            finally {
972                                    portletDataContext.setExportDataRootElement(
973                                            exportDataRootElement);
974                            }
975                    }
976    
977                    Document document = SAXReaderUtil.read(
978                            PortletPreferencesFactoryUtil.toXML(jxPortletPreferences));
979    
980                    Element rootElement = document.getRootElement();
981    
982                    rootElement.addAttribute("owner-id", String.valueOf(ownerId));
983                    rootElement.addAttribute("owner-type", String.valueOf(ownerType));
984                    rootElement.addAttribute("default-user", String.valueOf(defaultUser));
985                    rootElement.addAttribute("plid", String.valueOf(plid));
986                    rootElement.addAttribute("portlet-id", portletId);
987    
988                    if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
989                            PortletItem portletItem =
990                                    PortletItemLocalServiceUtil.getPortletItem(ownerId);
991    
992                            rootElement.addAttribute(
993                                    "archive-user-uuid", portletItem.getUserUuid());
994                            rootElement.addAttribute("archive-name", portletItem.getName());
995                    }
996                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) {
997                            User user = UserLocalServiceUtil.fetchUserById(ownerId);
998    
999                            if (user == null) {
1000                                    return;
1001                            }
1002    
1003                            rootElement.addAttribute("user-uuid", user.getUserUuid());
1004                    }
1005    
1006                    List<Node> nodes = document.selectNodes(
1007                            "/portlet-preferences/preference[name/text() = " +
1008                                    "'last-publish-date']");
1009    
1010                    for (Node node : nodes) {
1011                            document.remove(node);
1012                    }
1013    
1014                    String path = ExportImportPathUtil.getPortletPreferencesPath(
1015                            portletDataContext, portletId, ownerId, ownerType, plid);
1016    
1017                    portletPreferencesElement.addAttribute("path", path);
1018    
1019                    portletDataContext.addZipEntry(
1020                            path, document.formattedString(StringPool.TAB, false, false));
1021            }
1022    
1023            protected void exportPortletPreferences(
1024                            PortletDataContext portletDataContext, long ownerId, int ownerType,
1025                            boolean defaultUser, Layout layout, long plid, String portletId,
1026                            Element parentElement)
1027                    throws Exception {
1028    
1029                    PortletPreferences portletPreferences = null;
1030    
1031                    try {
1032                            portletPreferences = getPortletPreferences(
1033                                    ownerId, ownerType, plid, portletId);
1034                    }
1035                    catch (NoSuchPortletPreferencesException nsppe) {
1036                            return;
1037                    }
1038    
1039                    LayoutTypePortlet layoutTypePortlet = null;
1040    
1041                    if (layout != null) {
1042                            layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
1043                    }
1044    
1045                    if ((layoutTypePortlet == null) ||
1046                            layoutTypePortlet.hasPortletId(portletId)) {
1047    
1048                            exportPortletPreference(
1049                                    portletDataContext, ownerId, ownerType, defaultUser,
1050                                    portletPreferences, portletId, plid, parentElement);
1051                    }
1052            }
1053    
1054            protected void exportService(
1055                            PortletDataContext portletDataContext, Element rootElement,
1056                            boolean exportServiceSetup)
1057                    throws Exception {
1058    
1059                    if (!exportServiceSetup) {
1060                            return;
1061                    }
1062    
1063                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
1064                            portletDataContext.getPortletId());
1065    
1066                    PortletDataHandler portletDataHandler =
1067                            portlet.getPortletDataHandlerInstance();
1068    
1069                    String serviceName = portletDataHandler.getServiceName();
1070    
1071                    if (Validator.isNotNull(serviceName)) {
1072    
1073                            // Company service
1074    
1075                            exportServicePortletPreferences(
1076                                    portletDataContext, portletDataContext.getCompanyId(),
1077                                    PortletKeys.PREFS_OWNER_TYPE_COMPANY, serviceName, rootElement);
1078    
1079                            // Group service
1080    
1081                            exportServicePortletPreferences(
1082                                    portletDataContext, portletDataContext.getScopeGroupId(),
1083                                    PortletKeys.PREFS_OWNER_TYPE_GROUP, serviceName, rootElement);
1084                    }
1085            }
1086    
1087            protected void exportServicePortletPreference(
1088                            PortletDataContext portletDataContext, long ownerId, int ownerType,
1089                            PortletPreferences portletPreferences, String serviceName,
1090                            Element parentElement)
1091                    throws Exception {
1092    
1093                    String path = ExportImportPathUtil.getServicePortletPreferencesPath(
1094                            portletDataContext, serviceName, ownerId, ownerType);
1095    
1096                    if (portletDataContext.isPathProcessed(path)) {
1097                            return;
1098                    }
1099    
1100                    String preferencesXML = portletPreferences.getPreferences();
1101    
1102                    if (Validator.isNull(preferencesXML)) {
1103                            preferencesXML = PortletConstants.DEFAULT_PREFERENCES;
1104                    }
1105    
1106                    javax.portlet.PortletPreferences jxPortletPreferences =
1107                            PortletPreferencesFactoryUtil.fromDefaultXML(preferencesXML);
1108    
1109                    Element serviceElement = parentElement.addElement("service");
1110    
1111                    serviceElement.addAttribute("service-name", serviceName);
1112    
1113                    Document document = SAXReaderUtil.read(
1114                            PortletPreferencesFactoryUtil.toXML(jxPortletPreferences));
1115    
1116                    Element rootElement = document.getRootElement();
1117    
1118                    rootElement.addAttribute("owner-id", String.valueOf(ownerId));
1119                    rootElement.addAttribute("owner-type", String.valueOf(ownerType));
1120                    rootElement.addAttribute("default-user", String.valueOf(false));
1121                    rootElement.addAttribute("service-name", serviceName);
1122    
1123                    if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
1124                            PortletItem portletItem =
1125                                    PortletItemLocalServiceUtil.getPortletItem(ownerId);
1126    
1127                            rootElement.addAttribute(
1128                                    "archive-user-uuid", portletItem.getUserUuid());
1129                            rootElement.addAttribute("archive-name", portletItem.getName());
1130                    }
1131                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) {
1132                            User user = UserLocalServiceUtil.fetchUserById(ownerId);
1133    
1134                            if (user == null) {
1135                                    return;
1136                            }
1137    
1138                            rootElement.addAttribute("user-uuid", user.getUserUuid());
1139                    }
1140    
1141                    List<Node> nodes = document.selectNodes(
1142                            "/portlet-preferences/preference[name/text() = " +
1143                                    "'last-publish-date']");
1144    
1145                    for (Node node : nodes) {
1146                            document.remove(node);
1147                    }
1148    
1149                    serviceElement.addAttribute("path", path);
1150    
1151                    portletDataContext.addZipEntry(path, document.formattedString());
1152            }
1153    
1154            protected void exportServicePortletPreferences(
1155                            PortletDataContext portletDataContext, long ownerId, int ownerType,
1156                            String serviceName, Element parentElement)
1157                    throws Exception {
1158    
1159                    PortletPreferences portletPreferences = null;
1160    
1161                    try {
1162                            portletPreferences = getPortletPreferences(
1163                                    ownerId, ownerType, LayoutConstants.DEFAULT_PLID, serviceName);
1164                    }
1165                    catch (NoSuchPortletPreferencesException nsppe) {
1166                            return;
1167                    }
1168    
1169                    exportServicePortletPreference(
1170                            portletDataContext, ownerId, ownerType, portletPreferences,
1171                            serviceName, parentElement);
1172            }
1173    
1174            protected String getAssetLinkPath(
1175                    PortletDataContext portletDataContext, long assetLinkId) {
1176    
1177                    StringBundler sb = new StringBundler(4);
1178    
1179                    sb.append(ExportImportPathUtil.getRootPath(portletDataContext));
1180                    sb.append("/links/");
1181                    sb.append(assetLinkId);
1182                    sb.append(".xml");
1183    
1184                    return sb.toString();
1185            }
1186    
1187            protected String getAssetTagPath(
1188                    PortletDataContext portletDataContext, long assetCategoryId) {
1189    
1190                    StringBundler sb = new StringBundler(4);
1191    
1192                    sb.append(ExportImportPathUtil.getRootPath(portletDataContext));
1193                    sb.append("/tags/");
1194                    sb.append(assetCategoryId);
1195                    sb.append(".xml");
1196    
1197                    return sb.toString();
1198            }
1199    
1200            protected String getLockPath(
1201                    PortletDataContext portletDataContext, String className, String key,
1202                    Lock lock) {
1203    
1204                    StringBundler sb = new StringBundler(8);
1205    
1206                    sb.append(ExportImportPathUtil.getRootPath(portletDataContext));
1207                    sb.append("/locks/");
1208                    sb.append(PortalUtil.getClassNameId(className));
1209                    sb.append(CharPool.FORWARD_SLASH);
1210                    sb.append(key);
1211                    sb.append(CharPool.FORWARD_SLASH);
1212                    sb.append(lock.getLockId());
1213                    sb.append(".xml");
1214    
1215                    return sb.toString();
1216            }
1217    
1218            protected PortletDataContext getPortletDataContext(
1219                            long plid, long groupId, String portletId,
1220                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
1221                    throws PortalException {
1222    
1223                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
1224    
1225                    ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();
1226    
1227                    PortletDataContext portletDataContext =
1228                            PortletDataContextFactoryUtil.createExportPortletDataContext(
1229                                    layout.getCompanyId(), groupId, parameterMap, startDate,
1230                                    endDate, zipWriter);
1231    
1232                    portletDataContext.setOldPlid(plid);
1233                    portletDataContext.setPlid(plid);
1234                    portletDataContext.setPortletId(portletId);
1235    
1236                    return portletDataContext;
1237            }
1238    
1239            protected PortletPreferences getPortletPreferences(
1240                            long ownerId, int ownerType, long plid, String portletId)
1241                    throws PortalException {
1242    
1243                    PortletPreferences portletPreferences = null;
1244    
1245                    if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) ||
1246                            (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) ||
1247                            (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP)) {
1248    
1249                            portletPreferences =
1250                                    PortletPreferencesLocalServiceUtil.getPortletPreferences(
1251                                            ownerId, ownerType, LayoutConstants.DEFAULT_PLID,
1252                                            portletId);
1253                    }
1254                    else {
1255                            portletPreferences =
1256                                    PortletPreferencesLocalServiceUtil.getPortletPreferences(
1257                                            ownerId, ownerType, plid, portletId);
1258                    }
1259    
1260                    return portletPreferences;
1261            }
1262    
1263            private PortletExporter() {
1264            }
1265    
1266            private static final Log _log = LogFactoryUtil.getLog(
1267                    PortletExporter.class);
1268    
1269            private static final PortletExporter _instance = new PortletExporter();
1270    
1271            private final DeletionSystemEventExporter _deletionSystemEventExporter =
1272                    DeletionSystemEventExporter.getInstance();
1273            private final PermissionExporter _permissionExporter =
1274                    PermissionExporter.getInstance();
1275    
1276            private class UpdatePortletLastPublishDateCallable
1277                    implements Callable<Void> {
1278    
1279                    public UpdatePortletLastPublishDateCallable(
1280                            DateRange dateRange, Date endDate, long groupId, long plid,
1281                            String portletId) {
1282    
1283                            _dateRange = dateRange;
1284                            _endDate = endDate;
1285                            _groupId = groupId;
1286                            _plid = plid;
1287                            _portletId = portletId;
1288                    }
1289    
1290                    @Override
1291                    public Void call() throws PortalException {
1292                            Group group = GroupLocalServiceUtil.getGroup(_groupId);
1293    
1294                            if (group.isStagedRemotely()) {
1295                                    return null;
1296                            }
1297    
1298                            Layout layout = LayoutLocalServiceUtil.fetchLayout(_plid);
1299    
1300                            if (ExportImportThreadLocal.isStagingInProcess() &&
1301                                    group.hasStagingGroup()) {
1302    
1303                                    group = group.getStagingGroup();
1304    
1305                                    if (layout != null) {
1306                                            layout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
1307                                                    layout.getUuid(), group.getGroupId(),
1308                                                    layout.isPrivateLayout());
1309                                    }
1310                            }
1311    
1312                            if (layout == null) {
1313                                    layout = new LayoutImpl();
1314    
1315                                    layout.setCompanyId(group.getCompanyId());
1316                                    layout.setGroupId(group.getGroupId());
1317                            }
1318    
1319                            javax.portlet.PortletPreferences jxPortletPreferences =
1320                                    PortletPreferencesFactoryUtil.getStrictPortletSetup(
1321                                            layout, _portletId);
1322    
1323                            ExportImportDateUtil.updateLastPublishDate(
1324                                    _portletId, jxPortletPreferences, _dateRange, _endDate);
1325    
1326                            return null;
1327                    }
1328    
1329                    private final DateRange _dateRange;
1330                    private final Date _endDate;
1331                    private final long _groupId;
1332                    private final long _plid;
1333                    private final String _portletId;
1334    
1335            }
1336    
1337    }