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