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