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