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