001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.PortletDataContext;
022    import com.liferay.portal.kernel.lar.PortletDataHandler;
023    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
024    import com.liferay.portal.kernel.log.Log;
025    import com.liferay.portal.kernel.log.LogFactoryUtil;
026    import com.liferay.portal.kernel.util.CharPool;
027    import com.liferay.portal.kernel.util.FileUtil;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.MapUtil;
030    import com.liferay.portal.kernel.util.ReleaseInfo;
031    import com.liferay.portal.kernel.util.StringBundler;
032    import com.liferay.portal.kernel.util.StringPool;
033    import com.liferay.portal.kernel.util.StringUtil;
034    import com.liferay.portal.kernel.util.Time;
035    import com.liferay.portal.kernel.util.Validator;
036    import com.liferay.portal.kernel.xml.Document;
037    import com.liferay.portal.kernel.xml.Element;
038    import com.liferay.portal.kernel.xml.Node;
039    import com.liferay.portal.kernel.xml.SAXReaderUtil;
040    import com.liferay.portal.kernel.zip.ZipWriter;
041    import com.liferay.portal.kernel.zip.ZipWriterFactoryUtil;
042    import com.liferay.portal.model.Group;
043    import com.liferay.portal.model.Layout;
044    import com.liferay.portal.model.LayoutTypePortlet;
045    import com.liferay.portal.model.Lock;
046    import com.liferay.portal.model.Portlet;
047    import com.liferay.portal.model.PortletConstants;
048    import com.liferay.portal.model.PortletItem;
049    import com.liferay.portal.model.PortletPreferences;
050    import com.liferay.portal.model.User;
051    import com.liferay.portal.service.LayoutLocalServiceUtil;
052    import com.liferay.portal.service.PortletItemLocalServiceUtil;
053    import com.liferay.portal.service.PortletLocalServiceUtil;
054    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
055    import com.liferay.portal.service.UserLocalServiceUtil;
056    import com.liferay.portal.util.PortalUtil;
057    import com.liferay.portal.util.PortletKeys;
058    import com.liferay.portlet.PortletPreferencesFactoryUtil;
059    import com.liferay.portlet.asset.model.AssetCategory;
060    import com.liferay.portlet.asset.model.AssetCategoryConstants;
061    import com.liferay.portlet.asset.model.AssetCategoryProperty;
062    import com.liferay.portlet.asset.model.AssetVocabulary;
063    import com.liferay.portlet.asset.service.AssetCategoryPropertyLocalServiceUtil;
064    import com.liferay.portlet.asset.service.AssetCategoryServiceUtil;
065    import com.liferay.portlet.asset.service.persistence.AssetCategoryUtil;
066    import com.liferay.portlet.asset.service.persistence.AssetVocabularyUtil;
067    import com.liferay.portlet.messageboards.model.MBMessage;
068    import com.liferay.portlet.ratings.model.RatingsEntry;
069    
070    import java.io.File;
071    import java.io.IOException;
072    
073    import java.util.Date;
074    import java.util.HashSet;
075    import java.util.List;
076    import java.util.Map;
077    
078    import org.apache.commons.lang.time.StopWatch;
079    
080    /**
081     * @author Brian Wing Shun Chan
082     * @author Joel Kozikowski
083     * @author Charles May
084     * @author Raymond Augé
085     * @author Jorge Ferrer
086     * @author Bruno Farache
087     * @author Zsigmond Rab
088     * @author Douglas Wong
089     */
090    public class PortletExporter {
091    
092            public byte[] exportPortletInfo(
093                            long plid, long groupId, String portletId,
094                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
095                    throws Exception {
096    
097                    File file = exportPortletInfoAsFile(
098                            plid, groupId, portletId, parameterMap, startDate, endDate);
099    
100                    try {
101                            return FileUtil.getBytes(file);
102                    }
103                    catch (IOException ioe) {
104                            throw new SystemException(ioe);
105                    }
106                    finally {
107                            file.delete();
108                    }
109            }
110    
111            public File exportPortletInfoAsFile(
112                            long plid, long groupId, String portletId,
113                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
114                    throws Exception {
115    
116                    boolean exportCategories = MapUtil.getBoolean(
117                            parameterMap, PortletDataHandlerKeys.CATEGORIES);
118                    boolean exportPermissions = MapUtil.getBoolean(
119                            parameterMap, PortletDataHandlerKeys.PERMISSIONS);
120                    boolean exportPortletArchivedSetups = MapUtil.getBoolean(
121                            parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
122                    boolean exportPortletData = MapUtil.getBoolean(
123                            parameterMap, PortletDataHandlerKeys.PORTLET_DATA + "_" +
124                            PortletConstants.getRootPortletId(portletId));
125                    boolean exportPortletDataAll = MapUtil.getBoolean(
126                            parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);
127                    boolean exportPortletSetup = MapUtil.getBoolean(
128                            parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
129                    boolean exportPortletUserPreferences = MapUtil.getBoolean(
130                            parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
131                    boolean exportUserPermissions = MapUtil.getBoolean(
132                            parameterMap, PortletDataHandlerKeys.USER_PERMISSIONS);
133    
134                    if (_log.isDebugEnabled()) {
135                            _log.debug("Export categories " + exportCategories);
136                            _log.debug("Export permissions " + exportPermissions);
137                            _log.debug(
138                                    "Export portlet archived setups " +
139                                            exportPortletArchivedSetups);
140                            _log.debug("Export portlet data " + exportPortletData);
141                            _log.debug("Export all portlet data " + exportPortletDataAll);
142                            _log.debug("Export portlet setup " + exportPortletSetup);
143                            _log.debug(
144                                    "Export portlet user preferences " +
145                                            exportPortletUserPreferences);
146                            _log.debug("Export user permissions " + exportUserPermissions);
147                    }
148    
149                    if (exportPortletDataAll) {
150                            exportPortletData = true;
151                    }
152    
153                    long lastPublishDate = System.currentTimeMillis();
154    
155                    if (endDate != null) {
156                            lastPublishDate = endDate.getTime();
157                    }
158    
159                    StopWatch stopWatch = null;
160    
161                    if (_log.isInfoEnabled()) {
162                            stopWatch = new StopWatch();
163    
164                            stopWatch.start();
165                    }
166    
167                    LayoutCache layoutCache = new LayoutCache();
168    
169                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
170    
171                    if (!layout.isTypeControlPanel() && !layout.isTypePanel() &&
172                            !layout.isTypePortlet()) {
173    
174                            throw new LayoutImportException(
175                                    "Layout type " + layout.getType() + " is not valid");
176                    }
177    
178                    long companyId = layout.getCompanyId();
179                    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
180    
181                    ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();
182    
183                    long scopeGroupId = groupId;
184    
185                    javax.portlet.PortletPreferences jxPreferences =
186                            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
187                                    layout, portletId);
188    
189                    String scopeLayoutUuid = GetterUtil.getString(
190                            jxPreferences.getValue("lfr-scope-layout-uuid", null));
191    
192                    if (Validator.isNotNull(scopeLayoutUuid)) {
193                            Group scopeGroup = layout.getScopeGroup();
194    
195                            if (scopeGroup != null) {
196                                    scopeGroupId = scopeGroup.getGroupId();
197                            }
198                    }
199    
200                    PortletDataContext context = new PortletDataContextImpl(
201                            companyId, scopeGroupId, parameterMap, new HashSet<String>(),
202                            startDate, endDate, zipWriter);
203    
204                    context.setPortetDataContextListener(
205                            new PortletDataContextListenerImpl(context));
206    
207                    context.setPlid(plid);
208                    context.setOldPlid(plid);
209                    context.setScopeLayoutUuid(scopeLayoutUuid);
210    
211                    // Build compatibility
212    
213                    Document doc = SAXReaderUtil.createDocument();
214    
215                    Element root = doc.addElement("root");
216    
217                    Element header = root.addElement("header");
218    
219                    header.addAttribute(
220                            "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
221                    header.addAttribute("export-date", Time.getRFC822());
222    
223                    if (context.hasDateRange()) {
224                            header.addAttribute(
225                                    "start-date", String.valueOf(context.getStartDate()));
226                            header.addAttribute(
227                                    "end-date", String.valueOf(context.getEndDate()));
228                    }
229    
230                    header.addAttribute("type", "portlet");
231                    header.addAttribute("group-id", String.valueOf(scopeGroupId));
232                    header.addAttribute(
233                            "private-layout", String.valueOf(layout.isPrivateLayout()));
234                    header.addAttribute(
235                            "root-portlet-id", PortletConstants.getRootPortletId(portletId));
236    
237                    // Portlet
238    
239                    exportPortlet(
240                            context, layoutCache, portletId, layout, root, defaultUserId,
241                            exportPermissions, exportPortletArchivedSetups, exportPortletData,
242                            exportPortletSetup, exportPortletUserPreferences,
243                            exportUserPermissions);
244    
245                    // Categories
246    
247                    if (exportCategories) {
248                            exportCategories(context);
249                    }
250    
251                    // Comments
252    
253                    exportComments(context, root);
254    
255                    // Locks
256    
257                    exportLocks(context, root);
258    
259                    // Portlet data permissions
260    
261                    if (exportPermissions) {
262                            _permissionExporter.exportPortletDataPermissions(context);
263                    }
264    
265                    // Ratings
266    
267                    exportRatings(context, root);
268    
269                    // Tags
270    
271                    exportTags(context, root);
272    
273                    // Log
274    
275                    if (_log.isInfoEnabled()) {
276                            _log.info("Exporting portlet took " + stopWatch.getTime() + " ms");
277                    }
278    
279                    // Zip
280    
281                    try {
282                            context.addZipEntry("/manifest.xml", doc.formattedString());
283                    }
284                    catch (IOException ioe) {
285                            throw new SystemException(ioe);
286                    }
287    
288                    try {
289                            return zipWriter.getFile();
290                    }
291                    finally {
292                            updateLastPublishDate(layout, portletId, lastPublishDate);
293                    }
294            }
295    
296            protected void exportCategories(PortletDataContext context)
297                    throws SystemException {
298    
299                    try {
300                            Document doc = SAXReaderUtil.createDocument();
301    
302                            Element root = doc.addElement("categories-hierarchy");
303    
304                            exportCategories(context, root);
305    
306                            context.addZipEntry(
307                                    context.getRootPath() + "/categories-hierarchy.xml",
308                                    doc.formattedString());
309                    }
310                    catch (Exception e) {
311                            throw new SystemException(e);
312                    }
313            }
314    
315            protected void exportCategories(PortletDataContext context, Element root)
316                    throws SystemException {
317    
318                    try {
319                            Element vocabulariesEl = root.element("vocabularies");
320    
321                            if (vocabulariesEl == null) {
322                                    vocabulariesEl = root.addElement("vocabularies");
323                            }
324    
325                            Element assetsEl = root.addElement("assets");
326    
327                            Element categoriesEl = root.addElement("categories");
328    
329                            Map<String, String[]> assetCategoryUuidsMap =
330                                    context.getAssetCategoryUuidsMap();
331    
332                            for (Map.Entry<String, String[]> entry :
333                                            assetCategoryUuidsMap.entrySet()) {
334    
335                                    String[] categoryEntry = entry.getKey().split(StringPool.POUND);
336    
337                                    String className = categoryEntry[0];
338                                    long classPK = GetterUtil.getLong(categoryEntry[1]);
339    
340                                    Element asset = assetsEl.addElement("asset");
341    
342                                    asset.addAttribute("class-name", className);
343                                    asset.addAttribute("class-pk", String.valueOf(classPK));
344                                    asset.addAttribute(
345                                            "category-uuids", StringUtil.merge(entry.getValue()));
346    
347                                    List<AssetCategory> assetCategories =
348                                            AssetCategoryServiceUtil.getCategories(className, classPK);
349    
350                                    for (AssetCategory assestCategory : assetCategories) {
351                                            exportCategory(
352                                                    context, vocabulariesEl, categoriesEl, assestCategory);
353                                    }
354                            }
355                    }
356                    catch (Exception e) {
357                            throw new SystemException(e);
358                    }
359            }
360    
361            protected void exportCategory(
362                            PortletDataContext context, Element vocabulariesEl,
363                            Element categoryEls, long assetCategoryId)
364                    throws Exception {
365    
366                    AssetCategory assetCategory = AssetCategoryUtil.fetchByPrimaryKey(
367                            assetCategoryId);
368    
369                    if (assetCategory != null) {
370                            exportCategory(context, vocabulariesEl, categoryEls, assetCategory);
371                    }
372            }
373    
374            protected void exportCategory(
375                            PortletDataContext context, Element vocabulariesEl,
376                            Element categoriesEl, AssetCategory assetCategory)
377                    throws Exception {
378    
379                    exportVocabulary(
380                            context, vocabulariesEl, assetCategory.getVocabularyId());
381    
382                    if (assetCategory.getParentCategoryId() !=
383                                    AssetCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
384    
385                            exportCategory(
386                                    context, vocabulariesEl, categoriesEl,
387                                    assetCategory.getParentCategoryId());
388                    }
389    
390                    String path = getCategoryPath(context, assetCategory.getCategoryId());
391    
392                    if (!context.isPathNotProcessed(path)) {
393                            return;
394                    }
395    
396                    Element categoryEl = categoriesEl.addElement("category");
397    
398                    categoryEl.addAttribute("path", path);
399    
400                    assetCategory.setUserUuid(assetCategory.getUserUuid());
401    
402                    context.addZipEntry(path, assetCategory);
403    
404                    List<AssetCategoryProperty> assetCategoryProperties =
405                            AssetCategoryPropertyLocalServiceUtil.getCategoryProperties(
406                                    assetCategory.getCategoryId());
407    
408                    for (AssetCategoryProperty assetCategoryProperty :
409                                    assetCategoryProperties) {
410    
411                            Element propertyEl = categoryEl.addElement("property");
412    
413                            propertyEl.addAttribute(
414                                    "userUuid", assetCategoryProperty.getUserUuid());
415                            propertyEl.addAttribute("key", assetCategoryProperty.getKey());
416                            propertyEl.addAttribute("value", assetCategoryProperty.getValue());
417                    }
418    
419                    context.addPermissions(
420                            AssetCategory.class, assetCategory.getCategoryId());
421            }
422    
423            protected void exportComments(PortletDataContext context, Element parentEl)
424                    throws SystemException {
425    
426                    try {
427                            Document doc = SAXReaderUtil.createDocument();
428    
429                            Element root = doc.addElement("comments");
430    
431                            Map<String, List<MBMessage>> commentsMap = context.getComments();
432    
433                            for (Map.Entry<String, List<MBMessage>> entry :
434                                            commentsMap.entrySet()) {
435    
436                                    String[] comment = entry.getKey().split(StringPool.POUND);
437    
438                                    String path = getCommentsPath(context, comment[0], comment[1]);
439    
440                                    Element asset = root.addElement("asset");
441    
442                                    asset.addAttribute("path", path);
443                                    asset.addAttribute("class-name", comment[0]);
444                                    asset.addAttribute("class-pk", comment[1]);
445    
446                                    List<MBMessage> messages = entry.getValue();
447    
448                                    for (MBMessage message : messages) {
449                                            path = getCommentsPath(
450                                                    context, comment[0], comment[1], message);
451    
452                                            if (context.isPathNotProcessed(path)) {
453                                                    context.addZipEntry(path, message);
454                                            }
455                                    }
456                            }
457    
458                            context.addZipEntry(
459                                    context.getRootPath() + "/comments.xml", doc.formattedString());
460                    }
461                    catch (IOException ioe) {
462                            throw new SystemException(ioe);
463                    }
464            }
465    
466            protected void exportLocks(PortletDataContext context, Element parentEl)
467                    throws SystemException {
468    
469                    try {
470                            Document doc = SAXReaderUtil.createDocument();
471    
472                            Element root = doc.addElement("locks");
473    
474                            Map<String, Lock> locksMap = context.getLocks();
475    
476                            for (Map.Entry<String, Lock> entry : locksMap.entrySet()) {
477                                    Lock lock = entry.getValue();
478    
479                                    String entryKey = entry.getKey();
480    
481                                    int index = entryKey.indexOf(CharPool.POUND);
482    
483                                    String className = entryKey.substring(0, index);
484                                    String key = entryKey.substring(index + 1);
485                                    String path = getLocksPath(context, className, key, lock);
486    
487                                    Element asset = root.addElement("asset");
488    
489                                    asset.addAttribute("class-name", className);
490                                    asset.addAttribute("key", key);
491                                    asset.addAttribute("path", path);
492    
493                                    if (context.isPathNotProcessed(path)) {
494                                            context.addZipEntry(path, lock);
495                                    }
496                            }
497    
498                            context.addZipEntry(
499                                    context.getRootPath() + "/locks.xml", doc.formattedString());
500                    }
501                    catch (IOException ioe) {
502                            throw new SystemException(ioe);
503                    }
504            }
505    
506            protected void exportPortlet(
507                            PortletDataContext context, LayoutCache layoutCache,
508                            String portletId, Layout layout, Element parentEl,
509                            long defaultUserId, boolean exportPermissions,
510                            boolean exportPortletArchivedSetups, boolean exportPortletData,
511                            boolean exportPortletSetup, boolean exportPortletUserPreferences,
512                            boolean exportUserPermissions)
513                    throws PortalException, SystemException {
514    
515                    long companyId = context.getCompanyId();
516                    long groupId = context.getGroupId();
517    
518                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
519                            context.getCompanyId(), portletId);
520    
521                    if (portlet == null) {
522                            if (_log.isDebugEnabled()) {
523                                    _log.debug(
524                                            "Do not export portlet " + portletId +
525                                                    " because the portlet does not exist");
526                            }
527    
528                            return;
529                    }
530    
531                    if ((!portlet.isInstanceable()) &&
532                            (!portlet.isPreferencesUniquePerLayout()) &&
533                            (context.hasNotUniquePerLayout(portletId))) {
534    
535                            return;
536                    }
537    
538                    Document doc = SAXReaderUtil.createDocument();
539    
540                    Element portletEl = doc.addElement("portlet");
541    
542                    portletEl.addAttribute("portlet-id", portletId);
543                    portletEl.addAttribute(
544                            "root-portlet-id", PortletConstants.getRootPortletId(portletId));
545                    portletEl.addAttribute("old-plid", String.valueOf(layout.getPlid()));
546                    portletEl.addAttribute(
547                            "scope-layout-uuid", context.getScopeLayoutUuid());
548    
549                    // Data
550    
551                    javax.portlet.PortletPreferences jxPreferences =
552                            PortletPreferencesFactoryUtil.getPortletSetup(
553                                    layout, portletId, StringPool.BLANK);
554    
555                    if (exportPortletData) {
556                            if (!portlet.isPreferencesUniquePerLayout()) {
557                                    String dataKey =
558                                            portletId + StringPool.AT + context.getScopeLayoutUuid();
559    
560                                    if (!context.hasNotUniquePerLayout(dataKey)) {
561                                            context.putNotUniquePerLayout(dataKey);
562    
563                                            exportPortletData(
564                                                    context, portlet, layout, jxPreferences, portletEl);
565                                    }
566                            }
567                            else {
568                                    exportPortletData(
569                                            context, portlet, layout, jxPreferences, portletEl);
570                            }
571                    }
572    
573                    // Portlet preferences
574    
575                    if (exportPortletSetup) {
576                            exportPortletPreferences(
577                                    context, PortletKeys.PREFS_OWNER_ID_DEFAULT,
578                                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, false, layout, portletId,
579                                    portletEl);
580    
581                            exportPortletPreferences(
582                                    context, groupId, PortletKeys.PREFS_OWNER_TYPE_GROUP, false,
583                                    layout, portletId, portletEl);
584    
585                            exportPortletPreferences(
586                                    context, companyId, PortletKeys.PREFS_OWNER_TYPE_COMPANY, false,
587                                    layout, portletId, portletEl);
588                    }
589    
590                    // Portlet preferences
591    
592                    if (exportPortletUserPreferences) {
593                            exportPortletPreferences(
594                                    context, defaultUserId, PortletKeys.PREFS_OWNER_TYPE_USER,
595                                    true, layout, portletId, portletEl);
596    
597                            try {
598                                    PortletPreferences groupPortletPreferences =
599                                            PortletPreferencesLocalServiceUtil.getPortletPreferences(
600                                                    groupId, PortletKeys.PREFS_OWNER_TYPE_GROUP,
601                                                    PortletKeys.PREFS_PLID_SHARED, portletId);
602    
603                                    exportPortletPreference(
604                                            context, groupId, PortletKeys.PREFS_OWNER_TYPE_GROUP, false,
605                                            groupPortletPreferences, portletId,
606                                            PortletKeys.PREFS_PLID_SHARED, portletEl);
607                            }
608                            catch (NoSuchPortletPreferencesException nsppe) {
609                            }
610                    }
611    
612                    // Archived setups
613    
614                    if (exportPortletArchivedSetups) {
615                            String rootPortletId = PortletConstants.getRootPortletId(portletId);
616    
617                            List<PortletItem> portletItems =
618                                    PortletItemLocalServiceUtil.getPortletItems(
619                                            groupId, rootPortletId, PortletPreferences.class.getName());
620    
621                            for (PortletItem portletItem: portletItems) {
622                                    long ownerId = portletItem.getPortletItemId();
623                                    int ownerType = PortletKeys.PREFS_OWNER_TYPE_ARCHIVED;
624    
625                                    exportPortletPreferences(
626                                            context, ownerId, ownerType, false, null,
627                                            portletItem.getPortletId(), portletEl);
628                            }
629                    }
630    
631                    // Permissions
632    
633                    if (exportPermissions) {
634                            _permissionExporter.exportPortletPermissions(
635                                    context, layoutCache, portletId, layout, portletEl);
636                    }
637    
638                    // Zip
639    
640                    StringBundler sb = new StringBundler(4);
641    
642                    sb.append(context.getPortletPath(portletId));
643                    sb.append(StringPool.SLASH);
644                    sb.append(layout.getPlid());
645                    sb.append("/portlet.xml");
646    
647                    String path = sb.toString();
648    
649                    Element el = parentEl.addElement("portlet");
650    
651                    el.addAttribute("portlet-id", portletId);
652                    el.addAttribute("layout-id", String.valueOf(layout.getLayoutId()));
653                    el.addAttribute("path", path);
654    
655                    if (context.isPathNotProcessed(path)) {
656                            try {
657                                    context.addZipEntry(path, doc.formattedString());
658                            }
659                            catch (IOException ioe) {
660                                    if (_log.isWarnEnabled()) {
661                                            _log.warn(ioe.getMessage());
662                                    }
663                            }
664    
665                            context.addPrimaryKey(String.class, path);
666                    }
667            }
668    
669            protected void exportPortletData(
670                            PortletDataContext context, Portlet portlet, Layout layout,
671                            javax.portlet.PortletPreferences jxPreferences,
672                            Element parentEl)
673                    throws PortalException, SystemException {
674    
675                    PortletDataHandler portletDataHandler =
676                            portlet.getPortletDataHandlerInstance();
677    
678                    if (portletDataHandler == null) {
679                            return;
680                    }
681    
682                    String portletId = portlet.getPortletId();
683    
684                    Group liveGroup = layout.getGroup();
685    
686                    if (liveGroup.isStagingGroup()) {
687                            liveGroup = liveGroup.getLiveGroup();
688                    }
689    
690                    boolean staged = liveGroup.isStagedPortlet(portlet.getRootPortletId());
691    
692                    if (!staged) {
693                            if (_log.isDebugEnabled()) {
694                                    _log.debug(
695                                            "Not exporting data for " + portletId +
696                                                    " because it is configured not to be staged");
697                            }
698    
699                            return;
700                    }
701    
702                    if (_log.isDebugEnabled()) {
703                            _log.debug("Exporting data for " + portletId);
704                    }
705    
706                    StringBundler sb = new StringBundler(4);
707    
708                    sb.append(context.getPortletPath(portletId));
709                    sb.append(StringPool.SLASH);
710    
711                    if (portlet.isPreferencesUniquePerLayout()) {
712                            sb.append(layout.getPlid());
713                    }
714                    else {
715                            sb.append(context.getScopeGroupId());
716                    }
717    
718                    sb.append("/portlet-data.xml");
719    
720                    String path = sb.toString();
721    
722                    if (!context.isPathNotProcessed(path)) {
723                            return;
724                    }
725    
726                    String data = null;
727    
728                    long groupId = context.getGroupId();
729    
730                    context.setGroupId(context.getScopeGroupId());
731    
732                    try {
733                            data = portletDataHandler.exportData(
734                                    context, portletId, jxPreferences);
735                    }
736                    catch (Exception e) {
737                            throw new SystemException(e);
738                    }
739                    finally {
740                            context.setGroupId(groupId);
741                    }
742    
743                    if (Validator.isNull(data)) {
744                            if (_log.isDebugEnabled()) {
745                                    _log.debug(
746                                            "Not exporting data for " + portletId +
747                                                    " because null data was returned");
748                            }
749    
750                            return;
751                    }
752    
753                    Element portletDataEl = parentEl.addElement("portlet-data");
754    
755                    portletDataEl.addAttribute("path", path);
756    
757                    context.addZipEntry(path, data);
758            }
759    
760            protected void exportPortletPreference(
761                            PortletDataContext context, long ownerId, int ownerType,
762                            boolean defaultUser, PortletPreferences portletPreferences,
763                            String portletId, long plid, Element parentEl)
764                    throws SystemException {
765    
766                    try {
767                            Document preferencesDoc = SAXReaderUtil.read(
768                                    portletPreferences.getPreferences());
769    
770                            Element root = preferencesDoc.getRootElement();
771    
772                            root.addAttribute("owner-id", String.valueOf(ownerId));
773                            root.addAttribute("owner-type", String.valueOf(ownerType));
774                            root.addAttribute("default-user", String.valueOf(defaultUser));
775                            root.addAttribute("plid", String.valueOf(plid));
776                            root.addAttribute("portlet-id", portletId);
777    
778                            if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
779                                    PortletItem portletItem =
780                                            PortletItemLocalServiceUtil.getPortletItem(ownerId);
781    
782                                    User user = UserLocalServiceUtil.getUserById(
783                                            portletItem.getUserId());
784    
785                                    root.addAttribute("archive-user-uuid", user.getUuid());
786                                    root.addAttribute("archive-name", portletItem.getName());
787                            }
788    
789                            List<Node> nodes = preferencesDoc.selectNodes(
790                                    "/portlet-preferences/preference[name/text() = " +
791                                            "'last-publish-date']");
792    
793                            for (Node node : nodes) {
794                                    preferencesDoc.remove(node);
795                            }
796    
797                            String path = getPortletPreferencesPath(
798                                    context, portletId, ownerId, ownerType, plid);
799    
800                            parentEl.addElement(
801                                    "portlet-preferences").addAttribute("path", path);
802    
803                            if (context.isPathNotProcessed(path)) {
804                                    context.addZipEntry(path, preferencesDoc.formattedString());
805                            }
806                    }
807                    catch (Exception e) {
808                            throw new SystemException(e);
809                    }
810            }
811    
812            protected void exportPortletPreferences(
813                            PortletDataContext context, long ownerId, int ownerType,
814                            boolean defaultUser, Layout layout, String portletId,
815                            Element parentEl)
816                    throws PortalException, SystemException {
817    
818                    PortletPreferences portletPreferences = null;
819    
820                    long plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
821    
822                    if (layout != null) {
823                            plid = layout.getPlid();
824                    }
825    
826                    if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) ||
827                            (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) ||
828                            (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED)) {
829    
830                            plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
831                    }
832    
833                    try {
834                            portletPreferences =
835                                    PortletPreferencesLocalServiceUtil.getPortletPreferences(
836                                            ownerId, ownerType, plid, portletId);
837    
838                            LayoutTypePortlet layoutTypePortlet = null;
839    
840                            if (layout != null) {
841                                    layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
842                            }
843    
844                            if ((layoutTypePortlet == null) ||
845                                    (layoutTypePortlet.hasPortletId(portletId))) {
846    
847                                    exportPortletPreference(
848                                            context, ownerId, ownerType, defaultUser,
849                                            portletPreferences, portletId, plid, parentEl);
850                            }
851                    }
852                    catch (NoSuchPortletPreferencesException nsppe) {
853                    }
854            }
855    
856            protected void exportRatings(PortletDataContext context, Element parentEl)
857                    throws SystemException {
858    
859                    try {
860                            Document doc = SAXReaderUtil.createDocument();
861    
862                            Element root = doc.addElement("ratings");
863    
864                            Map<String, List<RatingsEntry>> ratingsEntriesMap =
865                                    context.getRatingsEntries();
866    
867                            for (Map.Entry<String, List<RatingsEntry>> entry :
868                                            ratingsEntriesMap.entrySet()) {
869    
870                                    String[] ratingsEntry = entry.getKey().split(StringPool.POUND);
871    
872                                    String ratingPath = getRatingsPath(
873                                            context, ratingsEntry[0], ratingsEntry[1]);
874    
875                                    Element asset = root.addElement("asset");
876    
877                                    asset.addAttribute("path", ratingPath);
878                                    asset.addAttribute("class-name", ratingsEntry[0]);
879                                    asset.addAttribute("class-pk", ratingsEntry[1]);
880    
881                                    List<RatingsEntry> ratingsEntries = entry.getValue();
882    
883                                    for (RatingsEntry rating : ratingsEntries) {
884                                            ratingPath = getRatingsPath(
885                                                    context, ratingsEntry[0], ratingsEntry[1], rating);
886    
887                                            context.addZipEntry(ratingPath, rating);
888                                    }
889                            }
890    
891                            context.addZipEntry(
892                                    context.getRootPath() + "/ratings.xml", doc.formattedString());
893                    }
894                    catch (Exception e) {
895                            throw new SystemException(e);
896                    }
897            }
898    
899            protected void exportTags(PortletDataContext context, Element parentEl)
900                    throws SystemException {
901    
902                    try {
903                            Document doc = SAXReaderUtil.createDocument();
904    
905                            Element root = doc.addElement("tags");
906    
907                            Map<String, String[]> assetTagNamesMap =
908                                    context.getAssetTagNamesMap();
909    
910                            for (Map.Entry<String, String[]> entry :
911                                            assetTagNamesMap.entrySet()) {
912    
913                                    String[] tagsEntry = entry.getKey().split(StringPool.POUND);
914    
915                                    Element asset = root.addElement("asset");
916    
917                                    asset.addAttribute("class-name", tagsEntry[0]);
918                                    asset.addAttribute("class-pk", tagsEntry[1]);
919                                    asset.addAttribute("tags", StringUtil.merge(entry.getValue()));
920                            }
921    
922                            context.addZipEntry(
923                                    context.getRootPath() + "/tags.xml", doc.formattedString());
924                    }
925                    catch (Exception e) {
926                            throw new SystemException(e);
927                    }
928            }
929    
930            protected void exportVocabulary(
931                            PortletDataContext context, Element vocabulariesEl,
932                            long assetVocabularyId)
933                    throws Exception {
934    
935                    AssetVocabulary assetVocabulary = AssetVocabularyUtil.findByPrimaryKey(
936                            assetVocabularyId);
937    
938                    exportVocabulary(context, vocabulariesEl, assetVocabulary);
939            }
940    
941            protected void exportVocabulary(
942                            PortletDataContext context, Element vocabulariesEl,
943                            AssetVocabulary assetVocabulary)
944                    throws Exception {
945    
946                    String path = getVocabulariesPath(
947                            context, assetVocabulary.getVocabularyId());
948    
949                    if (!context.isPathNotProcessed(path)) {
950                            return;
951                    }
952    
953                    Element vocabularyEl = vocabulariesEl.addElement("vocabulary");
954    
955                    vocabularyEl.addAttribute("path", path);
956    
957                    assetVocabulary.setUserUuid(assetVocabulary.getUserUuid());
958    
959                    context.addZipEntry(path, assetVocabulary);
960    
961                    context.addPermissions(
962                            AssetVocabulary.class, assetVocabulary.getVocabularyId());
963            }
964    
965            protected String getCategoryPath(
966                    PortletDataContext context, long assetCategoryId) {
967    
968                    StringBundler sb = new StringBundler(6);
969    
970                    sb.append(context.getRootPath());
971                    sb.append("/categories/");
972                    sb.append(assetCategoryId);
973                    sb.append(".xml");
974    
975                    return sb.toString();
976            }
977    
978            protected String getCommentsPath(
979                    PortletDataContext context, String className, String classPK) {
980    
981                    StringBundler sb = new StringBundler(6);
982    
983                    sb.append(context.getRootPath());
984                    sb.append("/comments/");
985                    sb.append(PortalUtil.getClassNameId(className));
986                    sb.append(CharPool.FORWARD_SLASH);
987                    sb.append(classPK);
988                    sb.append(CharPool.FORWARD_SLASH);
989    
990                    return sb.toString();
991            }
992    
993            protected String getCommentsPath(
994                    PortletDataContext context, String className, String classPK,
995                    MBMessage message) {
996    
997                    StringBundler sb = new StringBundler(8);
998    
999                    sb.append(context.getRootPath());
1000                    sb.append("/comments/");
1001                    sb.append(PortalUtil.getClassNameId(className));
1002                    sb.append(CharPool.FORWARD_SLASH);
1003                    sb.append(classPK);
1004                    sb.append(CharPool.FORWARD_SLASH);
1005                    sb.append(message.getMessageId());
1006                    sb.append(".xml");
1007    
1008                    return sb.toString();
1009            }
1010    
1011            protected String getLocksPath(
1012                    PortletDataContext context, String className, String key, Lock lock) {
1013    
1014                    StringBundler sb = new StringBundler(8);
1015    
1016                    sb.append(context.getRootPath());
1017                    sb.append("/locks/");
1018                    sb.append(PortalUtil.getClassNameId(className));
1019                    sb.append(CharPool.FORWARD_SLASH);
1020                    sb.append(key);
1021                    sb.append(CharPool.FORWARD_SLASH);
1022                    sb.append(lock.getLockId());
1023                    sb.append(".xml");
1024    
1025                    return sb.toString();
1026            }
1027    
1028            protected String getPortletDataPath(
1029                    PortletDataContext context, String portletId) {
1030    
1031                    return context.getPortletPath(portletId) + "/portlet-data.xml";
1032            }
1033    
1034            protected String getPortletPreferencesPath(
1035                    PortletDataContext context, String portletId, long ownerId,
1036                    int ownerType, long plid) {
1037    
1038                    StringBundler sb = new StringBundler(8);
1039    
1040                    sb.append(context.getPortletPath(portletId));
1041                    sb.append("/preferences/");
1042    
1043                    if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
1044                            sb.append("company/");
1045                    }
1046                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
1047                            sb.append("group/");
1048                    }
1049                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_LAYOUT) {
1050                            sb.append("layout/");
1051                    }
1052                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) {
1053                            sb.append("user/");
1054                    }
1055                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
1056                            sb.append("archived/");
1057                    }
1058    
1059                    sb.append(ownerId);
1060                    sb.append(CharPool.FORWARD_SLASH);
1061                    sb.append(plid);
1062                    sb.append(CharPool.FORWARD_SLASH);
1063                    sb.append("portlet-preferences.xml");
1064    
1065                    return sb.toString();
1066            }
1067    
1068            protected String getRatingsPath(
1069                    PortletDataContext context, String className, String classPK) {
1070    
1071                    StringBundler sb = new StringBundler(6);
1072    
1073                    sb.append(context.getRootPath());
1074                    sb.append("/ratings/");
1075                    sb.append(PortalUtil.getClassNameId(className));
1076                    sb.append(CharPool.FORWARD_SLASH);
1077                    sb.append(classPK);
1078                    sb.append(CharPool.FORWARD_SLASH);
1079    
1080                    return sb.toString();
1081            }
1082    
1083            protected String getRatingsPath(
1084                    PortletDataContext context, String className, String classPK,
1085                    RatingsEntry ratingsEntry) {
1086    
1087                    StringBundler sb = new StringBundler(8);
1088    
1089                    sb.append(context.getRootPath());
1090                    sb.append("/ratings/");
1091                    sb.append(PortalUtil.getClassNameId(className));
1092                    sb.append(CharPool.FORWARD_SLASH);
1093                    sb.append(classPK);
1094                    sb.append(CharPool.FORWARD_SLASH);
1095                    sb.append(ratingsEntry.getEntryId());
1096                    sb.append(".xml");
1097    
1098                    return sb.toString();
1099            }
1100    
1101            protected String getVocabulariesPath(
1102                    PortletDataContext context, long assetVocabularyId) {
1103    
1104                    StringBundler sb = new StringBundler(8);
1105    
1106                    sb.append(context.getRootPath());
1107                    sb.append("/vocabularies/");
1108                    sb.append(assetVocabularyId);
1109                    sb.append(".xml");
1110    
1111                    return sb.toString();
1112            }
1113    
1114            protected void updateLastPublishDate(
1115                            Layout layout, String portletId, long lastPublishDate)
1116                    throws Exception {
1117    
1118                    javax.portlet.PortletPreferences jxPreferences =
1119                            PortletPreferencesFactoryUtil.getPortletSetup(
1120                                    layout, portletId, StringPool.BLANK);
1121    
1122                    jxPreferences.setValue(
1123                            "last-publish-date", String.valueOf(lastPublishDate));
1124    
1125                    jxPreferences.store();
1126            }
1127    
1128            private static Log _log = LogFactoryUtil.getLog(PortletExporter.class);
1129    
1130            private PermissionExporter _permissionExporter = new PermissionExporter();
1131    
1132    }