1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.lar;
16  
17  import com.liferay.portal.LayoutImportException;
18  import com.liferay.portal.NoSuchPortletPreferencesException;
19  import com.liferay.portal.kernel.exception.PortalException;
20  import com.liferay.portal.kernel.exception.SystemException;
21  import com.liferay.portal.kernel.log.Log;
22  import com.liferay.portal.kernel.log.LogFactoryUtil;
23  import com.liferay.portal.kernel.util.CharPool;
24  import com.liferay.portal.kernel.util.FileUtil;
25  import com.liferay.portal.kernel.util.GetterUtil;
26  import com.liferay.portal.kernel.util.MapUtil;
27  import com.liferay.portal.kernel.util.ReleaseInfo;
28  import com.liferay.portal.kernel.util.StringBundler;
29  import com.liferay.portal.kernel.util.StringPool;
30  import com.liferay.portal.kernel.util.StringUtil;
31  import com.liferay.portal.kernel.util.Time;
32  import com.liferay.portal.kernel.util.Validator;
33  import com.liferay.portal.kernel.xml.Document;
34  import com.liferay.portal.kernel.xml.Element;
35  import com.liferay.portal.kernel.xml.SAXReaderUtil;
36  import com.liferay.portal.kernel.zip.ZipWriter;
37  import com.liferay.portal.kernel.zip.ZipWriterFactoryUtil;
38  import com.liferay.portal.model.Group;
39  import com.liferay.portal.model.Layout;
40  import com.liferay.portal.model.LayoutTypePortlet;
41  import com.liferay.portal.model.Portlet;
42  import com.liferay.portal.model.PortletConstants;
43  import com.liferay.portal.model.PortletItem;
44  import com.liferay.portal.model.PortletPreferences;
45  import com.liferay.portal.model.User;
46  import com.liferay.portal.service.LayoutLocalServiceUtil;
47  import com.liferay.portal.service.PortletItemLocalServiceUtil;
48  import com.liferay.portal.service.PortletLocalServiceUtil;
49  import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
50  import com.liferay.portal.service.UserLocalServiceUtil;
51  import com.liferay.portal.util.PortalUtil;
52  import com.liferay.portal.util.PortletKeys;
53  import com.liferay.portlet.PortletPreferencesFactoryUtil;
54  import com.liferay.portlet.messageboards.model.MBMessage;
55  import com.liferay.portlet.ratings.model.RatingsEntry;
56  
57  import java.io.File;
58  import java.io.IOException;
59  
60  import java.util.Date;
61  import java.util.HashSet;
62  import java.util.List;
63  import java.util.Map;
64  
65  import org.apache.commons.lang.time.StopWatch;
66  
67  /**
68   * <a href="PortletExporter.java.html"><b><i>View Source</i></b></a>
69   *
70   * @author Brian Wing Shun Chan
71   * @author Joel Kozikowski
72   * @author Charles May
73   * @author Raymond Augé
74   * @author Jorge Ferrer
75   * @author Bruno Farache
76   * @author Zsigmond Rab
77   * @author Douglas Wong
78   */
79  public class PortletExporter {
80  
81      public byte[] exportPortletInfo(
82              long plid, long groupId, String portletId,
83              Map<String, String[]> parameterMap, Date startDate, Date endDate)
84          throws PortalException, SystemException {
85  
86          File file = exportPortletInfoAsFile(
87              plid, groupId, portletId, parameterMap, startDate, endDate);
88  
89          try {
90              return FileUtil.getBytes(file);
91          }
92          catch (IOException ioe) {
93              throw new SystemException(ioe);
94          }
95          finally {
96              file.delete();
97          }
98      }
99  
100     public File exportPortletInfoAsFile(
101             long plid, long groupId, String portletId,
102             Map<String, String[]> parameterMap, Date startDate, Date endDate)
103         throws PortalException, SystemException {
104 
105         boolean exportPermissions = MapUtil.getBoolean(
106             parameterMap, PortletDataHandlerKeys.PERMISSIONS);
107         boolean exportPortletArchivedSetups = MapUtil.getBoolean(
108             parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
109         boolean exportPortletData = MapUtil.getBoolean(
110             parameterMap, PortletDataHandlerKeys.PORTLET_DATA + "_" +
111             PortletConstants.getRootPortletId(portletId));
112         boolean exportPortletDataAll = MapUtil.getBoolean(
113             parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);
114         boolean exportPortletSetup = MapUtil.getBoolean(
115             parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
116         boolean exportPortletUserPreferences = MapUtil.getBoolean(
117             parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
118         boolean exportUserPermissions = MapUtil.getBoolean(
119             parameterMap, PortletDataHandlerKeys.USER_PERMISSIONS);
120 
121         if (_log.isDebugEnabled()) {
122             _log.debug("Export permissions " + exportPermissions);
123             _log.debug(
124                 "Export portlet archived setups " +
125                     exportPortletArchivedSetups);
126             _log.debug("Export portlet data " + exportPortletData);
127             _log.debug("Export all portlet data " + exportPortletDataAll);
128             _log.debug("Export portlet setup " + exportPortletSetup);
129             _log.debug(
130                 "Export portlet user preferences " +
131                     exportPortletUserPreferences);
132             _log.debug("Export user permissions " + exportUserPermissions);
133         }
134 
135         if (exportPortletDataAll) {
136             exportPortletData = true;
137         }
138 
139         StopWatch stopWatch = null;
140 
141         if (_log.isInfoEnabled()) {
142             stopWatch = new StopWatch();
143 
144             stopWatch.start();
145         }
146 
147         LayoutCache layoutCache = new LayoutCache();
148 
149         Layout layout = LayoutLocalServiceUtil.getLayout(plid);
150 
151         if (!layout.isTypeControlPanel() && !layout.isTypePanel() &&
152             !layout.isTypePortlet()) {
153 
154             throw new LayoutImportException(
155                 "Layout type " + layout.getType() + " is not valid");
156         }
157 
158         long companyId = layout.getCompanyId();
159         long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
160 
161         ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();
162 
163         long scopeGroupId = groupId;
164 
165         javax.portlet.PortletPreferences jxPreferences =
166             PortletPreferencesFactoryUtil.getLayoutPortletSetup(
167                 layout, portletId);
168 
169         long scopeLayoutId = GetterUtil.getLong(
170             jxPreferences.getValue("lfr-scope-layout-id", null));
171 
172         if (scopeLayoutId != 0) {
173             Group scopeGroup = layout.getScopeGroup();
174 
175             if (scopeGroup != null) {
176                 scopeGroupId = scopeGroup.getGroupId();
177             }
178         }
179 
180         PortletDataContext context = new PortletDataContextImpl(
181             companyId, scopeGroupId, parameterMap, new HashSet<String>(),
182             startDate, endDate, zipWriter);
183 
184         context.setPlid(plid);
185         context.setOldPlid(plid);
186         context.setScopeLayoutId(scopeLayoutId);
187 
188         // Build compatibility
189 
190         Document doc = SAXReaderUtil.createDocument();
191 
192         Element root = doc.addElement("root");
193 
194         Element header = root.addElement("header");
195 
196         header.addAttribute(
197             "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
198         header.addAttribute("export-date", Time.getRFC822());
199 
200         if (context.hasDateRange()) {
201             header.addAttribute(
202                 "start-date", String.valueOf(context.getStartDate()));
203             header.addAttribute(
204                 "end-date", String.valueOf(context.getEndDate()));
205         }
206 
207         header.addAttribute("type", "portlet");
208         header.addAttribute("group-id", String.valueOf(scopeGroupId));
209         header.addAttribute(
210             "private-layout", String.valueOf(layout.isPrivateLayout()));
211         header.addAttribute(
212             "root-portlet-id", PortletConstants.getRootPortletId(portletId));
213 
214         // Portlet
215 
216         exportPortlet(
217             context, layoutCache, portletId, layout, root, defaultUserId,
218             exportPermissions, exportPortletArchivedSetups, exportPortletData,
219             exportPortletSetup, exportPortletUserPreferences,
220             exportUserPermissions);
221 
222         // Categories
223 
224         exportCategories(context, root);
225 
226         // Comments
227 
228         exportComments(context, root);
229 
230         // Portlet data permissions
231 
232         if (exportPermissions) {
233             _permissionExporter.exportPortletDataPermissions(context);
234         }
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         catch (IOException ioe) {
256             throw new SystemException(ioe);
257         }
258 
259         return zipWriter.getFile();
260     }
261 
262     protected void exportCategories(
263             PortletDataContext context, Element parentEl)
264         throws SystemException {
265 
266         try {
267             Document doc = SAXReaderUtil.createDocument();
268 
269             Element root = doc.addElement("categories");
270 
271             Map<String, String[]> assetCategoryIdsMap =
272                 context.getAssetCategoryUuidsMap();
273 
274             for (Map.Entry<String, String[]> entry :
275                     assetCategoryIdsMap.entrySet()) {
276 
277                 String[] categoryEntry = entry.getKey().split(StringPool.POUND);
278 
279                 Element asset = root.addElement("asset");
280 
281                 asset.addAttribute("class-name", categoryEntry[0]);
282                 asset.addAttribute("class-pk", categoryEntry[1]);
283                 asset.addAttribute(
284                     "category-uuids", StringUtil.merge(entry.getValue()));
285             }
286 
287             context.addZipEntry(
288                 context.getRootPath() + "/categories.xml",
289                 doc.formattedString());
290         }
291         catch (Exception e) {
292             throw new SystemException(e);
293         }
294     }
295 
296     protected void exportComments(PortletDataContext context, Element parentEl)
297         throws SystemException {
298 
299         try {
300             Document doc = SAXReaderUtil.createDocument();
301 
302             Element root = doc.addElement("comments");
303 
304             Map<String, List<MBMessage>> commentsMap = context.getComments();
305 
306             for (Map.Entry<String, List<MBMessage>> entry :
307                     commentsMap.entrySet()) {
308 
309                 String[] comment = entry.getKey().split(StringPool.POUND);
310 
311                 String path = getCommentsPath(context, comment[0], comment[1]);
312 
313                 Element asset = root.addElement("asset");
314 
315                 asset.addAttribute("path", path);
316                 asset.addAttribute("class-name", comment[0]);
317                 asset.addAttribute("class-pk", comment[1]);
318 
319                 List<MBMessage> messages = entry.getValue();
320 
321                 for (MBMessage message : messages) {
322                     path = getCommentsPath(
323                         context, comment[0], comment[1], message);
324 
325                     if (context.isPathNotProcessed(path)) {
326                         context.addZipEntry(path, message);
327                     }
328                 }
329             }
330 
331             context.addZipEntry(
332                 context.getRootPath() + "/comments.xml", doc.formattedString());
333         }
334         catch (IOException ioe) {
335             throw new SystemException(ioe);
336         }
337     }
338 
339     protected void exportPortlet(
340             PortletDataContext context, LayoutCache layoutCache,
341             String portletId, Layout layout, Element parentEl,
342             long defaultUserId, boolean exportPermissions,
343             boolean exportPortletArchivedSetups, boolean exportPortletData,
344             boolean exportPortletSetup, boolean exportPortletUserPreferences,
345             boolean exportUserPermissions)
346         throws PortalException, SystemException {
347 
348         long companyId = context.getCompanyId();
349         long groupId = context.getGroupId();
350 
351         Portlet portlet = PortletLocalServiceUtil.getPortletById(
352             context.getCompanyId(), portletId);
353 
354         if (portlet == null) {
355             if (_log.isDebugEnabled()) {
356                 _log.debug(
357                     "Do not export portlet " + portletId +
358                         " because the portlet does not exist");
359             }
360 
361             return;
362         }
363 
364         if ((!portlet.isInstanceable()) &&
365             (!portlet.isPreferencesUniquePerLayout()) &&
366             (context.hasNotUniquePerLayout(portletId))) {
367 
368             return;
369         }
370 
371         Document doc = SAXReaderUtil.createDocument();
372 
373         Element portletEl = doc.addElement("portlet");
374 
375         portletEl.addAttribute("portlet-id", portletId);
376         portletEl.addAttribute(
377             "root-portlet-id", PortletConstants.getRootPortletId(portletId));
378         portletEl.addAttribute("old-plid", String.valueOf(layout.getPlid()));
379         portletEl.addAttribute(
380             "scope-layout-id", String.valueOf(context.getScopeLayoutId()));
381 
382         // Data
383 
384         javax.portlet.PortletPreferences jxPreferences =
385             PortletPreferencesFactoryUtil.getPortletSetup(
386                 layout, portletId, StringPool.BLANK);
387 
388         if (exportPortletData) {
389             if (!portlet.isPreferencesUniquePerLayout()) {
390                 String dataKey =
391                     portletId + StringPool.AT + context.getScopeLayoutId();
392 
393                 if (!context.hasNotUniquePerLayout(dataKey)) {
394                     context.putNotUniquePerLayout(dataKey);
395 
396                     exportPortletData(
397                         context, portlet, layout, jxPreferences, portletEl);
398                 }
399             }
400             else {
401                 exportPortletData(
402                     context, portlet, layout, jxPreferences, portletEl);
403             }
404         }
405 
406         // Portlet preferences
407 
408         if (exportPortletSetup) {
409             exportPortletPreferences(
410                 context, PortletKeys.PREFS_OWNER_ID_DEFAULT,
411                 PortletKeys.PREFS_OWNER_TYPE_LAYOUT, false, layout, portletId,
412                 portletEl);
413 
414             exportPortletPreferences(
415                 context, groupId, PortletKeys.PREFS_OWNER_TYPE_GROUP, false,
416                 layout, portletId, portletEl);
417 
418             exportPortletPreferences(
419                 context, companyId, PortletKeys.PREFS_OWNER_TYPE_COMPANY, false,
420                 layout, portletId, portletEl);
421         }
422 
423         // Portlet preferences
424 
425         if (exportPortletUserPreferences) {
426             exportPortletPreferences(
427                 context, defaultUserId, PortletKeys.PREFS_OWNER_TYPE_USER,
428                 true, layout, portletId, portletEl);
429 
430             try {
431                 PortletPreferences groupPortletPreferences =
432                     PortletPreferencesLocalServiceUtil.getPortletPreferences(
433                         groupId, PortletKeys.PREFS_OWNER_TYPE_GROUP,
434                         PortletKeys.PREFS_PLID_SHARED, portletId);
435 
436                 exportPortletPreference(
437                     context, groupId, PortletKeys.PREFS_OWNER_TYPE_GROUP, false,
438                     groupPortletPreferences, portletId,
439                     PortletKeys.PREFS_PLID_SHARED, portletEl);
440             }
441             catch (NoSuchPortletPreferencesException nsppe) {
442             }
443         }
444 
445         // Archived setups
446 
447         if (exportPortletArchivedSetups) {
448             String rootPortletId = PortletConstants.getRootPortletId(portletId);
449 
450             List<PortletItem> portletItems =
451                 PortletItemLocalServiceUtil.getPortletItems(
452                     groupId, rootPortletId, PortletPreferences.class.getName());
453 
454             for (PortletItem portletItem: portletItems) {
455                 long ownerId = portletItem.getPortletItemId();
456                 int ownerType = PortletKeys.PREFS_OWNER_TYPE_ARCHIVED;
457 
458                 exportPortletPreferences(
459                     context, ownerId, ownerType, false, null,
460                     portletItem.getPortletId(), portletEl);
461             }
462         }
463 
464         // Permissions
465 
466         if (exportPermissions) {
467             _permissionExporter.exportPortletPermissions(
468                 context, layoutCache, portletId, layout, portletEl);
469         }
470 
471         // Zip
472 
473         StringBundler sb = new StringBundler(4);
474 
475         sb.append(context.getPortletPath(portletId));
476         sb.append(StringPool.SLASH);
477         sb.append(layout.getPlid());
478         sb.append("/portlet.xml");
479 
480         String path = sb.toString();
481 
482         Element el = parentEl.addElement("portlet");
483 
484         el.addAttribute("portlet-id", portletId);
485         el.addAttribute("layout-id", String.valueOf(layout.getLayoutId()));
486         el.addAttribute("path", path);
487 
488         if (context.isPathNotProcessed(path)) {
489             try {
490                 context.addZipEntry(path, doc.formattedString());
491             }
492             catch (IOException ioe) {
493                 if (_log.isWarnEnabled()) {
494                     _log.warn(ioe.getMessage());
495                 }
496             }
497 
498             context.addPrimaryKey(String.class, path);
499         }
500     }
501 
502     protected void exportPortletData(
503             PortletDataContext context, Portlet portlet, Layout layout,
504             javax.portlet.PortletPreferences portletPreferences,
505             Element parentEl)
506         throws SystemException {
507 
508         PortletDataHandler portletDataHandler =
509             portlet.getPortletDataHandlerInstance();
510 
511         if (portletDataHandler == null) {
512             return;
513         }
514 
515         String portletId = portlet.getPortletId();
516 
517         if (_log.isDebugEnabled()) {
518             _log.debug("Exporting data for " + portletId);
519         }
520 
521         String data = null;
522 
523         long groupId = context.getGroupId();
524 
525         context.setGroupId(context.getScopeGroupId());
526 
527         try {
528             data = portletDataHandler.exportData(
529                 context, portletId, portletPreferences);
530         }
531         catch (Exception e) {
532             throw new SystemException(e);
533         }
534         finally {
535             context.setGroupId(groupId);
536         }
537 
538         if (Validator.isNull(data)) {
539             if (_log.isDebugEnabled()) {
540                 _log.debug(
541                     "Not exporting data for " + portletId +
542                         " because null data was returned");
543             }
544 
545             return;
546         }
547 
548         StringBundler sb = new StringBundler(4);
549 
550         sb.append(context.getPortletPath(portletId));
551 
552         if (portlet.isPreferencesUniquePerLayout()) {
553             sb.append(StringPool.SLASH);
554             sb.append(layout.getPlid());
555         }
556 
557         sb.append("/portlet-data.xml");
558 
559         Element portletDataEl = parentEl.addElement("portlet-data");
560 
561         portletDataEl.addAttribute("path", sb.toString());
562 
563         context.addZipEntry(sb.toString(), data);
564     }
565 
566     protected void exportPortletPreference(
567             PortletDataContext context, long ownerId, int ownerType,
568             boolean defaultUser, PortletPreferences portletPreferences,
569             String portletId, long plid, Element parentEl)
570         throws SystemException {
571 
572         try {
573             Document preferencesDoc = SAXReaderUtil.read(
574                 portletPreferences.getPreferences());
575 
576             Element root = preferencesDoc.getRootElement();
577 
578             root.addAttribute("owner-id", String.valueOf(ownerId));
579             root.addAttribute("owner-type", String.valueOf(ownerType));
580             root.addAttribute("default-user", String.valueOf(defaultUser));
581             root.addAttribute("plid", String.valueOf(plid));
582             root.addAttribute("portlet-id", portletId);
583 
584             if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
585                 PortletItem portletItem =
586                     PortletItemLocalServiceUtil.getPortletItem(ownerId);
587 
588                 User user = UserLocalServiceUtil.getUserById(
589                     portletItem.getUserId());
590 
591                 root.addAttribute("archive-user-uuid", user.getUuid());
592                 root.addAttribute("archive-name", portletItem.getName());
593             }
594 
595             String path = getPortletPreferencesPath(
596                 context, portletId, ownerId, ownerType, plid);
597 
598             parentEl.addElement(
599                 "portlet-preferences").addAttribute("path", path);
600 
601             if (context.isPathNotProcessed(path)) {
602                 context.addZipEntry(path, preferencesDoc.formattedString());
603             }
604         }
605         catch (Exception e) {
606             throw new SystemException(e);
607         }
608     }
609 
610     protected void exportPortletPreferences(
611             PortletDataContext context, long ownerId, int ownerType,
612             boolean defaultUser, Layout layout, String portletId,
613             Element parentEl)
614         throws PortalException, SystemException {
615 
616         PortletPreferences portletPreferences = null;
617 
618         long plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
619 
620         if (layout != null) {
621             plid = layout.getPlid();
622         }
623 
624         if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) ||
625             (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) ||
626             (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED)) {
627 
628             plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
629         }
630 
631         try {
632             portletPreferences =
633                 PortletPreferencesLocalServiceUtil.getPortletPreferences(
634                     ownerId, ownerType, plid, portletId);
635 
636             LayoutTypePortlet layoutTypePortlet = null;
637 
638             if (layout != null) {
639                 layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
640             }
641 
642             if ((layoutTypePortlet == null) ||
643                 (layoutTypePortlet.hasPortletId(portletId))) {
644 
645                 exportPortletPreference(
646                     context, ownerId, ownerType, defaultUser,
647                     portletPreferences, portletId, plid, parentEl);
648             }
649         }
650         catch (NoSuchPortletPreferencesException nsppe) {
651         }
652     }
653 
654     protected void exportRatings(PortletDataContext context, Element parentEl)
655         throws SystemException {
656 
657         try {
658             Document doc = SAXReaderUtil.createDocument();
659 
660             Element root = doc.addElement("ratings");
661 
662             Map<String, List<RatingsEntry>> ratingsEntriesMap =
663                 context.getRatingsEntries();
664 
665             for (Map.Entry<String, List<RatingsEntry>> entry :
666                     ratingsEntriesMap.entrySet()) {
667 
668                 String[] ratingsEntry = entry.getKey().split(StringPool.POUND);
669 
670                 String ratingPath = getRatingsPath(
671                     context, ratingsEntry[0], ratingsEntry[1]);
672 
673                 Element asset = root.addElement("asset");
674 
675                 asset.addAttribute("path", ratingPath);
676                 asset.addAttribute("class-name", ratingsEntry[0]);
677                 asset.addAttribute("class-pk", ratingsEntry[1]);
678 
679                 List<RatingsEntry> ratingsEntries = entry.getValue();
680 
681                 for (RatingsEntry rating : ratingsEntries) {
682                     ratingPath = getRatingsPath(
683                         context, ratingsEntry[0], ratingsEntry[1], rating);
684 
685                     context.addZipEntry(ratingPath, rating);
686                 }
687             }
688 
689             context.addZipEntry(
690                 context.getRootPath() + "/ratings.xml", doc.formattedString());
691         }
692         catch (Exception e) {
693             throw new SystemException(e);
694         }
695     }
696 
697     protected void exportTags(PortletDataContext context, Element parentEl)
698         throws SystemException {
699 
700         try {
701             Document doc = SAXReaderUtil.createDocument();
702 
703             Element root = doc.addElement("tags");
704 
705             Map<String, String[]> assetTagNamesMap =
706                 context.getAssetTagNamesMap();
707 
708             for (Map.Entry<String, String[]> entry :
709                     assetTagNamesMap.entrySet()) {
710 
711                 String[] tagsEntry = entry.getKey().split(StringPool.POUND);
712 
713                 Element asset = root.addElement("asset");
714 
715                 asset.addAttribute("class-name", tagsEntry[0]);
716                 asset.addAttribute("class-pk", tagsEntry[1]);
717                 asset.addAttribute("tags", StringUtil.merge(entry.getValue()));
718             }
719 
720             context.addZipEntry(
721                 context.getRootPath() + "/tags.xml", doc.formattedString());
722         }
723         catch (Exception e) {
724             throw new SystemException(e);
725         }
726     }
727 
728     protected String getCommentsPath(
729         PortletDataContext context, String className, String classPK) {
730 
731         StringBundler sb = new StringBundler(6);
732 
733         sb.append(context.getRootPath());
734         sb.append("/comments/");
735         sb.append(PortalUtil.getClassNameId(className));
736         sb.append(CharPool.FORWARD_SLASH);
737         sb.append(classPK);
738         sb.append(CharPool.FORWARD_SLASH);
739 
740         return sb.toString();
741     }
742 
743     protected String getCommentsPath(
744         PortletDataContext context, String className, String classPK,
745         MBMessage message) {
746 
747         StringBundler sb = new StringBundler(8);
748 
749         sb.append(context.getRootPath());
750         sb.append("/comments/");
751         sb.append(PortalUtil.getClassNameId(className));
752         sb.append(CharPool.FORWARD_SLASH);
753         sb.append(classPK);
754         sb.append(CharPool.FORWARD_SLASH);
755         sb.append(message.getMessageId());
756         sb.append(".xml");
757 
758         return sb.toString();
759     }
760 
761     protected String getPortletDataPath(
762         PortletDataContext context, String portletId) {
763 
764         return context.getPortletPath(portletId) + "/portlet-data.xml";
765     }
766 
767     protected String getPortletPreferencesPath(
768         PortletDataContext context, String portletId, long ownerId,
769         int ownerType, long plid) {
770 
771         StringBundler sb = new StringBundler(8);
772 
773         sb.append(context.getPortletPath(portletId));
774         sb.append("/preferences/");
775 
776         if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
777             sb.append("company/");
778         }
779         else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
780             sb.append("group/");
781         }
782         else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_LAYOUT) {
783             sb.append("layout/");
784         }
785         else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) {
786             sb.append("user/");
787         }
788         else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
789             sb.append("archived/");
790         }
791 
792         sb.append(ownerId);
793         sb.append(CharPool.FORWARD_SLASH);
794         sb.append(plid);
795         sb.append(CharPool.FORWARD_SLASH);
796         sb.append("portlet-preferences.xml");
797 
798         return sb.toString();
799     }
800 
801     protected String getRatingsPath(
802         PortletDataContext context, String className, String classPK) {
803 
804         StringBundler sb = new StringBundler(6);
805 
806         sb.append(context.getRootPath());
807         sb.append("/ratings/");
808         sb.append(PortalUtil.getClassNameId(className));
809         sb.append(CharPool.FORWARD_SLASH);
810         sb.append(classPK);
811         sb.append(CharPool.FORWARD_SLASH);
812 
813         return sb.toString();
814     }
815 
816     protected String getRatingsPath(
817         PortletDataContext context, String className, String classPK,
818         RatingsEntry rating) {
819 
820         StringBundler sb = new StringBundler(8);
821 
822         sb.append(context.getRootPath());
823         sb.append("/ratings/");
824         sb.append(PortalUtil.getClassNameId(className));
825         sb.append(CharPool.FORWARD_SLASH);
826         sb.append(classPK);
827         sb.append(CharPool.FORWARD_SLASH);
828         sb.append(rating.getEntryId());
829         sb.append(".xml");
830 
831         return sb.toString();
832     }
833 
834     private static Log _log = LogFactoryUtil.getLog(PortletExporter.class);
835 
836     private PermissionExporter _permissionExporter = new PermissionExporter();
837 
838 }