com.adobe.aem.importer.impl.DocImporterImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.adobe.aem.importer.impl.DocImporterImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Licensed under the Apache License 2.0.
 * http://www.apache.org/licenses/LICENSE-2.0
 ******************************************************************************/

package com.adobe.aem.importer.impl;

import com.adobe.aem.importer.DocImporter;
import com.adobe.aem.importer.xml.FilterXmlBuilder;
import com.adobe.aem.importer.xml.RejectingEntityResolver;
import com.day.cq.commons.jcr.JcrUtil;
import net.sf.saxon.Configuration;
import net.sf.saxon.jaxp.TransformerImpl;
import net.sf.saxon.TransformerFactoryImpl;
import net.sf.saxon.lib.UnparsedTextURIResolver;
import org.apache.commons.io.IOUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.vault.fs.api.ImportMode;
import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
import org.apache.jackrabbit.vault.fs.io.Importer;
import org.apache.jackrabbit.vault.fs.io.JcrArchive;
import org.apache.sling.jcr.api.SlingRepository;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.net.URI;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

@Component
@org.apache.felix.scr.annotations.Properties({
        @Property(name = Constants.SERVICE_DESCRIPTION, value = "AEM Content Importer"),
        @Property(name = Constants.SERVICE_VENDOR, value = "Adobe") })
@Service(value = DocImporter.class)
public class DocImporterImpl implements DocImporter {
    private static final Logger log = LoggerFactory.getLogger(DocImporterImpl.class);
    private Session session;

    private String xsltFilePath;
    private String masterFileName;
    private String graphicsFolderName;
    private String targetPath;

    private Node importRootNode;
    private Node sourceFolderNode;
    private Properties properties;

    @Reference
    private SlingRepository slingRepository;

    @Activate
    protected final void activate(final Map<String, String> properties) throws Exception {
    }

    @Deactivate
    protected final void deactivate(final Map<String, String> properties) {
    }

    private boolean initImport(String importRootPath) {
        log.info("importRootPath:" + importRootPath);
        try {
            this.session = slingRepository.loginAdministrative(null);
            log.info("this.session:" + this.session);

            if (!this.session.nodeExists(importRootPath)) {
                log.info("importRootPath " + importRootPath + " not found!");
                return false;
            }
            this.importRootNode = this.session.getNode(importRootPath);
            log.info("this.importRootNode: " + this.importRootNode);

            if (!this.importRootNode.hasNode(DocImporter.CONFIG_FILE_NAME)) {
                log.info("config file " + DocImporter.CONFIG_FILE_NAME + " not found!");
                return false;
            }

            this.properties = new Properties();
            this.properties
                    .loadFromXML(JcrUtils.readFile(this.importRootNode.getNode(DocImporter.CONFIG_FILE_NAME)));
            log.info("this.properties: " + Arrays.deepToString(this.properties.values().toArray()));

            String sourceFolder = properties.getProperty(DocImporter.CONFIG_PARAM_SOURCE_FOLDER,
                    DocImporter.DEFAULT_SOURCE_FOLDER);
            log.info("sourceFolder: " + sourceFolder);

            if (!this.importRootNode.hasNode(sourceFolder)) {
                log.info("sourceFolder " + sourceFolder + " not found!");
                return false;
            }
            this.sourceFolderNode = importRootNode.getNode(sourceFolder);
            log.info("this.sourceFolderNode: " + this.sourceFolderNode);

            this.masterFileName = properties.getProperty(DocImporter.CONFIG_PARAM_MASTER_FILE,
                    DocImporter.DEFAULT_MASTER_FILE);
            log.info("this.masterFileName: " + this.masterFileName);

            if (!this.sourceFolderNode.hasNode(this.masterFileName)) {
                log.info("masterFileName " + this.masterFileName + " not found!");
                return false;
            }

            this.graphicsFolderName = properties.getProperty(DocImporter.CONFIG_PARAM_GRAPHICS_FOLDER,
                    DocImporter.DEFAULT_GRAPHICS_FOLDER);
            log.info("this.graphicsFolderName: " + this.graphicsFolderName);

            this.targetPath = properties.getProperty(DocImporter.CONFIG_PARAM_TARGET_PATH,
                    DocImporter.DEFAULT_TARGET_PATH);
            log.info("this.targetPath: " + this.targetPath);

            String sourceFormat = this.properties.getProperty(DocImporter.CONFIG_PARAM_SOURCE_FORMAT,
                    DocImporter.DEFAULT_SOURCE_FORMAT);
            log.info("sourceFormat: " + sourceFormat);

            if (sourceFormat.equalsIgnoreCase(DocImporter.SOURCE_FORMAT_DOCBOOK)) {
                this.xsltFilePath = DocImporter.DOCBOOK_XSLT_PATH;
            } else {
                this.xsltFilePath = DocImporter.DITA_XSLT_PATH;
            }
            log.info("this.xsltFilePath: " + this.xsltFilePath);

        } catch (RepositoryException e) {
            log.error(e.toString());
        } catch (IOException e) {
            log.error(e.toString());
        }
        return true;
    }

    public void doImport(String importRootPath) {
        try {
            if (!initImport(importRootPath)) {
                log.info("initImport failed!");
                return;
            }

            Node xsltNode = this.session.getNode(xsltFilePath);
            log.info("xsltNode: " + xsltNode);

            XMLReader xmlReader = XMLReaderFactory.createXMLReader();
            log.info("xmlReader: " + xmlReader);

            xmlReader.setEntityResolver(new RejectingEntityResolver());

            URIResolver uriResolver = new DocImporterURIResolver(xsltNode, this.sourceFolderNode, xmlReader);
            log.info("uriResolver: " + uriResolver);

            TransformerFactoryImpl transformerFactoryImpl = new TransformerFactoryImpl();
            log.info("transformerFactoryImpl: " + transformerFactoryImpl);

            transformerFactoryImpl.setURIResolver(uriResolver);

            Transformer transformer = transformerFactoryImpl
                    .newTransformer(new StreamSource(JcrUtils.readFile(xsltNode)));

            TransformerImpl transformerImpl = (TransformerImpl) transformer;
            transformerImpl.getUnderlyingController()
                    .setUnparsedTextURIResolver(new DocImporterUnparsedTextURIResolver(this.sourceFolderNode));
            log.info("transformer: " + transformer);

            for (Entry<Object, Object> entry : properties.entrySet()) {
                transformer.setParameter(entry.getKey().toString(), entry.getValue());
                log.info("transformer.setParameter: " + entry.getKey().toString() + " = " + entry.getValue());
            }
            transformer.setParameter("xsltFilePath", this.xsltFilePath);
            log.info("transformer.setParameter: xsltFilePath = " + this.xsltFilePath);

            ByteArrayOutputStream output = new ByteArrayOutputStream();
            transformer
                    .transform(
                            new SAXSource(xmlReader,
                                    new InputSource(
                                            JcrUtils.readFile(this.sourceFolderNode.getNode(masterFileName)))),
                            new StreamResult(output));
            InputStream result = new ByteArrayInputStream(output.toByteArray());
            log.info("result: " + result);

            if (this.session.itemExists(DocImporter.CONTENT_PACKAGE_PATH)) {
                this.session.removeItem(DocImporter.CONTENT_PACKAGE_PATH);
                this.session.save();
                log.info("old package removed");
            }
            Node contentPackageNode = JcrUtils.getOrCreateByPath(DocImporter.CONTENT_PACKAGE_PATH, "nt:folder",
                    "nt:folder", this.session, true);
            this.session.getWorkspace().copy(DocImporter.CONTENT_PACKAGE_TEMPLATE_PATH + "/META-INF",
                    contentPackageNode.getPath() + "/META-INF");
            log.info("new package created");

            Node vaultNode = contentPackageNode.getNode("META-INF/vault");
            Node contentXMLNode = JcrUtil.createPath(contentPackageNode.getPath() + "/jcr_root" + targetPath,
                    "nt:folder", "nt:folder", this.session, true);
            JcrUtils.putFile(contentXMLNode, ".content.xml", "application/xml", result);
            log.info("content.xml written");

            if (this.graphicsFolderName != null && this.sourceFolderNode.hasNode(this.graphicsFolderName)) {
                JcrUtil.copy(this.sourceFolderNode.getNode(graphicsFolderName), contentXMLNode,
                        this.graphicsFolderName);
            }
            JcrUtils.putFile(vaultNode, "filter.xml", "application/xml",
                    FilterXmlBuilder.fromRoot(this.targetPath + "/").toStream(this.graphicsFolderName));
            log.info("filter.xml written");

            JcrArchive archive = new JcrArchive(contentPackageNode, "/");
            archive.open(true);
            Importer importer = new Importer();
            importer.getOptions().setImportMode(ImportMode.MERGE);
            importer.getOptions().setAccessControlHandling(AccessControlHandling.MERGE);
            importer.run(archive, contentPackageNode.getSession().getNode("/"));
            log.info("content.xml imported");

            //contentPackageNode.remove();
            this.session.save();
            log.info("session saved.");

        } catch (RepositoryException e) {
            log.error(e.toString());
        } catch (TransformerException e) {
            log.error(e.toString());
        } catch (SAXException e) {
            log.error(e.toString());
        } catch (IOException e) {
            log.error(e.toString());
        } catch (ConfigurationException e) {
            log.error(e.toString());
        }
    }

    private class DocImporterURIResolver implements URIResolver {
        private Node xsltNode;
        private Node srcNode;
        private XMLReader xmlReader;

        public DocImporterURIResolver(Node xsltNode, Node srcNode, XMLReader xmlReader) {
            this.xsltNode = xsltNode;
            this.srcNode = srcNode;
            this.xmlReader = xmlReader;
        }

        public Source resolve(String href, String base) throws TransformerException {
            try {
                final Node node = (href.endsWith("xsl") ? this.xsltNode.getParent().getNode(href)
                        : this.srcNode.getNode(href));
                return new SAXSource(this.xmlReader, new InputSource(JcrUtils.readFile(node)));
            } catch (RepositoryException e) {
                throw new TransformerException("Cannot resolve " + href + " in either [parent of " + this.xsltNode
                        + " or " + this.srcNode + "]");
            }
        }
    }

    private class DocImporterUnparsedTextURIResolver implements UnparsedTextURIResolver {
        private Node srcNode;

        public DocImporterUnparsedTextURIResolver(Node srcNode) {
            this.srcNode = srcNode;
        }

        public Reader resolve(URI absoluteURI, String encoding, Configuration config)
                throws net.sf.saxon.trans.XPathException {
            String absolutePath = absoluteURI.getPath();
            InputStreamReader isr;

            // Hardcoded hack, requires that HTML files are always in the html/ subdir of the src/ dir
            int pos = absolutePath.lastIndexOf("html/");
            String relativePath = absolutePath.substring(pos);

            try {
                if (this.srcNode.hasNode(relativePath)) {
                    isr = new InputStreamReader(JcrUtils.readFile(this.srcNode.getNode(relativePath)));
                } else {
                    String message = "<html><body><h2>HTML file " + relativePath + " not found<h2></body></html>";
                    isr = new InputStreamReader(IOUtils.toInputStream(message, "UTF-8"));
                    log.info("HTML file " + relativePath + " not found");
                }
                return isr;
            } catch (RepositoryException e) {
                throw new net.sf.saxon.trans.XPathException("Oops...", e);
            } catch (IOException e) {
                throw new net.sf.saxon.trans.XPathException("Oops...", e);
            }
        }
    }
}