PathRewriterTransformer.java 11.8 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.commons.Externalizer
 *  com.day.cq.rewriter.linkchecker.LinkChecker
 *  com.day.text.Text
 *  org.apache.cocoon.xml.sax.AbstractSAXPipe
 *  org.apache.commons.lang.StringUtils
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.rewriter.ProcessingComponentConfiguration
 *  org.apache.sling.rewriter.ProcessingContext
 *  org.apache.sling.rewriter.Transformer
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.mobile.dps.impl.rewriter;

import com.adobe.cq.mobile.dps.impl.rewriter.PathRewriterOptions;
import com.adobe.cq.mobile.dps.impl.rewriter.PathRewriterTransformerConfig;
import com.day.cq.commons.Externalizer;
import com.day.cq.rewriter.linkchecker.LinkChecker;
import com.day.text.Text;
import java.io.IOException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.cocoon.xml.sax.AbstractSAXPipe;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.rewriter.ProcessingComponentConfiguration;
import org.apache.sling.rewriter.ProcessingContext;
import org.apache.sling.rewriter.Transformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

public class PathRewriterTransformer
extends AbstractSAXPipe
implements Transformer {
    private static final Logger log = LoggerFactory.getLogger(PathRewriterTransformer.class);
    private static final String SCRIPT_TAG = "script";
    private static final String HTML_RESOURCES = "HTMLResources";
    private final LinkChecker checker;
    private final Externalizer externalizer;
    private boolean enabled = false;
    private SlingHttpServletRequest request;
    private PathRewriterOptions options;
    private PathRewriterOptions.PageType pageType;
    private String requestedPathPath = null;
    private PathRewriterTransformerConfig config;
    private boolean insideScript;
    private StringBuffer scriptBuffer;

    public PathRewriterTransformer(LinkChecker checker, Externalizer externalizer, PathRewriterTransformerConfig config) {
        this.checker = checker;
        this.externalizer = externalizer;
        this.config = config;
        this.insideScript = false;
    }

    public void init(ProcessingContext context, ProcessingComponentConfiguration config) throws IOException {
        this.request = context.getRequest();
        this.options = (PathRewriterOptions)this.request.getAttribute("publishPathRewritingOptions");
        boolean bl = this.enabled = this.options != null;
        if (this.enabled) {
            this.requestedPathPath = this.getRequestedPagePath(this.request.getPathInfo());
            this.pageType = (PathRewriterOptions.PageType)((Object)this.request.getAttribute("publishPathRewritingPageType"));
            log.debug("Rewriting paths for links ({}), clientlibs ({}) and images ({})", new Object[]{this.options.getRewriteMode("links").name(), this.options.getRewriteMode("clientlibs").name(), this.options.getRewriteMode("images").name()});
            log.debug("Rewrite page type: " + (Object)((Object)this.pageType));
        }
    }

    public void dispose() {
    }

    public void startElement(String uri, String name, String raw, Attributes a) throws SAXException {
        if (this.enabled) {
            AttributesImpl attrs = new AttributesImpl(a);
            boolean result = false;
            result |= this.internalRewrite(uri, this.config.linksMapping, "links", name, attrs);
            result |= this.internalRewrite(uri, this.config.clientlibsMapping, "clientlibs", name, attrs);
            if (result |= this.internalRewrite(uri, this.config.imagesMapping, "images", name, attrs)) {
                super.startElement(uri, name, raw, (Attributes)attrs);
                return;
            }
            if (name.equals("script") && attrs.getValue("type") != null && attrs.getValue("type").equals("text/javascript")) {
                this.insideScript = true;
                this.scriptBuffer = new StringBuffer();
            }
        }
        super.startElement(uri, name, raw, a);
    }

    private boolean internalRewrite(String uri, Map<String, String> mapping, String rewriteOption, String name, AttributesImpl attrs) throws SAXException {
        if (mapping.containsKey(name) && this.isTargetOfInterest(attrs.getValue(mapping.get(name)))) {
            if (this.options.isExternal(rewriteOption)) {
                this.makeExternal(uri, mapping.get(name), attrs);
            } else if (this.options.isRelative(rewriteOption)) {
                this.makeRelative(uri, mapping.get(name), attrs, rewriteOption);
            }
            return true;
        }
        return false;
    }

    public void characters(char[] chars, int start, int length) throws SAXException {
        if (this.insideScript) {
            this.scriptBuffer.append(chars, start, length);
        } else {
            super.characters(chars, start, length);
        }
    }

    public void endElement(String uri, String loc, String raw) throws SAXException {
        if (loc.equals("script") && this.insideScript) {
            StringBuffer result = new StringBuffer();
            if (Pattern.compile(".*CQClientLibraryManager.*", 32).matcher(this.scriptBuffer).matches()) {
                Pattern pattern = Pattern.compile(this.config.clientLibraryPattern);
                Matcher matcher = pattern.matcher(this.scriptBuffer);
                while (matcher.find()) {
                    String group = matcher.group(1);
                    if (this.options.isExternal("clientlibs")) {
                        matcher.appendReplacement(result, this.config.clientLibraryReplace.replace("$1", this.externalizer.externalLink(null, "local", group)));
                        continue;
                    }
                    matcher.appendReplacement(result, this.config.clientLibraryReplace.replace("$1", this.getClientLibPath(uri, group)));
                }
                matcher.appendTail(result);
            } else {
                result = this.scriptBuffer;
            }
            super.characters(result.toString().toCharArray(), 0, result.length());
            this.insideScript = false;
        }
        super.endElement(uri, loc, raw);
    }

    private boolean isTargetOfInterest(String target) {
        return target != null && !this.checker.isSpecial(target) && target.startsWith("/");
    }

    private void makeExternal(String uri, String name, AttributesImpl attributes) {
        int index = attributes.getIndex(name);
        String origVal = attributes.getValue(name);
        String value = this.externalizer.externalLink(null, "local", origVal);
        attributes.setAttribute(index, "", name, name, "String", value);
        if (log.isDebugEnabled()) {
            Object[] args = new Object[]{name, origVal, value};
            if (origVal.equals(value)) {
                log.debug("Attribute \"{}\" NOT rewritten : {}", args);
            } else {
                log.debug("Attribute \"{}\" rewritten: {} to: {}", args);
            }
        }
    }

    private void makeRelative(String uri, String name, AttributesImpl attributes, String rewriteOption) {
        int index = attributes.getIndex(name);
        String origVal = attributes.getValue(name);
        String relativePath = this.getRelativePath(uri, origVal, rewriteOption);
        attributes.setAttribute(index, "", name, name, "String", relativePath);
        if (log.isDebugEnabled()) {
            Object[] args = new Object[]{name, origVal, relativePath};
            if (origVal.equals(relativePath)) {
                log.debug("Attribute \"{}\" NOT rewritten : {}", args);
            } else {
                log.debug("Attribute \"{}\" rewritten: {} to: {}", args);
            }
        }
    }

    private String getRelativePath(String uri, String path, String rewriteOption) {
        String relativePath = path;
        if (rewriteOption.equals("clientlibs")) {
            relativePath = this.getClientLibPath(uri, path);
        } else if (rewriteOption.equals("images")) {
            relativePath = this.getImageLibRelativePathPrefix(uri, path);
        } else if (rewriteOption.equals("links")) {
            relativePath = this.getLinkRelativePathPrefix(uri, path);
        }
        return relativePath;
    }

    private String getRelativePathPrefix(String uri) {
        String prefix = "";
        int depth = Text.explode((String)uri, (int)47).length;
        prefix = StringUtils.repeat((String)"../", (int)(depth - 1));
        prefix = StringUtils.removeEnd((String)prefix, (String)"/");
        return prefix;
    }

    private String getHTMLResourceBasedPath(String path) {
        String htmlResourceBasePath = "../HTMLResources";
        if (this.pageType == PathRewriterOptions.PageType.SUB_PAGE) {
            htmlResourceBasePath = this.getRelativePathPrefix(this.requestedPathPath) + "/" + htmlResourceBasePath;
        }
        String newPath = htmlResourceBasePath + path;
        log.debug("Rewrote path '" + path + "' to '" + newPath + "'");
        return newPath;
    }

    private String getClientLibPath(String uri, String path) {
        return this.getHTMLResourceBasedPath(path);
    }

    private String getLinkRelativePathPrefix(String uri, String path) {
        String linkPath = path;
        String linkParentPath = Text.getRelativeParent((String)linkPath, (int)1);
        String pagePath = this.requestedPathPath;
        String parentPath = Text.getRelativeParent((String)pagePath, (int)1);
        if (linkParentPath.equals(pagePath)) {
            linkPath = "." + linkPath;
        } else if (linkParentPath.equals(parentPath)) {
            linkPath = this.mapCQPathToDPSExportPath(path);
        } else if (linkPath.startsWith("/content/dam")) {
            linkPath = this.getHTMLResourceBasedPath(linkPath);
        }
        return linkPath;
    }

    private String getImageLibRelativePathPrefix(String uri, String path) {
        String pagePath = this.requestedPathPath;
        String parentPath = Text.getRelativeParent((String)pagePath, (int)1);
        pagePath = StringUtils.replace((String)pagePath, (String)" ", (String)"%20");
        parentPath = StringUtils.replace((String)parentPath, (String)" ", (String)"%20");
        String imagePath = path;
        imagePath = imagePath.startsWith(pagePath) ? "." + imagePath.substring(parentPath.length()) : (imagePath.startsWith(parentPath) ? ".." + imagePath.substring(parentPath.length()) : this.getHTMLResourceBasedPath(imagePath));
        return imagePath;
    }

    private String mapCQPathToDPSExportPath(String path) {
        boolean forHTML = false;
        String pagePath = this.requestedPathPath;
        String parentPath = Text.getRelativeParent((String)pagePath, (int)1);
        String mappedPath = ".." + path.substring(parentPath.length());
        String[] pathArray = Text.explode((String)mappedPath, (int)47);
        String nameWithExtension = pathArray[pathArray.length - 1];
        String[] nameArray = Text.explode((String)nameWithExtension, (int)46);
        String nameWithoutExtension = nameArray[0];
        if (forHTML) {
            pathArray[pathArray.length - 1] = nameWithoutExtension;
            mappedPath = Text.implode((String[])pathArray, (String)"/") + "/" + nameWithExtension;
        } else {
            mappedPath = "navto://" + nameWithoutExtension;
        }
        return mappedPath;
    }

    private String getRequestedPagePath(String pagePath) {
        int selectorIndex = pagePath.indexOf(".");
        if (selectorIndex > 0) {
            pagePath = pagePath.substring(0, selectorIndex);
        }
        return pagePath;
    }
}