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