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