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