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.kernel.backgroundtask.BackgroundTaskThreadLocal;
018    import com.liferay.portal.kernel.language.LanguageUtil;
019    import com.liferay.portal.kernel.lar.ExportImportHelperUtil;
020    import com.liferay.portal.kernel.lar.ExportImportPathUtil;
021    import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
022    import com.liferay.portal.kernel.lar.ManifestSummary;
023    import com.liferay.portal.kernel.lar.PortletDataContext;
024    import com.liferay.portal.kernel.lar.PortletDataContextFactoryUtil;
025    import com.liferay.portal.kernel.lar.PortletDataHandler;
026    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
027    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
028    import com.liferay.portal.kernel.lar.PortletDataHandlerStatusMessageSenderUtil;
029    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
030    import com.liferay.portal.kernel.lar.StagedModelType;
031    import com.liferay.portal.kernel.log.Log;
032    import com.liferay.portal.kernel.log.LogFactoryUtil;
033    import com.liferay.portal.kernel.staging.LayoutStagingUtil;
034    import com.liferay.portal.kernel.util.ArrayUtil;
035    import com.liferay.portal.kernel.util.Constants;
036    import com.liferay.portal.kernel.util.FileUtil;
037    import com.liferay.portal.kernel.util.GetterUtil;
038    import com.liferay.portal.kernel.util.LocaleUtil;
039    import com.liferay.portal.kernel.util.MapUtil;
040    import com.liferay.portal.kernel.util.ReleaseInfo;
041    import com.liferay.portal.kernel.util.StringPool;
042    import com.liferay.portal.kernel.util.StringUtil;
043    import com.liferay.portal.kernel.util.Time;
044    import com.liferay.portal.kernel.util.Validator;
045    import com.liferay.portal.kernel.xml.Document;
046    import com.liferay.portal.kernel.xml.Element;
047    import com.liferay.portal.kernel.xml.SAXReaderUtil;
048    import com.liferay.portal.kernel.zip.ZipWriter;
049    import com.liferay.portal.kernel.zip.ZipWriterFactoryUtil;
050    import com.liferay.portal.model.Group;
051    import com.liferay.portal.model.Image;
052    import com.liferay.portal.model.Layout;
053    import com.liferay.portal.model.LayoutConstants;
054    import com.liferay.portal.model.LayoutPrototype;
055    import com.liferay.portal.model.LayoutRevision;
056    import com.liferay.portal.model.LayoutSet;
057    import com.liferay.portal.model.LayoutSetBranch;
058    import com.liferay.portal.model.LayoutSetPrototype;
059    import com.liferay.portal.model.LayoutStagingHandler;
060    import com.liferay.portal.model.LayoutTypePortlet;
061    import com.liferay.portal.model.Portlet;
062    import com.liferay.portal.model.impl.LayoutImpl;
063    import com.liferay.portal.service.GroupLocalServiceUtil;
064    import com.liferay.portal.service.ImageLocalServiceUtil;
065    import com.liferay.portal.service.LayoutLocalServiceUtil;
066    import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
067    import com.liferay.portal.service.LayoutRevisionLocalServiceUtil;
068    import com.liferay.portal.service.LayoutSetBranchLocalServiceUtil;
069    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
070    import com.liferay.portal.service.LayoutSetPrototypeLocalServiceUtil;
071    import com.liferay.portal.service.PortletLocalServiceUtil;
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.service.permission.PortletPermissionUtil;
076    import com.liferay.portlet.PortletPreferencesFactoryUtil;
077    import com.liferay.portlet.asset.model.AssetCategory;
078    import com.liferay.portlet.asset.model.AssetVocabulary;
079    import com.liferay.portlet.asset.service.AssetVocabularyLocalServiceUtil;
080    import com.liferay.portlet.asset.service.persistence.AssetCategoryUtil;
081    
082    import java.io.File;
083    
084    import java.util.ArrayList;
085    import java.util.Date;
086    import java.util.HashMap;
087    import java.util.HashSet;
088    import java.util.Iterator;
089    import java.util.LinkedHashMap;
090    import java.util.List;
091    import java.util.Map;
092    import java.util.Set;
093    
094    import org.apache.commons.lang.time.StopWatch;
095    
096    /**
097     * @author Brian Wing Shun Chan
098     * @author Joel Kozikowski
099     * @author Charles May
100     * @author Raymond Aug??
101     * @author Jorge Ferrer
102     * @author Bruno Farache
103     * @author Karthik Sudarshan
104     * @author Zsigmond Rab
105     * @author Douglas Wong
106     * @author Mate Thurzo
107     */
108    public class LayoutExporter {
109    
110            public static final String SAME_GROUP_FRIENDLY_URL =
111                    "/[$SAME_GROUP_FRIENDLY_URL$]";
112    
113            public static List<Portlet> getDataSiteLevelPortlets(long companyId)
114                    throws Exception {
115    
116                    List<Portlet> portlets = PortletLocalServiceUtil.getPortlets(companyId);
117    
118                    Iterator<Portlet> itr = portlets.iterator();
119    
120                    while (itr.hasNext()) {
121                            Portlet portlet = itr.next();
122    
123                            if (!portlet.isActive()) {
124                                    itr.remove();
125    
126                                    continue;
127                            }
128    
129                            PortletDataHandler portletDataHandler =
130                                    portlet.getPortletDataHandlerInstance();
131    
132                            if ((portletDataHandler == null) ||
133                                    !portletDataHandler.isDataSiteLevel()) {
134    
135                                    itr.remove();
136                            }
137                    }
138    
139                    return portlets;
140            }
141    
142            public static Map<String, Boolean> getExportPortletControlsMap(
143                            long companyId, String portletId,
144                            Map<String, String[]> parameterMap)
145                    throws Exception {
146    
147                    return getExportPortletControlsMap(
148                            companyId, portletId, parameterMap, "layout-set");
149            }
150    
151            public static Map<String, Boolean> getExportPortletControlsMap(
152                            long companyId, String portletId,
153                            Map<String, String[]> parameterMap, String type)
154                    throws Exception {
155    
156                    boolean exportPortletConfiguration = MapUtil.getBoolean(
157                            parameterMap, PortletDataHandlerKeys.PORTLET_CONFIGURATION);
158                    boolean exportPortletConfigurationAll = MapUtil.getBoolean(
159                            parameterMap, PortletDataHandlerKeys.PORTLET_CONFIGURATION_ALL);
160                    boolean exportPortletData = MapUtil.getBoolean(
161                            parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
162                    boolean exportPortletDataAll = MapUtil.getBoolean(
163                            parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);
164    
165                    if (_log.isDebugEnabled()) {
166                            _log.debug("Export portlet data " + exportPortletData);
167                            _log.debug("Export all portlet data " + exportPortletDataAll);
168                            _log.debug(
169                                    "Export portlet configuration " + exportPortletConfiguration);
170                    }
171    
172                    boolean exportCurPortletData = exportPortletData;
173    
174                    String rootPortletId =
175                            ExportImportHelperUtil.getExportableRootPortletId(
176                                    companyId, portletId);
177    
178                    if (exportPortletDataAll) {
179                            exportCurPortletData = true;
180                    }
181                    else if (rootPortletId != null) {
182    
183                            // PORTLET_DATA and the PORTLET_DATA for this specific data handler
184                            // must be true
185    
186                            exportCurPortletData =
187                                    exportPortletData &&
188                                    MapUtil.getBoolean(
189                                            parameterMap,
190                                            PortletDataHandlerKeys.PORTLET_DATA +
191                                                    StringPool.UNDERLINE + rootPortletId);
192                    }
193    
194                    boolean exportCurPortletArchivedSetups = exportPortletConfiguration;
195                    boolean exportCurPortletConfiguration = exportPortletConfiguration;
196                    boolean exportCurPortletSetup = exportPortletConfiguration;
197                    boolean exportCurPortletUserPreferences = exportPortletConfiguration;
198    
199                    if (exportPortletConfigurationAll ||
200                            (exportPortletConfiguration && type.equals("layout-prototype"))) {
201    
202                            exportCurPortletConfiguration = true;
203    
204                            exportCurPortletArchivedSetups =
205                                    MapUtil.getBoolean(
206                                            parameterMap,
207                                            PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS_ALL);
208                            exportCurPortletSetup =
209                                    MapUtil.getBoolean(
210                                            parameterMap, PortletDataHandlerKeys.PORTLET_SETUP_ALL);
211                            exportCurPortletUserPreferences =
212                                    MapUtil.getBoolean(
213                                            parameterMap,
214                                            PortletDataHandlerKeys.PORTLET_USER_PREFERENCES_ALL);
215                    }
216                    else if (rootPortletId != null) {
217                            exportCurPortletConfiguration =
218                                    exportPortletConfiguration &&
219                                    MapUtil.getBoolean(
220                                            parameterMap,
221                                            PortletDataHandlerKeys.PORTLET_CONFIGURATION +
222                                                    StringPool.UNDERLINE + rootPortletId);
223    
224                            exportCurPortletArchivedSetups =
225                                    exportCurPortletConfiguration &&
226                                    MapUtil.getBoolean(
227                                            parameterMap,
228                                            PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS +
229                                                    StringPool.UNDERLINE + rootPortletId);
230                            exportCurPortletSetup =
231                                    exportCurPortletConfiguration &&
232                                    MapUtil.getBoolean(
233                                            parameterMap,
234                                            PortletDataHandlerKeys.PORTLET_SETUP +
235                                                    StringPool.UNDERLINE + rootPortletId);
236                            exportCurPortletUserPreferences =
237                                    exportCurPortletConfiguration &&
238                                    MapUtil.getBoolean(
239                                            parameterMap,
240                                            PortletDataHandlerKeys.PORTLET_USER_PREFERENCES +
241                                                    StringPool.UNDERLINE + rootPortletId);
242                    }
243    
244                    Map<String, Boolean> exportPortletControlsMap =
245                            new HashMap<String, Boolean>();
246    
247                    exportPortletControlsMap.put(
248                            PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS,
249                            exportCurPortletArchivedSetups);
250                    exportPortletControlsMap.put(
251                            PortletDataHandlerKeys.PORTLET_CONFIGURATION,
252                            exportCurPortletConfiguration);
253                    exportPortletControlsMap.put(
254                            PortletDataHandlerKeys.PORTLET_DATA, exportCurPortletData);
255                    exportPortletControlsMap.put(
256                            PortletDataHandlerKeys.PORTLET_SETUP, exportCurPortletSetup);
257                    exportPortletControlsMap.put(
258                            PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
259                            exportCurPortletUserPreferences);
260    
261                    return exportPortletControlsMap;
262            }
263    
264            public static List<Portlet> getPortletDataHandlerPortlets(
265                            List<Layout> layouts)
266                    throws Exception {
267    
268                    List<Portlet> portlets = new ArrayList<Portlet>();
269                    Set<String> rootPortletIds = new HashSet<String>();
270    
271                    for (Layout layout : layouts) {
272                            if (!layout.isTypePortlet()) {
273                                    continue;
274                            }
275    
276                            LayoutTypePortlet layoutTypePortlet =
277                                    (LayoutTypePortlet)layout.getLayoutType();
278    
279                            for (String portletId : layoutTypePortlet.getPortletIds()) {
280                                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
281                                            layout.getCompanyId(), portletId);
282    
283                                    if ((portlet == null) ||
284                                            rootPortletIds.contains(portlet.getRootPortletId())) {
285    
286                                            continue;
287                                    }
288    
289                                    PortletDataHandler portletDataHandler =
290                                            portlet.getPortletDataHandlerInstance();
291    
292                                    if (portletDataHandler == null) {
293                                            continue;
294                                    }
295    
296                                    PortletDataHandlerControl[] portletDataHandlerControls =
297                                            portletDataHandler.getExportConfigurationControls(
298                                                    layout.getCompanyId(), layout.getGroupId(), portlet,
299                                                    layout.getPlid(), layout.getPrivateLayout());
300    
301                                    if (ArrayUtil.isNotEmpty(portletDataHandlerControls)) {
302                                            rootPortletIds.add(portlet.getRootPortletId());
303    
304                                            portlets.add(portlet);
305                                    }
306                            }
307                    }
308    
309                    return portlets;
310            }
311    
312            public static List<Portlet> getPortletDataHandlerPortlets(
313                            long groupId, boolean privateLayout)
314                    throws Exception {
315    
316                    return getPortletDataHandlerPortlets(
317                            LayoutLocalServiceUtil.getLayouts(groupId, privateLayout));
318            }
319    
320            public byte[] exportLayouts(
321                            long groupId, boolean privateLayout, long[] layoutIds,
322                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
323                    throws Exception {
324    
325                    File file = exportLayoutsAsFile(
326                            groupId, privateLayout, layoutIds, parameterMap, startDate,
327                            endDate);
328    
329                    try {
330                            return FileUtil.getBytes(file);
331                    }
332                    finally {
333                            file.delete();
334                    }
335            }
336    
337            public File exportLayoutsAsFile(
338                            long groupId, boolean privateLayout, long[] layoutIds,
339                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
340                    throws Exception {
341    
342                    try {
343                            ExportImportThreadLocal.setLayoutExportInProcess(true);
344    
345                            return doExportLayoutsAsFile(
346                                    groupId, privateLayout, layoutIds, parameterMap, startDate,
347                                    endDate);
348                    }
349                    finally {
350                            ExportImportThreadLocal.setLayoutExportInProcess(false);
351                    }
352            }
353    
354            protected File doExportLayoutsAsFile(
355                            long groupId, boolean privateLayout, long[] layoutIds,
356                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
357                    throws Exception {
358    
359                    boolean exportCategories = MapUtil.getBoolean(
360                            parameterMap, PortletDataHandlerKeys.CATEGORIES);
361                    boolean exportIgnoreLastPublishDate = MapUtil.getBoolean(
362                            parameterMap, PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE);
363                    boolean exportPermissions = MapUtil.getBoolean(
364                            parameterMap, PortletDataHandlerKeys.PERMISSIONS);
365                    boolean exportPortletDataAll = MapUtil.getBoolean(
366                            parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);
367                    boolean exportLogo = MapUtil.getBoolean(
368                            parameterMap, PortletDataHandlerKeys.LOGO);
369                    boolean exportLayoutSetSettings = MapUtil.getBoolean(
370                            parameterMap, PortletDataHandlerKeys.LAYOUT_SET_SETTINGS);
371    
372                    if (_log.isDebugEnabled()) {
373                            _log.debug("Export permissions " + exportPermissions);
374                    }
375    
376                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
377                            groupId, privateLayout);
378    
379                    long companyId = layoutSet.getCompanyId();
380                    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
381    
382                    ServiceContext serviceContext =
383                            ServiceContextThreadLocal.getServiceContext();
384    
385                    if (serviceContext == null) {
386                            serviceContext = new ServiceContext();
387    
388                            serviceContext.setCompanyId(companyId);
389                            serviceContext.setSignedIn(false);
390                            serviceContext.setUserId(defaultUserId);
391    
392                            ServiceContextThreadLocal.pushServiceContext(serviceContext);
393                    }
394    
395                    serviceContext.setAttribute("exporting", Boolean.TRUE);
396    
397                    long layoutSetBranchId = MapUtil.getLong(
398                            parameterMap, "layoutSetBranchId");
399    
400                    serviceContext.setAttribute("layoutSetBranchId", layoutSetBranchId);
401    
402                    if (exportIgnoreLastPublishDate) {
403                            endDate = null;
404                            startDate = null;
405                    }
406    
407                    StopWatch stopWatch = new StopWatch();
408    
409                    stopWatch.start();
410    
411                    LayoutCache layoutCache = new LayoutCache();
412    
413                    ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();
414    
415                    PortletDataContext portletDataContext =
416                            PortletDataContextFactoryUtil.createExportPortletDataContext(
417                                    companyId, groupId, parameterMap, startDate, endDate,
418                                    zipWriter);
419    
420                    portletDataContext.setPortetDataContextListener(
421                            new PortletDataContextListenerImpl(portletDataContext));
422    
423                    Document document = SAXReaderUtil.createDocument();
424    
425                    Element rootElement = document.addElement("root");
426    
427                    portletDataContext.setExportDataRootElement(rootElement);
428    
429                    Element headerElement = rootElement.addElement("header");
430    
431                    headerElement.addAttribute(
432                            "available-locales",
433                            StringUtil.merge(
434                                    LanguageUtil.getAvailableLocales(
435                                            portletDataContext.getScopeGroupId())));
436                    headerElement.addAttribute(
437                            "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
438                    headerElement.addAttribute("export-date", Time.getRFC822());
439    
440                    if (portletDataContext.hasDateRange()) {
441                            headerElement.addAttribute(
442                                    "start-date",
443                                    String.valueOf(portletDataContext.getStartDate()));
444                            headerElement.addAttribute(
445                                    "end-date", String.valueOf(portletDataContext.getEndDate()));
446                    }
447    
448                    headerElement.addAttribute(
449                            "company-id", String.valueOf(portletDataContext.getCompanyId()));
450                    headerElement.addAttribute(
451                            "company-group-id",
452                            String.valueOf(portletDataContext.getCompanyGroupId()));
453                    headerElement.addAttribute("group-id", String.valueOf(groupId));
454                    headerElement.addAttribute(
455                            "user-personal-site-group-id",
456                            String.valueOf(portletDataContext.getUserPersonalSiteGroupId()));
457                    headerElement.addAttribute(
458                            "private-layout", String.valueOf(privateLayout));
459    
460                    Group group = layoutSet.getGroup();
461    
462                    String type = "layout-set";
463    
464                    if (group.isLayoutPrototype()) {
465                            type = "layout-prototype";
466    
467                            LayoutPrototype layoutPrototype =
468                                    LayoutPrototypeLocalServiceUtil.getLayoutPrototype(
469                                            group.getClassPK());
470    
471                            headerElement.addAttribute("type-uuid", layoutPrototype.getUuid());
472                    }
473                    else if (group.isLayoutSetPrototype()) {
474                            type ="layout-set-prototype";
475    
476                            LayoutSetPrototype layoutSetPrototype =
477                                    LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototype(
478                                            group.getClassPK());
479    
480                            headerElement.addAttribute(
481                                    "type-uuid", layoutSetPrototype.getUuid());
482                    }
483    
484                    headerElement.addAttribute("type", type);
485    
486                    LayoutSetBranch layoutSetBranch =
487                            LayoutSetBranchLocalServiceUtil.fetchLayoutSetBranch(
488                                    layoutSetBranchId);
489    
490                    if (exportLogo) {
491                            Image image = null;
492    
493                            if (layoutSetBranch != null) {
494                                    image = ImageLocalServiceUtil.getImage(
495                                            layoutSetBranch.getLogoId());
496                            }
497                            else {
498                                    image = ImageLocalServiceUtil.getImage(layoutSet.getLogoId());
499                            }
500    
501                            if ((image != null) && (image.getTextObj() != null)) {
502                                    String logoPath = ExportImportPathUtil.getRootPath(
503                                            portletDataContext);
504    
505                                    logoPath += "/logo";
506    
507                                    headerElement.addAttribute("logo-path", logoPath);
508    
509                                    portletDataContext.addZipEntry(logoPath, image.getTextObj());
510                            }
511                    }
512    
513                    Element missingReferencesElement = rootElement.addElement(
514                            "missing-references");
515    
516                    portletDataContext.setMissingReferencesElement(
517                            missingReferencesElement);
518    
519                    if (layoutSetBranch != null) {
520                            _themeExporter.exportTheme(portletDataContext, layoutSetBranch);
521                    }
522                    else {
523                            _themeExporter.exportTheme(portletDataContext, layoutSet);
524                    }
525    
526                    if (exportLayoutSetSettings) {
527                            Element settingsElement = headerElement.addElement("settings");
528    
529                            if (layoutSetBranch != null) {
530                                    settingsElement.addCDATA(layoutSetBranch.getSettings());
531                            }
532                            else {
533                                    settingsElement.addCDATA(layoutSet.getSettings());
534                            }
535                    }
536    
537                    Map<String, Object[]> portletIds =
538                            new LinkedHashMap<String, Object[]>();
539    
540                    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
541                            groupId, privateLayout);
542    
543                    if (group.isStagingGroup()) {
544                            group = group.getLiveGroup();
545                    }
546    
547                    // Collect data portlets
548    
549                    for (Portlet portlet : getDataSiteLevelPortlets(companyId)) {
550                            String portletId = portlet.getRootPortletId();
551    
552                            if (!group.isStagedPortlet(portletId)) {
553                                    continue;
554                            }
555    
556                            // Calculate the amount of exported data
557    
558                            if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
559                                    PortletDataHandler portletDataHandler =
560                                            portlet.getPortletDataHandlerInstance();
561    
562                                    portletDataHandler.prepareManifestSummary(portletDataContext);
563                            }
564    
565                            // Add portlet ID to exportable portlets list
566    
567                            portletIds.put(
568                                    PortletPermissionUtil.getPrimaryKey(0, portletId),
569                                    new Object[] {
570                                            portletId, LayoutConstants.DEFAULT_PLID, groupId,
571                                            StringPool.BLANK, StringPool.BLANK
572                                    });
573    
574                            if (!portlet.isScopeable()) {
575                                    continue;
576                            }
577    
578                            // Scoped data
579    
580                            for (Layout layout : layouts) {
581                                    if ((!ArrayUtil.contains(layoutIds, layout.getLayoutId()) &&
582                                             ArrayUtil.isNotEmpty(layoutIds)) ||
583                                            !layout.isTypePortlet() || !layout.hasScopeGroup()) {
584    
585                                            continue;
586                                    }
587    
588                                    Group scopeGroup = layout.getScopeGroup();
589    
590                                    portletIds.put(
591                                            PortletPermissionUtil.getPrimaryKey(
592                                                    layout.getPlid(), portlet.getPortletId()),
593                                            new Object[] {
594                                                    portlet.getPortletId(), layout.getPlid(),
595                                                    scopeGroup.getGroupId(), StringPool.BLANK,
596                                                    layout.getUuid()
597                                            });
598                            }
599                    }
600    
601                    portletDataContext.addDeletionSystemEventStagedModelTypes(
602                            new StagedModelType(Layout.class));
603    
604                    Element layoutsElement = portletDataContext.getExportDataGroupElement(
605                            Layout.class);
606    
607                    String layoutSetPrototypeUuid = layoutSet.getLayoutSetPrototypeUuid();
608    
609                    if (!group.isStaged() && Validator.isNotNull(layoutSetPrototypeUuid)) {
610                            LayoutSetPrototype layoutSetPrototype =
611                                    LayoutSetPrototypeLocalServiceUtil.
612                                            getLayoutSetPrototypeByUuidAndCompanyId(
613                                                    layoutSetPrototypeUuid, companyId);
614    
615                            layoutsElement.addAttribute(
616                                    "layout-set-prototype-uuid", layoutSetPrototypeUuid);
617    
618                            layoutsElement.addAttribute(
619                                    "layout-set-prototype-name",
620                                    layoutSetPrototype.getName(LocaleUtil.getDefault()));
621                    }
622    
623                    for (Layout layout : layouts) {
624                            exportLayout(portletDataContext, layoutIds, portletIds, layout);
625                    }
626    
627                    if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
628                            ManifestSummary manifestSummary =
629                                    portletDataContext.getManifestSummary();
630    
631                            Set<String> portletIdsSet = portletIds.keySet();
632    
633                            PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
634                                    "layout", portletIdsSet.toArray(
635                                            new String[portletIdsSet.size()]),
636                                    manifestSummary);
637    
638                            manifestSummary.resetCounters();
639                    }
640    
641                    long previousScopeGroupId = portletDataContext.getScopeGroupId();
642    
643                    Element portletsElement = rootElement.addElement("portlets");
644    
645                    for (Map.Entry<String, Object[]> portletIdsEntry :
646                                    portletIds.entrySet()) {
647    
648                            Object[] portletObjects = portletIdsEntry.getValue();
649    
650                            String portletId = null;
651                            long plid = LayoutConstants.DEFAULT_PLID;
652                            long scopeGroupId = 0;
653                            String scopeType = StringPool.BLANK;
654                            String scopeLayoutUuid = null;
655    
656                            if (portletObjects.length == 4) {
657                                    portletId = (String)portletIdsEntry.getValue()[0];
658                                    plid = (Long)portletIdsEntry.getValue()[1];
659                                    scopeGroupId = (Long)portletIdsEntry.getValue()[2];
660                                    scopeLayoutUuid = (String)portletIdsEntry.getValue()[3];
661                            }
662                            else {
663                                    portletId = (String)portletIdsEntry.getValue()[0];
664                                    plid = (Long)portletIdsEntry.getValue()[1];
665                                    scopeGroupId = (Long)portletIdsEntry.getValue()[2];
666                                    scopeType = (String)portletIdsEntry.getValue()[3];
667                                    scopeLayoutUuid = (String)portletIdsEntry.getValue()[4];
668                            }
669    
670                            Layout layout = LayoutLocalServiceUtil.fetchLayout(plid);
671    
672                            if (layout == null) {
673                                    layout = new LayoutImpl();
674    
675                                    layout.setGroupId(groupId);
676                                    layout.setCompanyId(companyId);
677                            }
678    
679                            portletDataContext.setPlid(plid);
680                            portletDataContext.setOldPlid(plid);
681                            portletDataContext.setScopeGroupId(scopeGroupId);
682                            portletDataContext.setScopeType(scopeType);
683                            portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);
684    
685                            Map<String, Boolean> exportPortletControlsMap =
686                                    getExportPortletControlsMap(
687                                            companyId, portletId, parameterMap, type);
688    
689                            _portletExporter.exportPortlet(
690                                    portletDataContext, layoutCache, portletId, layout,
691                                    portletsElement, exportPermissions,
692                                    exportPortletControlsMap.get(
693                                            PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
694                                    exportPortletControlsMap.get(
695                                            PortletDataHandlerKeys.PORTLET_DATA),
696                                    exportPortletControlsMap.get(
697                                            PortletDataHandlerKeys.PORTLET_SETUP),
698                                    exportPortletControlsMap.get(
699                                            PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));
700                    }
701    
702                    portletDataContext.setScopeGroupId(previousScopeGroupId);
703    
704                    exportAssetCategories(
705                            portletDataContext, exportPortletDataAll, exportCategories,
706                            group.isCompany());
707    
708                    _portletExporter.exportAssetLinks(portletDataContext);
709                    _portletExporter.exportAssetTags(portletDataContext);
710                    _portletExporter.exportComments(portletDataContext);
711                    _portletExporter.exportExpandoTables(portletDataContext);
712                    _portletExporter.exportLocks(portletDataContext);
713    
714                    _deletionSystemEventExporter.exportDeletionSystemEvents(
715                            portletDataContext);
716    
717                    if (exportPermissions) {
718                            _permissionExporter.exportPortletDataPermissions(
719                                    portletDataContext);
720                    }
721    
722                    _portletExporter.exportRatingsEntries(portletDataContext, rootElement);
723    
724                    ExportImportHelperUtil.writeManifestSummary(
725                            document, portletDataContext.getManifestSummary());
726    
727                    if (_log.isInfoEnabled()) {
728                            _log.info("Exporting layouts takes " + stopWatch.getTime() + " ms");
729                    }
730    
731                    portletDataContext.addZipEntry(
732                            "/manifest.xml", document.formattedString());
733    
734                    return zipWriter.getFile();
735            }
736    
737            protected void exportAssetCategories(
738                            PortletDataContext portletDataContext, boolean exportPortletDataAll,
739                            boolean exportCategories, boolean companyGroup)
740                    throws Exception {
741    
742                    Document document = SAXReaderUtil.createDocument();
743    
744                    Element rootElement = document.addElement("categories-hierarchy");
745    
746                    if (exportPortletDataAll || exportCategories || companyGroup) {
747                            if (_log.isDebugEnabled()) {
748                                    _log.debug("Export categories");
749                            }
750    
751                            Element assetVocabulariesElement = rootElement.addElement(
752                                    "vocabularies");
753    
754                            List<AssetVocabulary> assetVocabularies =
755                                    AssetVocabularyLocalServiceUtil.getGroupVocabularies(
756                                            portletDataContext.getGroupId());
757    
758                            for (AssetVocabulary assetVocabulary : assetVocabularies) {
759                                    _portletExporter.exportAssetVocabulary(
760                                            portletDataContext, assetVocabulariesElement,
761                                            assetVocabulary);
762                            }
763    
764                            Element categoriesElement = rootElement.addElement("categories");
765    
766                            List<AssetCategory> assetCategories =
767                                    AssetCategoryUtil.findByGroupId(
768                                            portletDataContext.getGroupId());
769    
770                            for (AssetCategory assetCategory : assetCategories) {
771                                    _portletExporter.exportAssetCategory(
772                                            portletDataContext, assetVocabulariesElement,
773                                            categoriesElement, assetCategory);
774                            }
775                    }
776    
777                    _portletExporter.exportAssetCategories(portletDataContext, rootElement);
778    
779                    portletDataContext.addZipEntry(
780                            ExportImportPathUtil.getRootPath(portletDataContext) +
781                                    "/categories-hierarchy.xml",
782                            document.formattedString());
783            }
784    
785            protected void exportLayout(
786                            PortletDataContext portletDataContext, long[] layoutIds,
787                            Map<String, Object[]> portletIds, Layout layout)
788                    throws Exception {
789    
790                    if (!ArrayUtil.contains(layoutIds, layout.getLayoutId()) &&
791                            ArrayUtil.isNotEmpty(layoutIds)) {
792    
793                            Element layoutElement = portletDataContext.getExportDataElement(
794                                    layout);
795    
796                            layoutElement.addAttribute("action", Constants.SKIP);
797    
798                            return;
799                    }
800    
801                    boolean exportLAR = MapUtil.getBoolean(
802                            portletDataContext.getParameterMap(), "exportLAR");
803    
804                    if (!exportLAR && LayoutStagingUtil.isBranchingLayout(layout)) {
805                            long layoutSetBranchId = MapUtil.getLong(
806                                    portletDataContext.getParameterMap(), "layoutSetBranchId");
807    
808                            if (layoutSetBranchId <= 0) {
809                                    return;
810                            }
811    
812                            LayoutRevision layoutRevision =
813                                    LayoutRevisionLocalServiceUtil.fetchLayoutRevision(
814                                            layoutSetBranchId, true, layout.getPlid());
815    
816                            if (layoutRevision == null) {
817                                    return;
818                            }
819    
820                            LayoutStagingHandler layoutStagingHandler =
821                                    LayoutStagingUtil.getLayoutStagingHandler(layout);
822    
823                            layoutStagingHandler.setLayoutRevision(layoutRevision);
824                    }
825    
826                    StagedModelDataHandlerUtil.exportStagedModel(
827                            portletDataContext, layout);
828    
829                    if (!layout.isSupportsEmbeddedPortlets()) {
830    
831                            // Only portlet type layouts support page scoping
832    
833                            return;
834                    }
835    
836                    LayoutTypePortlet layoutTypePortlet =
837                            (LayoutTypePortlet)layout.getLayoutType();
838    
839                    // The getAllPortlets method returns all effective nonsystem portlets
840                    // for any layout type, including embedded portlets, or in the case of
841                    // panel type layout, selected portlets
842    
843                    for (Portlet portlet : layoutTypePortlet.getAllPortlets(false)) {
844                            String portletId = portlet.getPortletId();
845    
846                            javax.portlet.PortletPreferences jxPortletPreferences =
847                                    PortletPreferencesFactoryUtil.getLayoutPortletSetup(
848                                            layout, portletId);
849    
850                            String scopeType = GetterUtil.getString(
851                                    jxPortletPreferences.getValue("lfrScopeType", null));
852                            String scopeLayoutUuid = GetterUtil.getString(
853                                    jxPortletPreferences.getValue("lfrScopeLayoutUuid", null));
854    
855                            long scopeGroupId = portletDataContext.getScopeGroupId();
856    
857                            if (Validator.isNotNull(scopeType)) {
858                                    Group scopeGroup = null;
859    
860                                    if (scopeType.equals("company")) {
861                                            scopeGroup = GroupLocalServiceUtil.getCompanyGroup(
862                                                    layout.getCompanyId());
863                                    }
864                                    else if (scopeType.equals("layout")) {
865                                            Layout scopeLayout = null;
866    
867                                            scopeLayout =
868                                                    LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
869                                                            scopeLayoutUuid, portletDataContext.getGroupId(),
870                                                            portletDataContext.isPrivateLayout());
871    
872                                            if (scopeLayout == null) {
873                                                    continue;
874                                            }
875    
876                                            scopeGroup = scopeLayout.getScopeGroup();
877                                    }
878                                    else {
879                                            throw new IllegalArgumentException(
880                                                    "Scope type " + scopeType + " is invalid");
881                                    }
882    
883                                    if (scopeGroup != null) {
884                                            scopeGroupId = scopeGroup.getGroupId();
885                                    }
886                            }
887    
888                            String key = PortletPermissionUtil.getPrimaryKey(
889                                    layout.getPlid(), portletId);
890    
891                            portletIds.put(
892                                    key,
893                                    new Object[] {
894                                            portletId, layout.getPlid(), scopeGroupId, scopeType,
895                                            scopeLayoutUuid
896                                    }
897                            );
898                    }
899            }
900    
901            private static Log _log = LogFactoryUtil.getLog(LayoutExporter.class);
902    
903            private DeletionSystemEventExporter _deletionSystemEventExporter =
904                    new DeletionSystemEventExporter();
905            private PermissionExporter _permissionExporter = new PermissionExporter();
906            private PortletExporter _portletExporter = new PortletExporter();
907            private ThemeExporter _themeExporter = new ThemeExporter();
908    
909    }