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(
660                 "portlet-preference").addAttribute("path", path);
661 
662             if (context.isPathNotProcessed(path)) {
663                 context.addZipEntry(
664                     path, XMLFormatter.toString(prefsDoc));
665             }
666         }
667         catch (Exception e) {
668             throw new SystemException(e);
669         }
670     }
671 
672     protected void exportPortletPreferences(
673             PortletDataContext context, long ownerId, int ownerType,
674             boolean defaultUser, Layout layout, String portletId,
675             Element parentEl)
676         throws PortalException, SystemException {
677 
678         PortletPreferences portletPreferences = null;
679 
680         long plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
681 
682         if (layout != null) {
683             plid = layout.getPlid();
684         }
685 
686         if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) ||
687             (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) ||
688             (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED)) {
689 
690             plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
691         }
692 
693         try {
694             portletPreferences =
695                 PortletPreferencesLocalServiceUtil.getPortletPreferences(
696                     ownerId, ownerType, plid, portletId);
697 
698             LayoutTypePortlet layoutTypePortlet = null;
699 
700             if (layout != null) {
701                 layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
702             }
703 
704             if ((layoutTypePortlet == null) ||
705                 (layoutTypePortlet.hasPortletId(portletId))) {
706 
707                 exportPortletPreference(
708                     context, ownerId, ownerType, defaultUser,
709                     portletPreferences, portletId, plid, parentEl);
710             }
711         }
712         catch (NoSuchPortletPreferencesException nsppe) {
713         }
714     }
715 
716     protected void exportPortletRoles(
717             LayoutCache layoutCache, long companyId, long groupId,
718             String portletId, Element rolesEl)
719         throws PortalException, SystemException {
720 
721         String resourceName = PortletConstants.getRootPortletId(
722             portletId);
723 
724         Element portletEl = rolesEl.addElement("portlet");
725 
726         portletEl.addAttribute("portlet-id", portletId);
727 
728         exportGroupRoles(
729             layoutCache, companyId, groupId, resourceName, "community",
730             portletEl);
731 
732         exportUserRoles(
733             layoutCache, companyId, groupId, resourceName, portletEl);
734 
735         exportInheritedRoles(
736             layoutCache, companyId, groupId, resourceName, "organization",
737             portletEl);
738 
739         exportInheritedRoles(
740             layoutCache, companyId, groupId, resourceName, "location",
741             portletEl);
742 
743         exportInheritedRoles(
744             layoutCache, companyId, groupId, resourceName, "user-group",
745             portletEl);
746 
747         if (portletEl.elements().isEmpty()) {
748             rolesEl.remove(portletEl);
749         }
750     }
751 
752     protected void exportRatings(PortletDataContext context, Element parentEl)
753         throws SystemException {
754 
755         try {
756             Document doc = DocumentHelper.createDocument();
757 
758             Element root = doc.addElement("ratings");
759 
760             Map<String, List> ratingsEntriesMap = context.getRatingsEntries();
761 
762             for (Map.Entry<String, List> entry : ratingsEntriesMap.entrySet()) {
763                 String[] ratingsEntry = entry.getKey().split(StringPool.POUND);
764 
765                 String ratingPath = getRatingPath(
766                     context, ratingsEntry[0], ratingsEntry[1]);
767 
768                 Element asset = root.addElement("asset");
769                 asset.addAttribute("path", ratingPath);
770                 asset.addAttribute("class-name", ratingsEntry[0]);
771                 asset.addAttribute("class-pk", ratingsEntry[1]);
772 
773                 List<RatingsEntry> ratingsEntries = entry.getValue();
774 
775                 for (RatingsEntry rating : ratingsEntries) {
776                     ratingPath = getRatingPath(
777                         context, ratingsEntry[0], ratingsEntry[1], rating);
778 
779                     context.addZipEntry(ratingPath, rating);
780                 }
781             }
782 
783             context.addZipEntry(
784                 context.getRootPath() + "/ratings.xml",
785                 XMLFormatter.toString(doc));
786         }
787         catch (Exception e) {
788             throw new SystemException(e);
789         }
790     }
791 
792     protected Element exportRoles(
793             long companyId, String resourceName, int scope,
794             String resourcePrimKey, Element parentEl, String elName,
795             List<Role> roles)
796         throws SystemException {
797 
798         Element el = parentEl.addElement(elName);
799 
800         Map<String, List<String>> resourceRoles =
801             RoleLocalServiceUtil.getResourceRoles(
802                 companyId, resourceName, scope, resourcePrimKey);
803 
804         Iterator<Map.Entry<String, List<String>>> itr =
805             resourceRoles.entrySet().iterator();
806 
807         while (itr.hasNext()) {
808             Map.Entry<String, List<String>> entry = itr.next();
809 
810             String roleName = entry.getKey().toString();
811 
812             if (hasRole(roles, roleName)) {
813                 Element roleEl = el.addElement("role");
814 
815                 roleEl.addAttribute("name", roleName);
816 
817                 List<String> actions = entry.getValue();
818 
819                 for (int i = 0; i < actions.size(); i++) {
820                     String action = actions.get(i);
821 
822                     Element actionKeyEl = roleEl.addElement("action-key");
823 
824                     actionKeyEl.addText(action);
825                     actionKeyEl.addAttribute("scope", String.valueOf(scope));
826                 }
827             }
828         }
829 
830         return el;
831     }
832 
833     protected void exportTags(PortletDataContext context, Element parentEl)
834         throws SystemException {
835 
836         try {
837             Document doc = DocumentHelper.createDocument();
838 
839             Element root = doc.addElement("tags");
840 
841             Map<String, String[]> tagsEntries = context.getTagsEntries();
842 
843             for (Map.Entry<String, String[]> entry : tagsEntries.entrySet()) {
844                 String[] tagsEntry = entry.getKey().split(StringPool.POUND);
845 
846                 Element asset = root.addElement("asset");
847                 asset.addAttribute("class-name", tagsEntry[0]);
848                 asset.addAttribute("class-pk", tagsEntry[1]);
849                 asset.addAttribute(
850                     "entries", StringUtil.merge(entry.getValue(), ","));
851             }
852 
853             context.addZipEntry(
854                 context.getRootPath() + "/tags.xml",
855                 XMLFormatter.toString(doc));
856         }
857         catch (Exception e) {
858             throw new SystemException(e);
859         }
860     }
861 
862     protected void exportUserPermissions(
863             LayoutCache layoutCache, long companyId, long groupId,
864             String resourceName, String resourcePrimKey, Element parentEl)
865         throws PortalException, SystemException {
866 
867         StopWatch stopWatch = null;
868 
869         if (_log.isDebugEnabled()) {
870             stopWatch = new StopWatch();
871 
872             stopWatch.start();
873         }
874 
875         Element userPermissionsEl = DocumentHelper.createElement(
876             "user-permissions");
877 
878         List<User> users = layoutCache.getGroupUsers(groupId);
879 
880         for (User user : users) {
881             String emailAddress = user.getEmailAddress();
882 
883             Element userActionsEl =
884                 DocumentHelper.createElement("user-actions");
885 
886             List<Permission> permissions =
887                 PermissionLocalServiceUtil.getUserPermissions(
888                     user.getUserId(), companyId, resourceName,
889                     ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey);
890 
891             List<String> actions = ResourceActionsUtil.getActions(permissions);
892 
893             for (String action : actions) {
894                 Element actionKeyEl = userActionsEl.addElement("action-key");
895 
896                 actionKeyEl.addText(action);
897             }
898 
899             if (!userActionsEl.elements().isEmpty()) {
900                 userActionsEl.addAttribute("email-address", emailAddress);
901                 userPermissionsEl.add(userActionsEl);
902             }
903         }
904 
905         if (!userPermissionsEl.elements().isEmpty()) {
906             parentEl.add(userPermissionsEl);
907         }
908 
909         if (_log.isDebugEnabled()) {
910             _log.debug(
911                 "Export user permissions for {" + resourceName + ", " +
912                     resourcePrimKey + "} with " + users.size() +
913                         " users takes " + stopWatch.getTime() + " ms");
914         }
915     }
916 
917     protected void exportUserRoles(
918             LayoutCache layoutCache, long companyId, long groupId,
919             String resourceName, Element parentEl)
920         throws PortalException, SystemException {
921 
922         Element userRolesEl = DocumentHelper.createElement("user-roles");
923 
924         List<User> users = layoutCache.getGroupUsers(groupId);
925 
926         for (User user : users) {
927             long userId = user.getUserId();
928             String emailAddress = user.getEmailAddress();
929 
930             List<Role> userRoles = layoutCache.getUserRoles(userId);
931 
932             Element userEl = exportRoles(
933                 companyId, resourceName, ResourceConstants.SCOPE_GROUP,
934                 String.valueOf(groupId), userRolesEl, "user", userRoles);
935 
936             if (userEl.elements().isEmpty()) {
937                 userRolesEl.remove(userEl);
938             }
939             else {
940                 userEl.addAttribute("email-address", emailAddress);
941             }
942         }
943 
944         if (!userRolesEl.elements().isEmpty()) {
945             parentEl.add(userRolesEl);
946         }
947     }
948 
949     protected String getCommentPath(
950             PortletDataContext context, String className, String classPK) {
951 
952         StringBuilder sb = new StringBuilder();
953         sb.append(context.getRootPath());
954         sb.append("/comments/");
955         sb.append(PortalUtil.getClassNameId(className));
956         sb.append(CharPool.FORWARD_SLASH);
957         sb.append(classPK);
958         sb.append(CharPool.FORWARD_SLASH);
959 
960         return sb.toString();
961     }
962 
963     protected String getCommentPath(
964             PortletDataContext context, String className, String classPK,
965             MBMessage message) {
966 
967         StringBuilder sb = new StringBuilder();
968         sb.append(context.getRootPath());
969         sb.append("/comments/");
970         sb.append(PortalUtil.getClassNameId(className));
971         sb.append(CharPool.FORWARD_SLASH);
972         sb.append(classPK);
973         sb.append(CharPool.FORWARD_SLASH);
974         sb.append(message.getMessageId());
975         sb.append(".xml");
976 
977         return sb.toString();
978     }
979 
980     protected String getRatingPath(
981             PortletDataContext context, String className, String classPK) {
982 
983         StringBuilder sb = new StringBuilder();
984         sb.append(context.getRootPath());
985         sb.append("/ratings/");
986         sb.append(PortalUtil.getClassNameId(className));
987         sb.append(CharPool.FORWARD_SLASH);
988         sb.append(classPK);
989         sb.append(CharPool.FORWARD_SLASH);
990 
991         return sb.toString();
992     }
993 
994     protected String getRatingPath(
995             PortletDataContext context, String className, String classPK,
996             RatingsEntry rating) {
997 
998         StringBuilder sb = new StringBuilder();
999         sb.append(context.getRootPath());
1000        sb.append("/ratings/");
1001        sb.append(PortalUtil.getClassNameId(className));
1002        sb.append(CharPool.FORWARD_SLASH);
1003        sb.append(classPK);
1004        sb.append(CharPool.FORWARD_SLASH);
1005        sb.append(rating.getEntryId());
1006        sb.append(".xml");
1007
1008        return sb.toString();
1009    }
1010
1011    protected String getPortletDataPath(
1012            PortletDataContext context, String portletId) {
1013
1014        return context.getPortletPath(portletId) + "/portlet-data.xml";
1015    }
1016
1017    protected String getPortletPreferencesPath(
1018        PortletDataContext context, String portletId, long ownerId,
1019        int ownerType, long plid) {
1020
1021        StringBuilder sb = new StringBuilder();
1022
1023        sb.append(context.getPortletPath(portletId));
1024        sb.append("/preferences/");
1025
1026        switch(ownerType) {
1027            case PortletKeys.PREFS_OWNER_TYPE_COMPANY:
1028                sb.append("company/");
1029                break;
1030            case PortletKeys.PREFS_OWNER_TYPE_GROUP:
1031                sb.append("group/");
1032                break;
1033            case PortletKeys.PREFS_OWNER_TYPE_LAYOUT:
1034                sb.append("layout/");
1035                break;
1036            case PortletKeys.PREFS_OWNER_TYPE_USER:
1037                sb.append("user/");
1038                break;
1039            case PortletKeys.PREFS_OWNER_TYPE_ARCHIVED:
1040                sb.append("archived/");
1041                break;
1042        }
1043
1044        sb.append(ownerId);
1045        sb.append(CharPool.FORWARD_SLASH);
1046        sb.append(plid);
1047        sb.append(CharPool.FORWARD_SLASH);
1048        sb.append("portlet-preferences.xml");
1049
1050        return sb.toString();
1051    }
1052
1053    protected boolean hasRole(List<Role> roles, String roleName) {
1054        if ((roles == null) || (roles.size() == 0)) {
1055            return false;
1056        }
1057
1058        for (int i = 0; i < roles.size(); i++) {
1059            Role role = roles.get(i);
1060
1061            if (role.getName().equals(roleName)) {
1062                return true;
1063            }
1064        }
1065
1066        return false;
1067    }
1068
1069    private static Log _log = LogFactory.getLog(PortletExporter.class);
1070
1071}