001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.lar;
016    
017    import com.liferay.portal.LayoutImportException;
018    import com.liferay.portal.NoSuchPortletPreferencesException;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.lar.ImportExportThreadLocal;
022    import com.liferay.portal.kernel.lar.PortletDataContext;
023    import com.liferay.portal.kernel.lar.PortletDataHandler;
024    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.util.CharPool;
028    import com.liferay.portal.kernel.util.FileUtil;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.MapUtil;
031    import com.liferay.portal.kernel.util.ReleaseInfo;
032    import com.liferay.portal.kernel.util.StringBundler;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.StringUtil;
035    import com.liferay.portal.kernel.util.Time;
036    import com.liferay.portal.kernel.util.UnicodeProperties;
037    import com.liferay.portal.kernel.util.Validator;
038    import com.liferay.portal.kernel.xml.Document;
039    import com.liferay.portal.kernel.xml.Element;
040    import com.liferay.portal.kernel.xml.Node;
041    import com.liferay.portal.kernel.xml.SAXReaderUtil;
042    import com.liferay.portal.kernel.zip.ZipWriter;
043    import com.liferay.portal.kernel.zip.ZipWriterFactoryUtil;
044    import com.liferay.portal.model.Group;
045    import com.liferay.portal.model.Layout;
046    import com.liferay.portal.model.LayoutTypePortlet;
047    import com.liferay.portal.model.Lock;
048    import com.liferay.portal.model.Portlet;
049    import com.liferay.portal.model.PortletConstants;
050    import com.liferay.portal.model.PortletItem;
051    import com.liferay.portal.model.PortletPreferences;
052    import com.liferay.portal.service.GroupLocalServiceUtil;
053    import com.liferay.portal.service.LayoutLocalServiceUtil;
054    import com.liferay.portal.service.PortletItemLocalServiceUtil;
055    import com.liferay.portal.service.PortletLocalServiceUtil;
056    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
057    import com.liferay.portal.service.UserLocalServiceUtil;
058    import com.liferay.portal.util.PortalUtil;
059    import com.liferay.portal.util.PortletKeys;
060    import com.liferay.portlet.PortletPreferencesFactoryUtil;
061    import com.liferay.portlet.asset.model.AssetCategory;
062    import com.liferay.portlet.asset.model.AssetCategoryConstants;
063    import com.liferay.portlet.asset.model.AssetCategoryProperty;
064    import com.liferay.portlet.asset.model.AssetTag;
065    import com.liferay.portlet.asset.model.AssetTagProperty;
066    import com.liferay.portlet.asset.model.AssetVocabulary;
067    import com.liferay.portlet.asset.service.AssetCategoryPropertyLocalServiceUtil;
068    import com.liferay.portlet.asset.service.AssetCategoryServiceUtil;
069    import com.liferay.portlet.asset.service.AssetTagPropertyLocalServiceUtil;
070    import com.liferay.portlet.asset.service.AssetTagServiceUtil;
071    import com.liferay.portlet.asset.service.persistence.AssetCategoryUtil;
072    import com.liferay.portlet.asset.service.persistence.AssetVocabularyUtil;
073    import com.liferay.portlet.expando.model.ExpandoColumn;
074    import com.liferay.portlet.messageboards.model.MBMessage;
075    import com.liferay.portlet.ratings.model.RatingsEntry;
076    import com.liferay.util.xml.DocUtil;
077    
078    import java.io.File;
079    import java.io.IOException;
080    
081    import java.util.Date;
082    import java.util.HashSet;
083    import java.util.List;
084    import java.util.Map;
085    
086    import org.apache.commons.lang.time.StopWatch;
087    
088    /**
089     * @author Brian Wing Shun Chan
090     * @author Joel Kozikowski
091     * @author Charles May
092     * @author Raymond Augé
093     * @author Jorge Ferrer
094     * @author Bruno Farache
095     * @author Zsigmond Rab
096     * @author Douglas Wong
097     */
098    public class PortletExporter {
099    
100            public byte[] exportPortletInfo(
101                            long plid, long groupId, String portletId,
102                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
103                    throws Exception {
104    
105                    File file = exportPortletInfoAsFile(
106                            plid, groupId, portletId, parameterMap, startDate, endDate);
107    
108                    try {
109                            return FileUtil.getBytes(file);
110                    }
111                    catch (IOException ioe) {
112                            throw new SystemException(ioe);
113                    }
114                    finally {
115                            file.delete();
116                    }
117            }
118    
119            public File exportPortletInfoAsFile(
120                            long plid, long groupId, String portletId,
121                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
122                    throws Exception {
123    
124                    try {
125                            ImportExportThreadLocal.setPortletExportInProcess(true);
126    
127                            return doExportPortletInfoAsFile(
128                                    plid, groupId, portletId, parameterMap, startDate, endDate);
129                    }
130                    finally {
131                            ImportExportThreadLocal.setPortletExportInProcess(false);
132                    }
133            }
134    
135            protected File doExportPortletInfoAsFile(
136                            long plid, long groupId, String portletId,
137                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
138                    throws Exception {
139    
140                    boolean exportCategories = MapUtil.getBoolean(
141                            parameterMap, PortletDataHandlerKeys.CATEGORIES);
142                    boolean exportPermissions = MapUtil.getBoolean(
143                            parameterMap, PortletDataHandlerKeys.PERMISSIONS);
144                    boolean exportPortletArchivedSetups = MapUtil.getBoolean(
145                            parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
146    
147                    boolean exportPortletData = false;
148    
149                    if (parameterMap.containsKey(
150                                    PortletDataHandlerKeys.PORTLET_DATA + "_" +
151                                            PortletConstants.getRootPortletId(portletId))) {
152    
153                            exportPortletData = MapUtil.getBoolean(
154                                    parameterMap,
155                                    PortletDataHandlerKeys.PORTLET_DATA + "_" +
156                                            PortletConstants.getRootPortletId(portletId));
157                    }
158                    else {
159                            exportPortletData = MapUtil.getBoolean(
160                                    parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
161                    }
162    
163                    boolean exportPortletDataAll = MapUtil.getBoolean(
164                            parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);
165                    boolean exportPortletSetup = MapUtil.getBoolean(
166                            parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
167                    boolean exportPortletUserPreferences = MapUtil.getBoolean(
168                            parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
169                    boolean exportUserPermissions = MapUtil.getBoolean(
170                            parameterMap, PortletDataHandlerKeys.USER_PERMISSIONS);
171    
172                    if (_log.isDebugEnabled()) {
173                            _log.debug("Export categories " + exportCategories);
174                            _log.debug("Export permissions " + exportPermissions);
175                            _log.debug(
176                                    "Export portlet archived setups " +
177                                            exportPortletArchivedSetups);
178                            _log.debug("Export portlet data " + exportPortletData);
179                            _log.debug("Export all portlet data " + exportPortletDataAll);
180                            _log.debug("Export portlet setup " + exportPortletSetup);
181                            _log.debug(
182                                    "Export portlet user preferences " +
183                                            exportPortletUserPreferences);
184                            _log.debug("Export user permissions " + exportUserPermissions);
185                    }
186    
187                    if (exportPortletDataAll) {
188                            exportPortletData = true;
189                    }
190    
191                    StopWatch stopWatch = null;
192    
193                    if (_log.isInfoEnabled()) {
194                            stopWatch = new StopWatch();
195    
196                            stopWatch.start();
197                    }
198    
199                    LayoutCache layoutCache = new LayoutCache();
200    
201                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
202    
203                    if (!layout.isTypeControlPanel() && !layout.isTypePanel() &&
204                            !layout.isTypePortlet()) {
205    
206                            throw new LayoutImportException(
207                                    "Layout type " + layout.getType() + " is not valid");
208                    }
209    
210                    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
211                            layout.getCompanyId());
212    
213                    ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();
214    
215                    long scopeGroupId = groupId;
216    
217                    javax.portlet.PortletPreferences jxPreferences =
218                            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
219                                    layout, portletId);
220    
221                    String scopeType = GetterUtil.getString(
222                            jxPreferences.getValue("lfrScopeType", null));
223                    String scopeLayoutUuid = GetterUtil.getString(
224                            jxPreferences.getValue("lfrScopeLayoutUuid", null));
225    
226                    if (Validator.isNotNull(scopeType)) {
227                            Group scopeGroup = null;
228    
229                            if (scopeType.equals("company")) {
230                                    scopeGroup = GroupLocalServiceUtil.getCompanyGroup(
231                                            layout.getCompanyId());
232                            }
233                            else if (Validator.isNotNull(scopeLayoutUuid)) {
234                                    scopeGroup = layout.getScopeGroup();
235                            }
236    
237                            if (scopeGroup != null) {
238                                    scopeGroupId = scopeGroup.getGroupId();
239                            }
240                    }
241    
242                    PortletDataContext portletDataContext = new PortletDataContextImpl(
243                            layout.getCompanyId(), scopeGroupId, parameterMap,
244                            new HashSet<String>(), startDate, endDate, zipWriter);
245    
246                    portletDataContext.setPortetDataContextListener(
247                            new PortletDataContextListenerImpl(portletDataContext));
248    
249                    portletDataContext.setPlid(plid);
250                    portletDataContext.setOldPlid(plid);
251                    portletDataContext.setScopeType(scopeType);
252                    portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);
253    
254                    Document document = SAXReaderUtil.createDocument();
255    
256                    Element rootElement = document.addElement("root");
257    
258                    Element headerElement = rootElement.addElement("header");
259    
260                    headerElement.addAttribute(
261                            "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
262                    headerElement.addAttribute("export-date", Time.getRFC822());
263    
264                    if (portletDataContext.hasDateRange()) {
265                            headerElement.addAttribute(
266                                    "start-date",
267                                    String.valueOf(portletDataContext.getStartDate()));
268                            headerElement.addAttribute(
269                                    "end-date", String.valueOf(portletDataContext.getEndDate()));
270                    }
271    
272                    headerElement.addAttribute("type", "portlet");
273                    headerElement.addAttribute("group-id", String.valueOf(scopeGroupId));
274                    headerElement.addAttribute(
275                            "private-layout", String.valueOf(layout.isPrivateLayout()));
276                    headerElement.addAttribute(
277                            "root-portlet-id", PortletConstants.getRootPortletId(portletId));
278    
279                    exportPortlet(
280                            portletDataContext, layoutCache, portletId, layout, rootElement,
281                            defaultUserId, exportPermissions, exportPortletArchivedSetups,
282                            exportPortletData, exportPortletSetup, exportPortletUserPreferences,
283                            exportUserPermissions);
284    
285                    if (exportCategories) {
286                            exportAssetCategories(portletDataContext);
287                    }
288    
289                    exportAssetLinks(portletDataContext);
290                    exportAssetTags(portletDataContext);
291                    exportComments(portletDataContext);
292                    exportExpandoTables(portletDataContext);
293                    exportLocks(portletDataContext);
294    
295                    if (exportPermissions) {
296                            _permissionExporter.exportPortletDataPermissions(
297                                    portletDataContext);
298                    }
299    
300                    exportRatingsEntries(portletDataContext, rootElement);
301    
302                    if (_log.isInfoEnabled()) {
303                            _log.info("Exporting portlet took " + stopWatch.getTime() + " ms");
304                    }
305    
306                    try {
307                            portletDataContext.addZipEntry(
308                                    "/manifest.xml", document.formattedString());
309                    }
310                    catch (IOException ioe) {
311                            throw new SystemException(ioe);
312                    }
313    
314                    return zipWriter.getFile();
315            }
316    
317            protected void exportAssetCategories(PortletDataContext portletDataContext)
318                    throws Exception {
319    
320                    Document document = SAXReaderUtil.createDocument();
321    
322                    Element rootElement = document.addElement("categories-hierarchy");
323    
324                    exportAssetCategories(portletDataContext, rootElement);
325    
326                    portletDataContext.addZipEntry(
327                            portletDataContext.getRootPath() + "/categories-hierarchy.xml",
328                            document.formattedString());
329            }
330    
331            protected void exportAssetCategories(
332                            PortletDataContext portletDataContext, Element rootElement)
333                    throws Exception {
334    
335                    Element assetVocabulariesElement = rootElement.element("vocabularies");
336    
337                    if (assetVocabulariesElement == null) {
338                            assetVocabulariesElement = rootElement.addElement("vocabularies");
339                    }
340    
341                    Element assetsElement = rootElement.addElement("assets");
342    
343                    Element assetCategoriesElement = rootElement.addElement("categories");
344    
345                    Map<String, String[]> assetCategoryUuidsMap =
346                            portletDataContext.getAssetCategoryUuidsMap();
347    
348                    for (Map.Entry<String, String[]> entry :
349                                    assetCategoryUuidsMap.entrySet()) {
350    
351                            String[] assetCategoryEntryParts = StringUtil.split(
352                                    entry.getKey(), CharPool.POUND);
353    
354                            String className = assetCategoryEntryParts[0];
355                            long classPK = GetterUtil.getLong(assetCategoryEntryParts[1]);
356    
357                            Element assetElement = assetsElement.addElement("asset");
358    
359                            assetElement.addAttribute("class-name", className);
360                            assetElement.addAttribute("class-pk", String.valueOf(classPK));
361                            assetElement.addAttribute(
362                                    "category-uuids", StringUtil.merge(entry.getValue()));
363    
364                            List<AssetCategory> assetCategories =
365                                    AssetCategoryServiceUtil.getCategories(className, classPK);
366    
367                            for (AssetCategory assestCategory : assetCategories) {
368                                    exportAssetCategory(
369                                            portletDataContext, assetVocabulariesElement,
370                                            assetCategoriesElement, assestCategory);
371                            }
372                    }
373            }
374    
375            protected void exportAssetCategory(
376                            PortletDataContext portletDataContext,
377                            Element assetVocabulariesElement, Element assetCategoriesElement,
378                            AssetCategory assetCategory)
379                    throws Exception {
380    
381                    exportAssetVocabulary(
382                            portletDataContext, assetVocabulariesElement,
383                            assetCategory.getVocabularyId());
384    
385                    if (assetCategory.getParentCategoryId() !=
386                                    AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
387    
388                            exportAssetCategory(
389                                    portletDataContext, assetVocabulariesElement,
390                                    assetCategoriesElement, assetCategory.getParentCategoryId());
391                    }
392    
393                    String path = getAssetCategoryPath(
394                            portletDataContext, assetCategory.getCategoryId());
395    
396                    if (!portletDataContext.isPathNotProcessed(path)) {
397                            return;
398                    }
399    
400                    Element assetCategoryElement = assetCategoriesElement.addElement(
401                            "category");
402    
403                    assetCategoryElement.addAttribute("path", path);
404    
405                    assetCategory.setUserUuid(assetCategory.getUserUuid());
406    
407                    portletDataContext.addZipEntry(path, assetCategory);
408    
409                    List<AssetCategoryProperty> assetCategoryProperties =
410                            AssetCategoryPropertyLocalServiceUtil.getCategoryProperties(
411                                    assetCategory.getCategoryId());
412    
413                    for (AssetCategoryProperty assetCategoryProperty :
414                                    assetCategoryProperties) {
415    
416                            Element propertyElement = assetCategoryElement.addElement(
417                                    "property");
418    
419                            propertyElement.addAttribute(
420                                    "userUuid", assetCategoryProperty.getUserUuid());
421                            propertyElement.addAttribute("key", assetCategoryProperty.getKey());
422                            propertyElement.addAttribute(
423                                    "value", assetCategoryProperty.getValue());
424                    }
425    
426                    portletDataContext.addPermissions(
427                            AssetCategory.class, assetCategory.getCategoryId());
428            }
429    
430            protected void exportAssetCategory(
431                            PortletDataContext portletDataContext,
432                            Element assetVocabulariesElement, Element assetCategoriesElement,
433                            long assetCategoryId)
434                    throws Exception {
435    
436                    AssetCategory assetCategory = AssetCategoryUtil.fetchByPrimaryKey(
437                            assetCategoryId);
438    
439                    if (assetCategory != null) {
440                            exportAssetCategory(
441                                    portletDataContext, assetVocabulariesElement,
442                                    assetCategoriesElement, assetCategory);
443                    }
444            }
445    
446            protected void exportAssetLinks(PortletDataContext portletDataContext)
447                    throws Exception {
448    
449                    Document document = SAXReaderUtil.createDocument();
450    
451                    Element rootElement = document.addElement("links");
452    
453                    Map<String, String[]> assetLinkUuidsMap =
454                            portletDataContext.getAssetLinkUuidsMap();
455    
456                    for (Map.Entry<String, String[]> entry : assetLinkUuidsMap.entrySet()) {
457                            String[] assetLinkNameParts = StringUtil.split(
458                                    entry.getKey(), CharPool.POUND);
459                            String[] targetAssetEntryUuids = entry.getValue();
460    
461                            String sourceAssetEntryUuid = assetLinkNameParts[0];
462                            String assetLinkType = assetLinkNameParts[1];
463    
464                            Element assetElement = rootElement.addElement("asset-link");
465    
466                            assetElement.addAttribute("source-uuid", sourceAssetEntryUuid);
467                            assetElement.addAttribute(
468                                    "target-uuids", StringUtil.merge(targetAssetEntryUuids));
469                            assetElement.addAttribute("type", assetLinkType);
470                    }
471    
472                    portletDataContext.addZipEntry(
473                            portletDataContext.getRootPath() + "/links.xml",
474                            document.formattedString());
475            }
476    
477            protected void exportAssetTag(
478                            PortletDataContext portletDataContext, AssetTag assetTag,
479                            Element assetTagsElement)
480                    throws SystemException, PortalException {
481    
482                    String path = getAssetTagPath(portletDataContext, assetTag.getTagId());
483    
484                    if (!portletDataContext.isPathNotProcessed(path)) {
485                            return;
486                    }
487    
488                    Element assetTagElement = assetTagsElement.addElement("tag");
489    
490                    assetTagElement.addAttribute("path", path);
491    
492                    assetTag.setUserUuid(assetTag.getUserUuid());
493    
494                    portletDataContext.addZipEntry(path, assetTag);
495    
496                    List<AssetTagProperty> assetTagProperties =
497                            AssetTagPropertyLocalServiceUtil.getTagProperties(
498                                    assetTag.getTagId());
499    
500                    for (AssetTagProperty assetTagProperty : assetTagProperties) {
501                            Element propertyElement = assetTagElement.addElement("property");
502    
503                            propertyElement.addAttribute("key", assetTagProperty.getKey());
504                            propertyElement.addAttribute("value", assetTagProperty.getValue());
505                    }
506    
507                    portletDataContext.addPermissions(AssetTag.class, assetTag.getTagId());
508            }
509    
510            protected void exportAssetTags(PortletDataContext portletDataContext)
511                    throws Exception {
512    
513                    Document document = SAXReaderUtil.createDocument();
514    
515                    Element rootElement = document.addElement("tags");
516    
517                    Map<String, String[]> assetTagNamesMap =
518                            portletDataContext.getAssetTagNamesMap();
519    
520                    for (Map.Entry<String, String[]> entry : assetTagNamesMap.entrySet()) {
521                            String[] assetTagNameParts = StringUtil.split(
522                                    entry.getKey(), CharPool.POUND);
523    
524                            String className = assetTagNameParts[0];
525                            String classPK = assetTagNameParts[1];
526    
527                            Element assetElement = rootElement.addElement("asset");
528    
529                            assetElement.addAttribute("class-name", className);
530                            assetElement.addAttribute("class-pk", classPK);
531                            assetElement.addAttribute(
532                                    "tags", StringUtil.merge(entry.getValue()));
533                    }
534    
535                    List<AssetTag> assetTags = AssetTagServiceUtil.getGroupTags(
536                            portletDataContext.getScopeGroupId());
537    
538                    for (AssetTag assetTag : assetTags) {
539                            exportAssetTag(portletDataContext, assetTag, rootElement);
540                    }
541    
542                    portletDataContext.addZipEntry(
543                            portletDataContext.getRootPath() + "/tags.xml",
544                            document.formattedString());
545            }
546    
547            protected void exportAssetVocabulary(
548                            PortletDataContext portletDataContext,
549                            Element assetVocabulariesElement, AssetVocabulary assetVocabulary)
550                    throws Exception {
551    
552                    String path = getAssetVocabulariesPath(
553                            portletDataContext, assetVocabulary.getVocabularyId());
554    
555                    if (!portletDataContext.isPathNotProcessed(path)) {
556                            return;
557                    }
558    
559                    Element assetVocabularyElement = assetVocabulariesElement.addElement(
560                            "vocabulary");
561    
562                    assetVocabularyElement.addAttribute("path", path);
563    
564                    assetVocabulary.setUserUuid(assetVocabulary.getUserUuid());
565    
566                    portletDataContext.addZipEntry(path, assetVocabulary);
567    
568                    portletDataContext.addPermissions(
569                            AssetVocabulary.class, assetVocabulary.getVocabularyId());
570            }
571    
572            protected void exportAssetVocabulary(
573                            PortletDataContext portletDataContext,
574                            Element assetVocabulariesElement, long assetVocabularyId)
575                    throws Exception {
576    
577                    AssetVocabulary assetVocabulary = AssetVocabularyUtil.findByPrimaryKey(
578                            assetVocabularyId);
579    
580                    exportAssetVocabulary(
581                            portletDataContext, assetVocabulariesElement, assetVocabulary);
582            }
583    
584            protected void exportComments(PortletDataContext portletDataContext)
585                    throws Exception {
586    
587                    Document document = SAXReaderUtil.createDocument();
588    
589                    Element rootElement = document.addElement("comments");
590    
591                    Map<String, List<MBMessage>> commentsMap =
592                            portletDataContext.getComments();
593    
594                    for (Map.Entry<String, List<MBMessage>> entry :
595                                    commentsMap.entrySet()) {
596    
597                            String[] commentParts = StringUtil.split(
598                                    entry.getKey(), CharPool.POUND);
599    
600                            String className = commentParts[0];
601                            String classPK = commentParts[1];
602    
603                            String commentsPath = getCommentsPath(
604                                    portletDataContext, className, classPK);
605    
606                            Element assetElement = rootElement.addElement("asset");
607    
608                            assetElement.addAttribute("path", commentsPath);
609                            assetElement.addAttribute("class-name", className);
610                            assetElement.addAttribute("class-pk", classPK);
611    
612                            List<MBMessage> mbMessages = entry.getValue();
613    
614                            for (MBMessage mbMessage : mbMessages) {
615                                    String commentPath = getCommentPath(
616                                            portletDataContext, className, classPK, mbMessage);
617    
618                                    if (portletDataContext.isPathNotProcessed(commentPath)) {
619                                            portletDataContext.addZipEntry(commentPath, mbMessage);
620                                    }
621                            }
622                    }
623    
624                    portletDataContext.addZipEntry(
625                            portletDataContext.getRootPath() + "/comments.xml",
626                            document.formattedString());
627            }
628    
629            protected void exportExpandoTables(PortletDataContext portletDataContext)
630                    throws Exception {
631    
632                    Document document = SAXReaderUtil.createDocument();
633    
634                    Element rootElement = document.addElement("expando-tables");
635    
636                    Map<String, List<ExpandoColumn>> expandoColumnsMap =
637                            portletDataContext.getExpandoColumns();
638    
639                    for (Map.Entry<String, List<ExpandoColumn>> entry :
640                                    expandoColumnsMap.entrySet()) {
641    
642                            String className = entry.getKey();
643    
644                            Element expandoTableElement = rootElement.addElement(
645                                    "expando-table");
646    
647                            expandoTableElement.addAttribute("class-name", className);
648    
649                            List<ExpandoColumn> expandoColumns = entry.getValue();
650    
651                            for (ExpandoColumn expandoColumn: expandoColumns) {
652                                    Element expandoColumnElement =
653                                            expandoTableElement.addElement("expando-column");
654    
655                                    expandoColumnElement.addAttribute(
656                                            "column-id", String.valueOf(expandoColumn.getColumnId()));
657                                    expandoColumnElement.addAttribute(
658                                            "name", expandoColumn.getName());
659                                    expandoColumnElement.addAttribute(
660                                            "type", String.valueOf(expandoColumn.getType()));
661    
662                                    DocUtil.add(
663                                            expandoColumnElement, "default-data",
664                                            expandoColumn.getDefaultData());
665    
666                                    Element typeSettingsElement = expandoColumnElement.addElement(
667                                            "type-settings");
668    
669                                    UnicodeProperties typeSettingsProperties =
670                                            expandoColumn.getTypeSettingsProperties();
671    
672                                    typeSettingsElement.addCDATA(typeSettingsProperties.toString());
673                            }
674                    }
675    
676                    portletDataContext.addZipEntry(
677                            portletDataContext.getRootPath() + "/expando-tables.xml",
678                            document.formattedString());
679            }
680    
681            protected void exportLocks(PortletDataContext portletDataContext)
682                    throws Exception {
683    
684                    Document document = SAXReaderUtil.createDocument();
685    
686                    Element rootElement = document.addElement("locks");
687    
688                    Map<String, Lock> locksMap = portletDataContext.getLocks();
689    
690                    for (Map.Entry<String, Lock> entry : locksMap.entrySet()) {
691                            Lock lock = entry.getValue();
692    
693                            String entryKey = entry.getKey();
694    
695                            int pos = entryKey.indexOf(CharPool.POUND);
696    
697                            String className = entryKey.substring(0, pos);
698                            String key = entryKey.substring(pos + 1);
699    
700                            String path = getLockPath(portletDataContext, className, key, lock);
701    
702                            Element assetElement = rootElement.addElement("asset");
703    
704                            assetElement.addAttribute("path", path);
705                            assetElement.addAttribute("class-name", className);
706                            assetElement.addAttribute("key", key);
707    
708                            if (portletDataContext.isPathNotProcessed(path)) {
709                                    portletDataContext.addZipEntry(path, lock);
710                            }
711                    }
712    
713                    portletDataContext.addZipEntry(
714                            portletDataContext.getRootPath() + "/locks.xml",
715                            document.formattedString());
716            }
717    
718            protected void exportPortlet(
719                            PortletDataContext portletDataContext, LayoutCache layoutCache,
720                            String portletId, Layout layout, Element parentElement,
721                            long defaultUserId, boolean exportPermissions,
722                            boolean exportPortletArchivedSetups, boolean exportPortletData,
723                            boolean exportPortletSetup, boolean exportPortletUserPreferences,
724                            boolean exportUserPermissions)
725                    throws Exception {
726    
727                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
728                            portletDataContext.getCompanyId(), portletId);
729    
730                    if (portlet == null) {
731                            if (_log.isDebugEnabled()) {
732                                    _log.debug(
733                                            "Do not export portlet " + portletId +
734                                                    " because the portlet does not exist");
735                            }
736    
737                            return;
738                    }
739    
740                    if ((!portlet.isInstanceable()) &&
741                            (!portlet.isPreferencesUniquePerLayout()) &&
742                            (portletDataContext.hasNotUniquePerLayout(portletId))) {
743    
744                            return;
745                    }
746    
747                    Document document = SAXReaderUtil.createDocument();
748    
749                    Element portletElement = document.addElement("portlet");
750    
751                    portletElement.addAttribute("portlet-id", portletId);
752                    portletElement.addAttribute(
753                            "root-portlet-id", PortletConstants.getRootPortletId(portletId));
754                    portletElement.addAttribute(
755                            "old-plid", String.valueOf(layout.getPlid()));
756                    portletElement.addAttribute(
757                            "scope-layout-type", portletDataContext.getScopeType());
758                    portletElement.addAttribute(
759                            "scope-layout-uuid", portletDataContext.getScopeLayoutUuid());
760    
761                    // Data
762    
763                    if (exportPortletData) {
764                            javax.portlet.PortletPreferences jxPreferences =
765                                    PortletPreferencesFactoryUtil.getPortletSetup(
766                                            layout, portletId, StringPool.BLANK);
767    
768                            if (!portlet.isPreferencesUniquePerLayout()) {
769                                    StringBundler sb = new StringBundler(5);
770    
771                                    sb.append(portletId);
772                                    sb.append(StringPool.AT);
773                                    sb.append(portletDataContext.getScopeType());
774                                    sb.append(StringPool.AT);
775                                    sb.append(portletDataContext.getScopeLayoutUuid());
776    
777                                    String dataKey = sb.toString();
778    
779                                    if (!portletDataContext.hasNotUniquePerLayout(dataKey)) {
780                                            portletDataContext.putNotUniquePerLayout(dataKey);
781    
782                                            exportPortletData(
783                                                    portletDataContext, portlet, layout, jxPreferences,
784                                                    portletElement);
785                                    }
786                            }
787                            else {
788                                    exportPortletData(
789                                            portletDataContext, portlet, layout, jxPreferences,
790                                            portletElement);
791                            }
792                    }
793    
794                    // Portlet preferences
795    
796                    if (exportPortletSetup) {
797                            exportPortletPreferences(
798                                    portletDataContext, PortletKeys.PREFS_OWNER_ID_DEFAULT,
799                                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, false, layout, portletId,
800                                    portletElement);
801    
802                            exportPortletPreferences(
803                                    portletDataContext, portletDataContext.getScopeGroupId(),
804                                    PortletKeys.PREFS_OWNER_TYPE_GROUP, false, layout, portletId,
805                                    portletElement);
806    
807                            exportPortletPreferences(
808                                    portletDataContext, portletDataContext.getCompanyId(),
809                                    PortletKeys.PREFS_OWNER_TYPE_COMPANY, false, layout, portletId,
810                                    portletElement);
811                    }
812    
813                    // Portlet preferences
814    
815                    if (exportPortletUserPreferences) {
816                            exportPortletPreferences(
817                                    portletDataContext, defaultUserId,
818                                    PortletKeys.PREFS_OWNER_TYPE_USER, true, layout, portletId,
819                                    portletElement);
820    
821                            try {
822                                    PortletPreferences groupPortletPreferences =
823                                            PortletPreferencesLocalServiceUtil.getPortletPreferences(
824                                                    portletDataContext.getScopeGroupId(),
825                                                    PortletKeys.PREFS_OWNER_TYPE_GROUP,
826                                                    PortletKeys.PREFS_PLID_SHARED, portletId);
827    
828                                    exportPortletPreference(
829                                            portletDataContext, portletDataContext.getScopeGroupId(),
830                                            PortletKeys.PREFS_OWNER_TYPE_GROUP, false,
831                                            groupPortletPreferences, portletId,
832                                            PortletKeys.PREFS_PLID_SHARED, portletElement);
833                            }
834                            catch (NoSuchPortletPreferencesException nsppe) {
835                            }
836                    }
837    
838                    // Archived setups
839    
840                    if (exportPortletArchivedSetups) {
841                            String rootPortletId = PortletConstants.getRootPortletId(portletId);
842    
843                            List<PortletItem> portletItems =
844                                    PortletItemLocalServiceUtil.getPortletItems(
845                                            portletDataContext.getGroupId(), rootPortletId,
846                                            PortletPreferences.class.getName());
847    
848                            for (PortletItem portletItem : portletItems) {
849                                    exportPortletPreferences(
850                                            portletDataContext, portletItem.getPortletItemId(),
851                                            PortletKeys.PREFS_OWNER_TYPE_ARCHIVED, false, null,
852                                            portletItem.getPortletId(), portletElement);
853                            }
854                    }
855    
856                    // Permissions
857    
858                    if (exportPermissions) {
859                            _permissionExporter.exportPortletPermissions(
860                                    portletDataContext, layoutCache, portletId, layout,
861                                    portletElement);
862                    }
863    
864                    // Zip
865    
866                    StringBundler sb = new StringBundler(4);
867    
868                    sb.append(portletDataContext.getPortletPath(portletId));
869                    sb.append(StringPool.SLASH);
870                    sb.append(layout.getPlid());
871                    sb.append("/portlet.xml");
872    
873                    String path = sb.toString();
874    
875                    Element element = parentElement.addElement("portlet");
876    
877                    element.addAttribute("portlet-id", portletId);
878                    element.addAttribute("layout-id", String.valueOf(layout.getLayoutId()));
879                    element.addAttribute("path", path);
880    
881                    if (portletDataContext.isPathNotProcessed(path)) {
882                            try {
883                                    portletDataContext.addZipEntry(
884                                            path, document.formattedString());
885                            }
886                            catch (IOException ioe) {
887                                    if (_log.isWarnEnabled()) {
888                                            _log.warn(ioe.getMessage());
889                                    }
890                            }
891    
892                            portletDataContext.addPrimaryKey(String.class, path);
893                    }
894            }
895    
896            protected void exportPortletData(
897                            PortletDataContext portletDataContext, Portlet portlet,
898                            Layout layout, javax.portlet.PortletPreferences jxPreferences,
899                            Element parentElement)
900                    throws Exception {
901    
902                    PortletDataHandler portletDataHandler =
903                            portlet.getPortletDataHandlerInstance();
904    
905                    if (portletDataHandler == null) {
906                            return;
907                    }
908    
909                    String portletId = portlet.getPortletId();
910    
911                    Group liveGroup = layout.getGroup();
912    
913                    if (liveGroup.isStagingGroup()) {
914                            liveGroup = liveGroup.getLiveGroup();
915                    }
916    
917                    boolean staged = liveGroup.isStagedPortlet(portlet.getRootPortletId());
918    
919                    if (!staged && ImportExportThreadLocal.isLayoutExportInProcess()) {
920                            if (_log.isDebugEnabled()) {
921                                    _log.debug(
922                                            "Not exporting data for " + portletId +
923                                                    " because it is configured not to be staged");
924                            }
925    
926                            return;
927                    }
928    
929                    if (_log.isDebugEnabled()) {
930                            _log.debug("Exporting data for " + portletId);
931                    }
932    
933                    StringBundler sb = new StringBundler(4);
934    
935                    sb.append(portletDataContext.getPortletPath(portletId));
936                    sb.append(StringPool.SLASH);
937    
938                    if (portlet.isPreferencesUniquePerLayout()) {
939                            sb.append(layout.getPlid());
940                    }
941                    else {
942                            sb.append(portletDataContext.getScopeGroupId());
943                    }
944    
945                    sb.append("/portlet-data.xml");
946    
947                    String path = sb.toString();
948    
949                    if (!portletDataContext.isPathNotProcessed(path)) {
950                            return;
951                    }
952    
953                    long lastPublishDate = GetterUtil.getLong(
954                            jxPreferences.getValue("last-publish-date", StringPool.BLANK));
955    
956                    Date startDate = portletDataContext.getStartDate();
957    
958                    if ((lastPublishDate > 0) && (startDate != null) &&
959                            (lastPublishDate < startDate.getTime())) {
960    
961                            portletDataContext.setStartDate(new Date(lastPublishDate));
962                    }
963    
964                    String data = null;
965    
966                    long groupId = portletDataContext.getGroupId();
967    
968                    portletDataContext.setGroupId(portletDataContext.getScopeGroupId());
969    
970                    try {
971                            data = portletDataHandler.exportData(
972                                    portletDataContext, portletId, jxPreferences);
973                    }
974                    catch (Exception e) {
975                            throw new SystemException(e);
976                    }
977                    finally {
978                            portletDataContext.setGroupId(groupId);
979                            portletDataContext.setStartDate(startDate);
980                    }
981    
982                    if (Validator.isNull(data)) {
983                            if (_log.isDebugEnabled()) {
984                                    _log.debug(
985                                            "Not exporting data for " + portletId +
986                                                    " because null data was returned");
987                            }
988    
989                            return;
990                    }
991    
992                    Element portletDataElement = parentElement.addElement("portlet-data");
993    
994                    portletDataElement.addAttribute("path", path);
995    
996                    portletDataContext.addZipEntry(path, data);
997    
998                    Date endDate = portletDataContext.getEndDate();
999    
1000                    if (endDate != null) {
1001                            try {
1002                                    jxPreferences.setValue(
1003                                            "last-publish-date", String.valueOf(endDate.getTime()));
1004    
1005                                    jxPreferences.store();
1006                            }
1007                            catch (Exception e) {
1008                                    _log.error(e, e);
1009                            }
1010                    }
1011            }
1012    
1013            protected void exportPortletPreference(
1014                            PortletDataContext portletDataContext, long ownerId, int ownerType,
1015                            boolean defaultUser, PortletPreferences portletPreferences,
1016                            String portletId, long plid, Element parentElement)
1017                    throws Exception {
1018    
1019                    String preferencesXML = portletPreferences.getPreferences();
1020    
1021                    if (Validator.isNull(preferencesXML)) {
1022                            preferencesXML = PortletConstants.DEFAULT_PREFERENCES;
1023                    }
1024    
1025                    Document document = SAXReaderUtil.read(preferencesXML);
1026    
1027                    Element rootElement = document.getRootElement();
1028    
1029                    rootElement.addAttribute("owner-id", String.valueOf(ownerId));
1030                    rootElement.addAttribute("owner-type", String.valueOf(ownerType));
1031                    rootElement.addAttribute("default-user", String.valueOf(defaultUser));
1032                    rootElement.addAttribute("plid", String.valueOf(plid));
1033                    rootElement.addAttribute("portlet-id", portletId);
1034    
1035                    if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
1036                            PortletItem portletItem =
1037                                    PortletItemLocalServiceUtil.getPortletItem(ownerId);
1038    
1039                            rootElement.addAttribute(
1040                                    "archive-user-uuid", portletItem.getUserUuid());
1041                            rootElement.addAttribute("archive-name", portletItem.getName());
1042                    }
1043    
1044                    List<Node> nodes = document.selectNodes(
1045                            "/portlet-preferences/preference[name/text() = " +
1046                                    "'last-publish-date']");
1047    
1048                    for (Node node : nodes) {
1049                            document.remove(node);
1050                    }
1051    
1052                    String path = getPortletPreferencesPath(
1053                            portletDataContext, portletId, ownerId, ownerType, plid);
1054    
1055                    Element portletPreferencesElement = parentElement.addElement(
1056                            "portlet-preferences");
1057    
1058                    portletPreferencesElement.addAttribute("path", path);
1059    
1060                    if (portletDataContext.isPathNotProcessed(path)) {
1061                            portletDataContext.addZipEntry(
1062                                    path, document.formattedString(StringPool.TAB, false, false));
1063                    }
1064            }
1065    
1066            protected void exportPortletPreferences(
1067                            PortletDataContext portletDataContext, long ownerId, int ownerType,
1068                            boolean defaultUser, Layout layout, String portletId,
1069                            Element parentElement)
1070                    throws Exception {
1071    
1072                    PortletPreferences portletPreferences = null;
1073    
1074                    long plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
1075    
1076                    if (layout != null) {
1077                            plid = layout.getPlid();
1078                    }
1079    
1080                    if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) ||
1081                            (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) ||
1082                            (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED)) {
1083    
1084                            plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
1085                    }
1086    
1087                    try {
1088                            portletPreferences =
1089                                    PortletPreferencesLocalServiceUtil.getPortletPreferences(
1090                                            ownerId, ownerType, plid, portletId);
1091                    }
1092                    catch (NoSuchPortletPreferencesException nsppe) {
1093                            return;
1094                    }
1095    
1096                    LayoutTypePortlet layoutTypePortlet = null;
1097    
1098                    if (layout != null) {
1099                            layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
1100                    }
1101    
1102                    if ((layoutTypePortlet == null) ||
1103                            (layoutTypePortlet.hasPortletId(portletId))) {
1104    
1105                            exportPortletPreference(
1106                                    portletDataContext, ownerId, ownerType, defaultUser,
1107                                    portletPreferences, portletId, plid, parentElement);
1108                    }
1109            }
1110    
1111            protected void exportRatingsEntries(
1112                            PortletDataContext portletDataContext, Element parentElement)
1113                    throws Exception {
1114    
1115                    Document document = SAXReaderUtil.createDocument();
1116    
1117                    Element rootElement = document.addElement("ratings");
1118    
1119                    Map<String, List<RatingsEntry>> ratingsEntriesMap =
1120                            portletDataContext.getRatingsEntries();
1121    
1122                    for (Map.Entry<String, List<RatingsEntry>> entry :
1123                                    ratingsEntriesMap.entrySet()) {
1124    
1125                            String[] ratingsEntryParts = StringUtil.split(
1126                                    entry.getKey(), CharPool.POUND);
1127    
1128                            String className = ratingsEntryParts[0];
1129                            String classPK = ratingsEntryParts[1];
1130    
1131                            String ratingsEntriesPath = getRatingsEntriesPath(
1132                                    portletDataContext, className, classPK);
1133    
1134                            Element assetElement = rootElement.addElement("asset");
1135    
1136                            assetElement.addAttribute("path", ratingsEntriesPath);
1137                            assetElement.addAttribute("class-name", className);
1138                            assetElement.addAttribute("class-pk", classPK);
1139    
1140                            List<RatingsEntry> ratingsEntries = entry.getValue();
1141    
1142                            for (RatingsEntry ratingsEntry : ratingsEntries) {
1143                                    String ratingsEntryPath = getRatingsEntryPath(
1144                                            portletDataContext, className, classPK, ratingsEntry);
1145    
1146                                    portletDataContext.addZipEntry(ratingsEntryPath, ratingsEntry);
1147                            }
1148                    }
1149    
1150                    portletDataContext.addZipEntry(
1151                            portletDataContext.getRootPath() + "/ratings.xml",
1152                            document.formattedString());
1153            }
1154    
1155            protected String getAssetCategoryPath(
1156                    PortletDataContext portletDataContext, long assetCategoryId) {
1157    
1158                    StringBundler sb = new StringBundler(6);
1159    
1160                    sb.append(portletDataContext.getRootPath());
1161                    sb.append("/categories/");
1162                    sb.append(assetCategoryId);
1163                    sb.append(".xml");
1164    
1165                    return sb.toString();
1166            }
1167    
1168            protected String getAssetTagPath(
1169                    PortletDataContext portletDataContext, long assetCategoryId) {
1170    
1171                    StringBundler sb = new StringBundler(4);
1172    
1173                    sb.append(portletDataContext.getRootPath());
1174                    sb.append("/tags/");
1175                    sb.append(assetCategoryId);
1176                    sb.append(".xml");
1177    
1178                    return sb.toString();
1179            }
1180    
1181            protected String getAssetVocabulariesPath(
1182                    PortletDataContext portletDataContext, long assetVocabularyId) {
1183    
1184                    StringBundler sb = new StringBundler(8);
1185    
1186                    sb.append(portletDataContext.getRootPath());
1187                    sb.append("/vocabularies/");
1188                    sb.append(assetVocabularyId);
1189                    sb.append(".xml");
1190    
1191                    return sb.toString();
1192            }
1193    
1194            protected String getCommentPath(
1195                    PortletDataContext portletDataContext, String className, String classPK,
1196                    MBMessage mbMessage) {
1197    
1198                    StringBundler sb = new StringBundler(8);
1199    
1200                    sb.append(portletDataContext.getRootPath());
1201                    sb.append("/comments/");
1202                    sb.append(PortalUtil.getClassNameId(className));
1203                    sb.append(CharPool.FORWARD_SLASH);
1204                    sb.append(classPK);
1205                    sb.append(CharPool.FORWARD_SLASH);
1206                    sb.append(mbMessage.getMessageId());
1207                    sb.append(".xml");
1208    
1209                    return sb.toString();
1210            }
1211    
1212            protected String getCommentsPath(
1213                    PortletDataContext portletDataContext, String className,
1214                    String classPK) {
1215    
1216                    StringBundler sb = new StringBundler(6);
1217    
1218                    sb.append(portletDataContext.getRootPath());
1219                    sb.append("/comments/");
1220                    sb.append(PortalUtil.getClassNameId(className));
1221                    sb.append(CharPool.FORWARD_SLASH);
1222                    sb.append(classPK);
1223                    sb.append(CharPool.FORWARD_SLASH);
1224    
1225                    return sb.toString();
1226            }
1227    
1228            protected String getLockPath(
1229                    PortletDataContext portletDataContext, String className, String key,
1230                    Lock lock) {
1231    
1232                    StringBundler sb = new StringBundler(8);
1233    
1234                    sb.append(portletDataContext.getRootPath());
1235                    sb.append("/locks/");
1236                    sb.append(PortalUtil.getClassNameId(className));
1237                    sb.append(CharPool.FORWARD_SLASH);
1238                    sb.append(key);
1239                    sb.append(CharPool.FORWARD_SLASH);
1240                    sb.append(lock.getLockId());
1241                    sb.append(".xml");
1242    
1243                    return sb.toString();
1244            }
1245    
1246            protected String getPortletDataPath(
1247                    PortletDataContext portletDataContext, String portletId) {
1248    
1249                    return portletDataContext.getPortletPath(portletId) +
1250                            "/portlet-data.xml";
1251            }
1252    
1253            protected String getPortletPreferencesPath(
1254                    PortletDataContext portletDataContext, String portletId, long ownerId,
1255                    int ownerType, long plid) {
1256    
1257                    StringBundler sb = new StringBundler(8);
1258    
1259                    sb.append(portletDataContext.getPortletPath(portletId));
1260                    sb.append("/preferences/");
1261    
1262                    if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
1263                            sb.append("company/");
1264                    }
1265                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
1266                            sb.append("group/");
1267                    }
1268                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_LAYOUT) {
1269                            sb.append("layout/");
1270                    }
1271                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) {
1272                            sb.append("user/");
1273                    }
1274                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
1275                            sb.append("archived/");
1276                    }
1277    
1278                    sb.append(ownerId);
1279                    sb.append(CharPool.FORWARD_SLASH);
1280                    sb.append(plid);
1281                    sb.append(CharPool.FORWARD_SLASH);
1282                    sb.append("portlet-preferences.xml");
1283    
1284                    return sb.toString();
1285            }
1286    
1287            protected String getRatingsEntriesPath(
1288                    PortletDataContext portletDataContext, String className,
1289                    String classPK) {
1290    
1291                    StringBundler sb = new StringBundler(6);
1292    
1293                    sb.append(portletDataContext.getRootPath());
1294                    sb.append("/ratings/");
1295                    sb.append(PortalUtil.getClassNameId(className));
1296                    sb.append(CharPool.FORWARD_SLASH);
1297                    sb.append(classPK);
1298                    sb.append(CharPool.FORWARD_SLASH);
1299    
1300                    return sb.toString();
1301            }
1302    
1303            protected String getRatingsEntryPath(
1304                    PortletDataContext portletDataContext, String className, String classPK,
1305                    RatingsEntry ratingsEntry) {
1306    
1307                    StringBundler sb = new StringBundler(8);
1308    
1309                    sb.append(portletDataContext.getRootPath());
1310                    sb.append("/ratings/");
1311                    sb.append(PortalUtil.getClassNameId(className));
1312                    sb.append(CharPool.FORWARD_SLASH);
1313                    sb.append(classPK);
1314                    sb.append(CharPool.FORWARD_SLASH);
1315                    sb.append(ratingsEntry.getEntryId());
1316                    sb.append(".xml");
1317    
1318                    return sb.toString();
1319            }
1320    
1321            private static Log _log = LogFactoryUtil.getLog(PortletExporter.class);
1322    
1323            private PermissionExporter _permissionExporter = new PermissionExporter();
1324    
1325    }