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