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