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