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