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