1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   * 
13   */
14  
15  package com.liferay.portal.lar;
16  
17  import com.liferay.portal.PortalException;
18  import com.liferay.portal.SystemException;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  import com.liferay.portal.kernel.util.FileUtil;
22  import com.liferay.portal.kernel.util.GetterUtil;
23  import com.liferay.portal.kernel.util.ListUtil;
24  import com.liferay.portal.kernel.util.MapUtil;
25  import com.liferay.portal.kernel.util.ReleaseInfo;
26  import com.liferay.portal.kernel.util.StringBundler;
27  import com.liferay.portal.kernel.util.StringPool;
28  import com.liferay.portal.kernel.util.StringUtil;
29  import com.liferay.portal.kernel.util.Time;
30  import com.liferay.portal.kernel.util.UnicodeProperties;
31  import com.liferay.portal.kernel.xml.Document;
32  import com.liferay.portal.kernel.xml.Element;
33  import com.liferay.portal.kernel.xml.SAXReaderUtil;
34  import com.liferay.portal.kernel.zip.ZipWriter;
35  import com.liferay.portal.kernel.zip.ZipWriterFactoryUtil;
36  import com.liferay.portal.model.Group;
37  import com.liferay.portal.model.Image;
38  import com.liferay.portal.model.Layout;
39  import com.liferay.portal.model.LayoutSet;
40  import com.liferay.portal.model.LayoutTypePortlet;
41  import com.liferay.portal.model.Portlet;
42  import com.liferay.portal.model.PortletConstants;
43  import com.liferay.portal.model.Theme;
44  import com.liferay.portal.service.ImageLocalServiceUtil;
45  import com.liferay.portal.service.LayoutLocalServiceUtil;
46  import com.liferay.portal.service.LayoutSetLocalServiceUtil;
47  import com.liferay.portal.service.PortletLocalServiceUtil;
48  import com.liferay.portal.service.UserLocalServiceUtil;
49  import com.liferay.portal.service.permission.PortletPermissionUtil;
50  import com.liferay.portal.service.persistence.LayoutUtil;
51  import com.liferay.portal.theme.ThemeLoader;
52  import com.liferay.portal.theme.ThemeLoaderFactory;
53  import com.liferay.portal.util.ContentUtil;
54  import com.liferay.portal.util.PortletKeys;
55  import com.liferay.portal.util.PropsValues;
56  import com.liferay.portal.velocity.VelocityContextPool;
57  import com.liferay.portlet.PortletPreferencesFactoryUtil;
58  import com.liferay.portlet.tags.model.TagsEntry;
59  import com.liferay.portlet.tags.model.TagsEntryConstants;
60  import com.liferay.portlet.tags.model.TagsVocabulary;
61  import com.liferay.portlet.tags.service.TagsEntryLocalServiceUtil;
62  import com.liferay.portlet.tags.service.TagsVocabularyLocalServiceUtil;
63  
64  import java.io.File;
65  import java.io.IOException;
66  
67  import java.util.ArrayList;
68  import java.util.Date;
69  import java.util.HashSet;
70  import java.util.Iterator;
71  import java.util.LinkedHashMap;
72  import java.util.List;
73  import java.util.Map;
74  
75  import javax.servlet.ServletContext;
76  
77  import org.apache.commons.lang.time.StopWatch;
78  
79  /**
80   * <a href="LayoutExporter.java.html"><b><i>View Source</i></b></a>
81   *
82   * @author Brian Wing Shun Chan
83   * @author Joel Kozikowski
84   * @author Charles May
85   * @author Raymond Augé
86   * @author Jorge Ferrer
87   * @author Bruno Farache
88   * @author Karthik Sudarshan
89   * @author Zsigmond Rab
90   * @author Douglas Wong
91   */
92  public class LayoutExporter {
93  
94      public static final String SAME_GROUP_FRIENDLY_URL =
95          "/[$SAME_GROUP_FRIENDLY_URL$]";
96  
97      public static List<Portlet> getAlwaysExportablePortlets(long companyId)
98          throws SystemException {
99  
100         List<Portlet> portlets = PortletLocalServiceUtil.getPortlets(companyId);
101 
102         Iterator<Portlet> itr = portlets.iterator();
103 
104         while (itr.hasNext()) {
105             Portlet portlet = itr.next();
106 
107             if (!portlet.isActive()) {
108                 itr.remove();
109 
110                 continue;
111             }
112 
113             PortletDataHandler portletDataHandler =
114                 portlet.getPortletDataHandlerInstance();
115 
116             if ((portletDataHandler == null) ||
117                 (!portletDataHandler.isAlwaysExportable())) {
118 
119                 itr.remove();
120             }
121         }
122 
123         return portlets;
124     }
125 
126     public byte[] exportLayouts(
127             long groupId, boolean privateLayout, long[] layoutIds,
128             Map<String, String[]> parameterMap, Date startDate, Date endDate)
129         throws PortalException, SystemException {
130 
131         File file = exportLayoutsAsFile(
132             groupId, privateLayout, layoutIds, parameterMap, startDate,
133             endDate);
134 
135         try {
136             return FileUtil.getBytes(file);
137         }
138         catch (IOException ioe) {
139             throw new SystemException(ioe);
140         }
141         finally {
142             file.delete();
143         }
144     }
145 
146     public File exportLayoutsAsFile(
147             long groupId, boolean privateLayout, long[] layoutIds,
148             Map<String, String[]> parameterMap, Date startDate, Date endDate)
149         throws PortalException, SystemException {
150 
151         boolean exportCategories = MapUtil.getBoolean(
152             parameterMap, PortletDataHandlerKeys.CATEGORIES);
153         boolean exportPermissions = MapUtil.getBoolean(
154             parameterMap, PortletDataHandlerKeys.PERMISSIONS);
155         boolean exportUserPermissions = MapUtil.getBoolean(
156             parameterMap, PortletDataHandlerKeys.USER_PERMISSIONS);
157         boolean exportPortletArchivedSetups = MapUtil.getBoolean(
158             parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
159         boolean exportPortletUserPreferences = MapUtil.getBoolean(
160             parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
161         boolean exportTheme = MapUtil.getBoolean(
162             parameterMap, PortletDataHandlerKeys.THEME);
163 
164         if (_log.isDebugEnabled()) {
165             _log.debug("Export categories " + exportCategories);
166             _log.debug("Export permissions " + exportPermissions);
167             _log.debug("Export user permissions " + exportUserPermissions);
168             _log.debug(
169                 "Export portlet archived setups " +
170                     exportPortletArchivedSetups);
171             _log.debug(
172                 "Export portlet user preferences " +
173                     exportPortletUserPreferences);
174             _log.debug("Export theme " + exportTheme);
175         }
176 
177         StopWatch stopWatch = null;
178 
179         if (_log.isInfoEnabled()) {
180             stopWatch = new StopWatch();
181 
182             stopWatch.start();
183         }
184 
185         LayoutCache layoutCache = new LayoutCache();
186 
187         LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
188             groupId, privateLayout);
189 
190         long companyId = layoutSet.getCompanyId();
191         long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
192 
193         ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();
194 
195         PortletDataContext context = new PortletDataContextImpl(
196             companyId, groupId, parameterMap, new HashSet<String>(), startDate,
197             endDate, zipWriter);
198 
199         // Build compatibility
200 
201         Document doc = SAXReaderUtil.createDocument();
202 
203         Element root = doc.addElement("root");
204 
205         Element header = root.addElement("header");
206 
207         header.addAttribute(
208             "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
209         header.addAttribute("export-date", Time.getRFC822());
210 
211         if (context.hasDateRange()) {
212             header.addAttribute(
213                 "start-date", String.valueOf(context.getStartDate()));
214             header.addAttribute(
215                 "end-date", String.valueOf(context.getEndDate()));
216         }
217 
218         header.addAttribute("type", "layout-set");
219         header.addAttribute("group-id", String.valueOf(groupId));
220         header.addAttribute("private-layout", String.valueOf(privateLayout));
221         header.addAttribute("theme-id", layoutSet.getThemeId());
222         header.addAttribute("color-scheme-id", layoutSet.getColorSchemeId());
223 
224         // Layout Configuration Portlet
225 
226         Portlet layoutConfigurationPortlet =
227             PortletLocalServiceUtil.getPortletById(
228                 context.getCompanyId(), PortletKeys.LAYOUT_CONFIGURATION);
229 
230         // Layouts
231 
232         Map<String, Object[]> portletIds =
233             new LinkedHashMap<String, Object[]>();
234 
235         List<Layout> layouts = null;
236 
237         if ((layoutIds == null) || (layoutIds.length == 0)) {
238             layouts = LayoutLocalServiceUtil.getLayouts(groupId, privateLayout);
239         }
240         else {
241             layouts = LayoutLocalServiceUtil.getLayouts(
242                 groupId, privateLayout, layoutIds);
243         }
244 
245         Element layoutsEl = root.addElement("layouts");
246 
247         for (Layout layout : layouts) {
248             boolean deleteLayout = MapUtil.getBoolean(
249                 parameterMap, "delete_" + layout.getPlid());
250 
251             if (deleteLayout) {
252                 Element el = layoutsEl.addElement("layout");
253 
254                 el.addAttribute(
255                     "layout-id", String.valueOf(layout.getLayoutId()));
256                 el.addAttribute("delete", String.valueOf(true));
257 
258                 continue;
259             }
260 
261             fixTypeSettings(layout);
262 
263             context.setPlid(layout.getPlid());
264 
265             Document layoutDoc = SAXReaderUtil.createDocument();
266 
267             Element layoutEl = layoutDoc.addElement("layout");
268 
269             layoutEl.addAttribute("old-plid", String.valueOf(layout.getPlid()));
270             layoutEl.addAttribute(
271                 "layout-id", String.valueOf(layout.getLayoutId()));
272             layoutEl.addElement("parent-layout-id").addText(
273                 String.valueOf(layout.getParentLayoutId()));
274             layoutEl.addElement("name").addCDATA(layout.getName());
275             layoutEl.addElement("title").addCDATA(layout.getTitle());
276             layoutEl.addElement("description").addText(layout.getDescription());
277             layoutEl.addElement("type").addText(layout.getType());
278             layoutEl.addElement("type-settings").addCDATA(
279                 layout.getTypeSettings());
280             layoutEl.addElement("hidden").addText(
281                 String.valueOf(layout.getHidden()));
282             layoutEl.addElement("friendly-url").addText(
283                 layout.getFriendlyURL());
284             layoutEl.addElement("icon-image").addText(
285                 String.valueOf(layout.getIconImage()));
286 
287             if (layout.isIconImage()) {
288                 Image image = ImageLocalServiceUtil.getImage(
289                     layout.getIconImageId());
290 
291                 if (image != null) {
292                     String iconPath = getLayoutIconPath(context, layout, image);
293 
294                     layoutEl.addElement("icon-image-path").addText(
295                         iconPath);
296 
297                     context.addZipEntry(iconPath, image.getTextObj());
298                 }
299             }
300 
301             layoutEl.addElement("theme-id").addText(layout.getThemeId());
302             layoutEl.addElement("color-scheme-id").addText(
303                 layout.getColorSchemeId());
304             layoutEl.addElement("wap-theme-id").addText(layout.getWapThemeId());
305             layoutEl.addElement("wap-color-scheme-id").addText(
306                 layout.getWapColorSchemeId());
307             layoutEl.addElement("css").addCDATA(layout.getCss());
308             layoutEl.addElement("priority").addText(
309                 String.valueOf(layout.getPriority()));
310 
311             // Layout permissions
312 
313             if (exportPermissions) {
314                 _permissionExporter.exportLayoutPermissions(
315                     context, layoutCache, companyId, groupId, layout, layoutEl,
316                     exportUserPermissions);
317             }
318 
319             if (layout.isTypePortlet()) {
320                 LayoutTypePortlet layoutTypePortlet =
321                     (LayoutTypePortlet)layout.getLayoutType();
322 
323                 long scopeGroupId = groupId;
324 
325                 for (String portletId : layoutTypePortlet.getPortletIds()) {
326                     javax.portlet.PortletPreferences jxPreferences =
327                         PortletPreferencesFactoryUtil.getLayoutPortletSetup(
328                             layout, portletId);
329 
330                     long scopeLayoutId = GetterUtil.getLong(
331                         jxPreferences.getValue("lfr-scope-layout-id", null));
332 
333                     if (scopeLayoutId != 0) {
334                         Layout scopeLayout = LayoutLocalServiceUtil.getLayout(
335                             groupId, layout.isPrivateLayout(), scopeLayoutId);
336 
337                         Group scopeGroup = scopeLayout.getScopeGroup();
338 
339                         if (scopeGroup != null) {
340                             scopeGroupId = scopeGroup.getGroupId();
341                         }
342                     }
343 
344                     String key = PortletPermissionUtil.getPrimaryKey(
345                         layout.getPlid(), portletId);
346 
347                     portletIds.put(
348                         key,
349                         new Object[] {
350                             portletId, layout.getPlid(), scopeGroupId,
351                             scopeLayoutId
352                         }
353                     );
354                 }
355             }
356 
357             List<Portlet> portlets = getAlwaysExportablePortlets(
358                 context.getCompanyId());
359 
360             for (Portlet portlet : portlets) {
361                 String portletId = portlet.getRootPortletId();
362 
363                 if (portlet.isScopeable() && layout.hasScopeGroup()) {
364                     String key = PortletPermissionUtil.getPrimaryKey(
365                         layout.getPlid(), portletId);
366 
367                     portletIds.put(
368                         key,
369                         new Object[] {
370                             portletId, layout.getPlid(),
371                             layout.getScopeGroup().getGroupId(),
372                             layout.getLayoutId()
373                         }
374                     );
375                 }
376                 else {
377                     String key = PortletPermissionUtil.getPrimaryKey(
378                         0, portletId);
379 
380                     if (portletIds.get(key) == null) {
381                         portletIds.put(
382                             key,
383                             new Object[] {
384                                 portletId, layout.getPlid(), groupId, 0L
385                             }
386                         );
387                     }
388                 }
389             }
390 
391             String layoutPath = context.getLayoutPath(layout.getLayoutId()) +
392                 "/layout.xml";
393 
394             Element el = layoutsEl.addElement("layout");
395 
396             el.addAttribute("layout-id", String.valueOf(layout.getLayoutId()));
397             el.addAttribute("path", layoutPath);
398 
399             _portletExporter.exportPortletData(
400                 context, layoutConfigurationPortlet, layout, null, layoutEl);
401 
402             try {
403                 context.addZipEntry(layoutPath, layoutDoc.formattedString());
404             }
405             catch (IOException ioe) {
406             }
407         }
408 
409         if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM < 5) {
410             Element rolesEl = root.addElement("roles");
411 
412             // Layout roles
413 
414             if (exportPermissions) {
415                 _permissionExporter.exportLayoutRoles(
416                     layoutCache, companyId, groupId, rolesEl);
417             }
418         }
419 
420         // Export portlets
421 
422         long previousScopeGroupId = context.getScopeGroupId();
423 
424         Element portletsEl = root.addElement("portlets");
425 
426         for (Map.Entry<String, Object[]> portletIdsEntry :
427                 portletIds.entrySet()) {
428 
429             String portletId = (String)portletIdsEntry.getValue()[0];
430             long plid = (Long)portletIdsEntry.getValue()[1];
431             long scopeGroupId = (Long)portletIdsEntry.getValue()[2];
432             long scopeLayoutId = (Long)portletIdsEntry.getValue()[3];
433 
434             Layout layout = LayoutUtil.findByPrimaryKey(plid);
435 
436             context.setPlid(layout.getPlid());
437             context.setOldPlid(layout.getPlid());
438             context.setScopeGroupId(scopeGroupId);
439             context.setScopeLayoutId(scopeLayoutId);
440 
441             boolean[] exportPortletControls = getExportPortletControls(
442                 context.getCompanyId(), portletId, context, parameterMap);
443 
444             _portletExporter.exportPortlet(
445                 context, layoutCache, portletId, layout, portletsEl,
446                 defaultUserId, exportPermissions, exportPortletArchivedSetups,
447                 exportPortletControls[0], exportPortletControls[1],
448                 exportPortletUserPreferences, exportUserPermissions);
449         }
450 
451         context.setScopeGroupId(previousScopeGroupId);
452 
453         // Categories
454 
455         if (exportCategories) {
456             exportCategories(context);
457         }
458 
459         _portletExporter.exportCategories(context, root);
460 
461         // Comments
462 
463         _portletExporter.exportComments(context, root);
464 
465         // Portlet data permissions
466 
467         _permissionExporter.exportPortletDataPermissions(context);
468 
469         // Ratings
470 
471         _portletExporter.exportRatings(context, root);
472 
473         // Tags
474 
475         _portletExporter.exportTags(context, root);
476 
477         // Look and feel
478 
479         try {
480             if (exportTheme) {
481                 exportTheme(layoutSet, zipWriter);
482             }
483 
484             // Log
485 
486             if (_log.isInfoEnabled()) {
487                 _log.info(
488                     "Exporting layouts takes " + stopWatch.getTime() + " ms");
489             }
490 
491             // Zip
492 
493             context.addZipEntry("/manifest.xml", doc.formattedString());
494         }
495         catch (IOException ioe) {
496             throw new SystemException(ioe);
497         }
498 
499         return zipWriter.getFile();
500     }
501 
502     protected void exportCategories(PortletDataContext context)
503         throws SystemException {
504 
505         try {
506             Document doc = SAXReaderUtil.createDocument();
507 
508             Element root = doc.addElement("categories-hierarchy");
509 
510             List<TagsVocabulary> tagsVocabularies =
511                 TagsVocabularyLocalServiceUtil.getGroupVocabularies(
512                     context.getGroupId(),
513                     TagsEntryConstants.FOLKSONOMY_CATEGORY);
514 
515             for (TagsVocabulary tagsVocabulary : tagsVocabularies) {
516                 Element vocabularyEl = root.addElement("vocabulary");
517 
518                 String name = tagsVocabulary.getName();
519 
520                 vocabularyEl.addAttribute("name", name);
521                 vocabularyEl.addAttribute(
522                     "userUuid", tagsVocabulary.getUserUuid());
523 
524                 List<TagsEntry> tagsCategories =
525                     TagsEntryLocalServiceUtil.getGroupVocabularyEntries(
526                         context.getGroupId(), name);
527 
528                 tagsCategories = ListUtil.copy(tagsCategories);
529 
530                 orderCategories(
531                     tagsCategories, vocabularyEl,
532                     TagsEntryConstants.DEFAULT_PARENT_ENTRY_ID);
533             }
534 
535             context.addZipEntry(
536                 context.getRootPath() + "/categories-hierarchy.xml",
537                 doc.formattedString());
538         }
539         catch (Exception e) {
540             throw new SystemException(e);
541         }
542     }
543 
544     protected void exportTheme(LayoutSet layoutSet, ZipWriter zipWriter)
545         throws IOException, SystemException {
546 
547         Theme theme = layoutSet.getTheme();
548 
549         String lookAndFeelXML = ContentUtil.get(
550             "com/liferay/portal/dependencies/liferay-look-and-feel.xml.tmpl");
551 
552         lookAndFeelXML = StringUtil.replace(
553             lookAndFeelXML,
554             new String[] {
555                 "[$TEMPLATE_EXTENSION$]", "[$VIRTUAL_PATH$]"
556             },
557             new String[] {
558                 theme.getTemplateExtension(), theme.getVirtualPath()
559             }
560         );
561 
562         String servletContextName = theme.getServletContextName();
563 
564         ServletContext servletContext = VelocityContextPool.get(
565             servletContextName);
566 
567         if (servletContext == null) {
568             if (_log.isWarnEnabled()) {
569                 _log.warn(
570                     "Servlet context not found for theme " +
571                         theme.getThemeId());
572             }
573 
574             return;
575         }
576 
577         File themeZip = new File(zipWriter.getPath() + "/theme.zip");
578 
579         ZipWriter themeZipWriter = ZipWriterFactoryUtil.getZipWriter(themeZip);
580 
581         themeZipWriter.addEntry("liferay-look-and-feel.xml", lookAndFeelXML);
582 
583         File cssPath = null;
584         File imagesPath = null;
585         File javaScriptPath = null;
586         File templatesPath = null;
587 
588         if (!theme.isLoadFromServletContext()) {
589             ThemeLoader themeLoader = ThemeLoaderFactory.getThemeLoader(
590                 servletContextName);
591 
592             if (themeLoader == null) {
593                 _log.error(
594                     servletContextName + " does not map to a theme loader");
595             }
596             else {
597                 String realPath =
598                     themeLoader.getFileStorage().getPath() + StringPool.SLASH +
599                         theme.getName();
600 
601                 cssPath = new File(realPath + "/css");
602                 imagesPath = new File(realPath + "/images");
603                 javaScriptPath = new File(realPath + "/javascript");
604                 templatesPath = new File(realPath + "/templates");
605             }
606         }
607         else {
608             cssPath = new File(servletContext.getRealPath(theme.getCssPath()));
609             imagesPath = new File(
610                 servletContext.getRealPath(theme.getImagesPath()));
611             javaScriptPath = new File(
612                 servletContext.getRealPath(theme.getJavaScriptPath()));
613             templatesPath = new File(
614                 servletContext.getRealPath(theme.getTemplatesPath()));
615         }
616 
617         exportThemeFiles("css", cssPath, themeZipWriter);
618         exportThemeFiles("images", imagesPath, themeZipWriter);
619         exportThemeFiles("javascript", javaScriptPath, themeZipWriter);
620         exportThemeFiles("templates", templatesPath, themeZipWriter);
621     }
622 
623     protected void exportThemeFiles(String path, File dir, ZipWriter zipWriter)
624         throws IOException {
625 
626         if ((dir == null) || (!dir.exists())) {
627             return;
628         }
629 
630         File[] files = dir.listFiles();
631 
632         for (File file : files) {
633             if (file.isDirectory()) {
634                 exportThemeFiles(
635                     path + StringPool.SLASH + file.getName(), file, zipWriter);
636             }
637             else {
638                 zipWriter.addEntry(
639                     path + StringPool.SLASH + file.getName(),
640                     FileUtil.getBytes(file));
641             }
642         }
643     }
644 
645     protected void fixTypeSettings(Layout layout) {
646         if (!layout.isTypeURL()) {
647             return;
648         }
649 
650         UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
651 
652         String url = GetterUtil.getString(typeSettings.getProperty("url"));
653 
654         String friendlyURLPrivateGroupPath =
655             PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
656         String friendlyURLPrivateUserPath =
657             PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
658         String friendlyURLPublicPath =
659             PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
660 
661         if (!url.startsWith(friendlyURLPrivateGroupPath) &&
662             !url.startsWith(friendlyURLPrivateUserPath) &&
663             !url.startsWith(friendlyURLPublicPath)) {
664 
665             return;
666         }
667 
668         int x = url.indexOf(StringPool.SLASH, 1);
669 
670         if (x == -1) {
671             return;
672         }
673 
674         int y = url.indexOf(StringPool.SLASH, x + 1);
675 
676         if (y == -1) {
677             return;
678         }
679 
680         String friendlyURL = url.substring(x, y);
681         String groupFriendlyURL = layout.getGroup().getFriendlyURL();
682 
683         if (!friendlyURL.equals(groupFriendlyURL)) {
684             return;
685         }
686 
687         typeSettings.setProperty(
688             "url",
689             url.substring(0, x) + SAME_GROUP_FRIENDLY_URL + url.substring(y));
690     }
691 
692     protected boolean[] getExportPortletControls(
693             long companyId, String portletId, PortletDataContext context,
694             Map<String, String[]> parameterMap)
695         throws SystemException {
696 
697         boolean exportPortletData = MapUtil.getBoolean(
698             parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
699         boolean exportPortletDataAll = MapUtil.getBoolean(
700             parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);
701         boolean exportPortletSetup = MapUtil.getBoolean(
702             parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
703 
704         if (_log.isDebugEnabled()) {
705             _log.debug("Export portlet data " + exportPortletData);
706             _log.debug("Export all portlet data " + exportPortletDataAll);
707             _log.debug("Export portlet setup " + exportPortletSetup);
708         }
709 
710         boolean exportCurPortletData = exportPortletData;
711         boolean exportCurPortletSetup = exportPortletSetup;
712 
713         // If PORTLET_DATA_ALL is true, this means that staging has just been
714         // activated and all data and setup must be exported. There is no
715         // portlet export control to check in this case.
716 
717         if (exportPortletDataAll) {
718             exportCurPortletData = true;
719             exportCurPortletSetup = true;
720         }
721         else {
722             Portlet portlet = PortletLocalServiceUtil.getPortletById(
723                 companyId, portletId);
724 
725             if (portlet != null) {
726                 String portletDataHandlerClass =
727                     portlet.getPortletDataHandlerClass();
728 
729                 // Checking if the portlet has a data handler, if it doesn't,
730                 // the default values are the ones set in PORTLET_DATA and
731                 // PORTLET_SETUP. If it has a data handler, iterate over each
732                 // portlet export control.
733 
734                 if (portletDataHandlerClass != null) {
735                     String rootPortletId = PortletConstants.getRootPortletId(
736                         portletId);
737 
738                     // PORTLET_DATA and the PORTLET_DATA for this specific
739                     // data handler must be true
740 
741                     exportCurPortletData =
742                         exportPortletData &&
743                         MapUtil.getBoolean(
744                             parameterMap,
745                             PortletDataHandlerKeys.PORTLET_DATA +
746                                 StringPool.UNDERLINE + rootPortletId);
747 
748                     // PORTLET_DATA and the PORTLET_SETUP for this specific
749                     // data handler must be true
750 
751                     exportCurPortletSetup =
752                         exportPortletData &&
753                         MapUtil.getBoolean(
754                             parameterMap,
755                             PortletDataHandlerKeys.PORTLET_SETUP +
756                                 StringPool.UNDERLINE + rootPortletId);
757                 }
758             }
759         }
760 
761         return new boolean[] {exportCurPortletData, exportCurPortletSetup};
762     }
763 
764     protected String getLayoutIconPath(
765         PortletDataContext context, Layout layout, Image image) {
766 
767         StringBundler sb = new StringBundler(5);
768 
769         sb.append(context.getLayoutPath(layout.getLayoutId()));
770         sb.append("/icons/");
771         sb.append(image.getImageId());
772         sb.append(StringPool.PERIOD);
773         sb.append(image.getType());
774 
775         return sb.toString();
776     }
777 
778     protected void orderCategories(
779             List<TagsEntry> tagsCategories, Element parentEl,
780             long parentEntryId)
781         throws PortalException, SystemException {
782 
783         List<TagsEntry> tagsParentCategories = new ArrayList<TagsEntry>();
784 
785         Iterator<TagsEntry> itr = tagsCategories.iterator();
786 
787         while (itr.hasNext()) {
788             TagsEntry tagsCategory = itr.next();
789 
790             if (tagsCategory.getParentEntryId() == parentEntryId) {
791                 Element categoryEl = parentEl.addElement("category");
792 
793                 categoryEl.addAttribute("name", tagsCategory.getName());
794                 categoryEl.addAttribute(
795                     "parentEntryName", tagsCategory.getParentName());
796                 categoryEl.addAttribute("userUuid", tagsCategory.getUserUuid());
797 
798                 tagsParentCategories.add(tagsCategory);
799 
800                 itr.remove();
801             }
802         }
803 
804         for (TagsEntry tagsParentCategory : tagsParentCategories) {
805             orderCategories(
806                 tagsCategories, parentEl, tagsParentCategory.getEntryId());
807         }
808     }
809 
810     private static Log _log = LogFactoryUtil.getLog(LayoutExporter.class);
811 
812     private PermissionExporter _permissionExporter = new PermissionExporter();
813     private PortletExporter _portletExporter = new PortletExporter();
814 
815 }