Java tutorial
/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.exportimport.controller; import static com.liferay.exportimport.kernel.lifecycle.ExportImportLifecycleConstants.EVENT_LAYOUT_IMPORT_FAILED; import static com.liferay.exportimport.kernel.lifecycle.ExportImportLifecycleConstants.EVENT_LAYOUT_IMPORT_STARTED; import static com.liferay.exportimport.kernel.lifecycle.ExportImportLifecycleConstants.EVENT_LAYOUT_IMPORT_SUCCEEDED; import static com.liferay.exportimport.kernel.lifecycle.ExportImportLifecycleConstants.PROCESS_FLAG_LAYOUT_IMPORT_IN_PROCESS; import static com.liferay.exportimport.kernel.lifecycle.ExportImportLifecycleConstants.PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS; import aQute.bnd.annotation.ProviderType; import com.liferay.asset.kernel.model.adapter.StagedAssetLink; import com.liferay.exportimport.constants.ExportImportConstants; import com.liferay.exportimport.kernel.controller.ExportImportController; import com.liferay.exportimport.kernel.controller.ImportController; import com.liferay.exportimport.kernel.exception.LARFileException; import com.liferay.exportimport.kernel.exception.LARTypeException; import com.liferay.exportimport.kernel.exception.LayoutImportException; import com.liferay.exportimport.kernel.exception.MissingReferenceException; import com.liferay.exportimport.kernel.lar.ExportImportHelper; import com.liferay.exportimport.kernel.lar.ExportImportThreadLocal; import com.liferay.exportimport.kernel.lar.ManifestSummary; import com.liferay.exportimport.kernel.lar.MissingReference; import com.liferay.exportimport.kernel.lar.MissingReferences; import com.liferay.exportimport.kernel.lar.PortletDataContext; import com.liferay.exportimport.kernel.lar.PortletDataContextFactory; import com.liferay.exportimport.kernel.lar.PortletDataHandler; import com.liferay.exportimport.kernel.lar.PortletDataHandlerKeys; import com.liferay.exportimport.kernel.lar.StagedModelDataHandlerUtil; import com.liferay.exportimport.kernel.lar.StagedModelType; import com.liferay.exportimport.kernel.lar.UserIdStrategy; import com.liferay.exportimport.kernel.lifecycle.ExportImportLifecycleManager; import com.liferay.exportimport.kernel.model.ExportImportConfiguration; import com.liferay.exportimport.lar.DeletionSystemEventImporter; import com.liferay.exportimport.lar.LayoutCache; import com.liferay.exportimport.lar.PermissionImporter; import com.liferay.exportimport.portlet.data.handler.provider.PortletDataHandlerProvider; import com.liferay.portal.kernel.exception.LayoutPrototypeException; import com.liferay.portal.kernel.exception.LocaleException; import com.liferay.portal.kernel.exception.NoSuchLayoutPrototypeException; import com.liferay.portal.kernel.exception.NoSuchLayoutSetPrototypeException; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.language.LanguageUtil; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.Group; import com.liferay.portal.kernel.model.Layout; import com.liferay.portal.kernel.model.LayoutConstants; import com.liferay.portal.kernel.model.LayoutPrototype; import com.liferay.portal.kernel.model.LayoutSet; import com.liferay.portal.kernel.model.LayoutSetPrototype; import com.liferay.portal.kernel.model.Portlet; import com.liferay.portal.kernel.plugin.Version; import com.liferay.portal.kernel.service.GroupLocalService; import com.liferay.portal.kernel.service.LayoutLocalService; import com.liferay.portal.kernel.service.LayoutPrototypeLocalService; import com.liferay.portal.kernel.service.LayoutSetLocalService; import com.liferay.portal.kernel.service.LayoutSetPrototypeLocalService; import com.liferay.portal.kernel.service.PortletLocalService; import com.liferay.portal.kernel.service.ServiceContext; import com.liferay.portal.kernel.service.ServiceContextThreadLocal; import com.liferay.portal.kernel.util.Constants; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.LocaleUtil; import com.liferay.portal.kernel.util.MapUtil; import com.liferay.portal.kernel.util.ReleaseInfo; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Tuple; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.xml.Document; import com.liferay.portal.kernel.xml.Element; import com.liferay.portal.kernel.xml.Node; import com.liferay.portal.kernel.xml.SAXReaderUtil; import com.liferay.portal.kernel.xml.XPath; import com.liferay.portal.kernel.zip.ZipReader; import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil; import com.liferay.site.model.adapter.StagedGroup; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.function.BiPredicate; import java.util.stream.Stream; import org.apache.commons.lang.time.StopWatch; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; /** * @author Brian Wing Shun Chan * @author Joel Kozikowski * @author Charles May * @author Raymond Aug * @author Jorge Ferrer * @author Bruno Farache * @author Wesley Gong * @author Zsigmond Rab * @author Douglas Wong * @author Julio Camarero * @author Zsolt Berentey */ @Component(immediate = true, property = { "model.class.name=com.liferay.portal.kernel.model.Layout" }, service = { ExportImportController.class, LayoutImportController.class }) @ProviderType public class LayoutImportController implements ImportController { @Override public void importDataDeletions(ExportImportConfiguration exportImportConfiguration, File file) throws Exception { ZipReader zipReader = null; try { // LAR validation ExportImportThreadLocal.setLayoutDataDeletionImportInProcess(true); Map<String, Serializable> settingsMap = exportImportConfiguration.getSettingsMap(); long targetGroupId = MapUtil.getLong(settingsMap, "targetGroupId"); boolean privateLayout = MapUtil.getBoolean(settingsMap, "privateLayout"); Map<String, String[]> parameterMap = (Map<String, String[]>) settingsMap.get("parameterMap"); LayoutSet layoutSet = _layoutSetLocalService.getLayoutSet(targetGroupId, privateLayout); zipReader = ZipReaderFactoryUtil.getZipReader(file); validateFile(layoutSet.getCompanyId(), targetGroupId, parameterMap, zipReader); PortletDataContext portletDataContext = getPortletDataContext(exportImportConfiguration, file); boolean deletePortletData = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA); // Portlet data deletion if (deletePortletData) { if (_log.isDebugEnabled()) { _log.debug("Deleting portlet data"); } deletePortletData(portletDataContext); } // Deletion system events populateDeletionStagedModelTypes(portletDataContext); _deletionSystemEventImporter.importDeletionSystemEvents(portletDataContext); } finally { ExportImportThreadLocal.setLayoutDataDeletionImportInProcess(false); if (zipReader != null) { zipReader.close(); } } } @Override public void importFile(ExportImportConfiguration exportImportConfiguration, File file) throws Exception { PortletDataContext portletDataContext = null; try { ExportImportThreadLocal.setLayoutImportInProcess(true); portletDataContext = getPortletDataContext(exportImportConfiguration, file); _exportImportLifecycleManager.fireExportImportLifecycleEvent(EVENT_LAYOUT_IMPORT_STARTED, getProcessFlag(), String.valueOf(exportImportConfiguration.getExportImportConfigurationId()), _portletDataContextFactory.clonePortletDataContext(portletDataContext)); Map<String, Serializable> settingsMap = exportImportConfiguration.getSettingsMap(); long userId = MapUtil.getLong(settingsMap, "userId"); doImportFile(portletDataContext, userId); ExportImportThreadLocal.setLayoutImportInProcess(false); _exportImportLifecycleManager.fireExportImportLifecycleEvent(EVENT_LAYOUT_IMPORT_SUCCEEDED, getProcessFlag(), String.valueOf(exportImportConfiguration.getExportImportConfigurationId()), _portletDataContextFactory.clonePortletDataContext(portletDataContext), userId); } catch (Throwable t) { ExportImportThreadLocal.setLayoutImportInProcess(false); _exportImportLifecycleManager.fireExportImportLifecycleEvent(EVENT_LAYOUT_IMPORT_FAILED, getProcessFlag(), String.valueOf(exportImportConfiguration.getExportImportConfigurationId()), _portletDataContextFactory.clonePortletDataContext(portletDataContext), t); throw t; } } @Override public MissingReferences validateFile(ExportImportConfiguration exportImportConfiguration, File file) throws Exception { ZipReader zipReader = null; try { ExportImportThreadLocal.setLayoutValidationInProcess(true); Map<String, Serializable> settingsMap = exportImportConfiguration.getSettingsMap(); long targetGroupId = MapUtil.getLong(settingsMap, "targetGroupId"); boolean privateLayout = MapUtil.getBoolean(settingsMap, "privateLayout"); Map<String, String[]> parameterMap = (Map<String, String[]>) settingsMap.get("parameterMap"); LayoutSet layoutSet = _layoutSetLocalService.getLayoutSet(targetGroupId, privateLayout); zipReader = ZipReaderFactoryUtil.getZipReader(file); validateFile(layoutSet.getCompanyId(), targetGroupId, parameterMap, zipReader); PortletDataContext portletDataContext = getPortletDataContext(exportImportConfiguration, file); portletDataContext.setPrivateLayout(privateLayout); MissingReferences missingReferences = _exportImportHelper.validateMissingReferences(portletDataContext); Map<String, MissingReference> dependencyMissingReferences = missingReferences .getDependencyMissingReferences(); if (!dependencyMissingReferences.isEmpty()) { throw new MissingReferenceException(missingReferences); } return missingReferences; } finally { ExportImportThreadLocal.setLayoutValidationInProcess(false); if (zipReader != null) { zipReader.close(); } } } /** * @deprecated As of 4.0.0 */ @Deprecated protected void deleteMissingLayouts(PortletDataContext portletDataContext, List<String> sourceLayoutUuids, List<Layout> previousLayouts, ServiceContext serviceContext) throws Exception { } protected void deletePortletData(PortletDataContext portletDataContext) throws Exception { List<Element> portletElements = fetchPortletElements(portletDataContext.getImportDataRootElement()); Map<Long, Layout> layouts = (Map<Long, Layout>) portletDataContext .getNewPrimaryKeysMap(Layout.class + ".layout"); if (_log.isDebugEnabled()) { if (!portletElements.isEmpty()) { _log.debug("Deleting portlet data"); } } for (Element portletElement : portletElements) { long layoutId = GetterUtil.getLong(portletElement.attributeValue("layout-id")); long plid = LayoutConstants.DEFAULT_PLID; Layout layout = layouts.get(layoutId); if (layout != null) { plid = layout.getPlid(); } portletDataContext.setPlid(plid); portletDataContext.setPortletId(portletElement.attributeValue("portlet-id")); _portletImportController.deletePortletData(portletDataContext); } } protected void doImportFile(PortletDataContext portletDataContext, long userId) throws Exception { Map<String, String[]> parameterMap = portletDataContext.getParameterMap(); Group group = _groupLocalService.getGroup(portletDataContext.getGroupId()); String layoutsImportMode = MapUtil.getString(parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID); boolean permissions = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PERMISSIONS); if (group.isLayoutSetPrototype()) { parameterMap.put(PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED, new String[] { Boolean.FALSE.toString() }); } if (_log.isDebugEnabled()) { _log.debug("Import permissions " + permissions); } StopWatch stopWatch = new StopWatch(); stopWatch.start(); LayoutCache layoutCache = new LayoutCache(); long companyId = portletDataContext.getCompanyId(); ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext(); if (serviceContext == null) { serviceContext = new ServiceContext(); } serviceContext.setCompanyId(companyId); serviceContext.setSignedIn(false); serviceContext.setUserId(userId); ServiceContextThreadLocal.pushServiceContext(serviceContext); // LAR validation validateFile(companyId, portletDataContext.getGroupId(), parameterMap, portletDataContext.getZipReader()); // Source and target group id Map<Long, Long> groupIds = (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(Group.class); groupIds.put(portletDataContext.getSourceGroupId(), portletDataContext.getGroupId()); // Manifest ManifestSummary manifestSummary = _exportImportHelper.getManifestSummary(portletDataContext); portletDataContext.setManifestSummary(manifestSummary); // Layout and layout set prototype Element rootElement = portletDataContext.getImportDataRootElement(); Element headerElement = rootElement.element("header"); String layoutSetPrototypeUuid = headerElement.attributeValue("layout-set-prototype-uuid"); String larType = headerElement.attributeValue("type"); portletDataContext.setType(larType); if (group.isLayoutPrototype() && larType.equals("layout-prototype")) { parameterMap.put(PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS, new String[] { Boolean.FALSE.toString() }); LayoutPrototype layoutPrototype = _layoutPrototypeLocalService.getLayoutPrototype(group.getClassPK()); String layoutPrototypeUuid = GetterUtil.getString(headerElement.attributeValue("type-uuid")); LayoutPrototype existingLayoutPrototype = null; if (Validator.isNotNull(layoutPrototypeUuid)) { try { existingLayoutPrototype = _layoutPrototypeLocalService .getLayoutPrototypeByUuidAndCompanyId(layoutPrototypeUuid, companyId); } catch (NoSuchLayoutPrototypeException nslpe) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(nslpe, nslpe); } } } if (existingLayoutPrototype == null) { List<Layout> layouts = _layoutLocalService .getLayoutsByLayoutPrototypeUuid(layoutPrototype.getUuid()); layoutPrototype.setUuid(layoutPrototypeUuid); _layoutPrototypeLocalService.updateLayoutPrototype(layoutPrototype); for (Layout layout : layouts) { layout.setLayoutPrototypeUuid(layoutPrototypeUuid); _layoutLocalService.updateLayout(layout); } } } else if (group.isLayoutSetPrototype() && larType.equals("layout-set-prototype")) { parameterMap.put(PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_SETTINGS, new String[] { Boolean.TRUE.toString() }); LayoutSetPrototype layoutSetPrototype = _layoutSetPrototypeLocalService .getLayoutSetPrototype(group.getClassPK()); String importedLayoutSetPrototypeUuid = GetterUtil.getString(headerElement.attributeValue("type-uuid")); LayoutSetPrototype existingLayoutSetPrototype = null; if (Validator.isNotNull(importedLayoutSetPrototypeUuid)) { try { existingLayoutSetPrototype = _layoutSetPrototypeLocalService .getLayoutSetPrototypeByUuidAndCompanyId(importedLayoutSetPrototypeUuid, companyId); } catch (NoSuchLayoutSetPrototypeException nslspe) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(nslspe, nslspe); } } } if (existingLayoutSetPrototype == null) { List<LayoutSet> layoutSets = _layoutSetLocalService .getLayoutSetsByLayoutSetPrototypeUuid(layoutSetPrototype.getUuid()); layoutSetPrototype.setUuid(importedLayoutSetPrototypeUuid); _layoutSetPrototypeLocalService.updateLayoutSetPrototype(layoutSetPrototype); for (LayoutSet curLayoutSet : layoutSets) { curLayoutSet.setLayoutSetPrototypeUuid(importedLayoutSetPrototypeUuid); _layoutSetLocalService.updateLayoutSet(curLayoutSet); } } } else if (larType.equals("layout-set-prototype")) { parameterMap.put(PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_SETTINGS, new String[] { Boolean.TRUE.toString() }); layoutSetPrototypeUuid = GetterUtil.getString(headerElement.attributeValue("type-uuid")); } if (Validator.isNotNull(layoutSetPrototypeUuid)) { portletDataContext.setLayoutSetPrototypeUuid(layoutSetPrototypeUuid); } List<Element> portletElements = fetchPortletElements(rootElement); if (permissions) { for (Element portletElement : portletElements) { String portletPath = portletElement.attributeValue("path"); Document portletDocument = SAXReaderUtil.read(portletDataContext.getZipEntryAsString(portletPath)); _permissionImporter.checkRoles(layoutCache, companyId, portletDataContext.getGroupId(), userId, portletDocument.getRootElement()); } _permissionImporter.readPortletDataPermissions(portletDataContext); } if (!layoutsImportMode.equals(PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) { _portletImportController.readExpandoTables(portletDataContext); } _portletImportController.readLocks(portletDataContext); // Import the group Element groupsElement = portletDataContext.getImportDataGroupElement(StagedGroup.class); for (Element groupElement : groupsElement.elements()) { StagedModelDataHandlerUtil.importStagedModel(portletDataContext, groupElement); } // Asset links _portletImportController.importAssetLinks(portletDataContext); // Site _groupLocalService.updateSite(portletDataContext.getGroupId(), true); if (_log.isInfoEnabled()) { _log.info("Importing layouts takes " + stopWatch.getTime() + " ms"); } ZipReader zipReader = portletDataContext.getZipReader(); zipReader.close(); } protected List<Element> fetchPortletElements(Element rootElement) { List<Element> portletElements = new ArrayList<>(); // Site portlets Element sitePortletsElement = rootElement.element("site-portlets"); // LAR compatibility if (sitePortletsElement == null) { sitePortletsElement = rootElement.element("portlets"); } portletElements.addAll(sitePortletsElement.elements("portlet")); // Layout portlets XPath xPath = SAXReaderUtil.createXPath("staged-model/portlets/portlet"); Element layoutsElement = rootElement.element(Layout.class.getSimpleName()); List<Node> nodes = xPath.selectNodes(layoutsElement); Stream<Node> nodesStream = nodes.stream(); nodesStream.map(node -> (Element) node).forEach(portletElements::add); return portletElements; } protected PortletDataContext getPortletDataContext(ExportImportConfiguration exportImportConfiguration, File file) throws PortalException { Map<String, Serializable> settingsMap = exportImportConfiguration.getSettingsMap(); long userId = MapUtil.getLong(settingsMap, "userId"); long targetGroupId = MapUtil.getLong(settingsMap, "targetGroupId"); boolean privateLayout = MapUtil.getBoolean(settingsMap, "privateLayout"); Map<String, String[]> parameterMap = (Map<String, String[]>) settingsMap.get("parameterMap"); Group group = _groupLocalService.getGroup(targetGroupId); String userIdStrategyString = MapUtil.getString(parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY); UserIdStrategy userIdStrategy = _exportImportHelper.getUserIdStrategy(userId, userIdStrategyString); ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file); PortletDataContext portletDataContext = _portletDataContextFactory.createImportPortletDataContext( group.getCompanyId(), targetGroupId, parameterMap, userIdStrategy, zipReader); portletDataContext.setExportImportProcessId( String.valueOf(exportImportConfiguration.getExportImportConfigurationId())); portletDataContext.setPrivateLayout(privateLayout); return portletDataContext; } protected int getProcessFlag() { if (ExportImportThreadLocal.isLayoutStagingInProcess()) { return PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS; } return PROCESS_FLAG_LAYOUT_IMPORT_IN_PROCESS; } /** * @deprecated As of 4.0.0 */ @Deprecated protected void importLayout(PortletDataContext portletDataContext, List<String> sourceLayoutsUuids, Element layoutElement) throws Exception { } protected void populateDeletionStagedModelTypes(PortletDataContext portletDataContext) throws Exception { List<Element> portletElements = fetchPortletElements(portletDataContext.getImportDataRootElement()); for (Element portletElement : portletElements) { String portletId = portletElement.attributeValue("portlet-id"); Portlet portlet = _portletLocalService.getPortletById(portletDataContext.getCompanyId(), portletId); if ((portlet == null) || !portlet.isActive() || portlet.isUndeployedPortlet()) { continue; } PortletDataHandler portletDataHandler = _portletDataHandlerProvider .provide(portletDataContext.getCompanyId(), portletId); if (portletDataHandler == null) { continue; } portletDataContext.addDeletionSystemEventStagedModelTypes( portletDataHandler.getDeletionSystemEventStagedModelTypes()); } portletDataContext.addDeletionSystemEventStagedModelTypes(new StagedModelType(Layout.class)); portletDataContext.addDeletionSystemEventStagedModelTypes(new StagedModelType(StagedAssetLink.class)); } /** * @deprecated As of 4.0.0 */ @Deprecated protected void setExportImportLifecycleManager(ExportImportLifecycleManager exportImportLifecycleManager) { } /** * @deprecated As of 4.0.0 */ @Deprecated protected void setGroupLocalService(GroupLocalService groupLocalService) { } /** * @deprecated As of 4.0.0 */ @Deprecated protected void setLayoutLocalService(LayoutLocalService layoutLocalService) { } /** * @deprecated As of 4.0.0 */ @Deprecated protected void setLayoutPrototypeLocalService(LayoutPrototypeLocalService layoutPrototypeLocalService) { } /** * @deprecated As of 4.0.0 */ @Deprecated protected void setLayoutSetLocalService(LayoutSetLocalService layoutSetLocalService) { } /** * @deprecated As of 4.0.0 */ @Deprecated protected void setLayoutSetPrototypeLocalService( LayoutSetPrototypeLocalService layoutSetPrototypeLocalService) { } /** * @deprecated As of 4.0.0 */ @Deprecated protected void setPortletImportController(PortletImportController portletImportController) { } /** * @deprecated As of 4.0.0 */ @Deprecated protected void setPortletLocalService(PortletLocalService portletLocalService) { } /** * @deprecated As of 4.0.0 */ @Deprecated protected void setPortletScope(PortletDataContext portletDataContext, Element portletElement) { } /** * @deprecated As of 4.0.0 */ @Deprecated protected void updateLayoutPriorities(PortletDataContext portletDataContext, List<Element> layoutElements, boolean privateLayout) { } protected void validateFile(long companyId, long groupId, Map<String, String[]> parameterMap, ZipReader zipReader) throws Exception { // XML String xml = zipReader.getEntryAsString("/manifest.xml"); if (xml == null) { throw new LARFileException(LARFileException.TYPE_MISSING_MANIFEST); } Element rootElement = null; try { Document document = SAXReaderUtil.read(xml); rootElement = document.getRootElement(); } catch (Exception e) { throw new LARFileException(LARFileException.TYPE_INVALID_MANIFEST, e); } // Bundle compatibility Element headerElement = rootElement.element("header"); int importBuildNumber = GetterUtil.getInteger(headerElement.attributeValue("build-number")); if (importBuildNumber < ReleaseInfo.RELEASE_7_0_0_BUILD_NUMBER) { int buildNumber = ReleaseInfo.getBuildNumber(); if (buildNumber != importBuildNumber) { throw new LayoutImportException(LayoutImportException.TYPE_WRONG_BUILD_NUMBER, new Object[] { importBuildNumber, buildNumber }); } } else { BiPredicate<Version, Version> majorVersionBiPredicate = (currentVersion, importVersion) -> Objects .equals(currentVersion.getMajor(), importVersion.getMajor()); BiPredicate<Version, Version> minorVersionBiPredicate = (currentVersion, importVersion) -> { int currentMinorVersion = GetterUtil.getInteger(currentVersion.getMinor(), -1); int importedMinorVersion = GetterUtil.getInteger(importVersion.getMinor(), -1); if (((currentMinorVersion == -1) && (importedMinorVersion == -1)) || (currentMinorVersion < importedMinorVersion)) { return false; } return true; }; BiPredicate<Version, Version> manifestVersionBiPredicate = (currentVersion, importVersion) -> { BiPredicate<Version, Version> versionBiPredicate = majorVersionBiPredicate .and(minorVersionBiPredicate); return versionBiPredicate.test(currentVersion, importVersion); }; String importSchemaVersion = GetterUtil.getString(headerElement.attributeValue("schema-version"), "1.0.0"); if (!manifestVersionBiPredicate.test( Version.getInstance(ExportImportConstants.EXPORT_IMPORT_SCHEMA_VERSION), Version.getInstance(importSchemaVersion))) { throw new LayoutImportException(LayoutImportException.TYPE_WRONG_LAR_SCHEMA_VERSION, new Object[] { importSchemaVersion, ExportImportConstants.EXPORT_IMPORT_SCHEMA_VERSION }); } } // Type String larType = headerElement.attributeValue("type"); String[] expectedLARTypes = { "layout-prototype", "layout-set", "layout-set-prototype" }; Stream<String> stream = Stream.of(expectedLARTypes); if (stream.noneMatch(lt -> lt.equals(larType))) { throw new LARTypeException(larType, expectedLARTypes); } Group group = _groupLocalService.fetchGroup(groupId); String layoutsImportMode = MapUtil.getString(parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE); if (larType.equals("layout-prototype") && !group.isLayoutPrototype() && !layoutsImportMode.equals(PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) { throw new LARTypeException(LARTypeException.TYPE_LAYOUT_PROTOTYPE); } if (larType.equals("layout-set")) { if (group.isLayoutPrototype() || group.isLayoutSetPrototype()) { throw new LARTypeException(LARTypeException.TYPE_LAYOUT_SET); } long sourceCompanyGroupId = GetterUtil.getLong(headerElement.attributeValue("company-group-id")); long sourceGroupId = GetterUtil.getLong(headerElement.attributeValue("group-id")); boolean companySourceGroup = false; if (sourceCompanyGroupId == sourceGroupId) { companySourceGroup = true; } if (group.isCompany() ^ companySourceGroup) { throw new LARTypeException(LARTypeException.TYPE_COMPANY_GROUP); } } if (larType.equals("layout-set-prototype") && !group.isLayoutSetPrototype() && !layoutsImportMode.equals(PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) { throw new LARTypeException(LARTypeException.TYPE_LAYOUT_SET_PROTOTYPE); } // Portlets compatibility List<Element> portletElements = fetchPortletElements(rootElement); for (Element portletElement : portletElements) { String portletId = GetterUtil.getString(portletElement.attributeValue("portlet-id")); if (Validator.isNull(portletId)) { continue; } String schemaVersion = GetterUtil.getString(portletElement.attributeValue("schema-version")); PortletDataHandler portletDataHandler = _portletDataHandlerProvider.provide(companyId, portletId); if (portletDataHandler == null) { continue; } if (!portletDataHandler.validateSchemaVersion(schemaVersion)) { throw new LayoutImportException(LayoutImportException.TYPE_WRONG_PORTLET_SCHEMA_VERSION, new Object[] { schemaVersion, portletId, portletDataHandler.getSchemaVersion() }); } } // Available locales List<Locale> sourceAvailableLocales = Arrays.asList( LocaleUtil.fromLanguageIds(StringUtil.split(headerElement.attributeValue("available-locales")))); for (Locale sourceAvailableLocale : sourceAvailableLocales) { if (!LanguageUtil.isAvailableLocale(groupId, sourceAvailableLocale)) { LocaleException le = new LocaleException(LocaleException.TYPE_EXPORT_IMPORT); le.setSourceAvailableLocales(sourceAvailableLocales); le.setTargetAvailableLocales(LanguageUtil.getAvailableLocales(groupId)); throw le; } } // Layout prototypes validity Element layoutsElement = rootElement.element(Layout.class.getSimpleName()); validateLayoutPrototypes(companyId, headerElement, layoutsElement); } /** * @deprecated As of 3.0.0, replaced by {@link * #validateLayoutPrototypes(long, Element, Element)} */ @Deprecated protected void validateLayoutPrototypes(long companyId, Element layoutsElement) throws Exception { throw new UnsupportedOperationException( "This method is deprecated and replaced by " + "#validateLayoutPrototypes(long, Element, Element)"); } protected void validateLayoutPrototypes(long companyId, Element headerElement, Element layoutsElement) throws Exception { List<Tuple> missingLayoutPrototypes = new ArrayList<>(); String layoutSetPrototypeUuid = headerElement.attributeValue("layout-set-prototype-uuid"); if (Validator.isNotNull(layoutSetPrototypeUuid)) { try { _layoutSetPrototypeLocalService.getLayoutSetPrototypeByUuidAndCompanyId(layoutSetPrototypeUuid, companyId); } catch (NoSuchLayoutSetPrototypeException nslspe) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(nslspe, nslspe); } String layoutSetPrototypeName = headerElement.attributeValue("layout-set-prototype-name"); missingLayoutPrototypes.add(new Tuple(LayoutSetPrototype.class.getName(), layoutSetPrototypeUuid, layoutSetPrototypeName)); } } List<Element> layoutElements = layoutsElement.elements(); for (Element layoutElement : layoutElements) { String action = layoutElement.attributeValue(Constants.ACTION); if (action.equals(Constants.SKIP)) { continue; } String layoutPrototypeUuid = GetterUtil .getString(layoutElement.attributeValue("layout-prototype-uuid")); if (Validator.isNotNull(layoutPrototypeUuid)) { try { _layoutPrototypeLocalService.getLayoutPrototypeByUuidAndCompanyId(layoutPrototypeUuid, companyId); } catch (NoSuchLayoutPrototypeException nslpe) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(nslpe, nslpe); } String layoutPrototypeName = GetterUtil .getString(layoutElement.attributeValue("layout-prototype-name")); missingLayoutPrototypes.add( new Tuple(LayoutPrototype.class.getName(), layoutPrototypeUuid, layoutPrototypeName)); } } } if (!missingLayoutPrototypes.isEmpty()) { throw new LayoutPrototypeException(missingLayoutPrototypes); } } private static final Log _log = LogFactoryUtil.getLog(LayoutImportController.class); private final DeletionSystemEventImporter _deletionSystemEventImporter = DeletionSystemEventImporter .getInstance(); @Reference private ExportImportHelper _exportImportHelper; @Reference private ExportImportLifecycleManager _exportImportLifecycleManager; @Reference private GroupLocalService _groupLocalService; @Reference private LayoutLocalService _layoutLocalService; @Reference private LayoutPrototypeLocalService _layoutPrototypeLocalService; @Reference private LayoutSetLocalService _layoutSetLocalService; @Reference private LayoutSetPrototypeLocalService _layoutSetPrototypeLocalService; private final PermissionImporter _permissionImporter = PermissionImporter.getInstance(); @Reference private PortletDataContextFactory _portletDataContextFactory; @Reference private PortletDataHandlerProvider _portletDataHandlerProvider; @Reference private PortletImportController _portletImportController; @Reference private PortletLocalService _portletLocalService; }