DurboImporter.java 11.3 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.durbo.DurboInput
 *  com.day.durbo.DurboInput$Element
 *  com.day.durbo.DurboInput$Node
 *  com.day.durbo.DurboInput$Property
 *  com.day.durbo.io.RegionFileInputStream
 *  javax.jcr.Node
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.servlet.ServletInputStream
 *  org.apache.commons.io.FileUtils
 *  org.apache.commons.io.IOUtils
 *  org.apache.jackrabbit.util.Text
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.replication.impl.content.durbo;

import com.day.cq.replication.ReplicationException;
import com.day.cq.replication.impl.content.durbo.BinaryLessDurboImportTransformer;
import com.day.cq.replication.impl.content.durbo.DurboImportConfiguration;
import com.day.cq.replication.impl.content.durbo.DurboImportResult;
import com.day.cq.replication.impl.content.durbo.DurboImportTransformer;
import com.day.cq.replication.impl.content.durbo.DurboUtil;
import com.day.durbo.DurboInput;
import com.day.durbo.io.RegionFileInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.util.Text;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.ResourceResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DurboImporter {
    private final Logger logger = LoggerFactory.getLogger(DurboImporter.class);
    private boolean useStableUUIDs = false;
    private Hook hook;
    private long tempFileThreshold = 0x100000;
    private DurboImportConfiguration configuration;

    public DurboImporter(DurboImportConfiguration configuration) {
        this.configuration = configuration;
    }

    private Node createParentPath(Session session, String path, boolean useParentNodeType, String[] parentNodeTypes, String[] parentNodeProperties, int index) throws RepositoryException, ReplicationException {
        if (session.itemExists(path)) {
            return session.getNode(path);
        }
        if ("/".equals(path)) {
            return session.getRootNode();
        }
        int lastIndex = path.lastIndexOf("/");
        String leafNode = path.substring(lastIndex + 1);
        String parentPath = path.substring(0, lastIndex);
        if (lastIndex == 0) {
            parentPath = "/";
        }
        Node parentNode = this.createParentPath(session, parentPath, useParentNodeType, parentNodeTypes, parentNodeProperties, index + 1);
        if (useParentNodeType) {
            String pt = parentNodeTypes[index];
            this.logger.debug("Creating new node {} at {} with node type {}.", new Object[]{leafNode, parentPath, pt});
            if (DurboUtil.isAuthorizableNodeType(pt, 3)) {
                String parentPropertiesString;
                String string = parentPropertiesString = parentNodeProperties != null && index < parentNodeProperties.length ? parentNodeProperties[index] : null;
                if (parentPropertiesString != null) {
                    Map<String, String> properties = DurboUtil.urlDecodeMap(parentPropertiesString);
                    return DurboImportTransformer.addSimpleAuthorizable(parentNode, leafNode, pt, properties);
                }
                throw new RuntimeException("parent properties are required for authorizable " + path);
            }
            return parentNode.addNode(leafNode, pt);
        }
        this.logger.debug("Creating new node {} at {} with default node type.", (Object)leafNode, (Object)path);
        return parentNode.addNode(leafNode);
    }

    private Node createParentPath(Session session, String replicationPath, Map<String, DurboInput.Property> headerProps, Hook hook) throws RepositoryException, ReplicationException {
        String parentNodeTypeValues = DurboUtil.getValue(headerProps, "parentNodeTypes", null);
        String parentNodePropertiesValues = DurboUtil.getValue(headerProps, "parentNodeProperties", null);
        String[] parentNodeTypes = Text.explode((String)parentNodeTypeValues, (int)44);
        String[] parentNodeProperties = parentNodePropertiesValues != null ? Text.explode((String)parentNodePropertiesValues, (int)44, (boolean)true) : null;
        int pos = replicationPath.lastIndexOf(47);
        if (pos != -1) {
            String parentPath = replicationPath.substring(0, pos);
            if (pos == 0) {
                return session.getRootNode();
            }
            StringTokenizer st = new StringTokenizer(parentPath = parentPath.replaceAll("\\[[0-9]*\\]", ""), "/");
            boolean useParentNodeType = st.countTokens() == parentNodeTypes.length;
            int index = 0;
            return this.createParentPath(session, parentPath, useParentNodeType, parentNodeTypes, parentNodeProperties, index);
        }
        return null;
    }

    public Node createNode(SlingHttpServletRequest request, String origPath) throws ReplicationException {
        this.logger.debug("Received new durbo request on path: {}", (Object)origPath);
        try {
            Session session = (Session)request.getResourceResolver().adaptTo(Session.class);
            int len = request.getContentLength();
            ServletInputStream in = request.getInputStream();
            return this.createNode(session, origPath, (InputStream)in, len, false).getCreatedNode();
        }
        catch (IOException e) {
            throw new ReplicationException("I/O error during node import: " + e.getMessage(), e);
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public DurboImportResult createNode(Session session, String origPath, InputStream in, long len, boolean binaryLess) throws ReplicationException {
        this.logger.debug("Received new durbo request on path: {}", (Object)origPath);
        File tmpFile = null;
        try {
            if (len <= 0 || len >= this.tempFileThreshold) {
                long now = System.currentTimeMillis();
                this.logger.info("Content size triggered creation of temp file: {}...", (Object)len);
                tmpFile = File.createTempFile("cqreplication", "tmp");
                FileOutputStream out = FileUtils.openOutputStream((File)tmpFile);
                try {
                    IOUtils.copy((InputStream)in, (OutputStream)out);
                }
                finally {
                    IOUtils.closeQuietly((OutputStream)out);
                }
                IOUtils.closeQuietly((InputStream)in);
                this.logger.info("Temporary file created in {}ms ({} bytes)", (Object)(System.currentTimeMillis() - now), (Object)tmpFile.length());
                in = new RegionFileInputStream(tmpFile);
            }
            DurboInput input = new DurboInput(in);
            DurboImportResult durboImportResult = this.createNode(session, origPath, input, binaryLess);
            return durboImportResult;
        }
        catch (IOException e) {
            throw new ReplicationException("Repository error during content import: " + e.getMessage(), e);
        }
        finally {
            try {
                if (session.hasPendingChanges()) {
                    session.refresh(false);
                }
            }
            catch (RepositoryException var13_15) {}
            IOUtils.closeQuietly((InputStream)in);
            if (tmpFile != null && !tmpFile.delete()) {
                throw new ReplicationException("could not delete temp file");
            }
        }
    }

    public DurboImportResult createNode(Session session, String origPath, DurboInput input, boolean binaryLess) throws ReplicationException {
        try {
            DurboInput.Element element;
            long start = System.currentTimeMillis();
            HashMap<String, DurboInput.Property> headerProps = new HashMap<String, DurboInput.Property>();
            do {
                if ((element = input.read()) == null || !element.isProperty()) continue;
                headerProps.put(element.name(), (DurboInput.Property)element);
            } while (element != null && element.isProperty());
            if (element == null) {
                throw new ReplicationException("Could not load syndication information, no node available.");
            }
            if (!(element instanceof DurboInput.Node)) {
                throw new ReplicationException("Could not load syndication information, node element expected.");
            }
            String path = this.getPath(this.hook, session, DurboUtil.getValue(headerProps, "startPath", origPath));
            this.logger.debug("Starting node creation for durbo request on path: {}", (Object)path);
            Node parentNode = this.createParentPath(session, path, headerProps, this.hook);
            this.logger.debug("writeback content...");
            final DurboImportTransformer transformer = binaryLess ? new BinaryLessDurboImportTransformer(this.configuration, session, input) : new DurboImportTransformer(this.configuration, session, input);
            final Node node = transformer.transform(parentNode, (DurboInput.Node)element);
            this.logger.debug("restore sibling order...");
            DurboUtil.setChildNodeOrder(parentNode, DurboUtil.getNodeNames(headerProps, "orderSiblings"));
            this.logger.debug("restore children order...");
            DurboUtil.setChildNodeOrder(node, DurboUtil.getNodeNames(headerProps, "orderChildren"));
            if (this.hook != null) {
                this.hook.beforeSave(node);
            }
            this.logger.debug("saving...");
            session.save();
            long end = System.currentTimeMillis();
            this.logger.info("imported content in {}ms for durbo request on path: {}", (Object)(end - start), (Object)path);
            return new DurboImportResult(){

                @Override
                public Node getCreatedNode() {
                    return node;
                }

                @Override
                public List<String> getFailedPaths() {
                    return transformer.getFailedPaths();
                }
            };
        }
        catch (IOException e) {
            throw new ReplicationException("Repository error during node import: " + e.getMessage(), e);
        }
        catch (RepositoryException e) {
            throw new ReplicationException("Repository error during node import: " + e.getMessage(), (Exception)e);
        }
    }

    public Hook getHook() {
        return this.hook;
    }

    public void setHook(Hook hook) {
        this.hook = hook;
    }

    public void setTempFileThreshold(long size) {
        this.tempFileThreshold = size;
    }

    private String getPath(Hook hook, Session session, String replicationPath) {
        if (hook != null) {
            return hook.transform(session, replicationPath);
        }
        return replicationPath;
    }

    public static interface Hook {
        public String transform(Session var1, String var2);

        public void beforeSave(Node var1) throws RepositoryException;
    }

}