diff --git a/.gitignore b/.gitignore index 08867be..83836a0 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ filter.xml # Mac .DS_Store -work/ \ No newline at end of file +work/ +migrate_chipCopy.groovy diff --git a/libs/commons-lang3-3.12.0.jar b/libs/commons-lang3-3.12.0.jar new file mode 100644 index 0000000..4d434a2 Binary files /dev/null and b/libs/commons-lang3-3.12.0.jar differ diff --git a/migrate.groovy b/migrate.groovy index 1404d5b..b5815a9 100755 --- a/migrate.groovy +++ b/migrate.groovy @@ -1,19 +1,4 @@ #!/usr/bin/env groovy -/* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program 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 General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - /** * Migration script for migrating legacy content using an AEM Content Package * See: https://github.com/PerficientDigital/AEM-Migration-Script @@ -137,7 +122,7 @@ void processPages(File source, File jcrRoot) { def template = templates[pageData['Template']] assert template : "Template ${pageData['Template']} not found!" - def sourceFile = new File(pageData['Source Path'],source) + def sourceFile = new File(source, pageData['Source Path']) assert sourceFile.exists() : "Source file ${sourceFile} not found!" println "Using template ${pageData['Template']} for ${sourceFile}" @@ -151,11 +136,12 @@ void processPages(File source, File jcrRoot) { template.renderPage(pageData, inXml, outXml, replacements) println 'Creating parent folder...' - def targetFile = new File("${pageData['New Path']}${File.separator}.content.xml",jcrRoot) - targetFile.getParentFile().mkdirs() + def targetFile = new File(jcrRoot.toString(), "${pageData['New Path'].toString()}${File.separator}.content.xml".toString()) + targetFile.parentFile.mkdirs() println "Writing results to $targetFile" targetFile.write(writer.toString(),ENCODING) + migrated++ } else { println 'No action required...' @@ -166,69 +152,95 @@ void processPages(File source, File jcrRoot) { println "${count} pages processed and ${migrated} migrated in ${TimeCategory.minus(new Date(), start)}" } -void processFiles(File source, File jcrRoot){ - - def contentXml = ''' - - - - - - -''' - def tika = new Tika() - def files = new File("work${File.separator}config${File.separator}file-mappings.csv") - def count = 0 - def migrated = 0 - println 'Processing files...' - for (fileData in parseCsv(files.getText(ENCODING), separator: SEPARATOR)) { - def assetRoot = new File(fileData['Target'], jcrRoot) - def sourceFile = new File(fileData['Source'], source) - def mimeType = tika.detect(sourceFile) - +def processFiles(sourceDir, targetDir) { + def sourcePath = sourceDir.toPath() + def targetPath = targetDir.toPath() + + Files.walk(sourcePath).forEach { sourceFile -> + def targetFile = targetPath.resolve(sourcePath.relativize(sourceFile)) + + if (Files.isDirectory(sourceFile)) { + Files.createDirectories(targetFile) + } else { + Files.createDirectories(targetFile.getParent()) + Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING) + } + + println "Copying ${sourceFile} to ${targetFile}" + } +} + +void processFile(File sourceFile, File assetRoot, Tika tika) { + if (sourceFile.isDirectory()) { + def targetDir = new File(assetRoot, sourceFile.name) + targetDir.mkdirs() + + for (file in sourceFile.listFiles()) { + def targetFile = new File(targetDir, file.name) + processFile(file, targetFile, tika) + } + } else { + // Process the file + def mimeType = "application/octet-stream" // Default MIME type for directories + println "Processing Source: ${sourceFile} Target: ${assetRoot}" - + + if (sourceFile.isFile()) { + try { + mimeType = tika.detect(sourceFile) + } catch (FileNotFoundException e) { + // Handle file not found exception + println "File not found: ${sourceFile}" + return + } + } + println 'Creating original.dir XML...' def writer = new StringWriter() def originalDirXml = new MarkupBuilder(writer) originalDirXml.'jcr:root'('xmlns:jcr':'http://www.jcp.org/jcr/1.0','xmlns:nt':'http://www.jcp.org/jcr/nt/1.0','jcr:primaryType':'nt:file'){ 'jcr:content'('jcr:mimeType': mimeType, 'jcr:primaryType': 'nt:resource') } - def originalDir = new File("_jcr_content${File.separator}renditions${File.separator}original.dir${File.separator}.content.xml",assetRoot) - originalDir.getParentFile().mkdirs() - originalDir.newWriter().withWriter { w -> - w << writer.toString() - } - + def originalDirPath = assetRoot.getAbsolutePath() + File.separator + "_jcr_content" + File.separator + "renditions" + File.separator + "original.dir" + def originalDir = new File(originalDirPath) + originalDir.mkdirs() + def contentXmlFile = new File(originalDir, ".content.xml") + println "Writing results to $contentXmlFile" + contentXmlFile.write(writer.toString(), ENCODING) + println 'Copying original file...' - Files.copy(sourceFile.toPath(), new File("_jcr_content${File.separator}renditions${File.separator}original",assetRoot).toPath(),StandardCopyOption.REPLACE_EXISTING,StandardCopyOption.COPY_ATTRIBUTES) - - println 'Writing .content.xml...' - new File('.content.xml',assetRoot).newWriter().withWriter { w -> - w << contentXml - } + def targetFile = new File(assetRoot, sourceFile.name) + Files.copy(sourceFile.toPath(), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING) } } -def configDir = new File(args[0]) -assert configDir.exists() +def newConfigDir = new File(args[0]) +assert newConfigDir.exists() println 'Copying configuration to work dir...' -def workConfig = new File("work${File.separator}config") -if(!workConfig.exists()){ - workConfig.mkdirs() +def workConfigDir = new File("work${File.separator}config") +if (!workConfigDir.exists()) { + workConfigDir.mkdirs() } -configDir.eachFile (FileType.FILES) { file -> - Files.copy(file.toPath(), new File(workConfig.getAbsolutePath()+File.separator+file.getName()).toPath(),StandardCopyOption.REPLACE_EXISTING,StandardCopyOption.COPY_ATTRIBUTES) +newConfigDir.eachFile { file -> + def destFile = new File(workConfigDir.getAbsolutePath() + File.separator + file.name) + def inputFile = new File(file.absolutePath) + def outputFile = new File(destFile.absolutePath) + + outputFile.parentFile.mkdirs() + + inputFile.withInputStream { inputStream -> + outputFile.withOutputStream { outputStream -> + outputStream << inputStream + } + } } + def base = new File('work') -def source = new File('source',base) +def source = new File(base,'source') println "Using source: ${source}" -def target = new File('target',base) -def jcrRoot = new File('jcr_root',target) +def target = new File(base,'target') +def jcrRoot = new File(target, 'jcr_root') println "Using target: ${target}" println 'Clearing target...' @@ -236,54 +248,56 @@ target.deleteDir(); target.mkdir(); processPages(source,jcrRoot) -processFiles(source,jcrRoot) +processFiles(new File("work${File.separator}source"), new File("work${File.separator}target${File.separator}jcr_root${File.separator}content${File.separator}dam")) println 'Updating filter.xml...' -def vlt = new File("META-INF${File.separator}vault",target) +def vlt = new File("work/target/META-INF/vault") vlt.mkdirs() -if(batch?.trim()){ +if (batch?.trim()) { def writer = new StringWriter() def filterXml = new MarkupBuilder(writer) - - def pageFile = new File("work${File.separator}config${File.separator}page-mappings.csv") - - filterXml.'workspaceFilter'('version':'1.0'){ + + def pageFile = new File("work/config/page-mappings.csv") + + filterXml.workspaceFilter(version: '1.0') { for (pageData in parseCsv(pageFile.getText(ENCODING), separator: SEPARATOR)) { - if(batch.equals(pageData['Batch']) && 'Remove' != pageData[0] && 'Missing' != pageData[0]){ - 'filter'('root':pageData['New Path']){ - 'include'('pattern':pageData['New Path']) - 'include'('pattern':"${pageData['New Path']}/jcr:content.*") + if ('Remove' != pageData[0] && 'Missing' != pageData[0]) { + filterXml.filter(root: pageData['New Path']) { + include(pattern: pageData['New Path']) + include(pattern: "${pageData['New Path']}/jcr:content.*") } } } - for (fileData in parseCsv(new File("work${File.separator}config${File.separator}file-mappings.csv").getText(ENCODING), separator: SEPARATOR)) { - if(batch.equals(fileData['Batch']) && 'Remove' != fileData[0] && 'Missing' != fileData[0]){ - 'filter'('root':fileData['Target']){ - 'include'('pattern':fileData['Target']) - 'include'('pattern':"${fileData['Target']}/jcr:content.*") + for (fileData in parseCsv(new File("work/config/file-mappings.csv").getText(ENCODING), separator: SEPARATOR)) { + if ('Remove' != fileData[0] && 'Missing' != fileData[0]) { + filterXml.filter(root: fileData['Target']) { + include(pattern: fileData['Target']) + include(pattern: "${fileData['Target']}/jcr:content.*") } } } } - new File('filter.xml',vlt) << writer.toString() + new File(vlt, 'filter.xml').withWriter { fileWriter -> + fileWriter << writer.toString() + } } else { - def filter = new File('filter.xml',workConfig) + def filter = new File('work/config/filter.xml') assert filter.exists() - Files.copy(filter.toPath(), new File('filter.xml',vlt).toPath(),StandardCopyOption.REPLACE_EXISTING,StandardCopyOption.COPY_ATTRIBUTES) + Files.copy(filter.toPath(), new File(vlt, 'filter.xml').toPath(), StandardCopyOption.REPLACE_EXISTING) } def now = new Date().format("yyyy-MM-dd-HH-mm-ss") println 'Updating properties.xml...' -def propertiesXml = new File('properties.xml',workConfig) +def propertiesXml = new File(workConfigDir, 'properties.xml') assert propertiesXml.exists() -new File('properties.xml',vlt) << propertiesXml.getText().replace('${version}',now).replace('${name}',"migrated-content-${configDir.getName()}") +new File(vlt, 'properties.xml') << propertiesXml.getText().replace('${version}',now).replace('${name}',"migrated-content-${workConfigDir.getName()}") println 'Creating package...' def ant = new AntBuilder() -ant.zip(destfile: "${base.getAbsolutePath()}${File.separator}migrated-content-${configDir.getName()}-${now}.zip", basedir: target) +ant.zip(destfile: "${base.getAbsolutePath()}${File.separator}migrated-content-${workConfigDir.getName()}-${now}.zip", basedir: target) -println "Package saved to: work${File.separator}migrated-content-${configDir.getName()}-${now}.zip" +println "Package saved to: work${File.separator}migrated-content-${workConfigDir.getName()}-${now}.zip" println "Content migrated in ${TimeCategory.minus(new Date(), start)}" -println "Package created successfully!!!" +println "Package created successfully!!!" \ No newline at end of file diff --git a/templates/.commons.groovy.txt b/templates/.commons.groovy.txt new file mode 100644 index 0000000..e10c05a --- /dev/null +++ b/templates/.commons.groovy.txt @@ -0,0 +1,67 @@ +import groovy.xml.slurpersupport.GPathResult +import groovy.xml.MarkupBuilder + + +Map component(String resourceType) { + return component(resourceType, [:]) +} + +Map component(String resourceType, Map properties) { + def p = unstructured() + p['sling:resourceType']=resourceType + properties.each{ k, v -> p[k] = v } + return p +} + +Map pageProperties(Object pageData, GPathResult inXml, String template){ + pageProperties(pageData, inXml, template, null) +} + +Map pageProperties(Object pageData, GPathResult inXml, String template, String resourceType, Map replacements){ + def pageProperties = [:] + pageProperties['jcr:primaryType']='cq:PageContent' + def pageTitle = inXml.metadata.title.toString() + if (pageTitle.isEmpty()) + pageTitle = inXml.title.toString() + pageProperties['jcr:title'] = pageTitle + + pageProperties['cq:contextHubPath'] = '/etc/cloudsettings/default/contexthub' + pageProperties['cq:contextHubSegmentsPath'] = '/etc/segmentation/contexthub' + pageProperties['cq:template'] = template + pageProperties['sling:resourceType'] = resourceType + pageProperties['legacyPath'] = pageData['Source Path'] + pageProperties['migrationBatch'] = pageData['Batch'] + + def description = inXml.metadata.description.toString() + if (description.isEmpty()) + description = inXml.description.toString() + if(description?.trim()) { + pageProperties['jcr:description'] = description + } + return pageProperties +} + +String replace(String source, Map replacements){ + replacements.each{ k, v -> + if(source.contains(k)){ + source = source.replace(k,v) + } + } + return source +} + +Map rootProperties() { + def p = [:] + p['xmlns:cq']='http://www.day.com/jcr/cq/1.0' + p['xmlns:jcr']='http://www.jcp.org/jcr/1.0' + p['xmlns:nt']='http://www.jcp.org/jcr/nt/1.0' + p['xmlns:sling']='http://sling.apache.org/jcr/sling/1.0' + p['jcr:primaryType']='cq:Page' + return p +} + +Map unstructured() { + def p = [:] + p['jcr:primaryType']='nt:unstructured' + return p +} diff --git a/templates/content.groovy b/templates/content.groovy index 4937492..12e10af 100644 --- a/templates/content.groovy +++ b/templates/content.groovy @@ -5,7 +5,7 @@ void renderPage(Object pageData, GPathResult inXml, MarkupBuilder outXml, Map re GroovyShell shell = new GroovyShell() def commons = shell.parse(new File('templates/.commons.groovy').text) - def pageProperties = commons.pageProperties(pageData, inXml, '/conf/sample/settings/wcm/templates/content-page','sample/components/structure/page', replacements) + def pageProperties = commons.pageProperties(pageData, inXml, '/conf/core-components-examples/settings/wcm/templates/content-page','sample/components/structure/page', replacements) outXml.'jcr:root'(commons.rootProperties()) { 'jcr:content'(pageProperties) { diff --git a/templates/content.groovy.txt b/templates/content.groovy.txt new file mode 100644 index 0000000..4937492 --- /dev/null +++ b/templates/content.groovy.txt @@ -0,0 +1,20 @@ +import groovy.xml.slurpersupport.GPathResult +import groovy.xml.MarkupBuilder + +void renderPage(Object pageData, GPathResult inXml, MarkupBuilder outXml, Map replacements){ + + GroovyShell shell = new GroovyShell() + def commons = shell.parse(new File('templates/.commons.groovy').text) + def pageProperties = commons.pageProperties(pageData, inXml, '/conf/sample/settings/wcm/templates/content-page','sample/components/structure/page', replacements) + + outXml.'jcr:root'(commons.rootProperties()) { + 'jcr:content'(pageProperties) { + 'root'(commons.component('wcm/foundation/components/responsivegrid')){ + 'responsivegrid'(commons.component('wcm/foundation/components/responsivegrid')){ + 'title'(commons.component('sample/components/content/title', ['fontSize': 'h1', 'header': inXml.metadata.title.toString()])) + 'text'(commons.component('sample/components/content/text', ['textIsRich': true, 'text': inXml.content.toString()])) + } + } + } + } +} \ No newline at end of file diff --git a/templates/post.groovy b/templates/post.groovy new file mode 100644 index 0000000..f1c1c9a --- /dev/null +++ b/templates/post.groovy @@ -0,0 +1,20 @@ +import groovy.xml.slurpersupport.GPathResult +import groovy.xml.MarkupBuilder + +void renderPage(Object pageData, GPathResult inXml, MarkupBuilder outXml, Map replacements){ + + GroovyShell shell = new GroovyShell() + def commons = shell.parse(new File('templates/.commons.groovy').text) + def pageProperties = commons.pageProperties(pageData, inXml, '/conf/sample/settings/wcm/templates/content-page','/apps/core/wcm/components/structure/page', replacements) + + outXml.'jcr:root'(commons.rootProperties()) { + 'jcr:content'(pageProperties) { + 'root'(commons.component('wcm/foundation/components/responsivegrid')){ + 'responsivegrid'(commons.component('wcm/foundation/components/responsivegrid')){ + 'title'(commons.component('/apps/core/wcm/components/content/title', ['fontSize': 'h1', 'header': inXml.metadata.title.toString()])) + 'text'(commons.component('/apps/core/wcm/components/content/text', ['textIsRich': true, 'text': inXml.content.toString()])) + } + } + } + } +} \ No newline at end of file diff --git a/templates/post.groovy.txt b/templates/post.groovy.txt new file mode 100644 index 0000000..4937492 --- /dev/null +++ b/templates/post.groovy.txt @@ -0,0 +1,20 @@ +import groovy.xml.slurpersupport.GPathResult +import groovy.xml.MarkupBuilder + +void renderPage(Object pageData, GPathResult inXml, MarkupBuilder outXml, Map replacements){ + + GroovyShell shell = new GroovyShell() + def commons = shell.parse(new File('templates/.commons.groovy').text) + def pageProperties = commons.pageProperties(pageData, inXml, '/conf/sample/settings/wcm/templates/content-page','sample/components/structure/page', replacements) + + outXml.'jcr:root'(commons.rootProperties()) { + 'jcr:content'(pageProperties) { + 'root'(commons.component('wcm/foundation/components/responsivegrid')){ + 'responsivegrid'(commons.component('wcm/foundation/components/responsivegrid')){ + 'title'(commons.component('sample/components/content/title', ['fontSize': 'h1', 'header': inXml.metadata.title.toString()])) + 'text'(commons.component('sample/components/content/text', ['textIsRich': true, 'text': inXml.content.toString()])) + } + } + } + } +} \ No newline at end of file