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