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