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