1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.lar;
16  
17  import com.liferay.counter.service.CounterLocalServiceUtil;
18  import com.liferay.portal.LARFileException;
19  import com.liferay.portal.LARTypeException;
20  import com.liferay.portal.LayoutImportException;
21  import com.liferay.portal.NoSuchLayoutException;
22  import com.liferay.portal.kernel.cluster.ClusterLinkUtil;
23  import com.liferay.portal.kernel.cluster.Priority;
24  import com.liferay.portal.kernel.exception.PortalException;
25  import com.liferay.portal.kernel.exception.SystemException;
26  import com.liferay.portal.kernel.log.Log;
27  import com.liferay.portal.kernel.log.LogFactoryUtil;
28  import com.liferay.portal.kernel.messaging.Message;
29  import com.liferay.portal.kernel.util.ArrayUtil;
30  import com.liferay.portal.kernel.util.FileUtil;
31  import com.liferay.portal.kernel.util.GetterUtil;
32  import com.liferay.portal.kernel.util.LocaleUtil;
33  import com.liferay.portal.kernel.util.MapUtil;
34  import com.liferay.portal.kernel.util.MethodWrapper;
35  import com.liferay.portal.kernel.util.ReleaseInfo;
36  import com.liferay.portal.kernel.util.StringPool;
37  import com.liferay.portal.kernel.util.StringUtil;
38  import com.liferay.portal.kernel.util.Time;
39  import com.liferay.portal.kernel.util.UnicodeProperties;
40  import com.liferay.portal.kernel.util.Validator;
41  import com.liferay.portal.kernel.xml.Document;
42  import com.liferay.portal.kernel.xml.DocumentException;
43  import com.liferay.portal.kernel.xml.Element;
44  import com.liferay.portal.kernel.xml.SAXReaderUtil;
45  import com.liferay.portal.kernel.zip.ZipReader;
46  import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
47  import com.liferay.portal.model.Group;
48  import com.liferay.portal.model.GroupConstants;
49  import com.liferay.portal.model.Layout;
50  import com.liferay.portal.model.LayoutConstants;
51  import com.liferay.portal.model.LayoutSet;
52  import com.liferay.portal.model.LayoutTemplate;
53  import com.liferay.portal.model.LayoutTypePortlet;
54  import com.liferay.portal.model.LayoutTypePortletConstants;
55  import com.liferay.portal.model.Portlet;
56  import com.liferay.portal.model.PortletConstants;
57  import com.liferay.portal.model.Resource;
58  import com.liferay.portal.model.ResourceConstants;
59  import com.liferay.portal.model.Role;
60  import com.liferay.portal.model.User;
61  import com.liferay.portal.model.impl.ColorSchemeImpl;
62  import com.liferay.portal.service.GroupLocalServiceUtil;
63  import com.liferay.portal.service.ImageLocalServiceUtil;
64  import com.liferay.portal.service.LayoutLocalServiceUtil;
65  import com.liferay.portal.service.LayoutSetLocalServiceUtil;
66  import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
67  import com.liferay.portal.service.PermissionLocalServiceUtil;
68  import com.liferay.portal.service.PortletLocalServiceUtil;
69  import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
70  import com.liferay.portal.service.RoleLocalServiceUtil;
71  import com.liferay.portal.service.ServiceContext;
72  import com.liferay.portal.service.permission.PortletPermissionUtil;
73  import com.liferay.portal.service.persistence.LayoutUtil;
74  import com.liferay.portal.service.persistence.UserUtil;
75  import com.liferay.portal.theme.ThemeLoader;
76  import com.liferay.portal.theme.ThemeLoaderFactory;
77  import com.liferay.portal.util.PortalUtil;
78  import com.liferay.portal.util.PortletKeys;
79  import com.liferay.portal.util.PropsValues;
80  import com.liferay.portlet.asset.DuplicateCategoryException;
81  import com.liferay.portlet.asset.DuplicateVocabularyException;
82  import com.liferay.portlet.asset.NoSuchCategoryException;
83  import com.liferay.portlet.asset.model.AssetCategory;
84  import com.liferay.portlet.asset.model.AssetVocabulary;
85  import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
86  import com.liferay.portlet.asset.service.AssetVocabularyLocalServiceUtil;
87  import com.liferay.portlet.asset.service.persistence.AssetCategoryUtil;
88  import com.liferay.portlet.asset.service.persistence.AssetVocabularyUtil;
89  import com.liferay.portlet.journal.model.JournalArticle;
90  import com.liferay.util.LocalizationUtil;
91  
92  import java.io.File;
93  import java.io.IOException;
94  import java.io.InputStream;
95  
96  import java.util.ArrayList;
97  import java.util.Date;
98  import java.util.HashMap;
99  import java.util.HashSet;
100 import java.util.Iterator;
101 import java.util.List;
102 import java.util.Locale;
103 import java.util.Map;
104 import java.util.Set;
105 
106 import org.apache.commons.lang.time.StopWatch;
107 
108 /**
109  * <a href="LayoutImporter.java.html"><b><i>View Source</i></b></a>
110  *
111  * @author Brian Wing Shun Chan
112  * @author Joel Kozikowski
113  * @author Charles May
114  * @author Raymond Augé
115  * @author Jorge Ferrer
116  * @author Bruno Farache
117  * @author Wesley Gong
118  */
119 public class LayoutImporter {
120 
121     public void importLayouts(
122             long userId, long groupId, boolean privateLayout,
123             Map<String, String[]> parameterMap, File file)
124         throws PortalException, SystemException {
125 
126         boolean deleteMissingLayouts = MapUtil.getBoolean(
127             parameterMap, PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
128             Boolean.TRUE.booleanValue());
129         boolean deletePortletData = MapUtil.getBoolean(
130             parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
131         boolean importCategories = MapUtil.getBoolean(
132             parameterMap, PortletDataHandlerKeys.CATEGORIES);
133         boolean importPermissions = MapUtil.getBoolean(
134             parameterMap, PortletDataHandlerKeys.PERMISSIONS);
135         boolean importUserPermissions = MapUtil.getBoolean(
136             parameterMap, PortletDataHandlerKeys.PERMISSIONS);
137         boolean importPortletData = MapUtil.getBoolean(
138             parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
139         boolean importPortletSetup = MapUtil.getBoolean(
140             parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
141         boolean importPortletArchivedSetups = MapUtil.getBoolean(
142             parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
143         boolean importPortletUserPreferences = MapUtil.getBoolean(
144             parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
145         boolean importTheme = MapUtil.getBoolean(
146             parameterMap, PortletDataHandlerKeys.THEME);
147         String layoutsImportMode = MapUtil.getString(
148             parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
149             PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_ID);
150         String portletsMergeMode = MapUtil.getString(
151             parameterMap, PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
152             PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
153         String userIdStrategy = MapUtil.getString(
154             parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
155 
156         if (_log.isDebugEnabled()) {
157             _log.debug("Delete portlet data " + deletePortletData);
158             _log.debug("Import categories " + importCategories);
159             _log.debug("Import permissions " + importPermissions);
160             _log.debug("Import user permissions " + importUserPermissions);
161             _log.debug("Import portlet data " + importPortletData);
162             _log.debug("Import portlet setup " + importPortletSetup);
163             _log.debug(
164                 "Import portlet archived setups " +
165                     importPortletArchivedSetups);
166             _log.debug(
167                 "Import portlet user preferences " +
168                     importPortletUserPreferences);
169             _log.debug("Import theme " + importTheme);
170         }
171 
172         StopWatch stopWatch = null;
173 
174         if (_log.isInfoEnabled()) {
175             stopWatch = new StopWatch();
176 
177             stopWatch.start();
178         }
179 
180         LayoutCache layoutCache = new LayoutCache();
181 
182         LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
183             groupId, privateLayout);
184 
185         long companyId = layoutSet.getCompanyId();
186 
187         User user = UserUtil.findByPrimaryKey(userId);
188 
189         UserIdStrategy strategy = _portletImporter.getUserIdStrategy(
190             user, userIdStrategy);
191 
192         ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
193 
194         PortletDataContext context = new PortletDataContextImpl(
195             companyId, groupId, parameterMap, new HashSet<String>(), strategy,
196             zipReader);
197 
198         context.setPrivateLayout(privateLayout);
199 
200         Group guestGroup = GroupLocalServiceUtil.getGroup(
201             companyId, GroupConstants.GUEST);
202 
203         // Zip
204 
205         Element root = null;
206         InputStream themeZip = null;
207 
208         // Manifest
209 
210         String xml = context.getZipEntryAsString("/manifest.xml");
211 
212         if (xml == null) {
213             throw new LARFileException("manifest.xml not found in the LAR");
214         }
215 
216         try {
217             Document doc = SAXReaderUtil.read(xml);
218 
219             root = doc.getRootElement();
220         }
221         catch (Exception e) {
222             throw new LARFileException(e);
223         }
224 
225         // Build compatibility
226 
227         Element header = root.element("header");
228 
229         int buildNumber = ReleaseInfo.getBuildNumber();
230 
231         int importBuildNumber = GetterUtil.getInteger(
232             header.attributeValue("build-number"));
233 
234         if (buildNumber != importBuildNumber) {
235             throw new LayoutImportException(
236                 "LAR build number " + importBuildNumber + " does not match " +
237                     "portal build number " + buildNumber);
238         }
239 
240         // Type compatibility
241 
242         String larType = header.attributeValue("type");
243 
244         if (!larType.equals("layout-set")) {
245             throw new LARTypeException(
246                 "Invalid type of LAR file (" + larType + ")");
247         }
248 
249         // Import GroupId
250 
251         long sourceGroupId = GetterUtil.getLong(
252             header.attributeValue("group-id"));
253 
254         context.setSourceGroupId(sourceGroupId);
255 
256         // Look and feel
257 
258         if (importTheme) {
259             themeZip = context.getZipEntryAsInputStream("theme.zip");
260         }
261 
262         // Look and feel
263 
264         String themeId = header.attributeValue("theme-id");
265         String colorSchemeId = header.attributeValue("color-scheme-id");
266 
267         boolean useThemeZip = false;
268 
269         if (themeZip != null) {
270             try {
271                 String importThemeId = importTheme(layoutSet, themeZip);
272 
273                 if (importThemeId != null) {
274                     themeId = importThemeId;
275                     colorSchemeId =
276                         ColorSchemeImpl.getDefaultRegularColorSchemeId();
277 
278                     useThemeZip = true;
279                 }
280 
281                 if (_log.isDebugEnabled()) {
282                     _log.debug(
283                         "Importing theme takes " + stopWatch.getTime() + " ms");
284                 }
285             }
286             catch (Exception e) {
287                 throw new SystemException(e);
288             }
289         }
290 
291         boolean wapTheme = false;
292 
293         LayoutSetLocalServiceUtil.updateLookAndFeel(
294             groupId, privateLayout, themeId, colorSchemeId, StringPool.BLANK,
295             wapTheme);
296 
297         // Read categories, comments, ratings, and tags to make them available
298         // to the data handlers through the context
299 
300         if (importCategories) {
301             importCategories(context);
302         }
303 
304         _portletImporter.readCategories(context, root);
305         _portletImporter.readComments(context, root);
306         _portletImporter.readRatings(context, root);
307         _portletImporter.readTags(context, root);
308 
309         // Layouts
310 
311         List<Layout> previousLayouts = LayoutUtil.findByG_P(
312             groupId, privateLayout);
313 
314         List<Layout> newLayouts = new ArrayList<Layout>();
315 
316         Set<Long> newLayoutIds = new HashSet<Long>();
317 
318         Map<Long, Long> newLayoutIdPlidMap =
319             (Map<Long, Long>)context.getNewPrimaryKeysMap(Layout.class);
320 
321         List<Element> layoutEls = root.element("layouts").elements("layout");
322 
323         if (_log.isDebugEnabled()) {
324             if (layoutEls.size() > 0) {
325                 _log.debug("Importing layouts");
326             }
327         }
328 
329         for (Element layoutRefEl : layoutEls) {
330             long layoutId = GetterUtil.getInteger(
331                 layoutRefEl.attributeValue("layout-id"));
332 
333             long oldLayoutId = layoutId;
334 
335             boolean deleteLayout = GetterUtil.getBoolean(
336                 layoutRefEl.attributeValue("delete"));
337 
338             if (deleteLayout) {
339                 try {
340                     LayoutLocalServiceUtil.deleteLayout(
341                         context.getGroupId(), privateLayout, oldLayoutId);
342                 }
343                 catch (NoSuchLayoutException nsle) {
344                     _log.warn(
345                         "Error deleting layout for {" + sourceGroupId + ", " +
346                             privateLayout + ", " + oldLayoutId + "}");
347                 }
348 
349                 continue;
350             }
351 
352             String layoutPath = layoutRefEl.attributeValue("path");
353 
354             Element layoutEl = null;
355 
356             try {
357                 Document layoutDoc = SAXReaderUtil.read(
358                     context.getZipEntryAsString(layoutPath));
359 
360                 layoutEl = layoutDoc.getRootElement();
361             }
362             catch (DocumentException de) {
363                 throw new SystemException(de);
364             }
365 
366             long parentLayoutId = GetterUtil.getInteger(
367                 layoutEl.elementText("parent-layout-id"));
368 
369             if (_log.isDebugEnabled()) {
370                 _log.debug(
371                     "Importing layout with layout id " + layoutId +
372                         " and parent layout id " + parentLayoutId);
373             }
374 
375             long oldPlid = GetterUtil.getInteger(
376                 layoutEl.attributeValue("old-plid"));
377 
378             String name = layoutEl.elementText("name");
379             String title = layoutEl.elementText("title");
380             String description = layoutEl.elementText("description");
381             String type = layoutEl.elementText("type");
382             String typeSettings = layoutEl.elementText("type-settings");
383             boolean hidden = GetterUtil.getBoolean(
384                 layoutEl.elementText("hidden"));
385             String friendlyURL = layoutEl.elementText("friendly-url");
386             boolean iconImage = GetterUtil.getBoolean(
387                 layoutEl.elementText("icon-image"));
388 
389             byte[] iconBytes = null;
390 
391             if (iconImage) {
392                 String path = layoutEl.elementText("icon-image-path");
393 
394                 iconBytes = context.getZipEntryAsByteArray(path);
395             }
396 
397             if (useThemeZip) {
398                 themeId = StringPool.BLANK;
399                 colorSchemeId = StringPool.BLANK;
400             }
401             else {
402                 themeId = layoutEl.elementText("theme-id");
403                 colorSchemeId = layoutEl.elementText("color-scheme-id");
404             }
405 
406             String wapThemeId = layoutEl.elementText("wap-theme-id");
407             String wapColorSchemeId = layoutEl.elementText(
408                 "wap-color-scheme-id");
409             String css = layoutEl.elementText("css");
410             int priority = GetterUtil.getInteger(
411                 layoutEl.elementText("priority"));
412 
413             Layout layout = null;
414 
415             if (layoutsImportMode.equals(
416                     PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_ADD_AS_NEW)) {
417 
418                 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
419                     groupId, privateLayout);
420                 friendlyURL = StringPool.SLASH + layoutId;
421             }
422             else if (layoutsImportMode.equals(
423                     PortletDataHandlerKeys.
424                         LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_NAME)) {
425 
426                 Locale locale = LocaleUtil.getDefault();
427 
428                 String localizedName = LocalizationUtil.getLocalization(
429                     name, LocaleUtil.toLanguageId(locale));
430 
431                 for (Layout curLayout : previousLayouts) {
432                     if (curLayout.getName(locale).equals(localizedName)) {
433                         layout = curLayout;
434 
435                         break;
436                     }
437                 }
438 
439                 if (layout == null) {
440                     layoutId = LayoutLocalServiceUtil.getNextLayoutId(
441                         groupId, privateLayout);
442                 }
443             }
444             else {
445                 layout = LayoutUtil.fetchByG_P_L(
446                     groupId, privateLayout, layoutId);
447             }
448 
449             if (_log.isDebugEnabled()) {
450                 if (layout == null) {
451                     _log.debug(
452                         "Layout with {groupId=" + groupId + ",privateLayout=" +
453                             privateLayout + ",layoutId=" + layoutId +
454                                 "} does not exist");
455                 }
456                 else {
457                     _log.debug(
458                         "Layout with {groupId=" + groupId + ",privateLayout=" +
459                             privateLayout + ",layoutId=" + layoutId +
460                                 "} exists");
461                 }
462             }
463 
464             if (layout == null) {
465                 long plid = CounterLocalServiceUtil.increment();
466 
467                 layout = LayoutUtil.create(plid);
468 
469                 layout.setGroupId(groupId);
470                 layout.setPrivateLayout(privateLayout);
471                 layout.setLayoutId(layoutId);
472             }
473 
474             layout.setCompanyId(user.getCompanyId());
475             layout.setParentLayoutId(parentLayoutId);
476             layout.setName(name);
477             layout.setTitle(title);
478             layout.setDescription(description);
479             layout.setType(type);
480 
481             if (layout.getType().equals(LayoutConstants.TYPE_PORTLET) &&
482                     Validator.isNotNull(layout.getTypeSettings()) &&
483                         !portletsMergeMode.equals(
484                             PortletDataHandlerKeys.
485                                 PORTLETS_MERGE_MODE_REPLACE)) {
486                 mergePortlets(layout, typeSettings, portletsMergeMode);
487             }
488             else {
489                 layout.setTypeSettings(typeSettings);
490             }
491 
492             layout.setHidden(hidden);
493             layout.setFriendlyURL(friendlyURL);
494 
495             if (iconImage) {
496                 layout.setIconImage(iconImage);
497 
498                 if (layout.isNew()) {
499                     long iconImageId = CounterLocalServiceUtil.increment();
500 
501                     layout.setIconImageId(iconImageId);
502                 }
503             }
504 
505             layout.setThemeId(themeId);
506             layout.setColorSchemeId(colorSchemeId);
507             layout.setWapThemeId(wapThemeId);
508             layout.setWapColorSchemeId(wapColorSchemeId);
509             layout.setCss(css);
510             layout.setPriority(priority);
511 
512             fixTypeSettings(layout);
513 
514             LayoutUtil.update(layout, false);
515 
516             if ((iconBytes != null) && (iconBytes.length > 0)) {
517                 ImageLocalServiceUtil.updateImage(
518                     layout.getIconImageId(), iconBytes);
519             }
520 
521             context.setPlid(layout.getPlid());
522             context.setOldPlid(oldPlid);
523 
524             newLayoutIdPlidMap.put(oldLayoutId, layout.getPlid());
525 
526             newLayoutIds.add(layoutId);
527 
528             newLayouts.add(layout);
529 
530             Element permissionsEl = layoutEl.element("permissions");
531 
532             // Layout permissions
533 
534             if (importPermissions && (permissionsEl != null)) {
535                 String resourceName = Layout.class.getName();
536                 String resourcePrimKey = String.valueOf(layout.getPlid());
537 
538                 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
539                     importLayoutPermissions_5(
540                         layoutCache, companyId, groupId, userId, resourceName,
541                         resourcePrimKey, permissionsEl);
542                 }
543                 else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
544                     importLayoutPermissions_6(
545                         layoutCache, companyId, groupId, userId, resourceName,
546                         resourcePrimKey, permissionsEl);
547                 }
548                 else {
549                     importLayoutPermissions_4(
550                         layoutCache, companyId, groupId, guestGroup, layout,
551                         resourceName, resourcePrimKey, permissionsEl,
552                         importUserPermissions);
553                 }
554             }
555 
556             _portletImporter.importPortletData(
557                 context, PortletKeys.LAYOUT_CONFIGURATION, null, layoutEl);
558         }
559 
560         List<Element> portletEls = root.element("portlets").elements("portlet");
561 
562         // Delete portlet data
563 
564         if (deletePortletData) {
565             if (_log.isDebugEnabled()) {
566                 if (portletEls.size() > 0) {
567                     _log.debug("Deleting portlet data");
568                 }
569             }
570 
571             for (Element portletRefEl : portletEls) {
572                 String portletId = portletRefEl.attributeValue("portlet-id");
573                 long layoutId = GetterUtil.getLong(
574                     portletRefEl.attributeValue("layout-id"));
575                 long plid = newLayoutIdPlidMap.get(layoutId);
576 
577                 context.setPlid(plid);
578 
579                 _portletImporter.deletePortletData(context, portletId, plid);
580             }
581         }
582 
583         // Import portlets
584 
585         if (_log.isDebugEnabled()) {
586             if (portletEls.size() > 0) {
587                 _log.debug("Importing portlets");
588             }
589         }
590 
591         for (Element portletRefEl : portletEls) {
592             String portletPath = portletRefEl.attributeValue("path");
593             String portletId = portletRefEl.attributeValue("portlet-id");
594             long layoutId = GetterUtil.getLong(
595                 portletRefEl.attributeValue("layout-id"));
596             long plid = newLayoutIdPlidMap.get(layoutId);
597             long oldPlid = GetterUtil.getLong(
598                 portletRefEl.attributeValue("old-plid"));
599 
600             Layout layout = LayoutUtil.findByPrimaryKey(plid);
601 
602             context.setPlid(plid);
603             context.setOldPlid(oldPlid);
604 
605             Element portletEl = null;
606 
607             try {
608                 Document portletDoc = SAXReaderUtil.read(
609                     context.getZipEntryAsString(portletPath));
610 
611                 portletEl = portletDoc.getRootElement();
612             }
613             catch (DocumentException de) {
614                 throw new SystemException(de);
615             }
616 
617             // The order of the import is important. You must always import
618             // the portlet preferences first, then the portlet data, then
619             // the portlet permissions. The import of the portlet data
620             // assumes that portlet preferences already exist.
621 
622             // Portlet preferences
623 
624             _portletImporter.importPortletPreferences(
625                 context, layoutSet.getCompanyId(), layout.getGroupId(),
626                 layout, null, portletEl, importPortletSetup,
627                 importPortletArchivedSetups, importPortletUserPreferences,
628                 false);
629 
630             // Portlet data scope
631 
632             long scopeLayoutId = GetterUtil.getLong(
633                 portletEl.attributeValue("scope-layout-id"));
634 
635             context.setScopeLayoutId(scopeLayoutId);
636 
637             // Portlet data
638 
639             Element portletDataEl = portletEl.element("portlet-data");
640 
641             if (importPortletData && portletDataEl != null) {
642                 _portletImporter.importPortletData(
643                     context, portletId, plid, portletDataEl);
644             }
645 
646             // Portlet permissions
647 
648             Element permissionsEl = portletEl.element("permissions");
649 
650             if (importPermissions && (permissionsEl != null)) {
651                 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
652                     String resourceName = PortletConstants.getRootPortletId(
653                         portletId);
654 
655                     String resourcePrimKey =
656                         PortletPermissionUtil.getPrimaryKey(
657                             layout.getPlid(), portletId);
658 
659                     importPortletPermissions_6(
660                         layoutCache, companyId, groupId, userId, resourceName,
661                         resourcePrimKey, permissionsEl);
662                 }
663                 else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
664                     String resourceName = PortletConstants.getRootPortletId(
665                         portletId);
666 
667                     String resourcePrimKey =
668                         PortletPermissionUtil.getPrimaryKey(
669                             layout.getPlid(), portletId);
670 
671                     importPortletPermissions_5(
672                         layoutCache, companyId, groupId, userId, resourceName,
673                         resourcePrimKey, permissionsEl);
674                 }
675                 else {
676                     importPortletPermissions_4(
677                         layoutCache, companyId, groupId, guestGroup, layout,
678                         permissionsEl, importUserPermissions);
679                 }
680             }
681 
682             // Archived setups
683 
684             _portletImporter.importPortletPreferences(
685                 context, layoutSet.getCompanyId(), groupId, null, null,
686                 portletEl, importPortletSetup, importPortletArchivedSetups,
687                 importPortletUserPreferences, false);
688 
689             if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM < 5) {
690 
691                 // Portlet roles
692 
693                 Element rolesEl = portletEl.element("roles");
694 
695                 if (importPermissions && (rolesEl != null)) {
696                     importPortletRoles(
697                         layoutCache, companyId, groupId, portletEl);
698 
699                     importPortletRoles(
700                         layoutCache, companyId, groupId, portletId, rolesEl);
701                 }
702             }
703         }
704 
705         if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM < 5) {
706             Element rolesEl = root.element("roles");
707 
708             // Layout roles
709 
710             if (importPermissions) {
711                 importLayoutRoles(layoutCache, companyId, groupId, rolesEl);
712             }
713         }
714 
715         // Delete missing layouts
716 
717         if (deleteMissingLayouts) {
718             deleteMissingLayouts(
719                 groupId, privateLayout, newLayoutIds, previousLayouts);
720         }
721 
722         // Page count
723 
724         LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);
725 
726         if (_log.isInfoEnabled()) {
727             _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
728         }
729 
730         // Web content layout type
731 
732         for (Layout layout : newLayouts) {
733             UnicodeProperties typeSettingsProperties =
734                 layout.getTypeSettingsProperties();
735 
736             String articleId = typeSettingsProperties.getProperty("article-id");
737 
738             if (Validator.isNotNull(articleId)) {
739                 Map<String, String> articleIds =
740                     (Map<String, String>)context.getNewPrimaryKeysMap(
741                         JournalArticle.class);
742 
743                 typeSettingsProperties.setProperty(
744                     "article-id",
745                     MapUtil.getString(articleIds, articleId, articleId));
746 
747                 LayoutUtil.update(layout, false);
748             }
749         }
750 
751         zipReader.close();
752     }
753 
754     protected void deleteMissingLayouts(
755             long groupId, boolean privateLayout, Set<Long> newLayoutIds,
756             List<Layout> previousLayouts)
757         throws PortalException, SystemException {
758 
759         // Layouts
760 
761         if (_log.isDebugEnabled()) {
762             if (newLayoutIds.size() > 0) {
763                 _log.debug("Delete missing layouts");
764             }
765         }
766 
767         for (Layout layout : previousLayouts) {
768             if (!newLayoutIds.contains(layout.getLayoutId())) {
769                 try {
770                     LayoutLocalServiceUtil.deleteLayout(layout, false);
771                 }
772                 catch (NoSuchLayoutException nsle) {
773                 }
774             }
775         }
776 
777         // Layout set
778 
779         LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);
780     }
781 
782     protected void fixTypeSettings(Layout layout) {
783         if (!layout.getType().equals(LayoutConstants.TYPE_URL)) {
784             return;
785         }
786 
787         UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
788 
789         String url = GetterUtil.getString(typeSettings.getProperty("url"));
790 
791         String friendlyURLPrivateGroupPath =
792             PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
793         String friendlyURLPrivateUserPath =
794             PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
795         String friendlyURLPublicPath =
796             PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
797 
798         if (!url.startsWith(friendlyURLPrivateGroupPath) &&
799             !url.startsWith(friendlyURLPrivateUserPath) &&
800             !url.startsWith(friendlyURLPublicPath)) {
801 
802             return;
803         }
804 
805         int x = url.indexOf(StringPool.SLASH, 1);
806 
807         if (x == -1) {
808             return;
809         }
810 
811         int y = url.indexOf(StringPool.SLASH, x + 1);
812 
813         if (y == -1) {
814             return;
815         }
816 
817         String friendlyURL = url.substring(x, y);
818 
819         if (!friendlyURL.equals(LayoutExporter.SAME_GROUP_FRIENDLY_URL)) {
820             return;
821         }
822 
823         typeSettings.setProperty(
824             "url",
825             url.substring(0, x) + layout.getGroup().getFriendlyURL() +
826                 url.substring(y));
827     }
828 
829     protected List<String> getActions(Element el) {
830         List<String> actions = new ArrayList<String>();
831 
832         Iterator<Element> itr = el.elements("action-key").iterator();
833 
834         while (itr.hasNext()) {
835             Element actionEl = itr.next();
836 
837             actions.add(actionEl.getText());
838         }
839 
840         return actions;
841     }
842 
843     protected AssetVocabulary getAssetVocabulary(
844             PortletDataContext context, String vocabularyUuid,
845             String vocabularyName, String userUuid,
846             ServiceContext serviceContext)
847         throws Exception {
848 
849         AssetVocabulary assetVocabulary = null;
850 
851         try {
852             if (context.getDataStrategy().equals(
853                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
854 
855                 AssetVocabulary existingAssetVocabulary =
856                     AssetVocabularyUtil.fetchByUUID_G(
857                         vocabularyUuid, context.getGroupId());
858 
859                 if (existingAssetVocabulary == null) {
860                     Map<Locale, String> titleMap =
861                         new HashMap<Locale, String>();
862 
863                     titleMap.put(LocaleUtil.getDefault(), vocabularyName);
864 
865                     assetVocabulary =
866                         AssetVocabularyLocalServiceUtil.addVocabulary(
867                             vocabularyUuid, context.getUserId(userUuid),
868                             titleMap, null, StringPool.BLANK, serviceContext);
869                 }
870                 else {
871                     assetVocabulary =
872                         AssetVocabularyLocalServiceUtil.updateVocabulary(
873                             existingAssetVocabulary.getVocabularyId(),
874                             existingAssetVocabulary.getTitleMap(),
875                             existingAssetVocabulary.getDescriptionMap(),
876                             existingAssetVocabulary.getSettings(),
877                             serviceContext);
878                 }
879             }
880             else {
881                 Map<Locale, String> titleMap =  new HashMap<Locale, String>();
882 
883                 titleMap.put(LocaleUtil.getDefault(), vocabularyName);
884 
885                 assetVocabulary = AssetVocabularyLocalServiceUtil.addVocabulary(
886                     null, context.getUserId(userUuid), titleMap, null,
887                     StringPool.BLANK, serviceContext);
888             }
889         }
890         catch (DuplicateVocabularyException dve) {
891             assetVocabulary =
892                 AssetVocabularyLocalServiceUtil.getGroupVocabulary(
893                     context.getGroupId(), vocabularyName);
894         }
895 
896         return assetVocabulary;
897     }
898 
899     protected void importCategories(PortletDataContext context)
900         throws SystemException {
901 
902         try {
903             String xml = context.getZipEntryAsString(
904                 context.getSourceRootPath() + "/categories-hierarchy.xml");
905 
906             if (Validator.isNull(xml)) {
907                 return;
908             }
909 
910             Document doc = SAXReaderUtil.read(xml);
911 
912             Element root = doc.getRootElement();
913 
914             List<Element> vocabularies = root.elements("vocabulary");
915 
916             for (Element vocabularyEl : vocabularies) {
917                 String vocabularyUuid = GetterUtil.getString(
918                     vocabularyEl.attributeValue("uuid"));
919                 String vocabularyName = GetterUtil.getString(
920                     vocabularyEl.attributeValue("name"));
921                 String userUuid = GetterUtil.getString(
922                     vocabularyEl.attributeValue("userUuid"));
923 
924                 ServiceContext serviceContext = new ServiceContext();
925 
926                 serviceContext.setAddCommunityPermissions(true);
927                 serviceContext.setAddGuestPermissions(true);
928                 serviceContext.setScopeGroupId(context.getGroupId());
929 
930                 AssetVocabulary assetVocabulary = getAssetVocabulary(
931                     context, vocabularyUuid, vocabularyName, userUuid,
932                     serviceContext);
933 
934                 List<Element> categories = vocabularyEl.elements("category");
935 
936                 for (Element category : categories) {
937                     String categoryUuid = GetterUtil.getString(
938                         category.attributeValue("uuid"));
939                     String parentCategoryUuid = GetterUtil.getString(
940                         category.attributeValue("parentCategoryUuid"));
941                     String categoryName = GetterUtil.getString(
942                         category.attributeValue("name"));
943                     String[] properties = null;
944 
945                     try {
946                         importCategory(
947                             context, categoryUuid, userUuid, parentCategoryUuid,
948                             categoryName, assetVocabulary.getVocabularyId(),
949                             properties, serviceContext);
950                     }
951                     catch (DuplicateCategoryException dce) {
952                     }
953                     catch (NoSuchCategoryException nsce) {
954                     }
955                 }
956             }
957         }
958         catch (Exception e) {
959             throw new SystemException(e);
960         }
961     }
962 
963     protected void importCategory(
964             PortletDataContext context, String categoryUuid, String userUuid,
965             String parentCategoryUuid, String categoryName, long vocabularyId,
966             String[] properties, ServiceContext serviceContext)
967         throws PortalException, SystemException {
968 
969         long parentCategoryId = 0;
970 
971         if (Validator.isNotNull(parentCategoryUuid)) {
972             AssetCategory parentCategory = AssetCategoryUtil.findByUUID_G(
973                 parentCategoryUuid,context.getScopeGroupId());
974 
975             parentCategoryId = parentCategory.getCategoryId();
976         }
977 
978         if (context.getDataStrategy().equals(
979                 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
980 
981             AssetCategory existingAssetCategory =
982                 AssetCategoryUtil.fetchByUUID_G(
983                     categoryUuid, context.getGroupId());
984 
985             if (existingAssetCategory == null) {
986                 Map<Locale, String> titleMap =  new HashMap<Locale, String>();
987 
988                 titleMap.put(LocaleUtil.getDefault(), categoryName);
989 
990                 AssetCategoryLocalServiceUtil.addCategory(
991                     categoryUuid, context.getUserId(userUuid), parentCategoryId,
992                     titleMap, vocabularyId, properties, serviceContext);
993             }
994             else {
995                 AssetCategoryLocalServiceUtil.updateCategory(
996                     context.getUserId(userUuid),
997                     existingAssetCategory.getCategoryId(), parentCategoryId,
998                     existingAssetCategory.getTitleMap(), vocabularyId,
999                     properties, serviceContext);
1000            }
1001        }
1002        else {
1003            Map<Locale, String> titleMap =  new HashMap<Locale, String>();
1004
1005            titleMap.put(LocaleUtil.getDefault(), categoryName);
1006
1007            AssetCategoryLocalServiceUtil.addCategory(
1008                null, context.getUserId(userUuid), parentCategoryId, titleMap,
1009                vocabularyId, properties, serviceContext);
1010        }
1011    }
1012
1013    protected void importGroupPermissions(
1014            LayoutCache layoutCache, long companyId, long groupId,
1015            String resourceName, String resourcePrimKey, Element parentEl,
1016            String elName, boolean portletActions)
1017        throws PortalException, SystemException {
1018
1019        Element actionEl = parentEl.element(elName);
1020
1021        if (actionEl == null) {
1022            return;
1023        }
1024
1025        List<String> actions = getActions(actionEl);
1026
1027        Resource resource = layoutCache.getResource(
1028            companyId, groupId, resourceName,
1029            ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
1030            portletActions);
1031
1032        PermissionLocalServiceUtil.setGroupPermissions(
1033            groupId, actions.toArray(new String[actions.size()]),
1034            resource.getResourceId());
1035    }
1036
1037    protected void importGroupRoles(
1038            LayoutCache layoutCache, long companyId, long groupId,
1039            String resourceName, String entityName,
1040            Element parentEl)
1041        throws PortalException, SystemException {
1042
1043        Element entityRolesEl = parentEl.element(entityName + "-roles");
1044
1045        if (entityRolesEl == null) {
1046            return;
1047        }
1048
1049        importRolePermissions(
1050            layoutCache, companyId, resourceName, ResourceConstants.SCOPE_GROUP,
1051            String.valueOf(groupId), entityRolesEl, true);
1052    }
1053
1054    protected void importInheritedPermissions(
1055            LayoutCache layoutCache, long companyId, String resourceName,
1056            String resourcePrimKey, Element permissionsEl, String entityName,
1057            boolean portletActions)
1058        throws PortalException, SystemException {
1059
1060        Element entityPermissionsEl = permissionsEl.element(
1061            entityName + "-permissions");
1062
1063        if (entityPermissionsEl == null) {
1064            return;
1065        }
1066
1067        List<Element> actionsEls = entityPermissionsEl.elements(
1068            entityName + "-actions");
1069
1070        for (int i = 0; i < actionsEls.size(); i++) {
1071            Element actionEl = actionsEls.get(i);
1072
1073            String name = actionEl.attributeValue("name");
1074
1075            long entityGroupId = layoutCache.getEntityGroupId(
1076                companyId, entityName, name);
1077
1078            if (entityGroupId == 0) {
1079                _log.warn(
1080                    "Ignore inherited permissions for entity " + entityName +
1081                        " with name " + name);
1082            }
1083            else {
1084                Element parentEl = SAXReaderUtil.createElement("parent");
1085
1086                parentEl.add(actionEl.createCopy());
1087
1088                importGroupPermissions(
1089                    layoutCache, companyId, entityGroupId, resourceName,
1090                    resourcePrimKey, parentEl, entityName + "-actions",
1091                    portletActions);
1092            }
1093        }
1094    }
1095
1096    protected void importInheritedRoles(
1097            LayoutCache layoutCache, long companyId, long groupId,
1098            String resourceName, String entityName, Element parentEl)
1099        throws PortalException, SystemException {
1100
1101        Element entityRolesEl = parentEl.element(entityName + "-roles");
1102
1103        if (entityRolesEl == null) {
1104            return;
1105        }
1106
1107        List<Element> entityEls = entityRolesEl.elements(entityName);
1108
1109        for (int i = 0; i < entityEls.size(); i++) {
1110            Element entityEl = entityEls.get(i);
1111
1112            String name = entityEl.attributeValue("name");
1113
1114            long entityGroupId = layoutCache.getEntityGroupId(
1115                companyId, entityName, name);
1116
1117            if (entityGroupId == 0) {
1118                _log.warn(
1119                    "Ignore inherited roles for entity " + entityName +
1120                        " with name " + name);
1121            }
1122            else {
1123                importRolePermissions(
1124                    layoutCache, companyId, resourceName,
1125                    ResourceConstants.SCOPE_GROUP, String.valueOf(groupId),
1126                    entityEl, false);
1127            }
1128        }
1129    }
1130
1131    protected void importLayoutPermissions_4(
1132            LayoutCache layoutCache, long companyId, long groupId,
1133            Group guestGroup, Layout layout, String resourceName,
1134            String resourcePrimKey, Element permissionsEl,
1135            boolean importUserPermissions)
1136        throws PortalException, SystemException {
1137
1138        importGroupPermissions(
1139            layoutCache, companyId, groupId, resourceName, resourcePrimKey,
1140            permissionsEl, "community-actions", false);
1141
1142        if (groupId != guestGroup.getGroupId()) {
1143            importGroupPermissions(
1144                layoutCache, companyId, guestGroup.getGroupId(), resourceName,
1145                resourcePrimKey, permissionsEl, "guest-actions", false);
1146        }
1147
1148        if (importUserPermissions) {
1149            importUserPermissions(
1150                layoutCache, companyId, groupId, resourceName, resourcePrimKey,
1151                permissionsEl, false);
1152        }
1153
1154        importInheritedPermissions(
1155            layoutCache, companyId, resourceName, resourcePrimKey,
1156            permissionsEl, "organization", false);
1157
1158        importInheritedPermissions(
1159            layoutCache, companyId, resourceName, resourcePrimKey,
1160            permissionsEl, "user-group", false);
1161    }
1162
1163    protected void importLayoutPermissions_5(
1164            LayoutCache layoutCache, long companyId, long groupId, long userId,
1165            String resourceName, String resourcePrimKey, Element permissionsEl)
1166        throws PortalException, SystemException {
1167
1168        boolean portletActions = false;
1169
1170        Resource resource = layoutCache.getResource(
1171            companyId, groupId, resourceName,
1172            ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
1173            portletActions);
1174
1175        importPermissions_5(
1176            layoutCache, companyId, userId, resource.getResourceId(),
1177            permissionsEl);
1178    }
1179
1180    protected void importLayoutPermissions_6(
1181            LayoutCache layoutCache, long companyId, long groupId, long userId,
1182            String resourceName, String resourcePrimKey, Element permissionsEl)
1183        throws PortalException, SystemException {
1184
1185        boolean portletActions = false;
1186
1187        importPermissions_6(
1188            layoutCache, companyId, groupId, userId, resourceName,
1189            resourcePrimKey, permissionsEl, portletActions);
1190    }
1191
1192    protected void importLayoutRoles(
1193            LayoutCache layoutCache, long companyId, long groupId,
1194            Element rolesEl)
1195        throws PortalException, SystemException {
1196
1197        String resourceName = Layout.class.getName();
1198
1199        importGroupRoles(
1200            layoutCache, companyId, groupId, resourceName, "community",
1201            rolesEl);
1202
1203        importUserRoles(layoutCache, companyId, groupId, resourceName, rolesEl);
1204
1205        importInheritedRoles(
1206            layoutCache, companyId, groupId, resourceName, "organization",
1207            rolesEl);
1208
1209        importInheritedRoles(
1210            layoutCache, companyId, groupId, resourceName, "user-group",
1211            rolesEl);
1212    }
1213
1214    protected void importPermissions_5(
1215            LayoutCache layoutCache, long companyId, long userId,
1216            long resourceId, Element permissionsEl)
1217        throws PortalException, SystemException {
1218
1219        List<Element> roleEls = permissionsEl.elements("role");
1220
1221        for (Element roleEl : roleEls) {
1222            String name = roleEl.attributeValue("name");
1223
1224            Role role = layoutCache.getRole(companyId, name);
1225
1226            if (role == null) {
1227                String description = roleEl.attributeValue("description");
1228                int type = Integer.valueOf(roleEl.attributeValue("type"));
1229
1230                role = RoleLocalServiceUtil.addRole(
1231                    userId, companyId, name, null, description, type);
1232            }
1233
1234            List<String> actions = getActions(roleEl);
1235
1236            PermissionLocalServiceUtil.setRolePermissions(
1237                role.getRoleId(), actions.toArray(new String[actions.size()]),
1238                resourceId);
1239        }
1240    }
1241
1242    protected void importPermissions_6(
1243            LayoutCache layoutCache, long companyId, long groupId, long userId,
1244            String resourceName, String resourcePrimKey, Element permissionsEl,
1245            boolean portletActions)
1246        throws PortalException, SystemException {
1247
1248        List<Element> roleEls = permissionsEl.elements("role");
1249
1250        for (Element roleEl : roleEls) {
1251            String name = roleEl.attributeValue("name");
1252
1253            Role role = layoutCache.getRole(companyId, name);
1254
1255            if (role == null) {
1256                String description = roleEl.attributeValue("description");
1257                int type = Integer.valueOf(roleEl.attributeValue("type"));
1258
1259                role = RoleLocalServiceUtil.addRole(
1260                    userId, companyId, name, null, description, type);
1261            }
1262
1263            List<String> actions = getActions(roleEl);
1264
1265            ResourcePermissionLocalServiceUtil.setResourcePermissions(
1266                companyId, resourceName, ResourceConstants.SCOPE_INDIVIDUAL,
1267                resourcePrimKey, role.getRoleId(),
1268                actions.toArray(new String[actions.size()]));
1269        }
1270    }
1271
1272    protected void importPortletPermissions_4(
1273            LayoutCache layoutCache, long companyId, long groupId,
1274            Group guestGroup, Layout layout, Element permissionsEl,
1275            boolean importUserPermissions)
1276        throws PortalException, SystemException {
1277
1278        Iterator<Element> itr = permissionsEl.elements("portlet").iterator();
1279
1280        while (itr.hasNext()) {
1281            Element portletEl = itr.next();
1282
1283            String portletId = portletEl.attributeValue("portlet-id");
1284
1285            String resourceName = PortletConstants.getRootPortletId(portletId);
1286            String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
1287                layout.getPlid(), portletId);
1288
1289            Portlet portlet = PortletLocalServiceUtil.getPortletById(
1290                companyId, resourceName);
1291
1292            if (portlet == null) {
1293                if (_log.isDebugEnabled()) {
1294                    _log.debug(
1295                        "Do not import portlet permissions for " + portletId +
1296                            " because the portlet does not exist");
1297                }
1298            }
1299            else {
1300                importGroupPermissions(
1301                    layoutCache, companyId, groupId, resourceName,
1302                    resourcePrimKey, portletEl, "community-actions", true);
1303
1304                if (groupId != guestGroup.getGroupId()) {
1305                    importGroupPermissions(
1306                        layoutCache, companyId, guestGroup.getGroupId(),
1307                        resourceName, resourcePrimKey, portletEl,
1308                        "guest-actions", true);
1309                }
1310
1311                if (importUserPermissions) {
1312                    importUserPermissions(
1313                        layoutCache, companyId, groupId, resourceName,
1314                        resourcePrimKey, portletEl, true);
1315                }
1316
1317                importInheritedPermissions(
1318                    layoutCache, companyId, resourceName, resourcePrimKey,
1319                    portletEl, "organization", true);
1320
1321                importInheritedPermissions(
1322                    layoutCache, companyId, resourceName, resourcePrimKey,
1323                    portletEl, "user-group", true);
1324            }
1325        }
1326    }
1327
1328    protected void importPortletPermissions_5(
1329            LayoutCache layoutCache, long companyId, long groupId, long userId,
1330            String resourceName, String resourcePrimKey, Element permissionsEl)
1331        throws PortalException, SystemException {
1332
1333        boolean portletActions = true;
1334
1335        Resource resource = layoutCache.getResource(
1336            companyId, groupId, resourceName,
1337            ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
1338            portletActions);
1339
1340        importPermissions_5(
1341            layoutCache, companyId, userId, resource.getResourceId(),
1342            permissionsEl);
1343    }
1344
1345    protected void importPortletPermissions_6(
1346            LayoutCache layoutCache, long companyId, long groupId, long userId,
1347            String resourceName, String resourcePrimKey, Element permissionsEl)
1348        throws PortalException, SystemException {
1349
1350        boolean portletActions = true;
1351
1352        importPermissions_6(
1353            layoutCache, companyId, groupId, userId, resourceName,
1354            resourcePrimKey, permissionsEl, portletActions);
1355    }
1356
1357    protected void importPortletRoles(
1358            LayoutCache layoutCache, long companyId, long groupId,
1359            String portletId, Element rolesEl)
1360        throws PortalException, SystemException {
1361
1362        String resourceName = PortletConstants.getRootPortletId(portletId);
1363
1364        Portlet portlet = PortletLocalServiceUtil.getPortletById(
1365            companyId, resourceName);
1366
1367        if (portlet == null) {
1368            if (_log.isDebugEnabled()) {
1369                _log.debug(
1370                    "Do not import portlet roles for " + portletId +
1371                        " because the portlet does not exist");
1372            }
1373        }
1374        else {
1375            importGroupRoles(
1376                layoutCache, companyId, groupId, resourceName, "community",
1377                rolesEl);
1378
1379            importUserRoles(
1380                layoutCache, companyId, groupId, resourceName, rolesEl);
1381
1382            importInheritedRoles(
1383                layoutCache, companyId, groupId, resourceName,
1384                "organization", rolesEl);
1385
1386            importInheritedRoles(
1387                layoutCache, companyId, groupId, resourceName, "user-group",
1388                rolesEl);
1389        }
1390    }
1391
1392    protected void importPortletRoles(
1393            LayoutCache layoutCache, long companyId, long groupId,
1394            Element rolesEl)
1395        throws PortalException, SystemException {
1396
1397        Iterator<Element> itr = rolesEl.elements("portlet").iterator();
1398
1399        while (itr.hasNext()) {
1400            Element portletEl = itr.next();
1401
1402            String portletId = portletEl.attributeValue("portlet-id");
1403
1404            String resourceName = PortletConstants.getRootPortletId(portletId);
1405
1406            Portlet portlet = PortletLocalServiceUtil.getPortletById(
1407                companyId, resourceName);
1408
1409            if (portlet == null) {
1410                if (_log.isDebugEnabled()) {
1411                    _log.debug(
1412                        "Do not import portlet roles for " + portletId +
1413                            " because the portlet does not exist");
1414                }
1415            }
1416            else {
1417                importGroupRoles(
1418                    layoutCache, companyId, groupId, resourceName, "community",
1419                    portletEl);
1420
1421                importUserRoles(
1422                    layoutCache, companyId, groupId, resourceName, portletEl);
1423
1424                importInheritedRoles(
1425                    layoutCache, companyId, groupId, resourceName,
1426                    "organization", portletEl);
1427
1428                importInheritedRoles(
1429                    layoutCache, companyId, groupId, resourceName, "user-group",
1430                    portletEl);
1431            }
1432        }
1433    }
1434
1435    protected void importRolePermissions(
1436            LayoutCache layoutCache, long companyId, String resourceName,
1437            int scope, String resourcePrimKey, Element parentEl,
1438            boolean communityRole)
1439        throws PortalException, SystemException {
1440
1441        List<Element> roleEls = parentEl.elements("role");
1442
1443        for (int i = 0; i < roleEls.size(); i++) {
1444            Element roleEl = roleEls.get(i);
1445
1446            String roleName = roleEl.attributeValue("name");
1447
1448            Role role = layoutCache.getRole(companyId, roleName);
1449
1450            if (role == null) {
1451                _log.warn(
1452                    "Ignoring permissions for role with name " + roleName);
1453            }
1454            else {
1455                List<String> actions = getActions(roleEl);
1456
1457                PermissionLocalServiceUtil.setRolePermissions(
1458                    role.getRoleId(), companyId, resourceName, scope,
1459                    resourcePrimKey,
1460                    actions.toArray(new String[actions.size()]));
1461
1462                if (communityRole) {
1463                    long[] groupIds = {GetterUtil.getLong(resourcePrimKey)};
1464
1465                    GroupLocalServiceUtil.addRoleGroups(
1466                        role.getRoleId(), groupIds);
1467                }
1468            }
1469        }
1470    }
1471
1472    protected String importTheme(LayoutSet layoutSet, InputStream themeZip)
1473        throws IOException {
1474
1475        ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
1476
1477        if (themeLoader == null) {
1478            _log.error("No theme loaders are deployed");
1479
1480            return null;
1481        }
1482
1483        ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(themeZip);
1484
1485        String lookAndFeelXML = zipReader.getEntryAsString(
1486            "liferay-look-and-feel.xml");
1487
1488        String themeId = String.valueOf(layoutSet.getGroupId());
1489
1490        if (layoutSet.isPrivateLayout()) {
1491            themeId += "-private";
1492        }
1493        else {
1494            themeId += "-public";
1495        }
1496
1497        if (PropsValues.THEME_LOADER_NEW_THEME_ID_ON_IMPORT) {
1498            Date now = new Date();
1499
1500            themeId += "-" + Time.getShortTimestamp(now);
1501        }
1502
1503        String themeName = themeId;
1504
1505        lookAndFeelXML = StringUtil.replace(
1506            lookAndFeelXML,
1507            new String[] {
1508                "[$GROUP_ID$]", "[$THEME_ID$]", "[$THEME_NAME$]"
1509            },
1510            new String[] {
1511                String.valueOf(layoutSet.getGroupId()), themeId, themeName
1512            }
1513        );
1514
1515        FileUtil.deltree(
1516            themeLoader.getFileStorage() + StringPool.SLASH + themeId);
1517
1518        List<String> zipEntries = zipReader.getEntries();
1519
1520        for (String zipEntry : zipEntries) {
1521            String key = zipEntry;
1522
1523            if (key.contains(StringPool.SLASH)) {
1524                key = key.substring(key.lastIndexOf(StringPool.SLASH));
1525            }
1526
1527            if (key.equals("liferay-look-and-feel.xml")) {
1528                FileUtil.write(
1529                    themeLoader.getFileStorage() + StringPool.SLASH + themeId +
1530                        StringPool.SLASH + key,
1531                    lookAndFeelXML.getBytes());
1532            }
1533            else {
1534                InputStream is = zipReader.getEntryAsInputStream(zipEntry);
1535
1536                FileUtil.write(
1537                    themeLoader.getFileStorage() + StringPool.SLASH + themeId +
1538                        StringPool.SLASH + key,
1539                    is);
1540            }
1541        }
1542
1543        themeLoader.loadThemes();
1544
1545        MethodWrapper methodWrapper = new MethodWrapper(
1546            ThemeLoaderFactory.class.getName(), "loadThemes");
1547
1548        Message message = new Message();
1549        message.setPayload(methodWrapper);
1550
1551        ClusterLinkUtil.sendMulticastMessage(message, Priority.LEVEL5);
1552
1553        themeId +=
1554            PortletConstants.WAR_SEPARATOR +
1555                themeLoader.getServletContextName();
1556
1557        return PortalUtil.getJsSafePortletId(themeId);
1558    }
1559
1560    protected void importUserPermissions(
1561            LayoutCache layoutCache, long companyId, long groupId,
1562            String resourceName, String resourcePrimKey, Element parentEl,
1563            boolean portletActions)
1564        throws PortalException, SystemException {
1565
1566        Element userPermissionsEl = parentEl.element("user-permissions");
1567
1568        if (userPermissionsEl == null) {
1569            return;
1570        }
1571
1572        List<Element> userActionsEls = userPermissionsEl.elements(
1573            "user-actions");
1574
1575        for (int i = 0; i < userActionsEls.size(); i++) {
1576            Element userActionsEl = userActionsEls.get(i);
1577
1578            String uuid = userActionsEl.attributeValue("uuid");
1579
1580            User user = layoutCache.getUser(companyId, groupId, uuid);
1581
1582            if (user == null) {
1583                if (_log.isWarnEnabled()) {
1584                    _log.warn(
1585                        "Ignoring permissions for user with uuid " + uuid);
1586                }
1587            }
1588            else {
1589                List<String> actions = getActions(userActionsEl);
1590
1591                Resource resource = layoutCache.getResource(
1592                    companyId, groupId, resourceName,
1593                    ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
1594                    portletActions);
1595
1596                PermissionLocalServiceUtil.setUserPermissions(
1597                    user.getUserId(),
1598                    actions.toArray(new String[actions.size()]),
1599                    resource.getResourceId());
1600            }
1601        }
1602    }
1603
1604    protected void importUserRoles(
1605            LayoutCache layoutCache, long companyId, long groupId,
1606            String resourceName, Element parentEl)
1607        throws PortalException, SystemException {
1608
1609        Element userRolesEl = parentEl.element("user-roles");
1610
1611        if (userRolesEl == null) {
1612            return;
1613        }
1614
1615        List<Element> userEls = userRolesEl.elements("user");
1616
1617        for (int i = 0; i < userEls.size(); i++) {
1618            Element userEl = userEls.get(i);
1619
1620            String uuid = userEl.attributeValue("uuid");
1621
1622            User user = layoutCache.getUser(companyId, groupId, uuid);
1623
1624            if (user == null) {
1625                if (_log.isWarnEnabled()) {
1626                    _log.warn("Ignoring roles for user with uuid " + uuid);
1627                }
1628            }
1629            else {
1630                importRolePermissions(
1631                    layoutCache, companyId, resourceName,
1632                    ResourceConstants.SCOPE_GROUP, String.valueOf(groupId),
1633                    userEl, false);
1634            }
1635        }
1636    }
1637
1638    protected void mergePortlets(
1639        Layout layout, String newTypeSettings, String portletsMergeMode) {
1640
1641        try {
1642            UnicodeProperties previousProps =
1643                layout.getTypeSettingsProperties();
1644            LayoutTypePortlet previousLayoutType =
1645                (LayoutTypePortlet)layout.getLayoutType();
1646            List<String> previousColumns =
1647                previousLayoutType.getLayoutTemplate().getColumns();
1648
1649            UnicodeProperties newProps = new UnicodeProperties(true);
1650
1651            newProps.load(newTypeSettings);
1652
1653            String layoutTemplateId = newProps.getProperty(
1654                    LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID);
1655
1656            LayoutTemplate newLayoutTemplate =
1657                LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1658                    layoutTemplateId, false, null);
1659
1660            String[] lostPortletIds = new String[0];
1661
1662            for (String columnId : newLayoutTemplate.getColumns()) {
1663                String columnValue =
1664                    newProps.getProperty(columnId);
1665
1666                String[] portletIds = StringUtil.split(columnValue);
1667
1668                if (!previousColumns.contains(columnId)) {
1669                    lostPortletIds = ArrayUtil.append(
1670                        lostPortletIds, portletIds);
1671                }
1672                else {
1673
1674                    String[] previousPortletIds = StringUtil.split(
1675                        previousProps.getProperty(columnId));
1676
1677                    portletIds = appendPortletIds(
1678                        previousPortletIds, portletIds, portletsMergeMode);
1679
1680                    previousProps.setProperty(
1681                        columnId, StringUtil.merge(portletIds));
1682                }
1683            }
1684
1685            // Add portlets in non-existent column to the first column
1686
1687            String columnId = previousColumns.get(0);
1688
1689            String[] portletIds = StringUtil.split(
1690                previousProps.getProperty(columnId));
1691
1692            appendPortletIds(portletIds, lostPortletIds, portletsMergeMode);
1693
1694            previousProps.setProperty(
1695                columnId, StringUtil.merge(portletIds));
1696
1697            layout.setTypeSettings(previousProps.toString());
1698
1699        }
1700        catch (IOException e) {
1701            layout.setTypeSettings(newTypeSettings);
1702        }
1703    }
1704
1705    protected String[] appendPortletIds(
1706        String[] portletIds, String[] newPortletIds,
1707        String portletsMergeMode) {
1708
1709        for (String portletId : newPortletIds) {
1710            if (ArrayUtil.contains(portletIds, portletId)) {
1711                continue;
1712            }
1713
1714            if (portletsMergeMode.equals(
1715                    PortletDataHandlerKeys.PORTLETS_MERGE_MODE_ADD_TO_BOTTOM)) {
1716                portletIds = ArrayUtil.append(
1717                    portletIds, portletId);
1718            }
1719            else {
1720                portletIds = ArrayUtil.append(
1721                    new String[] {portletId}, portletIds);
1722            }
1723        }
1724
1725        return portletIds;
1726    }
1727
1728    private static Log _log = LogFactoryUtil.getLog(LayoutImporter.class);
1729
1730    private PortletImporter _portletImporter = new PortletImporter();
1731
1732}