1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.lar;
16  
17  import com.liferay.portal.LayoutImportException;
18  import com.liferay.portal.NoSuchPortletPreferencesException;
19  import com.liferay.portal.kernel.exception.PortalException;
20  import com.liferay.portal.kernel.exception.SystemException;
21  import com.liferay.portal.kernel.log.Log;
22  import com.liferay.portal.kernel.log.LogFactoryUtil;
23  import com.liferay.portal.kernel.util.CharPool;
24  import com.liferay.portal.kernel.util.FileUtil;
25  import com.liferay.portal.kernel.util.GetterUtil;
26  import com.liferay.portal.kernel.util.MapUtil;
27  import com.liferay.portal.kernel.util.ReleaseInfo;
28  import com.liferay.portal.kernel.util.StringBundler;
29  import com.liferay.portal.kernel.util.StringPool;
30  import com.liferay.portal.kernel.util.StringUtil;
31  import com.liferay.portal.kernel.util.Time;
32  import com.liferay.portal.kernel.util.Validator;
33  import com.liferay.portal.kernel.xml.Document;
34  import com.liferay.portal.kernel.xml.Element;
35  import com.liferay.portal.kernel.xml.SAXReaderUtil;
36  import com.liferay.portal.kernel.zip.ZipWriter;
37  import com.liferay.portal.kernel.zip.ZipWriterFactoryUtil;
38  import com.liferay.portal.model.Group;
39  import com.liferay.portal.model.GroupConstants;
40  import com.liferay.portal.model.Layout;
41  import com.liferay.portal.model.LayoutConstants;
42  import com.liferay.portal.model.LayoutTypePortlet;
43  import com.liferay.portal.model.Permission;
44  import com.liferay.portal.model.Portlet;
45  import com.liferay.portal.model.PortletConstants;
46  import com.liferay.portal.model.PortletItem;
47  import com.liferay.portal.model.PortletPreferences;
48  import com.liferay.portal.model.Resource;
49  import com.liferay.portal.model.ResourceConstants;
50  import com.liferay.portal.model.Role;
51  import com.liferay.portal.model.RoleConstants;
52  import com.liferay.portal.model.User;
53  import com.liferay.portal.security.permission.ResourceActionsUtil;
54  import com.liferay.portal.service.GroupLocalServiceUtil;
55  import com.liferay.portal.service.LayoutLocalServiceUtil;
56  import com.liferay.portal.service.PermissionLocalServiceUtil;
57  import com.liferay.portal.service.PortletItemLocalServiceUtil;
58  import com.liferay.portal.service.PortletLocalServiceUtil;
59  import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
60  import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
61  import com.liferay.portal.service.RoleLocalServiceUtil;
62  import com.liferay.portal.service.UserLocalServiceUtil;
63  import com.liferay.portal.service.permission.PortletPermissionUtil;
64  import com.liferay.portal.util.PortalUtil;
65  import com.liferay.portal.util.PortletKeys;
66  import com.liferay.portal.util.PropsValues;
67  import com.liferay.portlet.PortletPreferencesFactoryUtil;
68  import com.liferay.portlet.messageboards.model.MBMessage;
69  import com.liferay.portlet.ratings.model.RatingsEntry;
70  
71  import java.io.File;
72  import java.io.IOException;
73  
74  import java.util.Date;
75  import java.util.HashSet;
76  import java.util.Iterator;
77  import java.util.List;
78  import java.util.Map;
79  
80  import org.apache.commons.lang.time.StopWatch;
81  
82  /**
83   * <a href="PortletExporter.java.html"><b><i>View Source</i></b></a>
84   *
85   * @author Brian Wing Shun Chan
86   * @author Joel Kozikowski
87   * @author Charles May
88   * @author Raymond Augé
89   * @author Jorge Ferrer
90   * @author Bruno Farache
91   */
92  public class PortletExporter {
93  
94      public byte[] exportPortletInfo(
95              long plid, long groupId, String portletId,
96              Map<String, String[]> parameterMap, Date startDate, Date endDate)
97          throws PortalException, SystemException {
98  
99          File file = exportPortletInfoAsFile(
100             plid, groupId, portletId, parameterMap, startDate, endDate);
101 
102         try {
103             return FileUtil.getBytes(file);
104         }
105         catch (IOException ioe) {
106             throw new SystemException(ioe);
107         }
108         finally {
109             file.delete();
110         }
111     }
112 
113     public File exportPortletInfoAsFile(
114             long plid, long groupId, String portletId,
115             Map<String, String[]> parameterMap, Date startDate, Date endDate)
116         throws PortalException, SystemException {
117 
118         boolean exportPermissions = MapUtil.getBoolean(
119             parameterMap, PortletDataHandlerKeys.PERMISSIONS);
120         boolean exportPortletArchivedSetups = MapUtil.getBoolean(
121             parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
122         boolean exportPortletData = MapUtil.getBoolean(
123             parameterMap, PortletDataHandlerKeys.PORTLET_DATA + "_" +
124             PortletConstants.getRootPortletId(portletId));
125         boolean exportPortletDataAll = MapUtil.getBoolean(
126             parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);
127         boolean exportPortletSetup = MapUtil.getBoolean(
128             parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
129         boolean exportPortletUserPreferences = MapUtil.getBoolean(
130             parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
131         boolean exportUserPermissions = MapUtil.getBoolean(
132             parameterMap, PortletDataHandlerKeys.USER_PERMISSIONS);
133 
134         if (_log.isDebugEnabled()) {
135             _log.debug("Export permissions " + exportPermissions);
136             _log.debug(
137                 "Export portlet archived setups " +
138                     exportPortletArchivedSetups);
139             _log.debug("Export portlet data " + exportPortletData);
140             _log.debug("Export all portlet data " + exportPortletDataAll);
141             _log.debug("Export portlet setup " + exportPortletSetup);
142             _log.debug(
143                 "Export portlet user preferences " +
144                     exportPortletUserPreferences);
145             _log.debug("Export user permissions " + exportUserPermissions);
146         }
147 
148         if (exportPortletDataAll) {
149             exportPortletData = true;
150         }
151 
152         StopWatch stopWatch = null;
153 
154         if (_log.isInfoEnabled()) {
155             stopWatch = new StopWatch();
156 
157             stopWatch.start();
158         }
159 
160         LayoutCache layoutCache = new LayoutCache();
161 
162         Layout layout = LayoutLocalServiceUtil.getLayout(plid);
163 
164         String type = layout.getType();
165 
166         if (!type.equals(LayoutConstants.TYPE_CONTROL_PANEL) &&
167             !type.equals(LayoutConstants.TYPE_PANEL) &&
168             !type.equals(LayoutConstants.TYPE_PORTLET)) {
169 
170             throw new LayoutImportException(
171                 "Layout type " + type + " is not valid");
172         }
173 
174         long companyId = layout.getCompanyId();
175         long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
176 
177         ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();
178 
179         long scopeGroupId = groupId;
180 
181         javax.portlet.PortletPreferences jxPreferences =
182             PortletPreferencesFactoryUtil.getLayoutPortletSetup(
183                 layout, portletId);
184 
185         long scopeLayoutId = GetterUtil.getLong(
186             jxPreferences.getValue("lfr-scope-layout-id", null));
187 
188         if (scopeLayoutId != 0) {
189             Group scopeGroup = layout.getScopeGroup();
190 
191             if (scopeGroup != null) {
192                 scopeGroupId = scopeGroup.getGroupId();
193             }
194         }
195 
196         PortletDataContext context = new PortletDataContextImpl(
197             companyId, scopeGroupId, parameterMap, new HashSet<String>(),
198             startDate, endDate, zipWriter);
199 
200         context.setPlid(plid);
201         context.setOldPlid(plid);
202         context.setScopeLayoutId(scopeLayoutId);
203 
204         // Build compatibility
205 
206         Document doc = SAXReaderUtil.createDocument();
207 
208         Element root = doc.addElement("root");
209 
210         Element header = root.addElement("header");
211 
212         header.addAttribute(
213             "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
214         header.addAttribute("export-date", Time.getRFC822());
215 
216         if (context.hasDateRange()) {
217             header.addAttribute(
218                 "start-date", String.valueOf(context.getStartDate()));
219             header.addAttribute(
220                 "end-date", String.valueOf(context.getEndDate()));
221         }
222 
223         header.addAttribute("type", "portlet");
224         header.addAttribute("group-id", String.valueOf(scopeGroupId));
225         header.addAttribute(
226             "private-layout", String.valueOf(layout.isPrivateLayout()));
227         header.addAttribute(
228             "root-portlet-id", PortletConstants.getRootPortletId(portletId));
229 
230         // Portlet
231 
232         exportPortlet(
233             context, layoutCache, portletId, layout, root, defaultUserId,
234             exportPermissions, exportPortletArchivedSetups, exportPortletData,
235             exportPortletSetup, exportPortletUserPreferences,
236             exportUserPermissions);
237 
238         // Categories
239 
240         exportCategories(context, root);
241 
242         // Comments
243 
244         exportComments(context, root);
245 
246         // Ratings
247 
248         exportRatings(context, root);
249 
250         // Tags
251 
252         exportTags(context, root);
253 
254         // Log
255 
256         if (_log.isInfoEnabled()) {
257             _log.info("Exporting portlet took " + stopWatch.getTime() + " ms");
258         }
259 
260         // Zip
261 
262         try {
263             context.addZipEntry("/manifest.xml", doc.formattedString());
264         }
265         catch (IOException ioe) {
266             throw new SystemException(ioe);
267         }
268 
269         return zipWriter.getFile();
270     }
271 
272     protected void exportCategories(
273             PortletDataContext context, Element parentEl)
274         throws SystemException {
275 
276         try {
277             Document doc = SAXReaderUtil.createDocument();
278 
279             Element root = doc.addElement("categories");
280 
281             Map<String, String[]> assetCategoryIdsMap =
282                 context.getAssetCategoryUuidsMap();
283 
284             for (Map.Entry<String, String[]> entry :
285                     assetCategoryIdsMap.entrySet()) {
286 
287                 String[] categoryEntry = entry.getKey().split(StringPool.POUND);
288 
289                 Element asset = root.addElement("asset");
290 
291                 asset.addAttribute("class-name", categoryEntry[0]);
292                 asset.addAttribute("class-pk", categoryEntry[1]);
293                 asset.addAttribute(
294                     "category-uuids", StringUtil.merge(entry.getValue()));
295             }
296 
297             context.addZipEntry(
298                 context.getRootPath() + "/categories.xml",
299                 doc.formattedString());
300         }
301         catch (Exception e) {
302             throw new SystemException(e);
303         }
304     }
305 
306     protected void exportComments(PortletDataContext context, Element parentEl)
307         throws SystemException {
308 
309         try {
310             Document doc = SAXReaderUtil.createDocument();
311 
312             Element root = doc.addElement("comments");
313 
314             Map<String, List<MBMessage>> commentsMap = context.getComments();
315 
316             for (Map.Entry<String, List<MBMessage>> entry :
317                     commentsMap.entrySet()) {
318 
319                 String[] comment = entry.getKey().split(StringPool.POUND);
320 
321                 String path = getCommentsPath(context, comment[0], comment[1]);
322 
323                 Element asset = root.addElement("asset");
324 
325                 asset.addAttribute("path", path);
326                 asset.addAttribute("class-name", comment[0]);
327                 asset.addAttribute("class-pk", comment[1]);
328 
329                 List<MBMessage> messages = entry.getValue();
330 
331                 for (MBMessage message : messages) {
332                     path = getCommentsPath(
333                         context, comment[0], comment[1], message);
334 
335                     if (context.isPathNotProcessed(path)) {
336                         context.addZipEntry(path, message);
337                     }
338                 }
339             }
340 
341             context.addZipEntry(
342                 context.getRootPath() + "/comments.xml", doc.formattedString());
343         }
344         catch (IOException ioe) {
345             throw new SystemException(ioe);
346         }
347     }
348 
349     protected Element exportGroupPermissions(
350             long companyId, long groupId, String resourceName,
351             String resourcePrimKey, Element parentEl, String elName)
352         throws SystemException {
353 
354         Element el = parentEl.addElement(elName);
355 
356         List<Permission> permissions =
357             PermissionLocalServiceUtil.getGroupPermissions(
358                 groupId, companyId, resourceName,
359                 ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey);
360 
361         List<String> actions = ResourceActionsUtil.getActions(permissions);
362 
363         for (int i = 0; i < actions.size(); i++) {
364             String action = actions.get(i);
365 
366             Element actionKeyEl = el.addElement("action-key");
367 
368             actionKeyEl.addText(action);
369         }
370 
371         return el;
372     }
373 
374     protected void exportGroupRoles(
375             LayoutCache layoutCache, long companyId, long groupId,
376             String resourceName, String entityName, Element parentEl)
377         throws SystemException {
378 
379         List<Role> roles = layoutCache.getGroupRoles_4(groupId);
380 
381         Element groupEl = exportRoles(
382             companyId, resourceName, ResourceConstants.SCOPE_GROUP,
383             String.valueOf(groupId), parentEl, entityName + "-roles", roles);
384 
385         if (groupEl.elements().isEmpty()) {
386             parentEl.remove(groupEl);
387         }
388     }
389 
390     protected void exportInheritedPermissions(
391             LayoutCache layoutCache, long companyId, String resourceName,
392             String resourcePrimKey, Element parentEl, String entityName)
393         throws SystemException {
394 
395         Element entityPermissionsEl = SAXReaderUtil.createElement(
396             entityName + "-permissions");
397 
398         Map<String, Long> entityMap = layoutCache.getEntityMap(
399             companyId, entityName);
400 
401         Iterator<Map.Entry<String, Long>> itr = entityMap.entrySet().iterator();
402 
403         while (itr.hasNext()) {
404             Map.Entry<String, Long> entry = itr.next();
405 
406             String name = entry.getKey().toString();
407 
408             long entityGroupId = entry.getValue();
409 
410             Element entityEl = exportGroupPermissions(
411                 companyId, entityGroupId, resourceName, resourcePrimKey,
412                 entityPermissionsEl, entityName + "-actions");
413 
414             if (entityEl.elements().isEmpty()) {
415                 entityPermissionsEl.remove(entityEl);
416             }
417             else {
418                 entityEl.addAttribute("name", name);
419             }
420         }
421 
422         if (!entityPermissionsEl.elements().isEmpty()) {
423             parentEl.add(entityPermissionsEl);
424         }
425     }
426 
427     protected void exportInheritedRoles(
428             LayoutCache layoutCache, long companyId, long groupId,
429             String resourceName, String entityName, Element parentEl)
430         throws SystemException {
431 
432         Element entityRolesEl = SAXReaderUtil.createElement(
433             entityName + "-roles");
434 
435         Map<String, Long> entityMap = layoutCache.getEntityMap(
436             companyId, entityName);
437 
438         Iterator<Map.Entry<String, Long>> itr = entityMap.entrySet().iterator();
439 
440         while (itr.hasNext()) {
441             Map.Entry<String, Long> entry = itr.next();
442 
443             String name = entry.getKey().toString();
444 
445             long entityGroupId = entry.getValue();
446 
447             List<Role> entityRoles = layoutCache.getGroupRoles_4(entityGroupId);
448 
449             Element entityEl = exportRoles(
450                 companyId, resourceName, ResourceConstants.SCOPE_GROUP,
451                 String.valueOf(groupId), entityRolesEl, entityName,
452                 entityRoles);
453 
454             if (entityEl.elements().isEmpty()) {
455                 entityRolesEl.remove(entityEl);
456             }
457             else {
458                 entityEl.addAttribute("name", name);
459             }
460         }
461 
462         if (!entityRolesEl.elements().isEmpty()) {
463             parentEl.add(entityRolesEl);
464         }
465     }
466 
467     protected void exportPermissions_5(
468             LayoutCache layoutCache, long groupId, String resourceName,
469             long resourceId, Element permissionsEl)
470         throws PortalException, SystemException {
471 
472         List<Role> roles = layoutCache.getGroupRoles_5(groupId, resourceName);
473 
474         for (Role role : roles) {
475             if (role.getName().equals(RoleConstants.ADMINISTRATOR)) {
476                 continue;
477             }
478 
479             Element roleEl = permissionsEl.addElement("role");
480 
481             roleEl.addAttribute("name", role.getName());
482             roleEl.addAttribute("description", role.getDescription());
483             roleEl.addAttribute("type", String.valueOf(role.getType()));
484 
485             List<Permission> permissions =
486                 PermissionLocalServiceUtil.getRolePermissions(
487                     role.getRoleId(), resourceId);
488 
489             List<String> actions = ResourceActionsUtil.getActions(permissions);
490 
491             for (String action : actions) {
492                 Element actionKeyEl = roleEl.addElement("action-key");
493 
494                 actionKeyEl.addText(action);
495             }
496         }
497     }
498 
499     protected void exportPermissions_6(
500             LayoutCache layoutCache, long companyId, long groupId,
501             String resourceName, String resourcePrimKey, Element permissionsEl,
502             boolean portletActions)
503         throws PortalException, SystemException {
504 
505         List<Role> roles = layoutCache.getGroupRoles_5(groupId, resourceName);
506 
507         for (Role role : roles) {
508             if (role.getName().equals(RoleConstants.ADMINISTRATOR)) {
509                 continue;
510             }
511 
512             Element roleEl = permissionsEl.addElement("role");
513 
514             roleEl.addAttribute("name", role.getName());
515             roleEl.addAttribute("description", role.getDescription());
516             roleEl.addAttribute("type", String.valueOf(role.getType()));
517 
518             List<String> actionIds = null;
519 
520             if (portletActions) {
521                 actionIds = ResourceActionsUtil.getPortletResourceActions(
522                     resourceName);
523             }
524             else {
525                 actionIds = ResourceActionsUtil.getModelResourceActions(
526                     resourceName);
527             }
528 
529             List<String> actions =
530                 ResourcePermissionLocalServiceUtil.
531                     getAvailableResourcePermissionActionIds(
532                         companyId, resourceName,
533                         ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
534                         role.getRoleId(), actionIds);
535 
536             for (String action : actions) {
537                 Element actionKeyEl = roleEl.addElement("action-key");
538 
539                 actionKeyEl.addText(action);
540             }
541         }
542     }
543 
544     protected void exportPortlet(
545             PortletDataContext context, LayoutCache layoutCache,
546             String portletId, Layout layout, Element parentEl,
547             long defaultUserId, boolean exportPermissions,
548             boolean exportPortletArchivedSetups, boolean exportPortletData,
549             boolean exportPortletSetup, boolean exportPortletUserPreferences,
550             boolean exportUserPermissions)
551         throws PortalException, SystemException {
552 
553         long companyId = context.getCompanyId();
554         long groupId = context.getGroupId();
555 
556         Portlet portlet = PortletLocalServiceUtil.getPortletById(
557             context.getCompanyId(), portletId);
558 
559         if (portlet == null) {
560             if (_log.isDebugEnabled()) {
561                 _log.debug(
562                     "Do not export portlet " + portletId +
563                         " because the portlet does not exist");
564             }
565 
566             return;
567         }
568 
569         if ((!portlet.isInstanceable()) &&
570             (!portlet.isPreferencesUniquePerLayout()) &&
571             (context.hasNotUniquePerLayout(portletId))) {
572 
573             return;
574         }
575 
576         Document doc = SAXReaderUtil.createDocument();
577 
578         Element portletEl = doc.addElement("portlet");
579 
580         portletEl.addAttribute("portlet-id", portletId);
581         portletEl.addAttribute(
582             "root-portlet-id", PortletConstants.getRootPortletId(portletId));
583         portletEl.addAttribute("old-plid", String.valueOf(layout.getPlid()));
584         portletEl.addAttribute(
585             "scope-layout-id", String.valueOf(context.getScopeLayoutId()));
586 
587         // Data
588 
589         javax.portlet.PortletPreferences jxPreferences =
590             PortletPreferencesFactoryUtil.getPortletSetup(
591                 layout, portletId, StringPool.BLANK);
592 
593         if (exportPortletData) {
594             if (!portlet.isPreferencesUniquePerLayout()) {
595                 String dataKey =
596                     portletId + StringPool.AT + context.getScopeLayoutId();
597 
598                 if (!context.hasNotUniquePerLayout(dataKey)) {
599                     context.putNotUniquePerLayout(dataKey);
600 
601                     exportPortletData(
602                         context, portlet, layout, jxPreferences, portletEl);
603                 }
604             }
605             else {
606                 exportPortletData(
607                     context, portlet, layout, jxPreferences, portletEl);
608             }
609         }
610 
611         // Portlet preferences
612 
613         if (exportPortletSetup) {
614             exportPortletPreferences(
615                 context, PortletKeys.PREFS_OWNER_ID_DEFAULT,
616                 PortletKeys.PREFS_OWNER_TYPE_LAYOUT, false, layout, portletId,
617                 portletEl);
618 
619             exportPortletPreferences(
620                 context, groupId, PortletKeys.PREFS_OWNER_TYPE_GROUP, false,
621                 layout, portletId, portletEl);
622 
623             exportPortletPreferences(
624                 context, companyId, PortletKeys.PREFS_OWNER_TYPE_COMPANY, false,
625                 layout, portletId, portletEl);
626         }
627 
628         // Portlet preferences
629 
630         if (exportPortletUserPreferences) {
631             exportPortletPreferences(
632                 context, defaultUserId, PortletKeys.PREFS_OWNER_TYPE_USER,
633                 true, layout, portletId, portletEl);
634 
635             try {
636                 PortletPreferences groupPortletPreferences =
637                     PortletPreferencesLocalServiceUtil.getPortletPreferences(
638                         groupId, PortletKeys.PREFS_OWNER_TYPE_GROUP,
639                         PortletKeys.PREFS_PLID_SHARED, portletId);
640 
641                 exportPortletPreference(
642                     context, groupId, PortletKeys.PREFS_OWNER_TYPE_GROUP, false,
643                     groupPortletPreferences, portletId,
644                     PortletKeys.PREFS_PLID_SHARED, portletEl);
645             }
646             catch (NoSuchPortletPreferencesException nsppe) {
647             }
648         }
649 
650         // Archived setups
651 
652         if (exportPortletArchivedSetups) {
653             String rootPortletId = PortletConstants.getRootPortletId(portletId);
654 
655             List<PortletItem> portletItems =
656                 PortletItemLocalServiceUtil.getPortletItems(
657                     groupId, rootPortletId, PortletPreferences.class.getName());
658 
659             for (PortletItem portletItem: portletItems) {
660                 long ownerId = portletItem.getPortletItemId();
661                 int ownerType = PortletKeys.PREFS_OWNER_TYPE_ARCHIVED;
662 
663                 exportPortletPreferences(
664                     context, ownerId, ownerType, false, null,
665                     portletItem.getPortletId(), portletEl);
666             }
667         }
668 
669         Group guestGroup = GroupLocalServiceUtil.getGroup(
670             companyId, GroupConstants.GUEST);
671 
672         // Permissions
673 
674         if (exportPermissions) {
675             Element permissionsEl = portletEl.addElement("permissions");
676 
677             String resourceName = PortletConstants.getRootPortletId(portletId);
678             String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
679                 layout.getPlid(), portletId);
680 
681             if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
682                 exportPortletPermissions_5(
683                     layoutCache, companyId, groupId, resourceName,
684                     resourcePrimKey, permissionsEl);
685             }
686             else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
687                 exportPortletPermissions_6(
688                     layoutCache, companyId, groupId, resourceName,
689                     resourcePrimKey, permissionsEl);
690             }
691             else {
692                 exportPortletPermissions_4(
693                     layoutCache, companyId, groupId, guestGroup, resourceName,
694                     resourcePrimKey, permissionsEl, exportUserPermissions);
695 
696                 Element rolesEl = portletEl.addElement("roles");
697 
698                 exportPortletRoles(
699                     layoutCache, companyId, groupId, portletId, rolesEl);
700             }
701         }
702 
703         // Zip
704 
705         StringBundler sb = new StringBundler(4);
706 
707         sb.append(context.getPortletPath(portletId));
708         sb.append(StringPool.SLASH);
709         sb.append(layout.getPlid());
710         sb.append("/portlet.xml");
711 
712         String path = sb.toString();
713 
714         Element el = parentEl.addElement("portlet");
715 
716         el.addAttribute("portlet-id", portletId);
717         el.addAttribute("layout-id", String.valueOf(layout.getLayoutId()));
718         el.addAttribute("path", path);
719 
720         if (context.isPathNotProcessed(path)) {
721             try {
722                 context.addZipEntry(path, doc.formattedString());
723             }
724             catch (IOException ioe) {
725                 if (_log.isWarnEnabled()) {
726                     _log.warn(ioe.getMessage());
727                 }
728             }
729 
730             context.addPrimaryKey(String.class, path);
731         }
732     }
733 
734     protected void exportPortletData(
735             PortletDataContext context, Portlet portlet, Layout layout,
736             javax.portlet.PortletPreferences portletPreferences,
737             Element parentEl)
738         throws SystemException {
739 
740         PortletDataHandler portletDataHandler =
741             portlet.getPortletDataHandlerInstance();
742 
743         if (portletDataHandler == null) {
744             return;
745         }
746 
747         String portletId = portlet.getPortletId();
748 
749         if (_log.isDebugEnabled()) {
750             _log.debug("Exporting data for " + portletId);
751         }
752 
753         String data = null;
754 
755         long groupId = context.getGroupId();
756 
757         context.setGroupId(context.getScopeGroupId());
758 
759         try {
760             data = portletDataHandler.exportData(
761                 context, portletId, portletPreferences);
762         }
763         catch (Exception e) {
764             throw new SystemException(e);
765         }
766         finally {
767             context.setGroupId(groupId);
768         }
769 
770         if (Validator.isNull(data)) {
771             if (_log.isDebugEnabled()) {
772                 _log.debug(
773                     "Not exporting data for " + portletId +
774                         " because null data was returned");
775             }
776 
777             return;
778         }
779 
780         StringBundler sb = new StringBundler(4);
781 
782         sb.append(context.getPortletPath(portletId));
783 
784         if (portlet.isPreferencesUniquePerLayout()) {
785             sb.append(StringPool.SLASH);
786             sb.append(layout.getPlid());
787         }
788 
789         sb.append("/portlet-data.xml");
790 
791         Element portletDataEl = parentEl.addElement("portlet-data");
792 
793         portletDataEl.addAttribute("path", sb.toString());
794 
795         context.addZipEntry(sb.toString(), data);
796     }
797 
798     protected void exportPortletPermissions_4(
799             LayoutCache layoutCache, long companyId, long groupId,
800             Group guestGroup, String resourceName, String resourcePrimKey,
801             Element permissionsEl, boolean exportUserPermissions)
802         throws SystemException {
803 
804         exportGroupPermissions(
805             companyId, groupId, resourceName, resourcePrimKey, permissionsEl,
806             "community-actions");
807 
808         if (groupId != guestGroup.getGroupId()) {
809             exportGroupPermissions(
810                 companyId, guestGroup.getGroupId(), resourceName,
811                 resourcePrimKey, permissionsEl, "guest-actions");
812         }
813 
814         if (exportUserPermissions) {
815             exportUserPermissions(
816                 layoutCache, companyId, groupId, resourceName, resourcePrimKey,
817                 permissionsEl);
818         }
819 
820         exportInheritedPermissions(
821             layoutCache, companyId, resourceName, resourcePrimKey,
822             permissionsEl, "organization");
823 
824         exportInheritedPermissions(
825             layoutCache, companyId, resourceName, resourcePrimKey,
826             permissionsEl, "user-group");
827     }
828 
829     protected void exportPortletPermissions_5(
830             LayoutCache layoutCache, long companyId, long groupId,
831             String resourceName, String resourcePrimKey, Element permissionsEl)
832         throws PortalException, SystemException {
833 
834         boolean portletActions = true;
835 
836         Resource resource = layoutCache.getResource(
837             companyId, groupId, resourceName,
838             ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
839             portletActions);
840 
841         exportPermissions_5(
842             layoutCache, groupId, resourceName, resource.getResourceId(),
843             permissionsEl);
844     }
845 
846     protected void exportPortletPermissions_6(
847             LayoutCache layoutCache, long companyId, long groupId,
848             String resourceName, String resourcePrimKey, Element permissionsEl)
849         throws PortalException, SystemException {
850 
851         boolean portletActions = true;
852 
853         exportPermissions_6(
854             layoutCache, companyId, groupId, resourceName, resourcePrimKey,
855             permissionsEl, portletActions);
856     }
857 
858     protected void exportPortletPreference(
859             PortletDataContext context, long ownerId, int ownerType,
860             boolean defaultUser, PortletPreferences portletPreferences,
861             String portletId, long plid, Element parentEl)
862         throws SystemException {
863 
864         try {
865             Document preferencesDoc = SAXReaderUtil.read(
866                 portletPreferences.getPreferences());
867 
868             Element root = preferencesDoc.getRootElement();
869 
870             root.addAttribute("owner-id", String.valueOf(ownerId));
871             root.addAttribute("owner-type", String.valueOf(ownerType));
872             root.addAttribute("default-user", String.valueOf(defaultUser));
873             root.addAttribute("plid", String.valueOf(plid));
874             root.addAttribute("portlet-id", portletId);
875 
876             if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
877                 PortletItem portletItem =
878                     PortletItemLocalServiceUtil.getPortletItem(ownerId);
879 
880                 User user = UserLocalServiceUtil.getUserById(
881                     portletItem.getUserId());
882 
883                 root.addAttribute("archive-user-uuid", user.getUuid());
884                 root.addAttribute("archive-name", portletItem.getName());
885             }
886 
887             String path = getPortletPreferencesPath(
888                 context, portletId, ownerId, ownerType, plid);
889 
890             parentEl.addElement(
891                 "portlet-preferences").addAttribute("path", path);
892 
893             if (context.isPathNotProcessed(path)) {
894                 context.addZipEntry(path, preferencesDoc.formattedString());
895             }
896         }
897         catch (Exception e) {
898             throw new SystemException(e);
899         }
900     }
901 
902     protected void exportPortletPreferences(
903             PortletDataContext context, long ownerId, int ownerType,
904             boolean defaultUser, Layout layout, String portletId,
905             Element parentEl)
906         throws PortalException, SystemException {
907 
908         PortletPreferences portletPreferences = null;
909 
910         long plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
911 
912         if (layout != null) {
913             plid = layout.getPlid();
914         }
915 
916         if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) ||
917             (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) ||
918             (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED)) {
919 
920             plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
921         }
922 
923         try {
924             portletPreferences =
925                 PortletPreferencesLocalServiceUtil.getPortletPreferences(
926                     ownerId, ownerType, plid, portletId);
927 
928             LayoutTypePortlet layoutTypePortlet = null;
929 
930             if (layout != null) {
931                 layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
932             }
933 
934             if ((layoutTypePortlet == null) ||
935                 (layoutTypePortlet.hasPortletId(portletId))) {
936 
937                 exportPortletPreference(
938                     context, ownerId, ownerType, defaultUser,
939                     portletPreferences, portletId, plid, parentEl);
940             }
941         }
942         catch (NoSuchPortletPreferencesException nsppe) {
943         }
944     }
945 
946     protected void exportPortletRoles(
947             LayoutCache layoutCache, long companyId, long groupId,
948             String portletId, Element rolesEl)
949         throws SystemException {
950 
951         String resourceName = PortletConstants.getRootPortletId(
952             portletId);
953 
954         Element portletEl = rolesEl.addElement("portlet");
955 
956         portletEl.addAttribute("portlet-id", portletId);
957 
958         exportGroupRoles(
959             layoutCache, companyId, groupId, resourceName, "community",
960             portletEl);
961 
962         exportUserRoles(
963             layoutCache, companyId, groupId, resourceName, portletEl);
964 
965         exportInheritedRoles(
966             layoutCache, companyId, groupId, resourceName, "organization",
967             portletEl);
968 
969         exportInheritedRoles(
970             layoutCache, companyId, groupId, resourceName, "user-group",
971             portletEl);
972 
973         if (portletEl.elements().isEmpty()) {
974             rolesEl.remove(portletEl);
975         }
976     }
977 
978     protected void exportRatings(PortletDataContext context, Element parentEl)
979         throws SystemException {
980 
981         try {
982             Document doc = SAXReaderUtil.createDocument();
983 
984             Element root = doc.addElement("ratings");
985 
986             Map<String, List<RatingsEntry>> ratingsEntriesMap =
987                 context.getRatingsEntries();
988 
989             for (Map.Entry<String, List<RatingsEntry>> entry :
990                     ratingsEntriesMap.entrySet()) {
991 
992                 String[] ratingsEntry = entry.getKey().split(StringPool.POUND);
993 
994                 String ratingPath = getRatingsPath(
995                     context, ratingsEntry[0], ratingsEntry[1]);
996 
997                 Element asset = root.addElement("asset");
998 
999                 asset.addAttribute("path", ratingPath);
1000                asset.addAttribute("class-name", ratingsEntry[0]);
1001                asset.addAttribute("class-pk", ratingsEntry[1]);
1002
1003                List<RatingsEntry> ratingsEntries = entry.getValue();
1004
1005                for (RatingsEntry rating : ratingsEntries) {
1006                    ratingPath = getRatingsPath(
1007                        context, ratingsEntry[0], ratingsEntry[1], rating);
1008
1009                    context.addZipEntry(ratingPath, rating);
1010                }
1011            }
1012
1013            context.addZipEntry(
1014                context.getRootPath() + "/ratings.xml", doc.formattedString());
1015        }
1016        catch (Exception e) {
1017            throw new SystemException(e);
1018        }
1019    }
1020
1021    protected Element exportRoles(
1022            long companyId, String resourceName, int scope,
1023            String resourcePrimKey, Element parentEl, String elName,
1024            List<Role> roles)
1025        throws SystemException {
1026
1027        Element el = parentEl.addElement(elName);
1028
1029        Map<String, List<String>> resourceRoles =
1030            RoleLocalServiceUtil.getResourceRoles(
1031                companyId, resourceName, scope, resourcePrimKey);
1032
1033        Iterator<Map.Entry<String, List<String>>> itr =
1034            resourceRoles.entrySet().iterator();
1035
1036        while (itr.hasNext()) {
1037            Map.Entry<String, List<String>> entry = itr.next();
1038
1039            String roleName = entry.getKey().toString();
1040
1041            if (hasRole(roles, roleName)) {
1042                Element roleEl = el.addElement("role");
1043
1044                roleEl.addAttribute("name", roleName);
1045
1046                List<String> actions = entry.getValue();
1047
1048                for (int i = 0; i < actions.size(); i++) {
1049                    String action = actions.get(i);
1050
1051                    Element actionKeyEl = roleEl.addElement("action-key");
1052
1053                    actionKeyEl.addText(action);
1054                    actionKeyEl.addAttribute("scope", String.valueOf(scope));
1055                }
1056            }
1057        }
1058
1059        return el;
1060    }
1061
1062    protected void exportTags(PortletDataContext context, Element parentEl)
1063        throws SystemException {
1064
1065        try {
1066            Document doc = SAXReaderUtil.createDocument();
1067
1068            Element root = doc.addElement("tags");
1069
1070            Map<String, String[]> assetTagNamesMap =
1071                context.getAssetTagNamesMap();
1072
1073            for (Map.Entry<String, String[]> entry :
1074                    assetTagNamesMap.entrySet()) {
1075
1076                String[] tagsEntry = entry.getKey().split(StringPool.POUND);
1077
1078                Element asset = root.addElement("asset");
1079
1080                asset.addAttribute("class-name", tagsEntry[0]);
1081                asset.addAttribute("class-pk", tagsEntry[1]);
1082                asset.addAttribute("tags", StringUtil.merge(entry.getValue()));
1083            }
1084
1085            context.addZipEntry(
1086                context.getRootPath() + "/tags.xml", doc.formattedString());
1087        }
1088        catch (Exception e) {
1089            throw new SystemException(e);
1090        }
1091    }
1092
1093    protected void exportUserPermissions(
1094            LayoutCache layoutCache, long companyId, long groupId,
1095            String resourceName, String resourcePrimKey, Element parentEl)
1096        throws SystemException {
1097
1098        StopWatch stopWatch = null;
1099
1100        if (_log.isDebugEnabled()) {
1101            stopWatch = new StopWatch();
1102
1103            stopWatch.start();
1104        }
1105
1106        Element userPermissionsEl = SAXReaderUtil.createElement(
1107            "user-permissions");
1108
1109        List<User> users = layoutCache.getGroupUsers(groupId);
1110
1111        for (User user : users) {
1112            String uuid = user.getUuid();
1113
1114            Element userActionsEl = SAXReaderUtil.createElement("user-actions");
1115
1116            List<Permission> permissions =
1117                PermissionLocalServiceUtil.getUserPermissions(
1118                    user.getUserId(), companyId, resourceName,
1119                    ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey);
1120
1121            List<String> actions = ResourceActionsUtil.getActions(permissions);
1122
1123            for (String action : actions) {
1124                Element actionKeyEl = userActionsEl.addElement("action-key");
1125
1126                actionKeyEl.addText(action);
1127            }
1128
1129            if (!userActionsEl.elements().isEmpty()) {
1130                userActionsEl.addAttribute("uuid", uuid);
1131                userPermissionsEl.add(userActionsEl);
1132            }
1133        }
1134
1135        if (!userPermissionsEl.elements().isEmpty()) {
1136            parentEl.add(userPermissionsEl);
1137        }
1138
1139        if (_log.isDebugEnabled()) {
1140            _log.debug(
1141                "Export user permissions for {" + resourceName + ", " +
1142                    resourcePrimKey + "} with " + users.size() +
1143                        " users takes " + stopWatch.getTime() + " ms");
1144        }
1145    }
1146
1147    protected void exportUserRoles(
1148            LayoutCache layoutCache, long companyId, long groupId,
1149            String resourceName, Element parentEl)
1150        throws SystemException {
1151
1152        Element userRolesEl = SAXReaderUtil.createElement("user-roles");
1153
1154        List<User> users = layoutCache.getGroupUsers(groupId);
1155
1156        for (User user : users) {
1157            long userId = user.getUserId();
1158            String uuid = user.getUuid();
1159
1160            List<Role> userRoles = layoutCache.getUserRoles(userId);
1161
1162            Element userEl = exportRoles(
1163                companyId, resourceName, ResourceConstants.SCOPE_GROUP,
1164                String.valueOf(groupId), userRolesEl, "user", userRoles);
1165
1166            if (userEl.elements().isEmpty()) {
1167                userRolesEl.remove(userEl);
1168            }
1169            else {
1170                userEl.addAttribute("uuid", uuid);
1171            }
1172        }
1173
1174        if (!userRolesEl.elements().isEmpty()) {
1175            parentEl.add(userRolesEl);
1176        }
1177    }
1178
1179    protected String getCommentsPath(
1180        PortletDataContext context, String className, String classPK) {
1181
1182        StringBundler sb = new StringBundler(6);
1183
1184        sb.append(context.getRootPath());
1185        sb.append("/comments/");
1186        sb.append(PortalUtil.getClassNameId(className));
1187        sb.append(CharPool.FORWARD_SLASH);
1188        sb.append(classPK);
1189        sb.append(CharPool.FORWARD_SLASH);
1190
1191        return sb.toString();
1192    }
1193
1194    protected String getCommentsPath(
1195        PortletDataContext context, String className, String classPK,
1196        MBMessage message) {
1197
1198        StringBundler sb = new StringBundler(8);
1199
1200        sb.append(context.getRootPath());
1201        sb.append("/comments/");
1202        sb.append(PortalUtil.getClassNameId(className));
1203        sb.append(CharPool.FORWARD_SLASH);
1204        sb.append(classPK);
1205        sb.append(CharPool.FORWARD_SLASH);
1206        sb.append(message.getMessageId());
1207        sb.append(".xml");
1208
1209        return sb.toString();
1210    }
1211
1212    protected String getPortletDataPath(
1213        PortletDataContext context, String portletId) {
1214
1215        return context.getPortletPath(portletId) + "/portlet-data.xml";
1216    }
1217
1218    protected String getPortletPreferencesPath(
1219        PortletDataContext context, String portletId, long ownerId,
1220        int ownerType, long plid) {
1221
1222        StringBundler sb = new StringBundler(8);
1223
1224        sb.append(context.getPortletPath(portletId));
1225        sb.append("/preferences/");
1226
1227        if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
1228            sb.append("company/");
1229        }
1230        else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
1231            sb.append("group/");
1232        }
1233        else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_LAYOUT) {
1234            sb.append("layout/");
1235        }
1236        else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) {
1237            sb.append("user/");
1238        }
1239        else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
1240            sb.append("archived/");
1241        }
1242
1243        sb.append(ownerId);
1244        sb.append(CharPool.FORWARD_SLASH);
1245        sb.append(plid);
1246        sb.append(CharPool.FORWARD_SLASH);
1247        sb.append("portlet-preferences.xml");
1248
1249        return sb.toString();
1250    }
1251
1252    protected String getRatingsPath(
1253        PortletDataContext context, String className, String classPK) {
1254
1255        StringBundler sb = new StringBundler(6);
1256
1257        sb.append(context.getRootPath());
1258        sb.append("/ratings/");
1259        sb.append(PortalUtil.getClassNameId(className));
1260        sb.append(CharPool.FORWARD_SLASH);
1261        sb.append(classPK);
1262        sb.append(CharPool.FORWARD_SLASH);
1263
1264        return sb.toString();
1265    }
1266
1267    protected String getRatingsPath(
1268        PortletDataContext context, String className, String classPK,
1269        RatingsEntry rating) {
1270
1271        StringBundler sb = new StringBundler(8);
1272
1273        sb.append(context.getRootPath());
1274        sb.append("/ratings/");
1275        sb.append(PortalUtil.getClassNameId(className));
1276        sb.append(CharPool.FORWARD_SLASH);
1277        sb.append(classPK);
1278        sb.append(CharPool.FORWARD_SLASH);
1279        sb.append(rating.getEntryId());
1280        sb.append(".xml");
1281
1282        return sb.toString();
1283    }
1284
1285    protected boolean hasRole(List<Role> roles, String roleName) {
1286        if ((roles == null) || (roles.size() == 0)) {
1287            return false;
1288        }
1289
1290        for (Role role : roles) {
1291            if (role.getName().equals(roleName)) {
1292                return true;
1293            }
1294        }
1295
1296        return false;
1297    }
1298
1299    private static Log _log = LogFactoryUtil.getLog(PortletExporter.class);
1300
1301}