From f28fc49c741249e2797484fcdf6813d387cb2595 Mon Sep 17 00:00:00 2001 From: "daniel.solis" <2894221+dsolistorres@users.noreply.github.com> Date: Wed, 29 May 2024 08:31:34 -0600 Subject: [PATCH] fix (import): handle URL field for pages imported (#28306) (#28662) ### Proposed Changes * This change will handle the URL field when importing pages to dotCMS * The URL field will be split in folder parent path and asset name. For example the URL "/parent1/parent2/test-page" will be used to import the page to the folder "/parent1/parent2" with the name "test-page" * If the import file contains the "hostFolder" field, it it points to a folder instead of a site, that value will take precedence to set the folder target for the imported page. ### Checklist - [x] Tests --------- Co-authored-by: freddyDOTCMS <147462678+freddyDOTCMS@users.noreply.github.com> Co-authored-by: erickgonzalez --- .../com/dotmarketing/util/ImportUtil.java | 260 ++++++++++++++++-- .../java/com/dotcms/util/ImportUtilTest.java | 120 ++++++++ 2 files changed, 358 insertions(+), 22 deletions(-) diff --git a/dotCMS/src/main/java/com/dotmarketing/util/ImportUtil.java b/dotCMS/src/main/java/com/dotmarketing/util/ImportUtil.java index ad27323b5771..1a108b569272 100644 --- a/dotCMS/src/main/java/com/dotmarketing/util/ImportUtil.java +++ b/dotCMS/src/main/java/com/dotmarketing/util/ImportUtil.java @@ -2,6 +2,9 @@ import com.dotcms.content.elasticsearch.util.ESUtils; import com.dotcms.contenttype.model.field.BinaryField; +import com.dotcms.contenttype.model.field.HostFolderField; +import com.dotcms.contenttype.model.type.BaseContentType; +import com.dotcms.contenttype.model.type.ContentType; import com.dotcms.contenttype.transform.contenttype.StructureTransformer; import com.dotcms.contenttype.transform.field.LegacyFieldTransformer; import com.dotcms.repackage.com.csvreader.CsvReader; @@ -34,6 +37,7 @@ import com.dotmarketing.portlets.contentlet.model.IndexPolicy; import com.dotmarketing.portlets.folders.business.FolderAPI; import com.dotmarketing.portlets.folders.model.Folder; +import com.dotmarketing.portlets.htmlpageasset.business.HTMLPageAssetAPI; import com.dotmarketing.portlets.languagesmanager.business.LanguageAPI; import com.dotmarketing.portlets.languagesmanager.model.Language; import com.dotmarketing.portlets.structure.factories.FieldFactory; @@ -62,6 +66,7 @@ import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; @@ -81,6 +86,7 @@ */ public class ImportUtil { + public static final String LINE_NO = "Line #"; private static PermissionAPI permissionAPI = APILocator.getPermissionAPI(); private final static ContentletAPI conAPI = APILocator.getContentletAPI(); private final static CategoryAPI catAPI = APILocator.getCategoryAPI(); @@ -279,8 +285,8 @@ public static HashMap> importFile(Long importId, String cur } } catch (final DotRuntimeException ex) { String errorMessage = getErrorMsgFromException(user, ex); - if(errorMessage.indexOf("Line #") == -1){ - errorMessage = "Line #" + lineNumber + ": " + errorMessage; + if(errorMessage.indexOf(LINE_NO) == -1){ + errorMessage = LINE_NO + lineNumber + ": " + errorMessage; } results.get("errors").add(errorMessage); errors++; @@ -687,10 +693,11 @@ private static void importLine ( String[] line, String currentHostId, Structure HashMap values = new HashMap<>(); Set categories = new HashSet<>(); Pair siteAndFolder = null; + Pair urlValue = null; for ( Integer column : headers.keySet() ) { Field field = headers.get( column ); if ( line.length < column ) { - throw new DotRuntimeException("Line #" + lineNumber + "doesn't contain all the required columns."); + throw new DotRuntimeException(LINE_NO + lineNumber + "doesn't contain all the required columns."); } String value = line[column]; Object valueObj = value; @@ -707,7 +714,7 @@ private static void importLine ( String[] line, String currentHostId, Structure for(String catKey : categoryKeys) { Category cat = catAPI.findByKey(catKey.trim(), user, false); if(cat == null) - throw new DotRuntimeException("Line #" + lineNumber + " contains errors. Column: '" + field.getVelocityVarName() + + throw new DotRuntimeException(LINE_NO + lineNumber + " contains errors. Column: '" + field.getVelocityVarName() + "', value: '" + value + "', invalid category key found. Line will be ignored."); categories.add(cat); } @@ -746,14 +753,14 @@ private static void importLine ( String[] line, String currentHostId, Structure } else if (field.getFieldType().equals(Field.FieldType.HOST_OR_FOLDER.toString())) { siteAndFolder = getSiteAndFolderFromIdOrName(value, user); if (siteAndFolder == null) { - throw new DotRuntimeException("Line #" + lineNumber + " contains errors. Column: '" + field.getVelocityVarName() + + throw new DotRuntimeException(LINE_NO + lineNumber + " contains errors. Column: '" + field.getVelocityVarName() + "', value: '" + value + "', invalid site/folder inode found. Line will be ignored."); } else { valueObj = value; } } else if (new LegacyFieldTransformer(field).from().typeName().equals(BinaryField.class.getName())){ if(UtilMethods.isSet(value) && !APILocator.getTempFileAPI().validUrl(value)){ - throw new DotRuntimeException("Line #" + lineNumber + " contains errors. URL is malformed or Response is not 200"); + throw new DotRuntimeException(LINE_NO + lineNumber + " contains errors. URL is malformed or Response is not 200"); } }else if(field.getFieldType().equals(Field.FieldType.IMAGE.toString()) || field.getFieldType().equals(Field.FieldType.FILE.toString())) { String filePath = value; @@ -804,6 +811,39 @@ private static void importLine ( String[] line, String currentHostId, Structure bean.setLanguageId(language); uniqueFieldBeans.add(bean); } + + if (valueObj != null + && field.getVelocityVarName().equals(HTMLPageAssetAPI.URL_FIELD)) { + final String uri = StringUtils.stripEnd( + StringUtils.strip(valueObj.toString()), StringPool.FORWARD_SLASH); + final StringBuilder uriBuilder = new StringBuilder(); + if (!uri.startsWith(StringPool.FORWARD_SLASH)) { + uriBuilder.append(StringPool.FORWARD_SLASH); + } + uriBuilder.append(uri); + urlValue = Pair.of(column, uriBuilder.toString()); + } + } + + // Check if the content type is HTMLPage and the URL field is set + final Pair, String> pathAndAssetNameForURL = + urlValue != null ? + checkURLFieldForHTMLPage(contentType, + urlValue.getRight(), siteAndFolder, user) : + null; + if (pathAndAssetNameForURL != null) { + final String assetNameForURL = pathAndAssetNameForURL.getRight(); + if (UtilMethods.isSet(assetNameForURL)) { + values.put(urlValue.getLeft(), assetNameForURL); + final Pair parentPathForURL = pathAndAssetNameForURL.getLeft(); + if (parentPathForURL == null) { + throw new DotRuntimeException(LINE_NO + lineNumber + " contains errors. Column: '" + + HTMLPageAssetAPI.URL_FIELD + "', value: '" + urlValue.getRight() + + "', invalid parent folder for URL. Line will be ignored."); + } else { + siteAndFolder = parentPathForURL; + } + } } //Find the relationships and their related contents @@ -875,26 +915,49 @@ private static void importLine ( String[] line, String currentHostId, Structure if ( UtilMethods.isSet( identifier ) ) { buffy.append(" +identifier:").append(identifier); - List contentsSearch = conAPI.searchIndex( buffy.toString(), 0, -1, null, user, true ); + List contentsSearch = conAPI.searchIndex(buffy.toString(), 0, -1, null, user, true); - if ( (contentsSearch == null) || (contentsSearch.size() == 0) ) { + if ((contentsSearch == null) || (contentsSearch.size() == 0)) { - Logger.warn(ImportUtil.class, "Line #" + lineNumber + ": Content not found with identifier " + identifier + "\n"); - throw new DotRuntimeException( "Line #" + lineNumber + ": Content not found with identifier " + identifier + "\n" ); + Logger.warn(ImportUtil.class, LINE_NO + lineNumber + ": Content not found with identifier " + identifier + "\n"); + throw new DotRuntimeException(LINE_NO + lineNumber + ": Content not found with identifier " + identifier + "\n"); } else { Contentlet contentlet; - for ( ContentletSearch contentSearch : contentsSearch ) { - contentlet = conAPI.find( contentSearch.getInode(), user, true ); - if ( (contentlet != null) && InodeUtils.isSet( contentlet.getInode() ) ) { - contentlets.add( contentlet ); + for (ContentletSearch contentSearch : contentsSearch) { + contentlet = conAPI.find(contentSearch.getInode(), user, true); + if ((contentlet != null) && InodeUtils.isSet(contentlet.getInode())) { + contentlets.add(contentlet); } else { - Logger.warn(ImportUtil.class, "Line #" + lineNumber + ": Content not found with identifier " + identifier + "\n"); - throw new DotRuntimeException( "Line #" + lineNumber + ": Content not found with identifier " + identifier + "\n" ); + Logger.warn(ImportUtil.class, LINE_NO + lineNumber + ": Content not found with identifier " + identifier + "\n"); + throw new DotRuntimeException(LINE_NO + lineNumber + ": Content not found with identifier " + identifier + "\n"); + } + } + } + } else if (pathAndAssetNameForURL != null && keyFields.isEmpty()) { + // For HTMLPageAsset, we need to search by URL to math existing pages + buffy.append( " +languageId:" ).append( language ); + buffy.append(addSiteAndFolderToESQuery(siteAndFolder, null)); + buffy.append(" +").append(contentType.getVelocityVarName()).append(StringPool.PERIOD) + .append(HTMLPageAssetAPI.URL_FIELD).append(StringPool.COLON) + .append(pathAndAssetNameForURL.getRight()); + List contentsSearch = conAPI.searchIndex( + buffy.toString(), 0, -1, null, user, true); + if (contentsSearch != null && !contentsSearch.isEmpty()) { + Contentlet contentlet; + for (ContentletSearch contentSearch : contentsSearch) { + contentlet = conAPI.find(contentSearch.getInode(), user, true); + if ((contentlet != null) && InodeUtils.isSet(contentlet.getInode())) { + contentlets.add(contentlet); + } else { + Logger.warn(ImportUtil.class, LINE_NO + lineNumber + ": Content not found with URL " + urlValue.getRight() + "\n"); + throw new DotRuntimeException(LINE_NO + lineNumber + ": Content not found with URL " + urlValue.getRight() + "\n"); } } } } else if (keyFields.size() > 0) { + boolean appendSiteToQuery = false; + String siteFieldValue = null; for (Integer column : keyFields.keySet()) { Field field = keyFields.get(column); Object value = values.get(column); @@ -918,10 +981,18 @@ private static void importLine ( String[] line, String currentHostId, Structure text = value.toString(); } if(!UtilMethods.isSet(text)){ - throw new DotRuntimeException("Line #" + lineNumber + " key field " + field.getVelocityVarName() + " is required since it was defined as a key\n"); + throw new DotRuntimeException(LINE_NO + lineNumber + " key field " + field.getVelocityVarName() + " is required since it was defined as a key\n"); }else{ - if(field.getFieldType().equals(Field.FieldType.HOST_OR_FOLDER.toString())) { - buffy.append(addSiteAndFolderToESQuery(siteAndFolder, text)); + if (field.getVelocityVarName().equals(HTMLPageAssetAPI.URL_FIELD) + && pathAndAssetNameForURL != null) { + appendSiteToQuery = true; + buffy.append(" +").append(contentType.getVelocityVarName()).append(StringPool.PERIOD) + .append(HTMLPageAssetAPI.URL_FIELD).append(StringPool.COLON) + .append(pathAndAssetNameForURL.getRight()); + value = getURLFromFolderAndAssetName(pathAndAssetNameForURL); + } else if(new LegacyFieldTransformer(field).from() instanceof HostFolderField) { + appendSiteToQuery = true; + siteFieldValue = text; } else { buffy.append(" +").append(contentType.getVelocityVarName()).append(StringPool.PERIOD) .append(field.getVelocityVarName()).append(field.isUnique()? ESUtils.SHA_256: "_dotraw") @@ -955,6 +1026,10 @@ private static void importLine ( String[] line, String currentHostId, Structure } + if (appendSiteToQuery) { + buffy.append(addSiteAndFolderToESQuery(siteAndFolder, siteFieldValue)); + } + String noLanguageQuery = buffy.toString(); if ( !isMultilingual && !UtilMethods.isSet( identifier ) ) { buffy.append( " +languageId:" ).append( language ); @@ -1010,6 +1085,11 @@ private static void importLine ( String[] line, String currentHostId, Structure break; } }else{ + if (field.getVelocityVarName().equals(HTMLPageAssetAPI.URL_FIELD) + && pathAndAssetNameForURL != null) { + value = getURLFromFolderAndAssetName(pathAndAssetNameForURL); + conValue = getURLFromContentId(con.getIdentifier()); + } Logger.debug(ImportUtil.class,"conValue: " + conValue.toString()); Logger.debug(ImportUtil.class,"Value: " + value.toString()); if(conValue.toString().equalsIgnoreCase(value.toString())){ @@ -1053,6 +1133,11 @@ can manage multilingual inserts for already stored records but not for the case //Ok, comparing our keys with the contentlets we found trying to see if there is a contentlet to update with the specified keys Object conValue = conAPI.getFieldValue( contentlet, field ); + if (field.getVelocityVarName().equals(HTMLPageAssetAPI.URL_FIELD) + && pathAndAssetNameForURL != null) { + value = getURLFromFolderAndAssetName(pathAndAssetNameForURL); + conValue = getURLFromContentId(contentlet.getIdentifier()); + } if ( !conValue.equals( value ) ) { match = false; } @@ -1289,7 +1374,7 @@ can manage multilingual inserts for already stored records but not for the case new ArrayList<>(categories)); } } catch (DotContentletValidationException ex) { - StringBuffer sb = new StringBuffer("Line #" + lineNumber + " contains errors\n"); + StringBuffer sb = new StringBuffer(LINE_NO + lineNumber + " contains errors\n"); HashMap> errors = (HashMap>) ex.getNotValidFields(); Set keys = errors.keySet(); for (String key : keys) { @@ -1555,7 +1640,7 @@ private static String addSiteAndFolderToESQuery( final Folder folder = siteAndFolder.getRight(); siteAndFolderQuery.append(" +conFolder:").append(folder.getInode()); } - } else { + } else if (UtilMethods.isSet(fieldValue)) { siteAndFolderQuery.append(" +(conhost:").append(fieldValue).append(" conFolder:") .append(fieldValue).append(")"); } @@ -1592,6 +1677,137 @@ private static void setSiteAndFolder(final User user, } } + /** + * Check if the URL field for an HTMLPage content type is set correctly + * @param contentType the content type + * @param urlValue the URL field value + * @param siteAndFolderFromLine the site and folder from the site field in the import line + * it can be null if the site field is not set + * @param user the current user + */ + private static Pair, String> checkURLFieldForHTMLPage( + final Structure contentType, final String urlValue, + final Pair siteAndFolderFromLine, final User user) + throws DotDataException, DotSecurityException { + + final ContentType targetContentType = new StructureTransformer(contentType).from(); + if (UtilMethods.isSet(urlValue) && + BaseContentType.HTMLPAGE.getType() == targetContentType.baseType().getType()) { + + // Check if the URL field value includes parent folder and asset name + String assetName = urlValue; + String parentPath = null; + if (StringUtils.lastIndexOf(urlValue, StringPool.FORWARD_SLASH) >= 0) { + assetName = StringUtils.substringAfterLast(urlValue, StringPool.FORWARD_SLASH); + parentPath = StringUtils.substringBeforeLast(urlValue, StringPool.FORWARD_SLASH); + } + + // If there is parent path and also a site without folder was already read + // from the site field in the import line, check if the parent folder exists and return it + // If there is a parent path and a site was not read from the site field, + // check if the parent folder exists in the default site instead + final Host site = siteAndFolderFromLine == null ? + hostAPI.findDefaultHost(user, false) : + siteAndFolderFromLine.getLeft(); + final Folder folder = siteAndFolderFromLine == null ? + folderAPI.findSystemFolder() : siteAndFolderFromLine.getRight(); + final Pair siteAndFolder = ImmutablePair.of(site, folder); + + if (UtilMethods.isSet(parentPath)) { + return ImmutablePair.of( + getHostAndFolderFromParentPathOrSiteField( + siteAndFolder, user, parentPath), + assetName); + } + + // If there is no parent path, return the site and folder from the site field + return ImmutablePair.of(siteAndFolder, assetName); + } + + return null; + } + + /** + * Get the host and folder from given parent path. + * Returns the host and folder from the site field in the import line if already set + * @param siteAndFolder the site and folder from the site field in the import line + * @param user the current user + * @param parentPath the parent path for the URL field value + * @return the host and folder from the parent path or the site field + */ + private static Pair getHostAndFolderFromParentPathOrSiteField( + final Pair siteAndFolder, + final User user, final String parentPath) + throws DotDataException, DotSecurityException { + + final Host site = siteAndFolder.getLeft(); + final Folder siteFolder = siteAndFolder.getRight(); + final Folder parentFolder = folderAPI.findFolderByPath( + parentPath, site, user, false); + if (isFolderSet(parentFolder)) { + if ((siteFolder == null || siteFolder.isSystemFolder())) { + return ImmutablePair.of(site, parentFolder); + } else { + if (isFolderSet(siteFolder) && !parentFolder.getInode().equals(siteFolder.getInode())) { + Logger.warn(ImportUtil.class, String.format( + "Folder from site field %s doesn't match parent folder for URL: %s", + siteFolder.getPath(), parentFolder.getPath())); + } + return siteAndFolder; + } + } else { + Logger.warn(ImportUtil.class, String.format( + "Parent folder not found for URL field value: %s", parentPath)); + return null; + } + + } + + /** + * Get the URL from the folder path and asset name + * @param folderAndAssetName the folder and asset name pair + * @return the URL for the given folder path and asset name + */ + private static String getURLFromFolderAndAssetName( + final Pair,String> folderAndAssetName) { + final Pair siteAndFolder = folderAndAssetName.getLeft(); + final String assetName = folderAndAssetName.getRight(); + final StringBuilder url = new StringBuilder(); + if (siteAndFolder != null) { + final Folder folder = siteAndFolder.getRight(); + if (isFolderSet(folder)) { + url.append(folder.getPath()); + if (UtilMethods.isSet(folder.getPath()) + && !folder.getPath().endsWith(StringPool.FORWARD_SLASH)) { + url.append(StringPool.FORWARD_SLASH); + } + } + } + url.append(assetName); + return url.toString(); + } + + /** + * Get the URL from the content identifier + * @param contentId the content identifier + * @return the URL for the given content identifier + */ + private static String getURLFromContentId(final String contentId) { + StringBuilder url = new StringBuilder(); + if (contentId != null ) { + try { + final Identifier identifier = APILocator.getIdentifierAPI().find(contentId); + if (UtilMethods.isSet(identifier) && UtilMethods.isSet(identifier.getId())) { + url.append(identifier.getURI()); + } + } catch (DotDataException e) { + Logger.error(ImportUtil.class, "Unable to get Identifier with id [" + + contentId + "]. Could not get the url", e ); + } + } + return url.toString(); + } + private static Contentlet runWorkflowIfCould(final User user, final List contentTypePermissions, final List categories, final Contentlet contentlet, final ContentletRelationships contentletRelationships) throws DotDataException, DotSecurityException { @@ -1792,7 +2008,7 @@ private static Object validateDateTypes(final int lineNumber, final Field field, valueObj = parseExcelDate(value); } catch (ParseException e) { throw new DotRuntimeException( - "Line #" + lineNumber + " contains errors, Column: " + field + LINE_NO + lineNumber + " contains errors, Column: " + field .getVelocityVarName() + ", value: " + value + ", couldn't be parsed as any of the following supported formats: " diff --git a/dotcms-integration/src/test/java/com/dotcms/util/ImportUtilTest.java b/dotcms-integration/src/test/java/com/dotcms/util/ImportUtilTest.java index de945391b743..a1d26b46e984 100644 --- a/dotcms-integration/src/test/java/com/dotcms/util/ImportUtilTest.java +++ b/dotcms-integration/src/test/java/com/dotcms/util/ImportUtilTest.java @@ -1,5 +1,6 @@ package com.dotcms.util; +import com.dotcms.LicenseTestUtil; import com.dotcms.contenttype.business.ContentTypeAPIImpl; import com.dotcms.contenttype.business.FieldAPI; import com.dotcms.contenttype.model.field.BinaryField; @@ -11,12 +12,15 @@ import com.dotcms.contenttype.model.field.ImmutableTextField; import com.dotcms.contenttype.model.field.RelationshipField; import com.dotcms.contenttype.model.field.TextField; +import com.dotcms.contenttype.model.type.BaseContentType; import com.dotcms.contenttype.model.type.ContentType; import com.dotcms.contenttype.transform.contenttype.StructureTransformer; import com.dotcms.datagen.ContentTypeDataGen; import com.dotcms.datagen.ContentletDataGen; import com.dotcms.datagen.FieldDataGen; import com.dotcms.datagen.FolderDataGen; +import com.dotcms.datagen.SiteDataGen; +import com.dotcms.datagen.TemplateDataGen; import com.dotcms.datagen.TestDataUtils; import com.dotcms.datagen.TestUserUtils; import com.dotcms.mock.request.MockAttributeRequest; @@ -43,12 +47,15 @@ import com.dotmarketing.portlets.contentlet.model.Contentlet; import com.dotmarketing.portlets.contentlet.model.IndexPolicy; import com.dotmarketing.portlets.folders.model.Folder; +import com.dotmarketing.portlets.htmlpageasset.business.HTMLPageAssetAPI; +import com.dotmarketing.portlets.htmlpageasset.model.HTMLPageAsset; import com.dotmarketing.portlets.languagesmanager.model.Language; import com.dotmarketing.portlets.structure.factories.FieldFactory; import com.dotmarketing.portlets.structure.factories.StructureFactory; import com.dotmarketing.portlets.structure.model.Field; import com.dotmarketing.portlets.structure.model.Relationship; import com.dotmarketing.portlets.structure.model.Structure; +import com.dotmarketing.portlets.templates.model.Template; import com.dotmarketing.portlets.workflows.actionlet.PublishContentActionlet; import com.dotmarketing.portlets.workflows.actionlet.SaveContentActionlet; import com.dotmarketing.portlets.workflows.actionlet.SaveContentAsDraftActionlet; @@ -2051,6 +2058,119 @@ public void importFile_success_when_lineContainsLegacyFolderInode() } } + /** + * Method to test: {@link ImportUtil#importFile} + * Case: Import file including a page with URL field set to a valid URL + * @throws DotSecurityException when there is a security exception + * @throws DotDataException when there is a dotCMS data exception + * @throws IOException when there is an IO exception + */ + @Test + public void importFile_PagesWithURL_success() + throws DotSecurityException, DotDataException, IOException { + + Host site = null; + Template template = null; + ContentType pageType = null; + Folder parentFolder = null; + try { + site = new SiteDataGen().nextPersisted(); + + // create test template + template = new TemplateDataGen() + .site(APILocator.systemHost()) + .nextPersisted(); + final String templateId = template.getIdentifier(); + + long time = System.currentTimeMillis(); + final String pageTypeName = "TestPageTypeWithURL_" + time; + final String pageTypeVarName = "velocityVarNameTestPageTypeWithURL_" + time; + + // create test page type + pageType = new ContentTypeDataGen() + .baseContentType(BaseContentType.HTMLPAGE) + .host(APILocator.systemHost()) + .name(pageTypeName) + .velocityVarName(pageTypeVarName) + .nextPersisted(); + + // create test folder + final String parentFolderName = "test-base-folder_" + time; + parentFolder = new FolderDataGen() + .name(parentFolderName) + .site(site) + .nextPersisted(); + final Folder subFolder = new FolderDataGen() + .name("test-sub-folder") + .parent(parentFolder) + .nextPersisted(); + + final String testPageURL = StringPool.FORWARD_SLASH + + parentFolderName + "/test-sub-folder/test-page-1"; + final Reader reader = createTempFile( + HTMLPageAssetAPI.TITLE_FIELD + + "," + HTMLPageAssetAPI.URL_FIELD + + ",hostFolder" + + "," + HTMLPageAssetAPI.TEMPLATE_FIELD + + "," + HTMLPageAssetAPI.FRIENDLY_NAME_FIELD + + "," + HTMLPageAssetAPI.SORT_ORDER_FIELD + + "," + HTMLPageAssetAPI.CACHE_TTL_FIELD + + "\r\n" + + "Test Page 1," + testPageURL + "," + + site.getIdentifier() + "," + templateId + + ",Test Page 1,0,300\r\n"); + + final CsvReader csvreader = new CsvReader(reader); + csvreader.setSafetySwitch(false); + + final String[] csvHeaders = csvreader.getHeaders(); + + final Map> results = ImportUtil + .importFile(0L, defaultSite.getInode(), pageType.inode(), + new String[]{}, false, false, + user, defaultLanguage.getId(), csvHeaders, csvreader, + -1, -1, + reader, null, getHttpRequest()); + + Logger.info(ImportUtilTest.class, "page errors: " + results.get("errors")); + validate(results, false, false, true); + + final List savedData = contentletAPI + .findByStructure(pageType.inode(), user, false, 0, 0); + assertNotNull(savedData); + assertEquals(1, savedData.size()); + + final Contentlet contentlet = savedData.get(0); + final Identifier identifier = APILocator.getIdentifierAPI().find(contentlet); + assertNotNull(identifier); + assertEquals(testPageURL, identifier.getURI()); + + } finally { + try { + if (parentFolder != null) { + FolderDataGen.remove(parentFolder); + } + + if (pageType != null) { + contentTypeApi.delete(pageType); + } + + if (template != null) { + TemplateDataGen.remove(template); + } + + if (null != site) { + APILocator.getHostAPI().archive(site, APILocator.systemUser(), false); + APILocator.getHostAPI().delete(site, APILocator.systemUser(), false); + } + + } catch (Exception e) { + Logger.error("Error deleting test page type", e); + } + + } + } + /** * * @param relationship