001    /**
002     * Copyright (c) 2000-2010 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.kernel.lar.PortletDataContext;
018    import com.liferay.portal.kernel.lar.PortletDataHandler;
019    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.servlet.ServletContextPool;
023    import com.liferay.portal.kernel.util.FileUtil;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.MapUtil;
026    import com.liferay.portal.kernel.util.ReleaseInfo;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.util.StringUtil;
030    import com.liferay.portal.kernel.util.Time;
031    import com.liferay.portal.kernel.util.UnicodeProperties;
032    import com.liferay.portal.kernel.util.Validator;
033    import com.liferay.portal.kernel.xml.Document;
034    import com.liferay.portal.kernel.xml.Element;
035    import com.liferay.portal.kernel.xml.SAXReaderUtil;
036    import com.liferay.portal.kernel.zip.ZipWriter;
037    import com.liferay.portal.kernel.zip.ZipWriterFactoryUtil;
038    import com.liferay.portal.model.Group;
039    import com.liferay.portal.model.Image;
040    import com.liferay.portal.model.Layout;
041    import com.liferay.portal.model.LayoutSet;
042    import com.liferay.portal.model.LayoutTypePortlet;
043    import com.liferay.portal.model.Portlet;
044    import com.liferay.portal.model.PortletConstants;
045    import com.liferay.portal.model.Theme;
046    import com.liferay.portal.service.ImageLocalServiceUtil;
047    import com.liferay.portal.service.LayoutLocalServiceUtil;
048    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
049    import com.liferay.portal.service.PortletLocalServiceUtil;
050    import com.liferay.portal.service.UserLocalServiceUtil;
051    import com.liferay.portal.service.permission.PortletPermissionUtil;
052    import com.liferay.portal.service.persistence.LayoutUtil;
053    import com.liferay.portal.theme.ThemeLoader;
054    import com.liferay.portal.theme.ThemeLoaderFactory;
055    import com.liferay.portal.util.ContentUtil;
056    import com.liferay.portal.util.PortletKeys;
057    import com.liferay.portal.util.PropsValues;
058    import com.liferay.portlet.PortletPreferencesFactoryUtil;
059    import com.liferay.portlet.asset.model.AssetCategory;
060    import com.liferay.portlet.asset.model.AssetVocabulary;
061    import com.liferay.portlet.asset.service.AssetVocabularyLocalServiceUtil;
062    import com.liferay.portlet.asset.service.persistence.AssetCategoryUtil;
063    
064    import java.io.File;
065    
066    import java.util.Date;
067    import java.util.HashSet;
068    import java.util.Iterator;
069    import java.util.LinkedHashMap;
070    import java.util.List;
071    import java.util.Map;
072    
073    import javax.servlet.ServletContext;
074    
075    import org.apache.commons.lang.time.StopWatch;
076    
077    /**
078     * @author Brian Wing Shun Chan
079     * @author Joel Kozikowski
080     * @author Charles May
081     * @author Raymond Augé
082     * @author Jorge Ferrer
083     * @author Bruno Farache
084     * @author Karthik Sudarshan
085     * @author Zsigmond Rab
086     * @author Douglas Wong
087     */
088    public class LayoutExporter {
089    
090            public static final String SAME_GROUP_FRIENDLY_URL =
091                    "/[$SAME_GROUP_FRIENDLY_URL$]";
092    
093            public static List<Portlet> getAlwaysExportablePortlets(long companyId)
094                    throws Exception {
095    
096                    List<Portlet> portlets = PortletLocalServiceUtil.getPortlets(companyId);
097    
098                    Iterator<Portlet> itr = portlets.iterator();
099    
100                    while (itr.hasNext()) {
101                            Portlet portlet = itr.next();
102    
103                            if (!portlet.isActive()) {
104                                    itr.remove();
105    
106                                    continue;
107                            }
108    
109                            PortletDataHandler portletDataHandler =
110                                    portlet.getPortletDataHandlerInstance();
111    
112                            if ((portletDataHandler == null) ||
113                                    (!portletDataHandler.isAlwaysExportable())) {
114    
115                                    itr.remove();
116                            }
117                    }
118    
119                    return portlets;
120            }
121    
122            public static void updateLastPublishDate(
123                            LayoutSet layoutSet, long lastPublishDate)
124                    throws Exception {
125    
126                    UnicodeProperties settingsProperties =
127                            layoutSet.getSettingsProperties();
128    
129                    if (lastPublishDate <= 0) {
130                            settingsProperties.remove("last-publish-date");
131                    }
132                    else {
133                            settingsProperties.setProperty(
134                                    "last-publish-date", String.valueOf(lastPublishDate));
135                    }
136    
137                    LayoutSetLocalServiceUtil.updateSettings(
138                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(),
139                            settingsProperties.toString());
140            }
141    
142            public byte[] exportLayouts(
143                            long groupId, boolean privateLayout, long[] layoutIds,
144                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
145                    throws Exception {
146    
147                    File file = exportLayoutsAsFile(
148                            groupId, privateLayout, layoutIds, parameterMap, startDate,
149                            endDate);
150    
151                    try {
152                            return FileUtil.getBytes(file);
153                    }
154                    finally {
155                            file.delete();
156                    }
157            }
158    
159            public File exportLayoutsAsFile(
160                            long groupId, boolean privateLayout, long[] layoutIds,
161                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
162                    throws Exception {
163    
164                    boolean exportCategories = MapUtil.getBoolean(
165                            parameterMap, PortletDataHandlerKeys.CATEGORIES);
166                    boolean exportIgnoreLastPublishDate = MapUtil.getBoolean(
167                            parameterMap, PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE);
168                    boolean exportPermissions = MapUtil.getBoolean(
169                            parameterMap, PortletDataHandlerKeys.PERMISSIONS);
170                    boolean exportUserPermissions = MapUtil.getBoolean(
171                            parameterMap, PortletDataHandlerKeys.USER_PERMISSIONS);
172                    boolean exportPortletArchivedSetups = MapUtil.getBoolean(
173                            parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
174                    boolean exportPortletUserPreferences = MapUtil.getBoolean(
175                            parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
176                    boolean exportTheme = MapUtil.getBoolean(
177                            parameterMap, PortletDataHandlerKeys.THEME);
178    
179                    if (_log.isDebugEnabled()) {
180                            _log.debug("Export categories " + exportCategories);
181                            _log.debug("Export permissions " + exportPermissions);
182                            _log.debug("Export user permissions " + exportUserPermissions);
183                            _log.debug(
184                                    "Export portlet archived setups " +
185                                            exportPortletArchivedSetups);
186                            _log.debug(
187                                    "Export portlet user preferences " +
188                                            exportPortletUserPreferences);
189                            _log.debug("Export theme " + exportTheme);
190                    }
191    
192                    long lastPublishDate = System.currentTimeMillis();
193    
194                    if (endDate != null) {
195                            lastPublishDate = endDate.getTime();
196                    }
197    
198                    if (exportIgnoreLastPublishDate) {
199                            endDate = null;
200                            startDate = null;
201                    }
202    
203                    StopWatch stopWatch = null;
204    
205                    if (_log.isInfoEnabled()) {
206                            stopWatch = new StopWatch();
207    
208                            stopWatch.start();
209                    }
210    
211                    LayoutCache layoutCache = new LayoutCache();
212    
213                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
214                            groupId, privateLayout);
215    
216                    long companyId = layoutSet.getCompanyId();
217                    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
218    
219                    ZipWriter zipWriter = ZipWriterFactoryUtil.getZipWriter();
220    
221                    PortletDataContext context = new PortletDataContextImpl(
222                            companyId, groupId, parameterMap, new HashSet<String>(), startDate,
223                            endDate, zipWriter);
224    
225                    context.setPortetDataContextListener(
226                            new PortletDataContextListenerImpl(context));
227    
228                    // Build compatibility
229    
230                    Document document = SAXReaderUtil.createDocument();
231    
232                    Element rootElement = document.addElement("root");
233    
234                    Element headerElement = rootElement.addElement("header");
235    
236                    headerElement.addAttribute(
237                            "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
238                    headerElement.addAttribute("export-date", Time.getRFC822());
239    
240                    if (context.hasDateRange()) {
241                            headerElement.addAttribute(
242                                    "start-date", String.valueOf(context.getStartDate()));
243                            headerElement.addAttribute(
244                                    "end-date", String.valueOf(context.getEndDate()));
245                    }
246    
247                    headerElement.addAttribute("type", "layout-set");
248                    headerElement.addAttribute("group-id", String.valueOf(groupId));
249                    headerElement.addAttribute(
250                            "private-layout", String.valueOf(privateLayout));
251                    headerElement.addAttribute("theme-id", layoutSet.getThemeId());
252                    headerElement.addAttribute(
253                            "color-scheme-id", layoutSet.getColorSchemeId());
254    
255                    // Layout configuration portlet
256    
257                    Portlet layoutConfigurationPortlet =
258                            PortletLocalServiceUtil.getPortletById(
259                                    context.getCompanyId(), PortletKeys.LAYOUT_CONFIGURATION);
260    
261                    // Layouts
262    
263                    Map<String, Object[]> portletIds =
264                            new LinkedHashMap<String, Object[]>();
265    
266                    List<Layout> layouts = null;
267    
268                    if ((layoutIds == null) || (layoutIds.length == 0)) {
269                            layouts = LayoutLocalServiceUtil.getLayouts(groupId, privateLayout);
270                    }
271                    else {
272                            layouts = LayoutLocalServiceUtil.getLayouts(
273                                    groupId, privateLayout, layoutIds);
274                    }
275    
276                    Layout firstLayout = layouts.get(0);
277    
278                    List<Portlet> portlets = getAlwaysExportablePortlets(companyId);
279    
280                    for (Portlet portlet : portlets) {
281                            String portletId = portlet.getRootPortletId();
282    
283                            if (portlet.isScopeable() && firstLayout.hasScopeGroup()) {
284                                    String key = PortletPermissionUtil.getPrimaryKey(
285                                            firstLayout.getPlid(), portletId);
286    
287                                    portletIds.put(
288                                            key,
289                                            new Object[] {
290                                                    portletId, firstLayout.getPlid(),
291                                                    firstLayout.getScopeGroup().getGroupId(),
292                                                    firstLayout.getUuid()
293                                            }
294                                    );
295                            }
296                            else {
297                                    String key = PortletPermissionUtil.getPrimaryKey(
298                                            0, portletId);
299    
300                                    if (portletIds.get(key) == null) {
301                                            portletIds.put(
302                                                    key,
303                                                    new Object[] {
304                                                            portletId, firstLayout.getPlid(), groupId,
305                                                            StringPool.BLANK
306                                                    }
307                                            );
308                                    }
309                            }
310                    }
311    
312                    Element layoutsElement = rootElement.addElement("layouts");
313    
314                    for (Layout layout : layouts) {
315                            exportLayout(
316                                    context, layoutConfigurationPortlet, layoutCache, portletIds,
317                                    exportPermissions, exportUserPermissions, layout,
318                                    layoutsElement);
319                    }
320    
321                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM < 5) {
322                            Element rolesElement = rootElement.addElement("roles");
323    
324                            // Layout roles
325    
326                            if (exportPermissions) {
327                                    _permissionExporter.exportLayoutRoles(
328                                            layoutCache, companyId, groupId, rolesElement);
329                            }
330                    }
331    
332                    // Export portlets
333    
334                    long previousScopeGroupId = context.getScopeGroupId();
335    
336                    Element portletsElement = rootElement.addElement("portlets");
337    
338                    for (Map.Entry<String, Object[]> portletIdsEntry :
339                                    portletIds.entrySet()) {
340    
341                            String portletId = (String)portletIdsEntry.getValue()[0];
342                            long plid = (Long)portletIdsEntry.getValue()[1];
343                            long scopeGroupId = (Long)portletIdsEntry.getValue()[2];
344                            String scopeLayoutUuid = (String)portletIdsEntry.getValue()[3];
345    
346                            Layout layout = LayoutUtil.findByPrimaryKey(plid);
347    
348                            context.setPlid(layout.getPlid());
349                            context.setOldPlid(layout.getPlid());
350                            context.setScopeGroupId(scopeGroupId);
351                            context.setScopeLayoutUuid(scopeLayoutUuid);
352    
353                            boolean[] exportPortletControls = getExportPortletControls(
354                                    companyId, portletId, context, parameterMap);
355    
356                            _portletExporter.exportPortlet(
357                                    context, layoutCache, portletId, layout, portletsElement,
358                                    defaultUserId, exportPermissions, exportPortletArchivedSetups,
359                                    exportPortletControls[0], exportPortletControls[1],
360                                    exportPortletUserPreferences, exportUserPermissions);
361                    }
362    
363                    context.setScopeGroupId(previousScopeGroupId);
364    
365                    // Categories
366    
367                    if (exportCategories) {
368                            exportCategories(context);
369                    }
370    
371                    // Comments
372    
373                    _portletExporter.exportComments(context, rootElement);
374    
375                    // Locks
376    
377                    _portletExporter.exportLocks(context, rootElement);
378    
379                    // Portlet data permissions
380    
381                    if (exportPermissions) {
382                            _permissionExporter.exportPortletDataPermissions(context);
383                    }
384    
385                    // Ratings
386    
387                    _portletExporter.exportRatings(context, rootElement);
388    
389                    // Tags
390    
391                    _portletExporter.exportTags(context, rootElement);
392    
393                    // Look and feel
394    
395                    if (exportTheme) {
396                            exportTheme(layoutSet, zipWriter);
397                    }
398    
399                    // Log
400    
401                    if (_log.isInfoEnabled()) {
402                            if (stopWatch != null) {
403                                    _log.info(
404                                            "Exporting layouts takes " + stopWatch.getTime() + " ms");
405                            }
406                            else {
407                                    _log.info("Exporting layouts is finished");
408                            }
409                    }
410    
411                    // Zip
412    
413                    context.addZipEntry("/manifest.xml", document.formattedString());
414    
415                    try {
416                            return zipWriter.getFile();
417                    }
418                    finally {
419                            updateLastPublishDate(layoutSet, lastPublishDate);
420                    }
421            }
422    
423            protected void exportCategories(PortletDataContext context)
424                    throws Exception {
425    
426                    Document document = SAXReaderUtil.createDocument();
427    
428                    Element rootElement = document.addElement("categories-hierarchy");
429    
430                    Element vocabulariesElement = rootElement.addElement("vocabularies");
431    
432                    List<AssetVocabulary> assetVocabularies =
433                            AssetVocabularyLocalServiceUtil.getGroupVocabularies(
434                                    context.getGroupId());
435    
436                    for (AssetVocabulary assetVocabulary : assetVocabularies) {
437                            _portletExporter.exportVocabulary(
438                                    context, vocabulariesElement, assetVocabulary);
439                    }
440    
441                    Element categoriesElement = rootElement.addElement("categories");
442    
443                    List<AssetCategory> assetCategories =
444                            AssetCategoryUtil.findByGroupId(context.getGroupId());
445    
446                    for (AssetCategory assetCategory : assetCategories) {
447                            _portletExporter.exportCategory(
448                                    context, vocabulariesElement, categoriesElement, assetCategory);
449                    }
450    
451                    _portletExporter.exportCategories(context, rootElement);
452    
453                    context.addZipEntry(
454                            context.getRootPath() + "/categories-hierarchy.xml",
455                            document.formattedString());
456            }
457    
458            protected void exportLayout(
459                            PortletDataContext context, Portlet layoutConfigurationPortlet,
460                            LayoutCache layoutCache, Map<String, Object[]> portletIds,
461                            boolean exportPermissions, boolean exportUserPermissions,
462                            Layout layout, Element layoutsElement)
463                    throws Exception {
464    
465                    String path = context.getLayoutPath(
466                            layout.getLayoutId()) + "/layout.xml";
467    
468                    if (!context.isPathNotProcessed(path)) {
469                            return;
470                    }
471    
472                    Element layoutElement = layoutsElement.addElement("layout");
473    
474                    layoutElement.addAttribute(
475                            "layout-uuid", layout.getUuid());
476                    layoutElement.addAttribute(
477                            "layout-id", String.valueOf(layout.getLayoutId()));
478    
479                    boolean deleteLayout = MapUtil.getBoolean(
480                            context.getParameterMap(), "delete_" + layout.getPlid());
481    
482                    if (deleteLayout) {
483                            layoutElement.addAttribute("delete", String.valueOf(true));
484    
485                            return;
486                    }
487    
488                    context.setPlid(layout.getPlid());
489    
490                    if (layout.isIconImage()) {
491                            Image image = ImageLocalServiceUtil.getImage(
492                                    layout.getIconImageId());
493    
494                            if (image != null) {
495                                    String iconPath = getLayoutIconPath(context, layout, image);
496    
497                                    layoutElement.addElement("icon-image-path").addText(iconPath);
498    
499                                    context.addZipEntry(iconPath, image.getTextObj());
500                            }
501                    }
502    
503                    _portletExporter.exportPortletData(
504                            context, layoutConfigurationPortlet, layout, null, layoutElement);
505    
506                    // Layout permissions
507    
508                    if (exportPermissions) {
509                            _permissionExporter.exportLayoutPermissions(
510                                    context, layoutCache, context.getCompanyId(),
511                                    context.getScopeGroupId(), layout, layoutElement,
512                                    exportUserPermissions);
513                    }
514    
515                    if (layout.isTypePortlet()) {
516                            LayoutTypePortlet layoutTypePortlet =
517                                    (LayoutTypePortlet)layout.getLayoutType();
518    
519                            for (String portletId : layoutTypePortlet.getPortletIds()) {
520                                    javax.portlet.PortletPreferences jxPreferences =
521                                            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
522                                                    layout, portletId);
523    
524                                    String scopeLayoutUuid = GetterUtil.getString(
525                                            jxPreferences.getValue("lfr-scope-layout-uuid", null));
526    
527                                    long scopeGroupId = context.getScopeGroupId();
528    
529                                    if (Validator.isNotNull(scopeLayoutUuid)) {
530                                            Layout scopeLayout =
531                                                    LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
532                                                            scopeLayoutUuid, scopeGroupId);
533    
534                                            Group scopeGroup = scopeLayout.getScopeGroup();
535    
536                                            if (scopeGroup != null) {
537                                                    scopeGroupId = scopeGroup.getGroupId();
538                                            }
539                                    }
540    
541                                    String key = PortletPermissionUtil.getPrimaryKey(
542                                            layout.getPlid(), portletId);
543    
544                                    portletIds.put(
545                                            key,
546                                            new Object[] {
547                                                    portletId, layout.getPlid(), scopeGroupId,
548                                                    scopeLayoutUuid
549                                            }
550                                    );
551                            }
552                    }
553                    else if (layout.isTypeLinkToLayout()) {
554                            UnicodeProperties typeSettingsProperties =
555                                    layout.getTypeSettingsProperties();
556    
557                            long linkToLayoutId = GetterUtil.getLong(
558                                    typeSettingsProperties.getProperty(
559                                            "linkToLayoutId", StringPool.BLANK));
560    
561                            Layout linkedToLayout = LayoutUtil.findByG_P_L(
562                                    context.getScopeGroupId(), layout.isPrivateLayout(),
563                                    linkToLayoutId);
564    
565                            exportLayout(
566                                    context, layoutConfigurationPortlet, layoutCache, portletIds,
567                                    exportPermissions, exportUserPermissions, linkedToLayout,
568                                    layoutsElement);
569                    }
570    
571                    fixTypeSettings(layout);
572    
573                    layoutElement.addAttribute("path", path);
574    
575                    context.addZipEntry(path, layout);
576            }
577    
578            protected void exportTheme(LayoutSet layoutSet, ZipWriter zipWriter)
579                    throws Exception {
580    
581                    Theme theme = layoutSet.getTheme();
582    
583                    String lookAndFeelXML = ContentUtil.get(
584                            "com/liferay/portal/dependencies/liferay-look-and-feel.xml.tmpl");
585    
586                    lookAndFeelXML = StringUtil.replace(
587                            lookAndFeelXML,
588                            new String[] {
589                                    "[$TEMPLATE_EXTENSION$]", "[$VIRTUAL_PATH$]"
590                            },
591                            new String[] {
592                                    theme.getTemplateExtension(), theme.getVirtualPath()
593                            }
594                    );
595    
596                    String servletContextName = theme.getServletContextName();
597    
598                    ServletContext servletContext = ServletContextPool.get(
599                            servletContextName);
600    
601                    if (servletContext == null) {
602                            if (_log.isWarnEnabled()) {
603                                    _log.warn(
604                                            "Servlet context not found for theme " +
605                                                    theme.getThemeId());
606                            }
607    
608                            return;
609                    }
610    
611                    File themeZip = new File(zipWriter.getPath() + "/theme.zip");
612    
613                    ZipWriter themeZipWriter = ZipWriterFactoryUtil.getZipWriter(themeZip);
614    
615                    themeZipWriter.addEntry("liferay-look-and-feel.xml", lookAndFeelXML);
616    
617                    File cssPath = null;
618                    File imagesPath = null;
619                    File javaScriptPath = null;
620                    File templatesPath = null;
621    
622                    if (!theme.isLoadFromServletContext()) {
623                            ThemeLoader themeLoader = ThemeLoaderFactory.getThemeLoader(
624                                    servletContextName);
625    
626                            if (themeLoader == null) {
627                                    _log.error(
628                                            servletContextName + " does not map to a theme loader");
629                            }
630                            else {
631                                    String realPath =
632                                            themeLoader.getFileStorage().getPath() + StringPool.SLASH +
633                                                    theme.getName();
634    
635                                    cssPath = new File(realPath + "/css");
636                                    imagesPath = new File(realPath + "/images");
637                                    javaScriptPath = new File(realPath + "/javascript");
638                                    templatesPath = new File(realPath + "/templates");
639                            }
640                    }
641                    else {
642                            cssPath = new File(servletContext.getRealPath(theme.getCssPath()));
643                            imagesPath = new File(
644                                    servletContext.getRealPath(theme.getImagesPath()));
645                            javaScriptPath = new File(
646                                    servletContext.getRealPath(theme.getJavaScriptPath()));
647                            templatesPath = new File(
648                                    servletContext.getRealPath(theme.getTemplatesPath()));
649                    }
650    
651                    exportThemeFiles("css", cssPath, themeZipWriter);
652                    exportThemeFiles("images", imagesPath, themeZipWriter);
653                    exportThemeFiles("javascript", javaScriptPath, themeZipWriter);
654                    exportThemeFiles("templates", templatesPath, themeZipWriter);
655            }
656    
657            protected void exportThemeFiles(String path, File dir, ZipWriter zipWriter)
658                    throws Exception {
659    
660                    if ((dir == null) || (!dir.exists())) {
661                            return;
662                    }
663    
664                    File[] files = dir.listFiles();
665    
666                    for (File file : files) {
667                            if (file.isDirectory()) {
668                                    exportThemeFiles(
669                                            path + StringPool.SLASH + file.getName(), file, zipWriter);
670                            }
671                            else {
672                                    zipWriter.addEntry(
673                                            path + StringPool.SLASH + file.getName(),
674                                            FileUtil.getBytes(file));
675                            }
676                    }
677            }
678    
679            protected void fixTypeSettings(Layout layout)
680                    throws Exception {
681    
682                    if (!layout.isTypeURL()) {
683                            return;
684                    }
685    
686                    UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
687    
688                    String url = GetterUtil.getString(typeSettings.getProperty("url"));
689    
690                    String friendlyURLPrivateGroupPath =
691                            PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
692                    String friendlyURLPrivateUserPath =
693                            PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
694                    String friendlyURLPublicPath =
695                            PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
696    
697                    if (!url.startsWith(friendlyURLPrivateGroupPath) &&
698                            !url.startsWith(friendlyURLPrivateUserPath) &&
699                            !url.startsWith(friendlyURLPublicPath)) {
700    
701                            return;
702                    }
703    
704                    int x = url.indexOf(StringPool.SLASH, 1);
705    
706                    if (x == -1) {
707                            return;
708                    }
709    
710                    int y = url.indexOf(StringPool.SLASH, x + 1);
711    
712                    if (y == -1) {
713                            return;
714                    }
715    
716                    String friendlyURL = url.substring(x, y);
717                    String groupFriendlyURL = layout.getGroup().getFriendlyURL();
718    
719                    if (!friendlyURL.equals(groupFriendlyURL)) {
720                            return;
721                    }
722    
723                    typeSettings.setProperty(
724                            "url",
725                            url.substring(0, x) + SAME_GROUP_FRIENDLY_URL + url.substring(y));
726            }
727    
728            protected boolean[] getExportPortletControls(
729                            long companyId, String portletId, PortletDataContext context,
730                            Map<String, String[]> parameterMap)
731                    throws Exception {
732    
733                    boolean exportPortletData = MapUtil.getBoolean(
734                            parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
735                    boolean exportPortletDataAll = MapUtil.getBoolean(
736                            parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);
737                    boolean exportPortletSetup = MapUtil.getBoolean(
738                            parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
739    
740                    if (_log.isDebugEnabled()) {
741                            _log.debug("Export portlet data " + exportPortletData);
742                            _log.debug("Export all portlet data " + exportPortletDataAll);
743                            _log.debug("Export portlet setup " + exportPortletSetup);
744                    }
745    
746                    boolean exportCurPortletData = exportPortletData;
747                    boolean exportCurPortletSetup = exportPortletSetup;
748    
749                    // If PORTLET_DATA_ALL is true, this means that staging has just been
750                    // activated and all data and setup must be exported. There is no
751                    // portlet export control to check in this case.
752    
753                    if (exportPortletDataAll) {
754                            exportCurPortletData = true;
755                            exportCurPortletSetup = true;
756                    }
757                    else {
758                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
759                                    companyId, portletId);
760    
761                            if (portlet != null) {
762                                    String portletDataHandlerClass =
763                                            portlet.getPortletDataHandlerClass();
764    
765                                    // Checking if the portlet has a data handler, if it doesn't,
766                                    // the default values are the ones set in PORTLET_DATA and
767                                    // PORTLET_SETUP. If it has a data handler, iterate over each
768                                    // portlet export control.
769    
770                                    if (portletDataHandlerClass != null) {
771                                            String rootPortletId = PortletConstants.getRootPortletId(
772                                                    portletId);
773    
774                                            // PORTLET_DATA and the PORTLET_DATA for this specific
775                                            // data handler must be true
776    
777                                            exportCurPortletData =
778                                                    exportPortletData &&
779                                                    MapUtil.getBoolean(
780                                                            parameterMap,
781                                                            PortletDataHandlerKeys.PORTLET_DATA +
782                                                                    StringPool.UNDERLINE + rootPortletId);
783    
784                                            // PORTLET_DATA and the PORTLET_SETUP for this specific
785                                            // data handler must be true
786    
787                                            exportCurPortletSetup =
788                                                    exportPortletData &&
789                                                    MapUtil.getBoolean(
790                                                            parameterMap,
791                                                            PortletDataHandlerKeys.PORTLET_SETUP +
792                                                                    StringPool.UNDERLINE + rootPortletId);
793                                    }
794                            }
795                    }
796    
797                    return new boolean[] {exportCurPortletData, exportCurPortletSetup};
798            }
799    
800            protected String getLayoutIconPath(
801                    PortletDataContext context, Layout layout, Image image) {
802    
803                    StringBundler sb = new StringBundler(5);
804    
805                    sb.append(context.getLayoutPath(layout.getLayoutId()));
806                    sb.append("/icons/");
807                    sb.append(image.getImageId());
808                    sb.append(StringPool.PERIOD);
809                    sb.append(image.getType());
810    
811                    return sb.toString();
812            }
813    
814            private static Log _log = LogFactoryUtil.getLog(LayoutExporter.class);
815    
816            private PermissionExporter _permissionExporter = new PermissionExporter();
817            private PortletExporter _portletExporter = new PortletExporter();
818    
819    }