Goal
Using this simple InDesign Server Connector module (deployed on Author or Publish) a user can Create PDFs using InDesign Templates and content entered as Raw Text or Content Fragments
Demo | Package Install | InDesign Template | Github
Connector Design
InDesign Template
Connector Configuration
http://localhost:4502/system/console/configMgr/apps.experienceaem.assets.core.services.impl.IDSServiceImpl
Get Template Structure (for content entry form)
http://localhost:4502/content/dam/experience-aem/weretail-brochure.indd.getTemplateStructure
Content for PDF as Raw Text
Content for PDF as Content Fragment
Solution
1) Create a servlet apps.experienceaem.assets.core.servlets.IDSRequestServlet to handle PDF processing requests. when POSTed with createPDF selector (eg. http://localhost:4502/content/dam/experience-aem/weretail-brochure.indd.createPDF) on a template and content set in request body, logic creates sling job item com/eaem/ids for InDesign Server communication. Requests are processed in order received, one at a time.
package apps.experienceaem.assets.core.servlets;
import com.adobe.cq.dam.cfm.ContentElement;
import com.adobe.cq.dam.cfm.ContentFragment;
import com.adobe.cq.dam.cfm.FragmentData;
import com.adobe.xfa.ut.StringUtils;
import com.day.cq.commons.TidyJSONWriter;
import com.day.cq.commons.jcr.JcrUtil;
import com.google.gson.JsonObject;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.JobManager;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Node;
import javax.jcr.Session;
import javax.servlet.Servlet;
import java.text.SimpleDateFormat;
import java.util.*;
import static apps.experienceaem.assets.core.util.Constants.*;
@Component(
immediate = true,
service = Servlet.class,
property = {
Constants.SERVICE_DESCRIPTION + "=Experience AEM InDesign Server Process Servlet",
"sling.servlet.methods=" + HttpConstants.METHOD_GET,
"sling.servlet.methods=" + HttpConstants.METHOD_POST,
"sling.servlet.resourceTypes=sling/servlet/default",
"sling.servlet.extensions=" + "createPDF"
}
)
public class IDSRequestServlet extends SlingAllMethodsServlet {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final SimpleDateFormat FOLDER_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
@Reference
private JobManager jobManager;
@Reference
private ResourceResolverFactory resolverFactory;
@Override
protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) {
resp.setContentType("application/json");
final Resource resource = req.getResource();
try {
TidyJSONWriter writer = new TidyJSONWriter(resp.getWriter());
writer.object();
if (resource == null) {
writer.key("error").value("No resource found");
writer.endObject();
}
ResourceResolver resolver = resolverFactory.getServiceResourceResolver(INDESIGN_AUTH_INFO);
Session session = resolver.adaptTo(Session.class);
Node jobNode = createJobNode(resolver, resource.getPath());
HashMap<String, Object> jobProps = new HashMap<String, Object>();
jobProps.put(INDESIGN_TEMPLATE_PATH, resource.getPath());
jobProps.put(JOB_PATH, jobNode.getPath());
jobProps.put(CONTENT_JSON, getStructuredContentAsJsonString(req, resolver));
Job job = jobManager.addJob(INDESIGN_SERVER_TOPIC, jobProps);
jobNode.setProperty("jobId", job.getId());
session.save();
writer.key("success").value(jobNode.getPath());
writer.endObject();
} catch (Exception e) {
logger.error("Error scheduling indesign server job for asset : ", resource.getPath());
}
}
@Override
protected void doPost(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) {
doGet(req, resp);
}
private String getStructuredContentAsJsonString(SlingHttpServletRequest req, ResourceResolver resolver) {
JsonObject contentMap = new JsonObject();
JsonObject valueJson = null;
boolean preview = false;
if(!StringUtils.isEmpty(req.getParameter(PARAM_PREVIEW))){
preview = Boolean.valueOf(req.getParameter(PARAM_PREVIEW));
}
int index = 1;
String paramPath, paramType, paramValue;
do {
paramPath = req.getParameter(PARAM_PREFIX + index + PARAM_PATH);
if (StringUtils.isEmpty(paramPath)) {
break;
}
paramPath = paramPath.substring(paramPath.lastIndexOf("/") + 1);
valueJson = new JsonObject();
paramType = req.getParameter(PARAM_PREFIX + index + PARAM_TYPE);
paramType = !StringUtils.isEmpty(paramType) ? paramType : RAW_TEXT;
paramValue = req.getParameter(PARAM_PREFIX + index + PARAM_VALUE);
if(paramType.equals(CF_PATH)){
addValuesFromCF(resolver, contentMap, paramPath, paramValue);
}else{
valueJson.addProperty("type", paramType);
paramValue = !StringUtils.isEmpty(paramValue) ? paramValue : "";
if(paramType.equals(JCR_PATH) && preview){
paramValue = paramValue + PREVIEW_RENDITION;
}
valueJson.addProperty("value", paramValue);
contentMap.add(paramPath, valueJson);
}
index = index + 1;
} while (true);
return contentMap.toString();
}
private void addValuesFromCF(ResourceResolver resolver, JsonObject contentMap, String idPathPrefix, String cfPath){
Resource cfResource = resolver.getResource(cfPath);
if(cfResource == null){
return;
}
JsonObject valueJson = null; String value = null;
ContentFragment cf = cfResource.adaptTo(ContentFragment.class);
Iterator<ContentElement> cfElementsItr = cf.getElements();
while(cfElementsItr.hasNext()) {
ContentElement cfElement = cfElementsItr.next();
if (cfElement == null) {
continue;
}
FragmentData fragValue = getVariationValue(cfElement, MASTER_VARIATION);
if(fragValue == null){
continue;
}
valueJson = new JsonObject();
value = String.valueOf(fragValue.getValue()).trim();
if(value.startsWith("/")){
valueJson.addProperty("type", JCR_PATH);
}else{
valueJson.addProperty("type", RAW_TEXT);
}
valueJson.addProperty("value", removeUnnecessaryChars(value));
contentMap.add(idPathPrefix + cfElement.getName(), valueJson);
}
}
private String removeUnnecessaryChars(String value){
if(StringUtils.isEmpty(value) || value.equals("null")){
return "";
}
if(value.startsWith(P_TAG)){
value = value.substring(P_TAG.length(), value.lastIndexOf(P_END_TAG));
}
return value;
}
private FragmentData getVariationValue(ContentElement cfElement, String variation){
if(StringUtils.isEmpty(variation) || "master".equals(variation)){
return cfElement.getValue();
}
return cfElement.getVariation(variation).getValue();
}
private Node createJobNode(ResourceResolver resolver, String indesignTemplatePath) throws Exception {
Resource reportRes = resolver.getResource(INDESIGN_GEN_REPORTS_PATH);
Node reportNode = null;
if (reportRes == null) {
JcrUtil.createPath(INDESIGN_GEN_REPORTS_PATH, "sling:Folder", "sling:Folder", resolver.adaptTo(Session.class), false);
}
reportNode = JcrUtil.createPath(INDESIGN_GEN_REPORTS_PATH + "/" + FOLDER_FORMAT.format(new Date()),
"sling:Folder", "sling:Folder", resolver.adaptTo(Session.class), true);
Calendar createTime = Calendar.getInstance();
createTime.setTimeInMillis(createTime.getTimeInMillis());
String jobNodeName = UUID.randomUUID().toString();
Node jobNode = reportNode.addNode(jobNodeName.replaceAll("/", "-"), "nt:unstructured");
jobNode.setProperty(INDESIGN_TEMPLATE_PATH, indesignTemplatePath);
jobNode.setProperty("jobStatus", JOB_STATUS_PROCESSING);
jobNode.setProperty("jcr:created", createTime);
return jobNode;
}
}
2) Create a Sling Job Consumer apps.experienceaem.assets.core.listeners.IDSJobConsumer for assembling the necessary SOAP payload (PDF creation scripts and content for IDS template) send a request to InDesign Server running on 8080 (> InDesignServer.com -port 8080)
package apps.experienceaem.assets.core.listeners;
import apps.experienceaem.assets.core.services.IDSService;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.consumer.JobConsumer;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Node;
import java.util.HashMap;
import java.util.Map;
import static apps.experienceaem.assets.core.util.Constants.*;
@Component(
immediate = true,
service = JobConsumer.class,
property = {
"job.topics=" + INDESIGN_SERVER_TOPIC,
}
)
public class IDSJobConsumer implements JobConsumer {
protected final Logger logger = LoggerFactory.getLogger(IDSJobConsumer.class);
@Reference
private ResourceResolverFactory resolverFactory;
@Reference
private IDSService idsService;
public JobResult process(Job job) {
ResourceResolver resolver = null;
String indesignTemplatePath = (String)job.getProperty(INDESIGN_TEMPLATE_PATH);
try {
resolver = resolverFactory.getServiceResourceResolver(INDESIGN_AUTH_INFO);
String exportStructure = (String)job.getProperty(EXPORT_STRUCTURE);
if(StringUtils.isNotEmpty(exportStructure)){
return executeStructureExport(indesignTemplatePath, resolver);
}else{
return executePDFExport(job, resolver);
}
} catch (Exception e) {
logger.error("Failed to process indesign server job for asset {} ", indesignTemplatePath, e);
return JobResult.FAILED;
} finally {
if(resolver != null){
resolver.close();
}
}
}
private String[] getIDSScriptForStructure(){
return new String[] { "/libs/settings/dam/indesign/scripts/json2.jsx/jcr:content",
"/libs/settings/dam/indesign/scripts/cq-lib.jsx/jcr:content",
"/apps/eaem-assets-ids-connector/indesign/scripts/export-structure.jsx/jcr:content"};
}
private JobResult executeStructureExport(String indesignTemplatePath, ResourceResolver resolver )
throws Exception{
Resource indesignRes = resolver.getResource(indesignTemplatePath);
if(indesignRes == null){
logger.error("File not found {} ", indesignTemplatePath);
return JobResult.FAILED;
}
Map<String, String> scriptArs = new HashMap<String, String>();
scriptArs.put("resourcePath", indesignTemplatePath);
String payload = idsService.buildSOAPPayload(resolver, scriptArs, indesignRes, getIDSScriptForStructure());
JsonObject responseObj = idsService.executeInDesignServerRequest(resolver, payload);
JsonElement structureJSON = responseObj.get("structure");
if(structureJSON == null){
JsonElement indesignError = responseObj.get("error");
logger.error("Indesign server job resulted in error for asset {} {} ", indesignTemplatePath, indesignError);
return JobResult.FAILED;
}
Resource metadataRes = indesignRes.getChild("jcr:content/metadata");
metadataRes.adaptTo(Node.class).setProperty(STRUCTURE_JSON, structureJSON.toString());
resolver.commit();
return JobResult.OK;
}
private JobResult executePDFExport(Job job, ResourceResolver resolver) throws Exception{
String indesignTemplatePath = (String)job.getProperty(INDESIGN_TEMPLATE_PATH);
Resource indesignRes = resolver.getResource(indesignTemplatePath);
String jobReportPath = (String)job.getProperty(JOB_PATH);
Resource jobReportRes = resolver.getResource(jobReportPath);
Node jobReportNode = jobReportRes.adaptTo(Node.class);
if(indesignRes == null){
logger.error("File not found {} ", indesignTemplatePath);
jobReportNode.setProperty("jobStatus", "File not found : " + indesignTemplatePath);
resolver.commit();
return JobResult.FAILED;
}
Map<String, String> scriptArs = new HashMap<String, String>();
scriptArs.put("resourcePath", indesignTemplatePath);
scriptArs.put("aemUploadPath", jobReportNode.getPath());
scriptArs.put(CONTENT_JSON, (String)job.getProperty(CONTENT_JSON));
String payload = idsService.buildSOAPPayload(resolver, scriptArs, indesignRes, null);
JsonObject responseObj = idsService.executeInDesignServerRequest(resolver, payload);
JsonElement indesignSuccess = responseObj.get("success");
if(indesignSuccess == null){
JsonElement indesignError = responseObj.get("error");
if(indesignError != null){
logger.error("Indesign server job resulted in error for asset {} {} ", indesignTemplatePath, indesignError.toString());
jobReportNode.setProperty("jobStatus", indesignError.toString());
}else{
jobReportNode.setProperty("jobStatus", "Error processing document, check indesign console log");
}
resolver.commit();
return JobResult.FAILED;
}
resolver.commit();
//idsService.uploadToS3(jobReportRes.getChildren().iterator().next());
jobReportNode.setProperty("jobStatus",JOB_STATUS_SUCCESS);
resolver.commit();
return JobResult.OK;
}
}
3) Create a OSGI service apps.experienceaem.assets.core.services.impl.IDSServiceImpl for configuration and helper methods to create request payload for InDesign Server...
package apps.experienceaem.assets.core.services.impl;
import apps.experienceaem.assets.core.listeners.IDSJobConsumer;
import apps.experienceaem.assets.core.services.IDSService;
import com.day.cq.dam.commons.xml.DocumentBuilderFactoryProvider;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.osgi.services.HttpClientBuilderFactory;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import javax.jcr.Node;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.Arrays;
import java.util.Map;
@Component(service = IDSService.class)
@Designate(ocd = IDSServiceImpl.IDSConfiguration.class)
public class IDSServiceImpl implements IDSService{
private final Logger logger = LoggerFactory.getLogger(IDSJobConsumer.class);
private String[] idsScripts = new String[0];
private String inDesignServerUrl = "";
private String base64EncodedAEMCreds = "";
private String aemHost = "";
private String s3BucketName = "";
private String s3AccessKey = "";
private String s3SecretKey = "";
private String s3Region = "";
@Reference
private transient HttpClientBuilderFactory httpClientBuilderFactory;
private transient CloseableHttpClient httpClient;
@Override
public JsonObject executeInDesignServerRequest(ResourceResolver resolver, String payload) throws Exception{
String response = Request.Post(inDesignServerUrl)
.addHeader("HttpPost", "")
.bodyString(payload, ContentType.APPLICATION_XML)
.execute().returnContent().asString();
logger.debug("InDesign Server Response : " + response);
Document document = getResponseDocument(response);
String resultJSON = document.getElementsByTagName("data").item(0).getFirstChild().getNodeValue();
JsonObject resultObj = new JsonParser().parse(resultJSON).getAsJsonObject();
return resultObj;
}
private Document getResponseDocument(String responseStr) throws Exception{
DocumentBuilderFactoryProvider factoryprovider = new DocumentBuilderFactoryProvider();
DocumentBuilderFactory factory = factoryprovider.createSecureBuilderFactory(false, false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setErrorHandler(new ErrorHandler() {
@Override
public void warning(SAXParseException exception) throws SAXException {
logger.debug("Error parsing SOAP response {}:", exception.getMessage());
}
@Override
public void error(SAXParseException exception) throws SAXException {
logger.debug("Error parsing SOAP response {}:", exception.getMessage());
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
logger.debug("Error parsing SOAP response {}:", exception.getMessage());
}
});
return builder.parse(new InputSource(new StringReader(responseStr)));
}
@Override
public String buildSOAPPayload(ResourceResolver resolver, Map<String, String> scriptArs,
Resource indesignRes, String[] customScripts){
StringBuilder payload = new StringBuilder();
payload.append(getSOAPHeader());
payload.append("<SOAP-ENV:Body><IDSP:RunScript><IDSP:runScriptParameters><IDSP:scriptText><![CDATA[");
payload.append(getGiantScript(resolver, customScripts));
payload.append("]]></IDSP:scriptText>");
payload.append(getScriptInputArgs(scriptArs, indesignRes));
payload.append("</IDSP:runScriptParameters></IDSP:RunScript></SOAP-ENV:Body>");
payload.append(getSOAPFooter());
return payload.toString();
}
private String getScriptInputArgs(Map<String, String> scriptArs, Resource indesignRes){
scriptArs.put("aemHost", aemHost);
scriptArs.put("base64EncodedAEMCreds", base64EncodedAEMCreds);
StringBuilder args = new StringBuilder();
args.append("<IDSP:scriptLanguage>javascript</IDSP:scriptLanguage>");
scriptArs.entrySet().forEach(entry -> {
args.append("<IDSP:scriptArgs>");
args.append("<IDSP:name>").append(entry.getKey()).append("</IDSP:name>");
args.append("<IDSP:value><![CDATA[").append(entry.getValue()).append("]]></IDSP:value>");
args.append("</IDSP:scriptArgs>");
});
return args.toString();
}
private String getSOAPHeader(){
return "<?xml version='1.0' encoding='UTF-8'?>" +
"<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' " +
"xmlns:xsd='http://www.w3.org/2001/XMLSchema' " +
"xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " +
"xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/' " +
"xmlns:IDSP='http://ns.adobe.com/InDesign/soap/'>";
}
private String getSOAPFooter(){
return "</SOAP-ENV:Envelope>";
}
private String getGiantScript(ResourceResolver resolver, String[] customScripts){
StringBuilder script = new StringBuilder();
if(ArrayUtils.isEmpty(customScripts)){
customScripts = idsScripts;
}
Arrays.stream(customScripts).forEach( scriptPath -> {
Resource resource = resolver.getResource(scriptPath);
if(resource == null){
throw new RuntimeException("Error finding script resource : " + scriptPath);
}
Node scriptNode = (Node)resource.adaptTo(Node.class);
try {
script.append(IOUtils.toString(scriptNode.getProperty("jcr:data").getBinary().getStream()));
} catch (Exception e) {
throw new RuntimeException("Error adding script resource : " + scriptPath);
}
});
return script.toString();
}
@Activate
@Modified
protected void activate(final IDSConfiguration config) {
idsScripts = config.inDesignServerScripts();
inDesignServerUrl = config.inDesignServerUrl();
aemHost = config.aemHost();
base64EncodedAEMCreds = config.base64EncodedAEMCreds();
final HttpClientBuilder builder = httpClientBuilderFactory.newBuilder();
final RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000)
.setSocketTimeout(30000).build();
builder.setDefaultRequestConfig(requestConfig);
httpClient = builder.build();
}
@ObjectClassDefinition(name = "Experience AEM InDesign Server Configuration")
public @interface IDSConfiguration {
@AttributeDefinition(
name = "InDesign Scripts in order",
description = "Add the InDesign Server Scripts in execution order",
type = AttributeType.STRING,
cardinality = 5
)
String[] inDesignServerScripts() default {
"/libs/settings/dam/indesign/scripts/json2.jsx/jcr:content",
"/libs/settings/dam/indesign/scripts/cq-lib.jsx/jcr:content",
"/apps/eaem-assets-ids-connector/indesign/scripts/create-pdf.jsx/jcr:content"
};
@AttributeDefinition(
name = "InDesign Server endpoint",
description = "Add the InDesign Server endpoint url eg. http://localhost:8080",
type = AttributeType.STRING
)
String inDesignServerUrl() default "http://localhost:8080";
@AttributeDefinition(
name = "AEM Server",
description = "The AEM Server, InDesign Server should connect to and download the documents/images/fragments",
type = AttributeType.STRING
)
String aemHost() default "localhost:4502";
@AttributeDefinition(
name = "Base64 encoded AEM Creds",
description = "Base 64 encoded AEM Credentials Indesign server should use for download, eg. admin:admin is YWRtaW46YWRtaW4=",
type = AttributeType.STRING
)
String base64EncodedAEMCreds() default "YWRtaW46YWRtaW4=";
}
}
4) Add the script /apps/eaem-assets-ids-connector/indesign/scripts/export-structure.jsx for exporting the ID template structure. This JSON array exported can be used in form dropdowns to enter content required for PDF....
http://localhost:4502/content/dam/experience-aem/weretail-brochure.indd.getTemplateStructure
(function () {
var returnObj = {}, aemHost, base64EncodedAEMCreds, resourcePath, document;
function setParamsFromScriptArgs(){
if (app.scriptArgs.isDefined("base64EncodedAEMCreds")) {
base64EncodedAEMCreds = app.scriptArgs.getValue("base64EncodedAEMCreds");
} else {
throw "AEM host credentials argument is missing";
}
if (app.scriptArgs.isDefined("aemHost")) {
aemHost = app.scriptArgs.getValue("aemHost");
} else {
throw "aemHost argument is missing";
}
if (app.scriptArgs.isDefined("resourcePath")) {
resourcePath = app.scriptArgs.getValue("resourcePath");
} else {
throw "resourcePath argument missing";
}
app.consoleout('base64EncodedAEMCreds --- ' + base64EncodedAEMCreds);
app.consoleout('aemHost --- ' + aemHost);
app.consoleout('resourcePath --- ' + resourcePath);
}
function exportStructureJSON(){
var sourceFolder = getSourceFolder(),
fileName = resourcePath.substring(resourcePath.lastIndexOf ('/') + 1),
xmlFile = new File( sourceFolder.fullName + "/" + fileName + ".xml"),
sourceFile = new File(sourceFolder.fullName + "/" + fileName);
app.consoleout('Fetching resource from AEM: ' + aemHost + resourcePath + ' to ' + sourceFile);
fetchResource (aemHost, base64EncodedAEMCreds, resourcePath, sourceFile);
app.consoleout('Exporting structure for - ' + sourceFile);
var document = app.open(sourceFile);
document.exportFile(ExportFormat.xml, xmlFile);
xmlFile.open('r');
var xmlContent = xmlFile.read();
xmlFile.close();
var structureXML = new XML (xmlContent),
structureJSON = [], parentPath,
eles = structureXML.elements(), element, eleName;
for(var x = 0 ; x < eles.length(); x++){
element = eles.child(x);
if(!parentPath){
parentPath = "/" + element.parent().name() + "/";
}
structureJSON.push(parentPath + element.name());
}
return structureJSON;
}
function getSourceFolder(){
var today = new Date(),
folderName = today.getFullYear() + "-" + today.getMonth() + "-" + today.getDate() + "-" + today.getHours()
+ "-" + today.getMinutes() + "-" + today.getSeconds();
var sourceFolder = new Folder(folderName);
sourceFolder.create();
return sourceFolder;
}
try{
setParamsFromScriptArgs();
returnObj.structure = exportStructureJSON();
}catch(err){
returnObj.error = err;
app.consoleout("Error processing document structure : " + resourcePath + ", error : " + err);
}finally{
if(document){
document.close(SaveOptions.no);
}
}
return JSON.stringify(returnObj);
}());
5) Add the script /apps/eaem-assets-ids-connector/indesign/scripts/create-pdf.jsx executed on InDesign Server to process the content payload received from AEM and create PDF
(function () {
var returnObj = {}, aemHost, base64EncodedAEMCreds, resourcePath, document,
aemUploadPath, contentJson;
function createPDF() {
var sourceFolder = getSourceFolder(),
fileName = resourcePath.substring(resourcePath.lastIndexOf ('/') + 1),
xmlFile = new File( sourceFolder.fullName + "/" + fileName + ".xml"),
sourceFile = new File(sourceFolder.fullName + "/" + fileName);
with (app.pdfExportPreferences) {
viewDocumentAfterExport = false;
pageRange = PageRange.ALL_PAGES;
}
app.consoleout('Fetching resource from AEM: ' + aemHost + resourcePath + ' to ' + sourceFile);
fetchResource (aemHost, base64EncodedAEMCreds, resourcePath, sourceFile);
var pdfOutputFile = new File(sourceFolder.fullName + "/" + fileName + '.pdf');
app.consoleout('Started PDF export - ' + pdfOutputFile);
if(contentJson){
document = app.open(sourceFile);
document.exportFile(ExportFormat.xml, xmlFile);
xmlFile.open('r');
var xmlContent = xmlFile.read();
xmlFile.close();
var structureXML = new XML (xmlContent),
eles = structureXML.elements(), element, eleName, data;
for(var x = 0 ; x < eles.length(); x++){
element = eles.child(x);
eleName = element.name();
data = contentJson[eleName];
if(data){
if(data.type === "JCR_PATH"){
var jcrName = data.value.substring(data.value.lastIndexOf ('/') + 1);
if(jcrName.indexOf("cq5dam.") == 0){
jcrName = data.value.substring(0, data.value.lastIndexOf ('/jcr:content/renditions'));
jcrName = jcrName.substring(jcrName.lastIndexOf ('/') + 1);
}
var jcrFile = new File(sourceFolder.fullName + "/" + jcrName);
app.consoleout('Fetching resource : ' + data.value + ' to ' + jcrFile);
fetchResource (aemHost, base64EncodedAEMCreds, data.value, jcrFile);
structureXML[eleName].@href = "file://./" + jcrName;
}else{
structureXML[eleName] = data.value;
}
}else{
delete structureXML[eleName];
}
}
xmlFile.encoding = "UTF8";
xmlFile.open("w");
xmlContent = structureXML.toString();
xmlFile.write(xmlContent);
xmlFile.close();
document.importXML(xmlFile);
}
document.exportFile(ExportFormat.pdfType, pdfOutputFile);
app.consoleout('Uploading PDF to - ' + aemUploadPath);
putResource(aemHost, base64EncodedAEMCreds, pdfOutputFile, pdfOutputFile.name, 'application/pdf', aemUploadPath);
sourceFolder.remove();
app.consoleout('PDF export complete...');
returnObj.success = "completed";
}
function getSourceFolder(){
var today = new Date(),
folderName = today.getFullYear() + "-" + today.getMonth() + "-" + today.getDate() + "-" + today.getHours()
+ "-" + today.getMinutes() + "-" + today.getSeconds();
var sourceFolder = new Folder(folderName);
sourceFolder.create();
return sourceFolder;
}
function setParamsFromScriptArgs(){
if (app.scriptArgs.isDefined("base64EncodedAEMCreds")) {
base64EncodedAEMCreds = app.scriptArgs.getValue("base64EncodedAEMCreds");
} else {
throw "AEM host credentials argument is missing";
}
if (app.scriptArgs.isDefined("aemHost")) {
aemHost = app.scriptArgs.getValue("aemHost");
} else {
throw "aemHost argument is missing";
}
if (app.scriptArgs.isDefined("resourcePath")) {
resourcePath = app.scriptArgs.getValue("resourcePath");
} else {
throw "resourcePath argument missing";
}
if (app.scriptArgs.isDefined("contentJson")) {
contentJson = JSON.parse(app.scriptArgs.getValue("contentJson"));
app.consoleout('contentJson: ' + app.scriptArgs.getValue("contentJson"));
} else {
throw "contentJson argument missing";
}
aemUploadPath = app.scriptArgs.getValue("aemUploadPath");
app.consoleout('base64EncodedAEMCreds --- ' + base64EncodedAEMCreds);
app.consoleout('aemHost --- ' + aemHost);
app.consoleout('resourcePath --- ' + resourcePath);
app.consoleout('aemUploadPath --- ' + aemUploadPath);
}
try{
setParamsFromScriptArgs();
//setTestParams();
createPDF();
}catch(err){
returnObj.error = err;
app.consoleout("Error processing document : " + resourcePath + ", error : " + err);
}finally{
if(document){
document.close(SaveOptions.no);
}
}
return JSON.stringify(returnObj);
}());
6) Add /apps/eaem-assets-ids-connector/osgiconfig/config/org.apache.sling.event.jobs.QueueConfiguration-eaem-ids with following properties for ordering the com/eaem/ids sling job queue IDS requests...
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="sling:OsgiConfig"
queue.maxparallel="{Long}1"
queue.name="Experience AEM InDesign Server Processing Queue"
queue.priority="MIN"
queue.retries="{Long}0"
queue.retrydelay="{Long}60000"
queue.topics="com/eaem/ids"
queue.type="ORDERED"/>
7) Add repoinit script in /apps/eaem-assets-ids-connector/osgiconfig/config/org.apache.sling.jcr.repoinit.RepositoryInitializer-eaem-ids.config for creating a service user eaem-ids-service and specifying ACLs
scripts=[
"
create service user eaem-ids-service with path system/experience-aem
set ACL for eaem-ids-service
allow jcr:read on /apps
allow jcr:read on /conf
allow jcr:read on /libs
allow jcr:all on /content
allow jcr:read on /var
allow jcr:all on /var/dam
end
"
]
8) Add core bundle to service user mapping in /apps/eaem-assets-ids-connector/osgiconfig/config/org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-eaem-ids.cfg.json
{
"user.mapping": [
"eaem-assets-ids-connector.core:eaem-ids-service=[eaem-ids-service]"
]
}
No comments:
Post a Comment