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