/** * 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.internal.content.processor; import com.liferay.document.library.kernel.exception.NoSuchFileEntryException; import com.liferay.document.library.kernel.model.DLFileEntry; import com.liferay.document.library.kernel.service.DLAppLocalService; import com.liferay.document.library.kernel.service.DLFileEntryLocalService; import com.liferay.document.library.kernel.util.DLUtil; import com.liferay.exportimport.content.processor.ExportImportContentProcessor; import com.liferay.exportimport.kernel.lar.ExportImportPathUtil; import com.liferay.exportimport.kernel.lar.PortletDataContext; import com.liferay.exportimport.kernel.lar.PortletDataHandlerKeys; import com.liferay.exportimport.kernel.lar.StagedModelDataHandlerUtil; import com.liferay.portal.kernel.exception.NoSuchLayoutException; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.Company; import com.liferay.portal.kernel.model.Group; import com.liferay.portal.kernel.model.Layout; import com.liferay.portal.kernel.model.LayoutFriendlyURL; import com.liferay.portal.kernel.model.LayoutSet; import com.liferay.portal.kernel.model.StagedModel; import com.liferay.portal.kernel.repository.model.FileEntry; import com.liferay.portal.kernel.service.CompanyLocalService; import com.liferay.portal.kernel.service.GroupLocalService; import com.liferay.portal.kernel.service.LayoutFriendlyURLLocalService; import com.liferay.portal.kernel.service.LayoutLocalService; import com.liferay.portal.kernel.service.ServiceContext; import com.liferay.portal.kernel.service.ServiceContextThreadLocal; import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.ArrayUtil; import com.liferay.portal.kernel.util.CharPool; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.Http; import com.liferay.portal.kernel.util.LocaleUtil; import com.liferay.portal.kernel.util.MapUtil; import com.liferay.portal.kernel.util.Portal; import com.liferay.portal.kernel.util.PortletKeys; import com.liferay.portal.kernel.util.PropsKeys; import com.liferay.portal.kernel.util.PropsUtil; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.xml.Element; import com.liferay.portal.util.PropsValues; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; /** * @author Daniel Kocsis */ @Component( immediate = true, property = {"model.class.name=java.lang.String"}, service = ExportImportContentProcessor.class ) public class DefaultTextExportImportContentProcessor implements ExportImportContentProcessor<String> { @Override public String replaceExportContentReferences( PortletDataContext portletDataContext, StagedModel stagedModel, String content, boolean exportReferencedContent, boolean escapeContent) throws Exception { content = replaceExportDLReferences( portletDataContext, stagedModel, content, exportReferencedContent); content = replaceExportLayoutReferences( portletDataContext, stagedModel, content); content = replaceExportLinksToLayouts( portletDataContext, stagedModel, content); if (escapeContent) { content = StringUtil.replace( content, StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND); } return content; } @Override public String replaceImportContentReferences( PortletDataContext portletDataContext, StagedModel stagedModel, String content) throws Exception { content = replaceImportDLReferences( portletDataContext, stagedModel, content); content = replaceImportLayoutReferences(portletDataContext, content); content = replaceImportLinksToLayouts(portletDataContext, content); return content; } @Override public void validateContentReferences(long groupId, String content) throws PortalException { validateDLReferences(groupId, content); validateLayoutReferences(groupId, content); validateLinksToLayoutsReferences(content); } protected void deleteTimestampParameters(StringBuilder sb, int beginPos) { beginPos = sb.indexOf(StringPool.CLOSE_BRACKET, beginPos); if ((beginPos == -1) || (beginPos == (sb.length() - 1)) || (sb.charAt(beginPos + 1) != CharPool.QUESTION)) { return; } int endPos = StringUtil.indexOfAny( sb.toString(), _DL_REFERENCE_LEGACY_STOP_CHARS, beginPos + 2); if (endPos == -1) { return; } String urlParams = sb.substring(beginPos + 1, endPos); urlParams = _http.removeParameter(urlParams, "t"); sb.replace(beginPos + 1, endPos, urlParams); } protected Map<String, String[]> getDLReferenceParameters( long groupId, String content, int beginPos, int endPos) { boolean legacyURL = true; char[] stopChars = _DL_REFERENCE_LEGACY_STOP_CHARS; if (content.startsWith("/documents/", beginPos)) { legacyURL = false; stopChars = _DL_REFERENCE_STOP_CHARS; } endPos = StringUtil.indexOfAny(content, stopChars, beginPos, endPos); if (endPos == -1) { return null; } Map<String, String[]> map = new HashMap<>(); String dlReference = content.substring(beginPos, endPos); while (dlReference.contains(StringPool.AMPERSAND_ENCODED)) { dlReference = dlReference.replace( StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND); } if (!legacyURL) { String[] pathArray = dlReference.split(StringPool.SLASH); if (pathArray.length < 3) { return map; } map.put("groupId", new String[] {pathArray[2]}); if (pathArray.length == 4) { map.put("uuid", new String[] {pathArray[3]}); } else if (pathArray.length == 5) { map.put("folderId", new String[] {pathArray[3]}); map.put("title", new String[] {_http.decodeURL(pathArray[4])}); } else if (pathArray.length > 5) { map.put("uuid", new String[] {pathArray[5]}); } } else { dlReference = dlReference.substring( dlReference.indexOf(CharPool.QUESTION) + 1); map = _http.parameterMapFromString(dlReference); String[] imageIds = null; if (map.containsKey("img_id")) { imageIds = map.get("img_id"); } else if (map.containsKey("i_id")) { imageIds = map.get("i_id"); } imageIds = ArrayUtil.filter(imageIds, Validator::isNotNull); if (ArrayUtil.isNotEmpty(imageIds)) { map.put("image_id", imageIds); } } map.put("endPos", new String[] {String.valueOf(endPos)}); String groupIdString = MapUtil.getString(map, "groupId"); if (groupIdString.equals("@group_id@")) { groupIdString = String.valueOf(groupId); map.put("groupId", new String[] {groupIdString}); } return map; } protected FileEntry getFileEntry(Map<String, String[]> map) { if (MapUtil.isEmpty(map)) { return null; } FileEntry fileEntry = null; try { String uuid = MapUtil.getString(map, "uuid"); long groupId = MapUtil.getLong(map, "groupId"); if (Validator.isNotNull(uuid)) { fileEntry = _dlAppLocalService.getFileEntryByUuidAndGroupId( uuid, groupId); } else { if (map.containsKey("folderId")) { long folderId = MapUtil.getLong(map, "folderId"); String name = MapUtil.getString(map, "name"); String title = MapUtil.getString(map, "title"); if (Validator.isNotNull(title)) { fileEntry = _dlAppLocalService.getFileEntry( groupId, folderId, title); } else { DLFileEntry dlFileEntry = _dlFileEntryLocalService.fetchFileEntryByName( groupId, folderId, name); if (dlFileEntry != null) { fileEntry = _dlAppLocalService.getFileEntry( dlFileEntry.getFileEntryId()); } } } else if (map.containsKey("image_id")) { DLFileEntry dlFileEntry = _dlFileEntryLocalService.fetchFileEntryByAnyImageId( MapUtil.getLong(map, "image_id")); if (dlFileEntry != null) { fileEntry = _dlAppLocalService.getFileEntry( dlFileEntry.getFileEntryId()); } } } } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } else if (_log.isWarnEnabled()) { _log.warn(e.getMessage()); } } return fileEntry; } protected String replaceExportDLReferences( PortletDataContext portletDataContext, StagedModel stagedModel, String content, boolean exportReferencedContent) throws Exception { Group group = _groupLocalService.getGroup( portletDataContext.getGroupId()); if (group.isStagingGroup()) { group = group.getLiveGroup(); } if (group.isStaged() && !group.isStagedRemotely() && !group.isStagedPortlet(PortletKeys.DOCUMENT_LIBRARY)) { return content; } StringBuilder sb = new StringBuilder(content); String contextPath = _portal.getPathContext(); String[] patterns = { contextPath.concat("/c/document_library/get_file?"), contextPath.concat("/documents/"), contextPath.concat("/image/image_gallery?") }; int beginPos = -1; int endPos = content.length(); while (true) { beginPos = StringUtil.lastIndexOfAny(content, patterns, endPos); if (beginPos == -1) { break; } Map<String, String[]> dlReferenceParameters = getDLReferenceParameters( portletDataContext.getScopeGroupId(), content, beginPos + contextPath.length(), endPos); FileEntry fileEntry = getFileEntry(dlReferenceParameters); if (fileEntry == null) { endPos = beginPos - 1; continue; } endPos = MapUtil.getInteger(dlReferenceParameters, "endPos"); try { if (exportReferencedContent) { StagedModelDataHandlerUtil.exportReferenceStagedModel( portletDataContext, stagedModel, fileEntry, PortletDataContext.REFERENCE_TYPE_DEPENDENCY); } else { Element entityElement = portletDataContext.getExportDataElement(stagedModel); portletDataContext.addReferenceElement( stagedModel, entityElement, fileEntry, PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true); } String path = ExportImportPathUtil.getModelPath(fileEntry); sb.replace(beginPos, endPos, "[$dl-reference=" + path + "$]"); deleteTimestampParameters(sb, beginPos); } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } else if (_log.isWarnEnabled()) { StringBundler exceptionSB = new StringBundler(6); exceptionSB.append("Unable to process file entry "); exceptionSB.append(fileEntry.getFileEntryId()); exceptionSB.append(" for staged model "); exceptionSB.append(stagedModel.getModelClassName()); exceptionSB.append(" with primary key "); exceptionSB.append(stagedModel.getPrimaryKeyObj()); _log.warn(exceptionSB.toString()); } } endPos = beginPos - 1; } return sb.toString(); } protected String replaceExportHostname( long groupId, String url, StringBundler urlSB) throws PortalException { if (!_http.hasProtocol(url)) { return url; } boolean secure = _http.isSecure(url); int serverPort = _portal.getPortalServerPort(secure); if (serverPort == -1) { return url; } Group group = _groupLocalService.getGroup(groupId); LayoutSet publicLayoutSet = group.getPublicLayoutSet(); String publicLayoutSetVirtualHostname = publicLayoutSet.getVirtualHostname(); String portalUrl = StringPool.BLANK; if (Validator.isNotNull(publicLayoutSetVirtualHostname)) { portalUrl = _portal.getPortalURL( publicLayoutSetVirtualHostname, serverPort, secure); if (url.startsWith(portalUrl)) { if (secure) { urlSB.append(_DATA_HANDLER_PUBLIC_LAYOUT_SET_SECURE_URL); } else { urlSB.append(_DATA_HANDLER_PUBLIC_LAYOUT_SET_URL); } return url.substring(portalUrl.length()); } } LayoutSet privateLayoutSet = group.getPrivateLayoutSet(); String privateLayoutSetVirtualHostname = privateLayoutSet.getVirtualHostname(); if (Validator.isNotNull(privateLayoutSetVirtualHostname)) { portalUrl = _portal.getPortalURL( privateLayoutSetVirtualHostname, serverPort, secure); if (url.startsWith(portalUrl)) { if (secure) { urlSB.append(_DATA_HANDLER_PRIVATE_LAYOUT_SET_SECURE_URL); } else { urlSB.append(_DATA_HANDLER_PRIVATE_LAYOUT_SET_URL); } return url.substring(portalUrl.length()); } } Company company = _companyLocalService.getCompany(group.getCompanyId()); String companyVirtualHostname = company.getVirtualHostname(); if (Validator.isNotNull(companyVirtualHostname)) { portalUrl = _portal.getPortalURL( companyVirtualHostname, serverPort, secure); if (url.startsWith(portalUrl)) { if (secure) { urlSB.append(_DATA_HANDLER_COMPANY_SECURE_URL); } else { urlSB.append(_DATA_HANDLER_COMPANY_URL); } return url.substring(portalUrl.length()); } } portalUrl = _portal.getPortalURL("localhost", serverPort, secure); if (url.startsWith(portalUrl)) { return url.substring(portalUrl.length()); } return url; } protected String replaceExportLayoutReferences( PortletDataContext portletDataContext, StagedModel stagedModel, String content) throws Exception { Group group = _groupLocalService.getGroup( portletDataContext.getScopeGroupId()); StringBuilder sb = new StringBuilder(content); String[] patterns = {"href=", "[["}; int beginPos = -1; int endPos = content.length(); int offset = 0; while (true) { if (beginPos > -1) { endPos = beginPos - 1; } beginPos = StringUtil.lastIndexOfAny(content, patterns, endPos); if (beginPos == -1) { break; } if (content.startsWith("href=", beginPos)) { offset = 5; char c = content.charAt(beginPos + offset); if ((c == CharPool.APOSTROPHE) || (c == CharPool.QUOTE)) { offset++; } } else if (content.charAt(beginPos) == CharPool.OPEN_BRACKET) { offset = 2; } endPos = StringUtil.indexOfAny( content, _LAYOUT_REFERENCE_STOP_CHARS, beginPos + offset, endPos); if (endPos == -1) { continue; } String url = content.substring(beginPos + offset, endPos); if (url.endsWith(StringPool.SLASH)) { url = url.substring(0, url.length() - 1); } StringBundler urlSB = new StringBundler(6); try { url = replaceExportHostname( portletDataContext.getScopeGroupId(), url, urlSB); if (!url.startsWith(StringPool.SLASH)) { continue; } String pathContext = _portal.getPathContext(); if (pathContext.length() > 1) { if (!url.startsWith(pathContext)) { continue; } urlSB.append(_DATA_HANDLER_PATH_CONTEXT); url = url.substring(pathContext.length()); } if (!url.startsWith(StringPool.SLASH)) { continue; } int pos = url.indexOf(StringPool.SLASH, 1); String localePath = StringPool.BLANK; Locale locale = null; if (pos != -1) { localePath = url.substring(0, pos); locale = LocaleUtil.fromLanguageId( localePath.substring(1), true, false); } if (locale != null) { String urlWithoutLocale = url.substring( localePath.length()); if (urlWithoutLocale.startsWith( _PRIVATE_GROUP_SERVLET_MAPPING) || urlWithoutLocale.startsWith( _PRIVATE_USER_SERVLET_MAPPING) || urlWithoutLocale.startsWith( _PUBLIC_GROUP_SERVLET_MAPPING)) { urlSB.append(localePath); url = urlWithoutLocale; } } boolean privateLayout = false; if (url.startsWith(_PRIVATE_GROUP_SERVLET_MAPPING)) { urlSB.append(_DATA_HANDLER_PRIVATE_GROUP_SERVLET_MAPPING); url = url.substring( _PRIVATE_GROUP_SERVLET_MAPPING.length() - 1); privateLayout = true; } else if (url.startsWith(_PRIVATE_USER_SERVLET_MAPPING)) { urlSB.append(_DATA_HANDLER_PRIVATE_USER_SERVLET_MAPPING); url = url.substring( _PRIVATE_USER_SERVLET_MAPPING.length() - 1); privateLayout = true; } else if (url.startsWith(_PUBLIC_GROUP_SERVLET_MAPPING)) { urlSB.append(_DATA_HANDLER_PUBLIC_SERVLET_MAPPING); url = url.substring( _PUBLIC_GROUP_SERVLET_MAPPING.length() - 1); } else { String urlSBString = urlSB.toString(); LayoutSet layoutSet = null; if (urlSBString.contains( _DATA_HANDLER_PUBLIC_LAYOUT_SET_SECURE_URL) || urlSBString.contains( _DATA_HANDLER_PUBLIC_LAYOUT_SET_URL)) { layoutSet = group.getPublicLayoutSet(); } else if (urlSBString.contains( _DATA_HANDLER_PRIVATE_LAYOUT_SET_SECURE_URL) || urlSBString.contains( _DATA_HANDLER_PRIVATE_LAYOUT_SET_URL)) { layoutSet = group.getPrivateLayoutSet(); } if (layoutSet == null) { continue; } privateLayout = layoutSet.isPrivateLayout(); LayoutFriendlyURL layoutFriendlyUrl = _layoutFriendlyURLLocalService. fetchFirstLayoutFriendlyURL( group.getGroupId(), privateLayout, url); if (layoutFriendlyUrl == null) { continue; } if (privateLayout) { if (group.isUser()) { urlSB.append( _DATA_HANDLER_PRIVATE_USER_SERVLET_MAPPING); } else { urlSB.append( _DATA_HANDLER_PRIVATE_GROUP_SERVLET_MAPPING); } } else { urlSB.append(_DATA_HANDLER_PUBLIC_SERVLET_MAPPING); } urlSB.append(_DATA_HANDLER_GROUP_FRIENDLY_URL); continue; } long groupId = group.getGroupId(); Layout layout = _layoutLocalService.fetchLayoutByFriendlyURL( groupId, privateLayout, url); if (layout != null) { Element entityElement = portletDataContext.getExportDataElement(stagedModel); portletDataContext.addReferenceElement( stagedModel, entityElement, layout, PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true); continue; } pos = url.indexOf(StringPool.SLASH, 1); String groupFriendlyURL = url; if (pos != -1) { groupFriendlyURL = url.substring(0, pos); } Group urlGroup = _groupLocalService.fetchFriendlyURLGroup( group.getCompanyId(), groupFriendlyURL); if (urlGroup == null) { throw new NoSuchLayoutException(); } urlSB.append(_DATA_HANDLER_GROUP_FRIENDLY_URL); if (pos == -1) { url = StringPool.BLANK; continue; } url = url.substring(pos); layout = _layoutLocalService.getFriendlyURLLayout( urlGroup.getGroupId(), privateLayout, url); Element entityElement = portletDataContext.getExportDataElement( stagedModel); portletDataContext.addReferenceElement( stagedModel, entityElement, layout, PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true); } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } else if (_log.isWarnEnabled()) { StringBundler exceptionSB = new StringBundler(6); exceptionSB.append("Unable to process layout URL "); exceptionSB.append(url); exceptionSB.append(" for staged model "); exceptionSB.append(stagedModel.getModelClassName()); exceptionSB.append(" with primary key "); exceptionSB.append(stagedModel.getPrimaryKeyObj()); _log.warn(exceptionSB.toString()); } } finally { if (urlSB.length() > 0) { urlSB.append(url); url = urlSB.toString(); } sb.replace(beginPos + offset, endPos, url); } } return sb.toString(); } protected String replaceExportLinksToLayouts( PortletDataContext portletDataContext, StagedModel stagedModel, String content) throws Exception { List<String> oldLinksToLayout = new ArrayList<>(); List<String> newLinksToLayout = new ArrayList<>(); Matcher matcher = _exportLinksToLayoutPattern.matcher(content); while (matcher.find()) { long layoutId = GetterUtil.getLong(matcher.group(1)); String type = matcher.group(2); boolean privateLayout = type.startsWith("private"); try { Layout layout = _layoutLocalService.getLayout( portletDataContext.getScopeGroupId(), privateLayout, layoutId); String oldLinkToLayout = matcher.group(0); StringBundler sb = new StringBundler(3); sb.append(type); sb.append(StringPool.AT); sb.append(layout.getPlid()); String newLinkToLayout = StringUtil.replace( oldLinkToLayout, type, sb.toString()); oldLinksToLayout.add(oldLinkToLayout); newLinksToLayout.add(newLinkToLayout); Element entityElement = portletDataContext.getExportDataElement( stagedModel); portletDataContext.addReferenceElement( stagedModel, entityElement, layout, PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true); } catch (Exception e) { if (_log.isDebugEnabled() || _log.isWarnEnabled()) { String message = "Unable to get layout with ID " + layoutId + " in group " + portletDataContext.getScopeGroupId(); if (_log.isDebugEnabled()) { _log.debug(message, e); } else { _log.warn(message); } } } } content = StringUtil.replace( content, ArrayUtil.toStringArray(oldLinksToLayout.toArray()), ArrayUtil.toStringArray(newLinksToLayout.toArray())); return content; } protected String replaceImportDLReferences( PortletDataContext portletDataContext, StagedModel stagedModel, String content) throws Exception { List<Element> referenceElements = portletDataContext.getReferenceElements( stagedModel, DLFileEntry.class); for (Element referenceElement : referenceElements) { Long classPK = GetterUtil.getLong( referenceElement.attributeValue("class-pk")); Element referenceDataElement = portletDataContext.getReferenceDataElement( stagedModel, DLFileEntry.class, classPK); String path = null; if (referenceDataElement != null) { path = referenceDataElement.attributeValue("path"); } long groupId = GetterUtil.getLong( referenceElement.attributeValue("group-id")); if (Validator.isNull(path)) { String className = referenceElement.attributeValue( "class-name"); path = ExportImportPathUtil.getModelPath( groupId, className, classPK); } if (!content.contains("[$dl-reference=" + path + "$]")) { continue; } try { StagedModelDataHandlerUtil.importReferenceStagedModel( portletDataContext, stagedModel, DLFileEntry.class, classPK); } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } else if (_log.isWarnEnabled()) { StringBundler sb = new StringBundler(6); sb.append("Unable to process file entry "); sb.append(classPK); sb.append(" for "); sb.append(stagedModel.getModelClassName()); sb.append(" with primary key "); sb.append(stagedModel.getPrimaryKeyObj()); _log.warn(sb.toString()); } } Map<Long, Long> dlFileEntryIds = (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap( DLFileEntry.class); long fileEntryId = MapUtil.getLong( dlFileEntryIds, classPK, classPK); FileEntry importedFileEntry = null; try { importedFileEntry = _dlAppLocalService.getFileEntry( fileEntryId); } catch (PortalException pe) { if (_log.isDebugEnabled()) { _log.debug(pe, pe); } else if (_log.isWarnEnabled()) { _log.warn(pe.getMessage()); } continue; } String url = DLUtil.getPreviewURL( importedFileEntry, importedFileEntry.getFileVersion(), null, StringPool.BLANK, false, false); if (url.contains(StringPool.QUESTION)) { content = StringUtil.replace(content, "$]?", "$]&"); } content = StringUtil.replace( content, "[$dl-reference=" + path + "$]", url); } return content; } protected String replaceImportLayoutReferences( PortletDataContext portletDataContext, String content) throws Exception { String companyPortalURL = StringPool.BLANK; String privateLayoutSetPortalURL = StringPool.BLANK; String publicLayoutSetPortalURL = StringPool.BLANK; Group group = _groupLocalService.getGroup( portletDataContext.getScopeGroupId()); Company company = _companyLocalService.getCompany(group.getCompanyId()); LayoutSet privateLayoutSet = group.getPrivateLayoutSet(); LayoutSet publicLayoutSet = group.getPublicLayoutSet(); int serverPort = _portal.getPortalServerPort(false); if (serverPort != -1) { if (Validator.isNotNull(company.getVirtualHostname())) { companyPortalURL = _portal.getPortalURL( company.getVirtualHostname(), serverPort, false); } if (Validator.isNotNull(privateLayoutSet.getVirtualHostname())) { privateLayoutSetPortalURL = _portal.getPortalURL( privateLayoutSet.getVirtualHostname(), serverPort, false); } if (Validator.isNotNull(publicLayoutSet.getVirtualHostname())) { publicLayoutSetPortalURL = _portal.getPortalURL( publicLayoutSet.getVirtualHostname(), serverPort, false); } } int secureSecurePort = _portal.getPortalServerPort(true); String companySecurePortalURL = StringPool.BLANK; String privateLayoutSetSecurePortalURL = StringPool.BLANK; String publicLayoutSetSecurePortalURL = StringPool.BLANK; if (secureSecurePort != -1) { if (Validator.isNotNull(company.getVirtualHostname())) { companySecurePortalURL = _portal.getPortalURL( company.getVirtualHostname(), secureSecurePort, true); } if (Validator.isNotNull(privateLayoutSet.getVirtualHostname())) { privateLayoutSetSecurePortalURL = _portal.getPortalURL( privateLayoutSet.getVirtualHostname(), secureSecurePort, true); } if (Validator.isNotNull(publicLayoutSet.getVirtualHostname())) { publicLayoutSetSecurePortalURL = _portal.getPortalURL( publicLayoutSet.getVirtualHostname(), secureSecurePort, true); } } content = StringUtil.replace( content, _DATA_HANDLER_COMPANY_SECURE_URL, companySecurePortalURL); content = StringUtil.replace( content, _DATA_HANDLER_COMPANY_URL, companyPortalURL); content = StringUtil.replace( content, _DATA_HANDLER_GROUP_FRIENDLY_URL, group.getFriendlyURL()); content = StringUtil.replace( content, _DATA_HANDLER_PATH_CONTEXT, _portal.getPathContext()); content = StringUtil.replace( content, _DATA_HANDLER_PRIVATE_GROUP_SERVLET_MAPPING, PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING); content = StringUtil.replace( content, _DATA_HANDLER_PRIVATE_LAYOUT_SET_SECURE_URL, privateLayoutSetSecurePortalURL); content = StringUtil.replace( content, _DATA_HANDLER_PRIVATE_LAYOUT_SET_URL, privateLayoutSetPortalURL); content = StringUtil.replace( content, _DATA_HANDLER_PRIVATE_USER_SERVLET_MAPPING, PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING); content = StringUtil.replace( content, _DATA_HANDLER_PUBLIC_LAYOUT_SET_SECURE_URL, publicLayoutSetSecurePortalURL); content = StringUtil.replace( content, _DATA_HANDLER_PUBLIC_LAYOUT_SET_URL, publicLayoutSetPortalURL); content = StringUtil.replace( content, _DATA_HANDLER_PUBLIC_SERVLET_MAPPING, PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING); return content; } protected String replaceImportLinksToLayouts( PortletDataContext portletDataContext, String content) throws Exception { List<String> oldLinksToLayout = new ArrayList<>(); List<String> newLinksToLayout = new ArrayList<>(); Matcher matcher = _importLinksToLayoutPattern.matcher(content); Map<Long, Long> layoutPlids = (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap( Layout.class); String layoutsImportMode = MapUtil.getString( portletDataContext.getParameterMap(), PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID); while (matcher.find()) { long oldPlid = GetterUtil.getLong(matcher.group(4)); Long newPlid = MapUtil.getLong(layoutPlids, oldPlid); long oldGroupId = GetterUtil.getLong(matcher.group(6)); long newGroupId = oldGroupId; long oldLayoutId = GetterUtil.getLong(matcher.group(1)); long newLayoutId = oldLayoutId; Layout layout = _layoutLocalService.fetchLayout(newPlid); if (layout != null) { newGroupId = layout.getGroupId(); newLayoutId = layout.getLayoutId(); } else if (_log.isWarnEnabled()) { _log.warn("Unable to get layout with plid " + oldPlid); } String oldLinkToLayout = matcher.group(0); String newLinkToLayout = StringUtil.replaceFirst( oldLinkToLayout, new String[] { StringPool.AT + oldPlid, String.valueOf(oldLayoutId) }, new String[] {StringPool.BLANK, String.valueOf(newLayoutId)}); if ((layout != null) && layout.isPublicLayout() && layoutsImportMode.equals( PortletDataHandlerKeys. LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) { newLinkToLayout = StringUtil.replace( newLinkToLayout, "private-group", "public"); } if ((oldGroupId != 0) && (oldGroupId != newGroupId)) { newLinkToLayout = StringUtil.replaceLast( newLinkToLayout, String.valueOf(oldGroupId), String.valueOf(newGroupId)); } oldLinksToLayout.add(oldLinkToLayout); newLinksToLayout.add(newLinkToLayout); } content = StringUtil.replace( content, ArrayUtil.toStringArray(oldLinksToLayout.toArray()), ArrayUtil.toStringArray(newLinksToLayout.toArray())); return content; } protected void validateDLReferences(long groupId, String content) throws PortalException { String portalURL = _portal.getPathContext(); ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext(); if ((serviceContext != null) && (serviceContext.getThemeDisplay() != null)) { ThemeDisplay themeDisplay = serviceContext.getThemeDisplay(); portalURL = _portal.getPortalURL(themeDisplay) + _portal.getPathContext(); } String[] patterns = { portalURL.concat("/c/document_library/get_file?"), portalURL.concat("/documents/"), portalURL.concat("/image/image_gallery?") }; String[] completePatterns = new String[patterns.length]; long[] companyIds = _portal.getCompanyIds(); for (long companyId : companyIds) { Company company = _companyLocalService.getCompany(companyId); String webId = company.getWebId(); int i = 0; for (String pattern : patterns) { completePatterns[i] = webId.concat(pattern); i++; } int beginPos = -1; int endPos = content.length(); while (true) { beginPos = StringUtil.lastIndexOfAny( content, completePatterns, endPos); if (beginPos == -1) { break; } Map<String, String[]> dlReferenceParameters = getDLReferenceParameters( groupId, content, beginPos + portalURL.length() + webId.length(), endPos); FileEntry fileEntry = getFileEntry(dlReferenceParameters); if (fileEntry == null) { StringBundler sb = new StringBundler(4); sb.append("Validation failed for a referenced file entry "); sb.append( "because a file entry could not be found with the "); sb.append("following parameters: "); sb.append(dlReferenceParameters); throw new NoSuchFileEntryException(sb.toString()); } endPos = beginPos - 1; } } } protected void validateLayoutReferences(long groupId, String content) throws PortalException { Group group = _groupLocalService.getGroup(groupId); String[] patterns = {"href=", "[["}; int beginPos = -1; int endPos = content.length(); int offset = 0; while (true) { if (beginPos > -1) { endPos = beginPos - 1; } beginPos = StringUtil.lastIndexOfAny(content, patterns, endPos); if (beginPos == -1) { break; } if (content.startsWith("href=", beginPos)) { offset = 5; char c = content.charAt(beginPos + offset); if ((c == CharPool.APOSTROPHE) || (c == CharPool.QUOTE)) { offset++; } } else if (content.charAt(beginPos) == CharPool.OPEN_BRACKET) { offset = 2; } endPos = StringUtil.indexOfAny( content, _LAYOUT_REFERENCE_STOP_CHARS, beginPos + offset, endPos); if (endPos == -1) { continue; } String url = content.substring(beginPos + offset, endPos); endPos = url.indexOf(Portal.FRIENDLY_URL_SEPARATOR); if (endPos != -1) { url = url.substring(0, endPos); } if (url.endsWith(StringPool.SLASH)) { url = url.substring(0, url.length() - 1); } StringBundler urlSB = new StringBundler(1); url = replaceExportHostname(groupId, url, urlSB); if (!url.startsWith(StringPool.SLASH)) { continue; } String pathContext = _portal.getPathContext(); if (pathContext.length() > 1) { if (!url.startsWith(pathContext)) { continue; } url = url.substring(pathContext.length()); } if (!url.startsWith(StringPool.SLASH)) { continue; } int pos = url.indexOf(StringPool.SLASH, 1); String localePath = StringPool.BLANK; Locale locale = null; if (pos != -1) { localePath = url.substring(0, pos); locale = LocaleUtil.fromLanguageId( localePath.substring(1), true, false); } if (locale != null) { String urlWithoutLocale = url.substring(localePath.length()); if (urlWithoutLocale.startsWith( _PRIVATE_GROUP_SERVLET_MAPPING) || urlWithoutLocale.startsWith( _PRIVATE_USER_SERVLET_MAPPING) || urlWithoutLocale.startsWith( _PUBLIC_GROUP_SERVLET_MAPPING)) { url = urlWithoutLocale; } } boolean privateLayout = false; if (url.startsWith(_PRIVATE_GROUP_SERVLET_MAPPING)) { url = url.substring( _PRIVATE_GROUP_SERVLET_MAPPING.length() - 1); privateLayout = true; } else if (url.startsWith(_PRIVATE_USER_SERVLET_MAPPING)) { url = url.substring(_PRIVATE_USER_SERVLET_MAPPING.length() - 1); privateLayout = true; } else if (url.startsWith(_PUBLIC_GROUP_SERVLET_MAPPING)) { url = url.substring(_PUBLIC_GROUP_SERVLET_MAPPING.length() - 1); } else { String urlSBString = urlSB.toString(); LayoutSet layoutSet = null; if (urlSBString.contains( _DATA_HANDLER_PUBLIC_LAYOUT_SET_SECURE_URL) || urlSBString.contains(_DATA_HANDLER_PUBLIC_LAYOUT_SET_URL)) { layoutSet = group.getPublicLayoutSet(); } else if (urlSBString.contains( _DATA_HANDLER_PRIVATE_LAYOUT_SET_SECURE_URL) || urlSBString.contains( _DATA_HANDLER_PRIVATE_LAYOUT_SET_URL)) { layoutSet = group.getPrivateLayoutSet(); } if (layoutSet == null) { continue; } privateLayout = layoutSet.isPrivateLayout(); } Layout layout = _layoutLocalService.fetchLayoutByFriendlyURL( groupId, privateLayout, url); if (layout != null) { continue; } pos = url.indexOf(StringPool.SLASH, 1); String groupFriendlyURL = url; if (pos != -1) { groupFriendlyURL = url.substring(0, pos); } Group urlGroup = _groupLocalService.fetchFriendlyURLGroup( group.getCompanyId(), groupFriendlyURL); if (urlGroup == null) { throw new NoSuchLayoutException( "Unable validate referenced page because it cannot be " + "found with url: " + url); } if (pos == -1) { continue; } url = url.substring(pos); layout = _layoutLocalService.fetchLayoutByFriendlyURL( urlGroup.getGroupId(), privateLayout, url); if (layout == null) { throw new NoSuchLayoutException( "Unable to validate referenced page because the page " + "group cannot be found: " + groupId); } } } protected void validateLinksToLayoutsReferences(String content) throws PortalException { Matcher matcher = _exportLinksToLayoutPattern.matcher(content); while (matcher.find()) { long groupId = GetterUtil.getLong(matcher.group(5)); String type = matcher.group(2); boolean privateLayout = type.startsWith("private"); long layoutId = GetterUtil.getLong(matcher.group(1)); Layout layout = _layoutLocalService.fetchLayout( groupId, privateLayout, layoutId); if (layout == null) { StringBundler exceptionMessage = new StringBundler(5); exceptionMessage.append( "Unable to validate referenced page because it cannot be"); exceptionMessage.append( "found with the following parameters: "); exceptionMessage.append("groupId " + groupId); exceptionMessage.append(", layoutId " + layoutId); exceptionMessage.append(", privateLayout " + privateLayout); throw new NoSuchLayoutException(exceptionMessage.toString()); } } } private static final String _DATA_HANDLER_COMPANY_SECURE_URL = "@data_handler_company_secure_url@"; private static final String _DATA_HANDLER_COMPANY_URL = "@data_handler_company_url@"; private static final String _DATA_HANDLER_GROUP_FRIENDLY_URL = "@data_handler_group_friendly_url@"; private static final String _DATA_HANDLER_PATH_CONTEXT = "@data_handler_path_context@"; private static final String _DATA_HANDLER_PRIVATE_GROUP_SERVLET_MAPPING = "@data_handler_private_group_servlet_mapping@"; private static final String _DATA_HANDLER_PRIVATE_LAYOUT_SET_SECURE_URL = "@data_handler_private_layout_set_secure_url@"; private static final String _DATA_HANDLER_PRIVATE_LAYOUT_SET_URL = "@data_handler_private_layout_set_url@"; private static final String _DATA_HANDLER_PRIVATE_USER_SERVLET_MAPPING = "@data_handler_private_user_servlet_mapping@"; private static final String _DATA_HANDLER_PUBLIC_LAYOUT_SET_SECURE_URL = "@data_handler_public_layout_set_secure_url@"; private static final String _DATA_HANDLER_PUBLIC_LAYOUT_SET_URL = "@data_handler_public_layout_set_url@"; private static final String _DATA_HANDLER_PUBLIC_SERVLET_MAPPING = "@data_handler_public_servlet_mapping@"; private static final char[] _DL_REFERENCE_LEGACY_STOP_CHARS = { CharPool.APOSTROPHE, CharPool.CLOSE_BRACKET, CharPool.CLOSE_CURLY_BRACE, CharPool.CLOSE_PARENTHESIS, CharPool.GREATER_THAN, CharPool.LESS_THAN, CharPool.PIPE, CharPool.QUOTE, CharPool.SPACE }; private static final char[] _DL_REFERENCE_STOP_CHARS = { CharPool.APOSTROPHE, CharPool.CLOSE_BRACKET, CharPool.CLOSE_CURLY_BRACE, CharPool.CLOSE_PARENTHESIS, CharPool.GREATER_THAN, CharPool.LESS_THAN, CharPool.PIPE, CharPool.QUESTION, CharPool.QUOTE, CharPool.SPACE }; private static final char[] _LAYOUT_REFERENCE_STOP_CHARS = { CharPool.APOSTROPHE, CharPool.CLOSE_BRACKET, CharPool.CLOSE_CURLY_BRACE, CharPool.CLOSE_PARENTHESIS, CharPool.GREATER_THAN, CharPool.LESS_THAN, CharPool.PIPE, CharPool.QUESTION, CharPool.QUOTE, CharPool.SPACE }; private static final String _PRIVATE_GROUP_SERVLET_MAPPING = PropsUtil.get( PropsKeys.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING) + StringPool.SLASH; private static final String _PRIVATE_USER_SERVLET_MAPPING = PropsUtil.get( PropsKeys.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING) + StringPool.SLASH; private static final String _PUBLIC_GROUP_SERVLET_MAPPING = PropsUtil.get( PropsKeys.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING) + StringPool.SLASH; private static final Log _log = LogFactoryUtil.getLog( DefaultTextExportImportContentProcessor.class); private static final Pattern _exportLinksToLayoutPattern = Pattern.compile( "\\[([\\d]+)@(private(-group|-user)?|public)(@([\\d]+))?\\]"); private static final Pattern _importLinksToLayoutPattern = Pattern.compile( "\\[([\\d]+)@(private(-group|-user)?|public)@([\\d]+)(@([\\d]+))?\\]"); @Reference private CompanyLocalService _companyLocalService; @Reference private DLAppLocalService _dlAppLocalService; @Reference private DLFileEntryLocalService _dlFileEntryLocalService; @Reference private GroupLocalService _groupLocalService; @Reference private Http _http; @Reference private LayoutFriendlyURLLocalService _layoutFriendlyURLLocalService; @Reference private LayoutLocalService _layoutLocalService; @Reference private Portal _portal; }