001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.exportimport.lar;
016    
017    import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.EVENT_LAYOUT_IMPORT_FAILED;
018    import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.EVENT_LAYOUT_IMPORT_STARTED;
019    import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.EVENT_LAYOUT_IMPORT_SUCCEEDED;
020    import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.EVENT_PORTLET_IMPORT_FAILED;
021    import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.EVENT_PORTLET_IMPORT_STARTED;
022    import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.EVENT_PORTLET_IMPORT_SUCCEEDED;
023    import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.PROCESS_FLAG_LAYOUT_IMPORT_IN_PROCESS;
024    import static com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleConstants.PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS;
025    
026    import com.liferay.portal.LayoutPrototypeException;
027    import com.liferay.portal.LocaleException;
028    import com.liferay.portal.NoSuchLayoutException;
029    import com.liferay.portal.NoSuchLayoutPrototypeException;
030    import com.liferay.portal.NoSuchLayoutSetPrototypeException;
031    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskThreadLocal;
032    import com.liferay.portal.kernel.exception.PortalException;
033    import com.liferay.portal.kernel.language.LanguageUtil;
034    import com.liferay.portal.kernel.log.Log;
035    import com.liferay.portal.kernel.log.LogFactoryUtil;
036    import com.liferay.portal.kernel.util.ArrayUtil;
037    import com.liferay.portal.kernel.util.Constants;
038    import com.liferay.portal.kernel.util.GetterUtil;
039    import com.liferay.portal.kernel.util.LocaleUtil;
040    import com.liferay.portal.kernel.util.MapUtil;
041    import com.liferay.portal.kernel.util.ReleaseInfo;
042    import com.liferay.portal.kernel.util.StringUtil;
043    import com.liferay.portal.kernel.util.Tuple;
044    import com.liferay.portal.kernel.util.UnicodeProperties;
045    import com.liferay.portal.kernel.util.Validator;
046    import com.liferay.portal.kernel.xml.Document;
047    import com.liferay.portal.kernel.xml.Element;
048    import com.liferay.portal.kernel.xml.SAXReaderUtil;
049    import com.liferay.portal.kernel.zip.ZipReader;
050    import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
051    import com.liferay.portal.model.Group;
052    import com.liferay.portal.model.GroupConstants;
053    import com.liferay.portal.model.Layout;
054    import com.liferay.portal.model.LayoutConstants;
055    import com.liferay.portal.model.LayoutPrototype;
056    import com.liferay.portal.model.LayoutSet;
057    import com.liferay.portal.model.LayoutSetPrototype;
058    import com.liferay.portal.model.Portlet;
059    import com.liferay.portal.model.impl.LayoutImpl;
060    import com.liferay.portal.service.GroupLocalServiceUtil;
061    import com.liferay.portal.service.LayoutLocalServiceUtil;
062    import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
063    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
064    import com.liferay.portal.service.LayoutSetPrototypeLocalServiceUtil;
065    import com.liferay.portal.service.PortletLocalServiceUtil;
066    import com.liferay.portal.service.ServiceContext;
067    import com.liferay.portal.service.ServiceContextThreadLocal;
068    import com.liferay.portal.service.persistence.LayoutUtil;
069    import com.liferay.portlet.exportimport.LARFileException;
070    import com.liferay.portlet.exportimport.LARTypeException;
071    import com.liferay.portlet.exportimport.LayoutImportException;
072    import com.liferay.portlet.exportimport.MissingReferenceException;
073    import com.liferay.portlet.exportimport.lifecycle.ExportImportLifecycleManager;
074    import com.liferay.portlet.exportimport.xstream.XStreamAliasRegistryUtil;
075    import com.liferay.portlet.sites.util.Sites;
076    import com.liferay.portlet.sites.util.SitesUtil;
077    
078    import java.io.File;
079    
080    import java.util.ArrayList;
081    import java.util.Arrays;
082    import java.util.HashMap;
083    import java.util.HashSet;
084    import java.util.List;
085    import java.util.Locale;
086    import java.util.Map;
087    import java.util.Set;
088    
089    import org.apache.commons.lang.time.StopWatch;
090    
091    /**
092     * @author Brian Wing Shun Chan
093     * @author Joel Kozikowski
094     * @author Charles May
095     * @author Raymond Aug??
096     * @author Jorge Ferrer
097     * @author Bruno Farache
098     * @author Wesley Gong
099     * @author Zsigmond Rab
100     * @author Douglas Wong
101     * @author Julio Camarero
102     * @author Zsolt Berentey
103     */
104    public class LayoutImporter {
105    
106            public static LayoutImporter getInstance() {
107                    return _instance;
108            }
109    
110            public void importLayouts(
111                            long userId, long groupId, boolean privateLayout,
112                            Map<String, String[]> parameterMap, File file)
113                    throws Exception {
114    
115                    PortletDataContext portletDataContext = null;
116    
117                    try {
118                            ExportImportThreadLocal.setLayoutImportInProcess(true);
119    
120                            portletDataContext = getPortletDataContext(
121                                    userId, groupId, privateLayout, parameterMap, file);
122    
123                            ExportImportLifecycleManager.fireExportImportLifecycleEvent(
124                                    EVENT_LAYOUT_IMPORT_STARTED, getProcessFlag(),
125                                    PortletDataContextFactoryUtil.clonePortletDataContext(
126                                            portletDataContext));
127    
128                            doImportLayouts(portletDataContext, userId);
129    
130                            ExportImportThreadLocal.setLayoutImportInProcess(false);
131    
132                            ExportImportLifecycleManager.fireExportImportLifecycleEvent(
133                                    EVENT_LAYOUT_IMPORT_SUCCEEDED, getProcessFlag(),
134                                    PortletDataContextFactoryUtil.clonePortletDataContext(
135                                            portletDataContext),
136                                    userId);
137                    }
138                    catch (Throwable t) {
139                            ExportImportThreadLocal.setLayoutImportInProcess(false);
140    
141                            ExportImportLifecycleManager.fireExportImportLifecycleEvent(
142                                    EVENT_LAYOUT_IMPORT_FAILED, getProcessFlag(),
143                                    PortletDataContextFactoryUtil.clonePortletDataContext(
144                                            portletDataContext),
145                                    t);
146    
147                            throw t;
148                    }
149            }
150    
151            public void importLayoutsDataDeletions(
152                            long userId, long groupId, boolean privateLayout,
153                            Map<String, String[]> parameterMap, File file)
154                    throws Exception {
155    
156                    ZipReader zipReader = null;
157    
158                    try {
159                            ExportImportThreadLocal.setLayoutDataDeletionImportInProcess(true);
160    
161                            // LAR validation
162    
163                            LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
164                                    groupId, privateLayout);
165    
166                            zipReader = ZipReaderFactoryUtil.getZipReader(file);
167    
168                            validateFile(
169                                    layoutSet.getCompanyId(), groupId, parameterMap, zipReader);
170    
171                            PortletDataContext portletDataContext = getPortletDataContext(
172                                    userId, groupId, privateLayout, parameterMap, file);
173    
174                            boolean deletePortletData = MapUtil.getBoolean(
175                                    parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
176    
177                            // Portlet data deletion
178    
179                            if (deletePortletData) {
180                                    if (_log.isDebugEnabled()) {
181                                            _log.debug("Deleting portlet data");
182                                    }
183    
184                                    deletePortletData(portletDataContext);
185                            }
186    
187                            // Deletion system events
188    
189                            populateDeletionStagedModelTypes(portletDataContext);
190    
191                            _deletionSystemEventImporter.importDeletionSystemEvents(
192                                    portletDataContext);
193                    }
194                    finally {
195                            ExportImportThreadLocal.setLayoutDataDeletionImportInProcess(false);
196    
197                            if (zipReader != null) {
198                                    zipReader.close();
199                            }
200                    }
201            }
202    
203            public MissingReferences validateFile(
204                            long userId, long groupId, boolean privateLayout,
205                            Map<String, String[]> parameterMap, File file)
206                    throws Exception {
207    
208                    ZipReader zipReader = null;
209    
210                    try {
211                            ExportImportThreadLocal.setLayoutValidationInProcess(true);
212    
213                            LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
214                                    groupId, privateLayout);
215    
216                            zipReader = ZipReaderFactoryUtil.getZipReader(file);
217    
218                            validateFile(
219                                    layoutSet.getCompanyId(), groupId, parameterMap, zipReader);
220    
221                            PortletDataContext portletDataContext = getPortletDataContext(
222                                    userId, groupId, privateLayout, parameterMap, file);
223    
224                            portletDataContext.setPrivateLayout(privateLayout);
225    
226                            MissingReferences missingReferences =
227                                    ExportImportHelperUtil.validateMissingReferences(
228                                            portletDataContext);
229    
230                            Map<String, MissingReference> dependencyMissingReferences =
231                                    missingReferences.getDependencyMissingReferences();
232    
233                            if (!dependencyMissingReferences.isEmpty()) {
234                                    throw new MissingReferenceException(missingReferences);
235                            }
236    
237                            return missingReferences;
238                    }
239                    finally {
240                            ExportImportThreadLocal.setLayoutValidationInProcess(false);
241    
242                            if (zipReader != null) {
243                                    zipReader.close();
244                            }
245                    }
246            }
247    
248            protected void deleteMissingLayouts(
249                            PortletDataContext portletDataContext,
250                            List<String> sourceLayoutUuids, List<Layout> previousLayouts,
251                            ServiceContext serviceContext)
252                    throws Exception {
253    
254                    if (_log.isDebugEnabled() && !sourceLayoutUuids.isEmpty()) {
255                            _log.debug("Delete missing layouts");
256                    }
257    
258                    Map<Long, Long> layoutPlids =
259                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
260                                    Layout.class);
261    
262                    for (Layout layout : previousLayouts) {
263                            if (!sourceLayoutUuids.contains(layout.getUuid()) &&
264                                    !layoutPlids.containsValue(layout.getPlid())) {
265    
266                                    try {
267                                            LayoutLocalServiceUtil.deleteLayout(
268                                                    layout, false, serviceContext);
269                                    }
270                                    catch (NoSuchLayoutException nsle) {
271                                    }
272                            }
273                    }
274            }
275    
276            protected void deletePortletData(PortletDataContext portletDataContext)
277                    throws Exception {
278    
279                    Element rootElement = portletDataContext.getImportDataRootElement();
280    
281                    Element portletsElement = rootElement.element("portlets");
282    
283                    List<Element> portletElements = portletsElement.elements("portlet");
284    
285                    Map<Long, Layout> layouts =
286                            (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
287                                    Layout.class + ".layout");
288    
289                    if (_log.isDebugEnabled()) {
290                            if (!portletElements.isEmpty()) {
291                                    _log.debug("Deleting portlet data");
292                            }
293                    }
294    
295                    for (Element portletElement : portletElements) {
296                            long layoutId = GetterUtil.getLong(
297                                    portletElement.attributeValue("layout-id"));
298    
299                            long plid = LayoutConstants.DEFAULT_PLID;
300    
301                            Layout layout = layouts.get(layoutId);
302    
303                            if (layout != null) {
304                                    plid = layout.getPlid();
305                            }
306    
307                            portletDataContext.setPlid(plid);
308                            portletDataContext.setPortletId(
309                                    portletElement.attributeValue("portlet-id"));
310    
311                            _portletImporter.deletePortletData(portletDataContext);
312                    }
313            }
314    
315            protected void doImportLayouts(
316                            PortletDataContext portletDataContext, long userId)
317                    throws Exception {
318    
319                    Map<String, String[]> parameterMap =
320                            portletDataContext.getParameterMap();
321    
322                    boolean deleteMissingLayouts = MapUtil.getBoolean(
323                            parameterMap, PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
324                            Boolean.TRUE.booleanValue());
325                    boolean importPermissions = MapUtil.getBoolean(
326                            parameterMap, PortletDataHandlerKeys.PERMISSIONS);
327                    boolean importLogo = MapUtil.getBoolean(
328                            parameterMap, PortletDataHandlerKeys.LOGO);
329                    boolean importLayoutSetSettings = MapUtil.getBoolean(
330                            parameterMap, PortletDataHandlerKeys.LAYOUT_SET_SETTINGS);
331    
332                    boolean layoutSetPrototypeLinkEnabled = MapUtil.getBoolean(
333                            parameterMap,
334                            PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED);
335    
336                    Group group = GroupLocalServiceUtil.getGroup(
337                            portletDataContext.getGroupId());
338    
339                    if (group.isLayoutSetPrototype()) {
340                            layoutSetPrototypeLinkEnabled = false;
341                    }
342    
343                    String layoutsImportMode = MapUtil.getString(
344                            parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
345                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID);
346    
347                    if (_log.isDebugEnabled()) {
348                            _log.debug("Import permissions " + importPermissions);
349                    }
350    
351                    StopWatch stopWatch = new StopWatch();
352    
353                    stopWatch.start();
354    
355                    LayoutCache layoutCache = new LayoutCache();
356    
357                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
358                            portletDataContext.getGroupId(),
359                            portletDataContext.isPrivateLayout());
360    
361                    long companyId = layoutSet.getCompanyId();
362    
363                    ServiceContext serviceContext =
364                            ServiceContextThreadLocal.getServiceContext();
365    
366                    if (serviceContext == null) {
367                            serviceContext = new ServiceContext();
368                    }
369    
370                    serviceContext.setCompanyId(companyId);
371                    serviceContext.setSignedIn(false);
372                    serviceContext.setUserId(userId);
373    
374                    ServiceContextThreadLocal.pushServiceContext(serviceContext);
375    
376                    // LAR validation
377    
378                    validateFile(
379                            companyId, portletDataContext.getGroupId(), parameterMap,
380                            portletDataContext.getZipReader());
381    
382                    // Source and target group id
383    
384                    Map<Long, Long> groupIds =
385                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
386                                    Group.class);
387    
388                    groupIds.put(
389                            portletDataContext.getSourceGroupId(),
390                            portletDataContext.getGroupId());
391    
392                    // Manifest
393    
394                    ManifestSummary manifestSummary =
395                            ExportImportHelperUtil.getManifestSummary(portletDataContext);
396    
397                    portletDataContext.setManifestSummary(manifestSummary);
398    
399                    // Layout and layout set prototype
400    
401                    Element layoutsElement = portletDataContext.getImportDataGroupElement(
402                            Layout.class);
403    
404                    String layoutSetPrototypeUuid = layoutsElement.attributeValue(
405                            "layout-set-prototype-uuid");
406    
407                    Element rootElement = portletDataContext.getImportDataRootElement();
408    
409                    Element headerElement = rootElement.element("header");
410    
411                    String larType = headerElement.attributeValue("type");
412    
413                    if (group.isLayoutPrototype() && larType.equals("layout-prototype")) {
414                            deleteMissingLayouts = false;
415    
416                            LayoutPrototype layoutPrototype =
417                                    LayoutPrototypeLocalServiceUtil.getLayoutPrototype(
418                                            group.getClassPK());
419    
420                            String layoutPrototypeUuid = GetterUtil.getString(
421                                    headerElement.attributeValue("type-uuid"));
422    
423                            LayoutPrototype existingLayoutPrototype = null;
424    
425                            if (Validator.isNotNull(layoutPrototypeUuid)) {
426                                    try {
427                                            existingLayoutPrototype =
428                                                    LayoutPrototypeLocalServiceUtil.
429                                                            getLayoutPrototypeByUuidAndCompanyId(
430                                                                    layoutPrototypeUuid, companyId);
431                                    }
432                                    catch (NoSuchLayoutPrototypeException nslpe) {
433                                    }
434                            }
435    
436                            if (existingLayoutPrototype == null) {
437                                    List<Layout> layouts =
438                                            LayoutLocalServiceUtil.getLayoutsByLayoutPrototypeUuid(
439                                                    layoutPrototype.getUuid());
440    
441                                    layoutPrototype.setUuid(layoutPrototypeUuid);
442    
443                                    LayoutPrototypeLocalServiceUtil.updateLayoutPrototype(
444                                            layoutPrototype);
445    
446                                    for (Layout layout : layouts) {
447                                            layout.setLayoutPrototypeUuid(layoutPrototypeUuid);
448    
449                                            LayoutLocalServiceUtil.updateLayout(layout);
450                                    }
451                            }
452                    }
453                    else if (group.isLayoutSetPrototype() &&
454                                     larType.equals("layout-set-prototype")) {
455    
456                            LayoutSetPrototype layoutSetPrototype =
457                                    LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototype(
458                                            group.getClassPK());
459    
460                            String importedLayoutSetPrototypeUuid = GetterUtil.getString(
461                                    headerElement.attributeValue("type-uuid"));
462    
463                            LayoutSetPrototype existingLayoutSetPrototype = null;
464    
465                            if (Validator.isNotNull(importedLayoutSetPrototypeUuid)) {
466                                    try {
467                                            existingLayoutSetPrototype =
468                                                    LayoutSetPrototypeLocalServiceUtil.
469                                                            getLayoutSetPrototypeByUuidAndCompanyId(
470                                                                    importedLayoutSetPrototypeUuid, companyId);
471                                    }
472                                    catch (NoSuchLayoutSetPrototypeException nslspe) {
473                                    }
474                            }
475    
476                            if (existingLayoutSetPrototype == null) {
477                                    List<LayoutSet> layoutSets =
478                                            LayoutSetLocalServiceUtil.
479                                                    getLayoutSetsByLayoutSetPrototypeUuid(
480                                                            layoutSetPrototype.getUuid());
481    
482                                    layoutSetPrototype.setUuid(importedLayoutSetPrototypeUuid);
483    
484                                    LayoutSetPrototypeLocalServiceUtil.updateLayoutSetPrototype(
485                                            layoutSetPrototype);
486    
487                                    for (LayoutSet curLayoutSet : layoutSets) {
488                                            curLayoutSet.setLayoutSetPrototypeUuid(
489                                                    importedLayoutSetPrototypeUuid);
490    
491                                            LayoutSetLocalServiceUtil.updateLayoutSet(curLayoutSet);
492                                    }
493                            }
494                    }
495                    else if (larType.equals("layout-set-prototype")) {
496                            layoutSetPrototypeUuid = GetterUtil.getString(
497                                    headerElement.attributeValue("type-uuid"));
498                    }
499    
500                    if (Validator.isNotNull(layoutSetPrototypeUuid)) {
501                            layoutSet.setLayoutSetPrototypeUuid(layoutSetPrototypeUuid);
502                            layoutSet.setLayoutSetPrototypeLinkEnabled(
503                                    layoutSetPrototypeLinkEnabled);
504    
505                            LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
506                    }
507    
508                    // Look and feel
509    
510                    if (importLogo) {
511                            String logoPath = headerElement.attributeValue("logo-path");
512    
513                            byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(
514                                    logoPath);
515    
516                            if (ArrayUtil.isNotEmpty(iconBytes)) {
517                                    LayoutSetLocalServiceUtil.updateLogo(
518                                            portletDataContext.getGroupId(),
519                                            portletDataContext.isPrivateLayout(), true, iconBytes);
520                            }
521                            else {
522                                    LayoutSetLocalServiceUtil.updateLogo(
523                                            portletDataContext.getGroupId(),
524                                            portletDataContext.isPrivateLayout(), false, (File)null);
525                            }
526                    }
527    
528                    _themeImporter.importTheme(portletDataContext, layoutSet);
529    
530                    if (importLayoutSetSettings) {
531                            String settings = GetterUtil.getString(
532                                    headerElement.elementText("settings"));
533    
534                            LayoutSetLocalServiceUtil.updateSettings(
535                                    portletDataContext.getGroupId(),
536                                    portletDataContext.isPrivateLayout(), settings);
537                    }
538    
539                    Element portletsElement = rootElement.element("portlets");
540    
541                    List<Element> portletElements = portletsElement.elements("portlet");
542    
543                    if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
544                            List<String> portletIds = new ArrayList<>();
545    
546                            for (Element portletElement : portletElements) {
547                                    String portletId = portletElement.attributeValue("portlet-id");
548    
549                                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
550                                            portletDataContext.getCompanyId(), portletId);
551    
552                                    if (!portlet.isActive() || portlet.isUndeployedPortlet()) {
553                                            continue;
554                                    }
555    
556                                    portletIds.add(portletId);
557                            }
558    
559                            PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
560                                    "layout", ArrayUtil.toStringArray(portletIds), manifestSummary);
561                    }
562    
563                    // Read expando tables, locks, and permissions to make them
564                    // available to the data handlers through the portlet data context
565    
566                    if (importPermissions) {
567                            for (Element portletElement : portletElements) {
568                                    String portletPath = portletElement.attributeValue("path");
569    
570                                    Document portletDocument = SAXReaderUtil.read(
571                                            portletDataContext.getZipEntryAsString(portletPath));
572    
573                                    _permissionImporter.checkRoles(
574                                            layoutCache, companyId, portletDataContext.getGroupId(),
575                                            userId, portletDocument.getRootElement());
576                            }
577    
578                            _permissionImporter.readPortletDataPermissions(portletDataContext);
579                    }
580    
581                    _portletImporter.readExpandoTables(portletDataContext);
582                    _portletImporter.readLocks(portletDataContext);
583    
584                    // Layouts
585    
586                    Set<Layout> modifiedLayouts = new HashSet<>();
587                    List<Layout> previousLayouts = LayoutUtil.findByG_P(
588                            portletDataContext.getGroupId(),
589                            portletDataContext.isPrivateLayout());
590    
591                    // Remove layouts that were deleted from the layout set prototype
592    
593                    if (Validator.isNotNull(layoutSetPrototypeUuid) &&
594                            layoutSetPrototypeLinkEnabled) {
595    
596                            LayoutSetPrototype layoutSetPrototype =
597                                    LayoutSetPrototypeLocalServiceUtil.
598                                            getLayoutSetPrototypeByUuidAndCompanyId(
599                                                    layoutSetPrototypeUuid, companyId);
600    
601                            for (Layout layout : previousLayouts) {
602                                    String sourcePrototypeLayoutUuid =
603                                            layout.getSourcePrototypeLayoutUuid();
604    
605                                    if (Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
606                                            continue;
607                                    }
608    
609                                    if (SitesUtil.isLayoutModifiedSinceLastMerge(layout)) {
610                                            modifiedLayouts.add(layout);
611    
612                                            continue;
613                                    }
614    
615                                    Layout sourcePrototypeLayout = LayoutUtil.fetchByUUID_G_P(
616                                            sourcePrototypeLayoutUuid, layoutSetPrototype.getGroupId(),
617                                            true);
618    
619                                    if (sourcePrototypeLayout == null) {
620                                            LayoutLocalServiceUtil.deleteLayout(
621                                                    layout, false, serviceContext);
622                                    }
623                            }
624                    }
625    
626                    List<Element> layoutElements = layoutsElement.elements();
627    
628                    if (_log.isDebugEnabled()) {
629                            if (!layoutElements.isEmpty()) {
630                                    _log.debug("Importing layouts");
631                            }
632                    }
633    
634                    List<String> sourceLayoutsUuids = new ArrayList<>();
635    
636                    for (Element layoutElement : layoutElements) {
637                            importLayout(portletDataContext, sourceLayoutsUuids, layoutElement);
638                    }
639    
640                    // Import portlets
641    
642                    if (_log.isDebugEnabled()) {
643                            if (!portletElements.isEmpty()) {
644                                    _log.debug("Importing portlets");
645                            }
646                    }
647    
648                    Map<Long, Layout> layouts =
649                            (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
650                                    Layout.class + ".layout");
651    
652                    for (Element portletElement : portletElements) {
653                            String portletPath = portletElement.attributeValue("path");
654                            String portletId = portletElement.attributeValue("portlet-id");
655                            long layoutId = GetterUtil.getLong(
656                                    portletElement.attributeValue("layout-id"));
657                            long oldPlid = GetterUtil.getLong(
658                                    portletElement.attributeValue("old-plid"));
659    
660                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
661                                    portletDataContext.getCompanyId(), portletId);
662    
663                            if (!portlet.isActive() || portlet.isUndeployedPortlet()) {
664                                    continue;
665                            }
666    
667                            Layout layout = layouts.get(layoutId);
668    
669                            long plid = LayoutConstants.DEFAULT_PLID;
670    
671                            if (layout != null) {
672                                    plid = layout.getPlid();
673    
674                                    if (modifiedLayouts.contains(layout)) {
675                                            continue;
676                                    }
677                            }
678    
679                            portletDataContext.setPlid(plid);
680                            portletDataContext.setOldPlid(oldPlid);
681                            portletDataContext.setPortletId(portletId);
682    
683                            if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
684                                    PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
685                                            "portlet", portletId, manifestSummary);
686                            }
687    
688                            Document portletDocument = SAXReaderUtil.read(
689                                    portletDataContext.getZipEntryAsString(portletPath));
690    
691                            portletElement = portletDocument.getRootElement();
692    
693                            // The order of the import is important. You must always import the
694                            // portlet preferences first, then the portlet data, then the
695                            // portlet permissions. The import of the portlet data assumes that
696                            // portlet preferences already exist.
697    
698                            setPortletScope(portletDataContext, portletElement);
699    
700                            long portletPreferencesGroupId = portletDataContext.getGroupId();
701    
702                            Element portletDataElement = portletElement.element("portlet-data");
703    
704                            Map<String, Boolean> importPortletControlsMap =
705                                    ExportImportHelperUtil.getImportPortletControlsMap(
706                                            companyId, portletId, parameterMap, portletDataElement,
707                                            manifestSummary);
708    
709                            if (layout != null) {
710                                    portletPreferencesGroupId = layout.getGroupId();
711                            }
712    
713                            try {
714                                    ExportImportLifecycleManager.fireExportImportLifecycleEvent(
715                                            EVENT_PORTLET_IMPORT_STARTED, getProcessFlag(),
716                                            PortletDataContextFactoryUtil.clonePortletDataContext(
717                                                    portletDataContext));
718    
719                                    // Portlet preferences
720    
721                                    _portletImporter.importPortletPreferences(
722                                            portletDataContext, layoutSet.getCompanyId(),
723                                            portletPreferencesGroupId, layout, portletElement, false,
724                                            importPortletControlsMap.get(
725                                                    PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
726                                            importPortletControlsMap.get(
727                                                    PortletDataHandlerKeys.PORTLET_DATA),
728                                            importPortletControlsMap.get(
729                                                    PortletDataHandlerKeys.PORTLET_SETUP),
730                                            importPortletControlsMap.get(
731                                                    PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));
732    
733                                    // Portlet data
734    
735                                    if (importPortletControlsMap.get(
736                                                    PortletDataHandlerKeys.PORTLET_DATA)) {
737    
738                                            _portletImporter.importPortletData(
739                                                    portletDataContext, portletDataElement);
740                                    }
741    
742                                    ExportImportLifecycleManager.fireExportImportLifecycleEvent(
743                                            EVENT_PORTLET_IMPORT_SUCCEEDED, getProcessFlag(),
744                                            PortletDataContextFactoryUtil.clonePortletDataContext(
745                                                    portletDataContext));
746                            }
747                            catch (Throwable t) {
748                                    ExportImportLifecycleManager.fireExportImportLifecycleEvent(
749                                            EVENT_PORTLET_IMPORT_FAILED, getProcessFlag(),
750                                            PortletDataContextFactoryUtil.clonePortletDataContext(
751                                                    portletDataContext),
752                                            t);
753    
754                                    throw t;
755                            }
756                            finally {
757                                    _portletImporter.resetPortletScope(
758                                            portletDataContext, portletPreferencesGroupId);
759                            }
760    
761                            // Portlet permissions
762    
763                            if (importPermissions) {
764                                    _permissionImporter.importPortletPermissions(
765                                            layoutCache, companyId, portletDataContext.getGroupId(),
766                                            userId, layout, portletElement, portletId);
767                            }
768    
769                            // Archived setups
770    
771                            _portletImporter.importPortletPreferences(
772                                    portletDataContext, layoutSet.getCompanyId(),
773                                    portletDataContext.getGroupId(), null, portletElement, false,
774                                    importPortletControlsMap.get(
775                                            PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
776                                    importPortletControlsMap.get(
777                                            PortletDataHandlerKeys.PORTLET_DATA),
778                                    importPortletControlsMap.get(
779                                            PortletDataHandlerKeys.PORTLET_SETUP),
780                                    importPortletControlsMap.get(
781                                            PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));
782                    }
783    
784                    // Import services
785    
786                    if (_log.isDebugEnabled() && !portletElements.isEmpty()) {
787                            _log.debug("Importing services");
788                    }
789    
790                    Element servicesElement = rootElement.element("services");
791    
792                    List<Element> serviceElements = servicesElement.elements("service");
793    
794                    for (Element serviceElement : serviceElements) {
795                            String path = serviceElement.attributeValue("path");
796    
797                            Document serviceDocument = SAXReaderUtil.read(
798                                    portletDataContext.getZipEntryAsString(path));
799    
800                            serviceElement = serviceDocument.getRootElement();
801    
802                            _portletImporter.importServicePortletPreferences(
803                                    portletDataContext, serviceElement);
804                    }
805    
806                    // Asset links
807    
808                    _portletImporter.readAssetLinks(portletDataContext);
809    
810                    // Delete missing layouts
811    
812                    if (deleteMissingLayouts) {
813                            deleteMissingLayouts(
814                                    portletDataContext, sourceLayoutsUuids, previousLayouts,
815                                    serviceContext);
816                    }
817    
818                    // Page count
819    
820                    layoutSet = LayoutSetLocalServiceUtil.updatePageCount(
821                            portletDataContext.getGroupId(),
822                            portletDataContext.isPrivateLayout());
823    
824                    // Site
825    
826                    GroupLocalServiceUtil.updateSite(portletDataContext.getGroupId(), true);
827    
828                    // Page priorities
829    
830                    updateLayoutPriorities(
831                            portletDataContext, layoutElements,
832                            portletDataContext.isPrivateLayout());
833    
834                    // Last merge time is updated only if there aren not any modified
835                    // layouts
836    
837                    if (layoutsImportMode.equals(
838                                    PortletDataHandlerKeys.
839                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
840    
841                            long lastMergeTime = System.currentTimeMillis();
842    
843                            for (Layout layout : layouts.values()) {
844                                    layout = LayoutLocalServiceUtil.getLayout(layout.getPlid());
845    
846                                    if (modifiedLayouts.contains(layout)) {
847                                            continue;
848                                    }
849    
850                                    UnicodeProperties typeSettingsProperties =
851                                            layout.getTypeSettingsProperties();
852    
853                                    typeSettingsProperties.setProperty(
854                                            Sites.LAST_MERGE_TIME, String.valueOf(lastMergeTime));
855    
856                                    LayoutUtil.update(layout);
857                            }
858    
859                            // The layout set may be stale because LayoutUtil#update(layout)
860                            // triggers LayoutSetPrototypeLayoutModelListener and that may have
861                            // updated this layout set
862    
863                            layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
864                                    layoutSet.getLayoutSetId());
865    
866                            UnicodeProperties settingsProperties =
867                                    layoutSet.getSettingsProperties();
868    
869                            String mergeFailFriendlyURLLayouts = settingsProperties.getProperty(
870                                    Sites.MERGE_FAIL_FRIENDLY_URL_LAYOUTS);
871    
872                            if (Validator.isNull(mergeFailFriendlyURLLayouts) &&
873                                    modifiedLayouts.isEmpty()) {
874    
875                                    settingsProperties.setProperty(
876                                            Sites.LAST_MERGE_TIME, String.valueOf(lastMergeTime));
877    
878                                    LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
879                            }
880                    }
881    
882                    if (_log.isInfoEnabled()) {
883                            _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
884                    }
885    
886                    ZipReader zipReader = portletDataContext.getZipReader();
887    
888                    zipReader.close();
889            }
890    
891            protected PortletDataContext getPortletDataContext(
892                            long userId, long groupId, boolean privateLayout,
893                            Map<String, String[]> parameterMap, File file)
894                    throws PortalException {
895    
896                    Group group = GroupLocalServiceUtil.getGroup(groupId);
897    
898                    String userIdStrategyString = MapUtil.getString(
899                            parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
900    
901                    UserIdStrategy userIdStrategy =
902                            ExportImportHelperUtil.getUserIdStrategy(
903                                    userId, userIdStrategyString);
904    
905                    ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
906    
907                    PortletDataContext portletDataContext =
908                            PortletDataContextFactoryUtil.createImportPortletDataContext(
909                                    group.getCompanyId(), groupId, parameterMap, userIdStrategy,
910                                    zipReader);
911    
912                    portletDataContext.setPrivateLayout(privateLayout);
913    
914                    return portletDataContext;
915            }
916    
917            protected int getProcessFlag() {
918                    if (ExportImportThreadLocal.isLayoutStagingInProcess()) {
919                            return PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS;
920                    }
921    
922                    return PROCESS_FLAG_LAYOUT_IMPORT_IN_PROCESS;
923            }
924    
925            protected void importLayout(
926                            PortletDataContext portletDataContext,
927                            List<String> sourceLayoutsUuids, Element layoutElement)
928                    throws Exception {
929    
930                    String action = layoutElement.attributeValue(Constants.ACTION);
931    
932                    if (!action.equals(Constants.SKIP)) {
933                            StagedModelDataHandlerUtil.importStagedModel(
934                                    portletDataContext, layoutElement);
935                    }
936    
937                    if (!action.equals(Constants.DELETE)) {
938                            sourceLayoutsUuids.add(layoutElement.attributeValue("uuid"));
939                    }
940            }
941    
942            protected void populateDeletionStagedModelTypes(
943                            PortletDataContext portletDataContext)
944                    throws Exception {
945    
946                    Element rootElement = portletDataContext.getImportDataRootElement();
947    
948                    Element portletsElement = rootElement.element("portlets");
949    
950                    List<Element> portletElements = portletsElement.elements("portlet");
951    
952                    for (Element portletElement : portletElements) {
953                            String portletId = portletElement.attributeValue("portlet-id");
954    
955                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
956                                    portletDataContext.getCompanyId(), portletId);
957    
958                            if ((portlet == null) || !portlet.isActive() ||
959                                    portlet.isUndeployedPortlet()) {
960    
961                                    continue;
962                            }
963    
964                            PortletDataHandler portletDataHandler =
965                                    portlet.getPortletDataHandlerInstance();
966    
967                            if (portletDataHandler == null) {
968                                    continue;
969                            }
970    
971                            portletDataContext.addDeletionSystemEventStagedModelTypes(
972                                    portletDataHandler.getDeletionSystemEventStagedModelTypes());
973                    }
974            }
975    
976            protected void setPortletScope(
977                    PortletDataContext portletDataContext, Element portletElement) {
978    
979                    // Portlet data scope
980    
981                    String scopeLayoutUuid = GetterUtil.getString(
982                            portletElement.attributeValue("scope-layout-uuid"));
983                    String scopeLayoutType = GetterUtil.getString(
984                            portletElement.attributeValue("scope-layout-type"));
985    
986                    portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);
987                    portletDataContext.setScopeType(scopeLayoutType);
988    
989                    // Layout scope
990    
991                    try {
992                            Group scopeGroup = null;
993    
994                            if (scopeLayoutType.equals("company")) {
995                                    scopeGroup = GroupLocalServiceUtil.getCompanyGroup(
996                                            portletDataContext.getCompanyId());
997                            }
998                            else if (Validator.isNotNull(scopeLayoutUuid)) {
999                                    Layout scopeLayout =
1000                                            LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1001                                                    scopeLayoutUuid, portletDataContext.getGroupId(),
1002                                                    portletDataContext.isPrivateLayout());
1003    
1004                                    if (scopeLayout.hasScopeGroup()) {
1005                                            scopeGroup = scopeLayout.getScopeGroup();
1006                                    }
1007                                    else {
1008                                            Map<Locale, String> nameMap = new HashMap<>();
1009    
1010                                            nameMap.put(
1011                                                    LocaleUtil.getDefault(),
1012                                                    String.valueOf(scopeLayout.getPlid()));
1013    
1014                                            scopeGroup = GroupLocalServiceUtil.addGroup(
1015                                                    portletDataContext.getUserId(null),
1016                                                    GroupConstants.DEFAULT_PARENT_GROUP_ID,
1017                                                    Layout.class.getName(), scopeLayout.getPlid(),
1018                                                    GroupConstants.DEFAULT_LIVE_GROUP_ID, nameMap, null, 0,
1019                                                    true, GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION,
1020                                                    null, false, true, null);
1021                                    }
1022    
1023                                    Group group = scopeLayout.getGroup();
1024    
1025                                    if (group.isStaged() && !group.isStagedRemotely()) {
1026                                            try {
1027                                                    boolean privateLayout = GetterUtil.getBoolean(
1028                                                            portletElement.attributeValue("private-layout"));
1029    
1030                                                    Layout oldLayout =
1031                                                            LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1032                                                                    scopeLayoutUuid,
1033                                                                    portletDataContext.getSourceGroupId(),
1034                                                                    privateLayout);
1035    
1036                                                    Group oldScopeGroup = oldLayout.getScopeGroup();
1037    
1038                                                    if (group.isStagingGroup()) {
1039                                                            scopeGroup.setLiveGroupId(
1040                                                                    oldScopeGroup.getGroupId());
1041    
1042                                                            GroupLocalServiceUtil.updateGroup(scopeGroup);
1043                                                    }
1044                                                    else {
1045                                                            oldScopeGroup.setLiveGroupId(
1046                                                                    scopeGroup.getGroupId());
1047    
1048                                                            GroupLocalServiceUtil.updateGroup(oldScopeGroup);
1049                                                    }
1050                                            }
1051                                            catch (NoSuchLayoutException nsle) {
1052                                                    if (_log.isWarnEnabled()) {
1053                                                            _log.warn(nsle);
1054                                                    }
1055                                            }
1056                                    }
1057                            }
1058    
1059                            if (scopeGroup != null) {
1060                                    portletDataContext.setScopeGroupId(scopeGroup.getGroupId());
1061    
1062                                    Map<Long, Long> groupIds =
1063                                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
1064                                                    Group.class);
1065    
1066                                    long oldScopeGroupId = GetterUtil.getLong(
1067                                            portletElement.attributeValue("scope-group-id"));
1068    
1069                                    groupIds.put(oldScopeGroupId, scopeGroup.getGroupId());
1070                            }
1071                    }
1072                    catch (PortalException pe) {
1073                    }
1074                    catch (Exception e) {
1075                            _log.error(e, e);
1076                    }
1077            }
1078    
1079            protected void updateLayoutPriorities(
1080                    PortletDataContext portletDataContext, List<Element> layoutElements,
1081                    boolean privateLayout) {
1082    
1083                    Map<Long, Layout> layouts =
1084                            (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
1085                                    Layout.class + ".layout");
1086    
1087                    Map<Long, Integer> layoutPriorities = new HashMap<>();
1088    
1089                    int maxPriority = Integer.MIN_VALUE;
1090    
1091                    for (Element layoutElement : layoutElements) {
1092                            String action = layoutElement.attributeValue(Constants.ACTION);
1093    
1094                            if (action.equals(Constants.SKIP)) {
1095    
1096                                    // We only want to update priorites if there are no elements
1097                                    // with the SKIP action
1098    
1099                                    return;
1100                            }
1101    
1102                            if (action.equals(Constants.ADD)) {
1103                                    long layoutId = GetterUtil.getLong(
1104                                            layoutElement.attributeValue("layout-id"));
1105    
1106                                    Layout layout = layouts.get(layoutId);
1107    
1108                                    // Layout might have not been imported due to a controlled
1109                                    // error. See SitesImpl#addMergeFailFriendlyURLLayout.
1110    
1111                                    if (layout == null) {
1112                                            continue;
1113                                    }
1114    
1115                                    int layoutPriority = GetterUtil.getInteger(
1116                                            layoutElement.attributeValue("layout-priority"));
1117    
1118                                    layoutPriorities.put(layout.getPlid(), layoutPriority);
1119    
1120                                    if (maxPriority < layoutPriority) {
1121                                            maxPriority = layoutPriority;
1122                                    }
1123                            }
1124                    }
1125    
1126                    List<Layout> layoutSetLayouts = LayoutLocalServiceUtil.getLayouts(
1127                            portletDataContext.getGroupId(), privateLayout);
1128    
1129                    for (Layout layout : layoutSetLayouts) {
1130                            if (layoutPriorities.containsKey(layout.getPlid())) {
1131                                    layout.setPriority(layoutPriorities.get(layout.getPlid()));
1132                            }
1133                            else {
1134                                    layout.setPriority(++maxPriority);
1135                            }
1136    
1137                            LayoutLocalServiceUtil.updateLayout(layout);
1138                    }
1139            }
1140    
1141            protected void validateFile(
1142                            long companyId, long groupId, Map<String, String[]> parameterMap,
1143                            ZipReader zipReader)
1144                    throws Exception {
1145    
1146                    // XML
1147    
1148                    String xml = zipReader.getEntryAsString("/manifest.xml");
1149    
1150                    if (xml == null) {
1151                            throw new LARFileException("manifest.xml not found in the LAR");
1152                    }
1153    
1154                    Element rootElement = null;
1155    
1156                    try {
1157                            Document document = SAXReaderUtil.read(xml);
1158    
1159                            rootElement = document.getRootElement();
1160                    }
1161                    catch (Exception e) {
1162                            throw new LARFileException(e);
1163                    }
1164    
1165                    // Build compatibility
1166    
1167                    int buildNumber = ReleaseInfo.getBuildNumber();
1168    
1169                    Element headerElement = rootElement.element("header");
1170    
1171                    int importBuildNumber = GetterUtil.getInteger(
1172                            headerElement.attributeValue("build-number"));
1173    
1174                    if (buildNumber != importBuildNumber) {
1175                            throw new LayoutImportException(
1176                                    "LAR build number " + importBuildNumber + " does not match " +
1177                                            "portal build number " + buildNumber);
1178                    }
1179    
1180                    // Type
1181    
1182                    String larType = headerElement.attributeValue("type");
1183    
1184                    if (!larType.equals("layout-prototype") &&
1185                            !larType.equals("layout-set") &&
1186                            !larType.equals("layout-set-prototype")) {
1187    
1188                            throw new LARTypeException(larType);
1189                    }
1190    
1191                    Group group = GroupLocalServiceUtil.fetchGroup(groupId);
1192    
1193                    String layoutsImportMode = MapUtil.getString(
1194                            parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE);
1195    
1196                    if (larType.equals("layout-prototype") && !group.isLayoutPrototype() &&
1197                            !layoutsImportMode.equals(
1198                                    PortletDataHandlerKeys.
1199                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
1200    
1201                            throw new LARTypeException(
1202                                    "A page template can only be imported to a page template");
1203                    }
1204    
1205                    if (larType.equals("layout-set")) {
1206                            if (group.isLayoutPrototype() || group.isLayoutSetPrototype()) {
1207                                    throw new LARTypeException(
1208                                            "A site can only be imported to a site");
1209                            }
1210    
1211                            long sourceCompanyGroupId = GetterUtil.getLong(
1212                                    headerElement.attributeValue("company-group-id"));
1213                            long sourceGroupId = GetterUtil.getLong(
1214                                    headerElement.attributeValue("group-id"));
1215    
1216                            boolean companySourceGroup = false;
1217    
1218                            if (sourceCompanyGroupId == sourceGroupId) {
1219                                    companySourceGroup = true;
1220                            }
1221                            else if (group.isStaged() || group.hasStagingGroup()) {
1222                                    Group sourceGroup = GroupLocalServiceUtil.fetchGroup(
1223                                            sourceGroupId);
1224    
1225                                    companySourceGroup = sourceGroup.isCompany();
1226                            }
1227    
1228                            if (group.isCompany() ^ companySourceGroup) {
1229                                    throw new LARTypeException(
1230                                            "A company site can only be imported to a company site");
1231                            }
1232                    }
1233    
1234                    if (larType.equals("layout-set-prototype") &&
1235                            !group.isLayoutSetPrototype() &&
1236                            !layoutsImportMode.equals(
1237                                    PortletDataHandlerKeys.
1238                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
1239    
1240                            throw new LARTypeException(
1241                                    "A site template can only be imported to a site template");
1242                    }
1243    
1244                    // Available locales
1245    
1246                    List<Locale> sourceAvailableLocales = Arrays.asList(
1247                            LocaleUtil.fromLanguageIds(
1248                                    StringUtil.split(
1249                                            headerElement.attributeValue("available-locales"))));
1250    
1251                    for (Locale sourceAvailableLocale : sourceAvailableLocales) {
1252                            if (!LanguageUtil.isAvailableLocale(
1253                                            groupId, sourceAvailableLocale)) {
1254    
1255                                    LocaleException le = new LocaleException(
1256                                            LocaleException.TYPE_EXPORT_IMPORT);
1257    
1258                                    le.setSourceAvailableLocales(sourceAvailableLocales);
1259                                    le.setTargetAvailableLocales(
1260                                            LanguageUtil.getAvailableLocales(groupId));
1261    
1262                                    throw le;
1263                            }
1264                    }
1265    
1266                    // Layout prototypes validity
1267    
1268                    Element layoutsElement = rootElement.element(
1269                            Layout.class.getSimpleName());
1270    
1271                    validateLayoutPrototypes(companyId, layoutsElement);
1272            }
1273    
1274            protected void validateLayoutPrototypes(
1275                            long companyId, Element layoutsElement)
1276                    throws Exception {
1277    
1278                    List<Tuple> missingLayoutPrototypes = new ArrayList<>();
1279    
1280                    String layoutSetPrototypeUuid = layoutsElement.attributeValue(
1281                            "layout-set-prototype-uuid");
1282    
1283                    if (Validator.isNotNull(layoutSetPrototypeUuid)) {
1284                            try {
1285                                    LayoutSetPrototypeLocalServiceUtil.
1286                                            getLayoutSetPrototypeByUuidAndCompanyId(
1287                                                    layoutSetPrototypeUuid, companyId);
1288                            }
1289                            catch (NoSuchLayoutSetPrototypeException nlspe) {
1290                                    String layoutSetPrototypeName = layoutsElement.attributeValue(
1291                                            "layout-set-prototype-name");
1292    
1293                                    missingLayoutPrototypes.add(
1294                                            new Tuple(
1295                                                    LayoutSetPrototype.class.getName(),
1296                                                    layoutSetPrototypeUuid, layoutSetPrototypeName));
1297                            }
1298                    }
1299    
1300                    List<Element> layoutElements = layoutsElement.elements();
1301    
1302                    for (Element layoutElement : layoutElements) {
1303                            String action = layoutElement.attributeValue(Constants.ACTION);
1304    
1305                            if (action.equals(Constants.SKIP)) {
1306                                    continue;
1307                            }
1308    
1309                            String layoutPrototypeUuid = GetterUtil.getString(
1310                                    layoutElement.attributeValue("layout-prototype-uuid"));
1311    
1312                            if (Validator.isNotNull(layoutPrototypeUuid)) {
1313                                    try {
1314                                            LayoutPrototypeLocalServiceUtil.
1315                                                    getLayoutPrototypeByUuidAndCompanyId(
1316                                                            layoutPrototypeUuid, companyId);
1317                                    }
1318                                    catch (NoSuchLayoutPrototypeException nslpe) {
1319                                            String layoutPrototypeName = GetterUtil.getString(
1320                                                    layoutElement.attributeValue("layout-prototype-name"));
1321    
1322                                            missingLayoutPrototypes.add(
1323                                                    new Tuple(
1324                                                            LayoutPrototype.class.getName(),
1325                                                            layoutPrototypeUuid, layoutPrototypeName));
1326                                    }
1327                            }
1328                    }
1329    
1330                    if (!missingLayoutPrototypes.isEmpty()) {
1331                            throw new LayoutPrototypeException(missingLayoutPrototypes);
1332                    }
1333            }
1334    
1335            private LayoutImporter() {
1336                    XStreamAliasRegistryUtil.register(LayoutImpl.class, "Layout");
1337            }
1338    
1339            private static final Log _log = LogFactoryUtil.getLog(LayoutImporter.class);
1340    
1341            private static final LayoutImporter _instance = new LayoutImporter();
1342    
1343            private final DeletionSystemEventImporter _deletionSystemEventImporter =
1344                    DeletionSystemEventImporter.getInstance();
1345            private final PermissionImporter _permissionImporter =
1346                    PermissionImporter.getInstance();
1347            private final PortletImporter _portletImporter =
1348                    PortletImporter.getInstance();
1349            private final ThemeImporter _themeImporter = ThemeImporter.getInstance();
1350    
1351    }