ExternalizerImpl.java 11.8 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.text.Text
 *  javax.servlet.http.HttpServletRequest
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.commons.osgi.OsgiUtil
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.commons.impl;

import com.day.cq.commons.Externalizer;
import com.day.text.Text;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.osgi.OsgiUtil;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=1, label="Day CQ Link Externalizer", description="Creates absolute URLs")
@Service
@Properties(value={@Property(name="service.description", value={"Creates absolute URLs"})})
public class ExternalizerImpl
implements Externalizer {
    private final Logger log = LoggerFactory.getLogger(ExternalizerImpl.class);
    private static final String DEFAULT_SCHEME = "http";
    private static final String SCHEME_SEP = "://";
    private static final String DEFAULT_LOCAL_DOMAIN = "local http://localhost:4502";
    private static final String DEFAULT_AUTHOR_DOMAIN = "author http://localhost:4502";
    private static final String DEFAULT_PUBLISH_DOMAIN = "publish http://localhost:4503";
    private static final String[] DEFAULT_DOMAINS = new String[]{"local http://localhost:4502", "author http://localhost:4502", "publish http://localhost:4503"};
    @Property(value={"local http://localhost:4502", "author http://localhost:4502", "publish http://localhost:4503"})
    private static final String DOMAINS_CONFIG = "externalizer.domains";
    @Deprecated
    @Property(value={""})
    private static final String HOST_CONFIG = "externalizer.host";
    @Deprecated
    @Property(value={""})
    private static final String CONTEXT_PATH_CONFIG = "externalizer.contextpath";
    private Map<String, URI> domains = new HashMap<String, URI>();
    @Property(boolValue={0})
    private static final String ASSUME_ENCODED_PATH = "externalizer.encodedpath";
    private boolean assumeEncodedPath;

    protected void activate(ComponentContext ctx) {
        this.domains = this.parseDomainConfig(OsgiUtil.toStringArray(ctx.getProperties().get("externalizer.domains"), (String[])DEFAULT_DOMAINS));
        this.assumeEncodedPath = OsgiUtil.toBoolean(ctx.getProperties().get("externalizer.encodedpath"), (boolean)false);
        this.handleLegacyConfig(OsgiUtil.toString(ctx.getProperties().get("externalizer.host"), (String)"").trim(), OsgiUtil.toString(ctx.getProperties().get("externalizer.contextpath"), (String)"").trim());
    }

    public void setConfig(String host, String contextPath, String[] domains, boolean assumeEncodedPath) {
        this.domains = this.parseDomainConfig(domains == null ? DEFAULT_DOMAINS : domains);
        this.assumeEncodedPath = assumeEncodedPath;
        this.handleLegacyConfig(host == null ? "" : host.trim(), contextPath == null ? "" : contextPath.trim());
    }

    private void handleLegacyConfig(String host, String contextPath) {
        if (host.length() > 0) {
            try {
                this.domains.put("local", URI.create("http://" + host.trim() + contextPath.trim()));
            }
            catch (Exception e) {
                this.log.error("Invalid host and/or context path configuration: '{}' '{}'", (Object)host, (Object)contextPath);
            }
        }
    }

    private Map<String, URI> parseDomainConfig(String[] domainCfgs) {
        HashMap<String, URI> domains = new HashMap<String, URI>();
        if (domainCfgs == null) {
            return domains;
        }
        for (String domainCfg : domainCfgs) {
            int splitAt = (domainCfg = domainCfg.trim()).indexOf(32);
            if (splitAt <= 0) continue;
            String name = domainCfg.substring(0, splitAt);
            try {
                String domain = domainCfg.substring(splitAt + 1);
                if (!domain.contains("://")) {
                    domain = "http://" + domain;
                }
                domains.put(name, URI.create(domain));
                continue;
            }
            catch (IllegalArgumentException e) {
                this.log.error("Invalid URI in domain configuration '{}'", (Object)domainCfg);
            }
        }
        return domains;
    }

    private static String getAuthority(String scheme, String host, int port) {
        if (port <= 0 || "http".equals(scheme) && port == 80 || "https".equals(scheme) && port == 443) {
            return host;
        }
        return host + ":" + port;
    }

    private String encodePath(String path) {
        String[] pathSegs;
        StringBuilder encoded = new StringBuilder(64);
        for (String seg : pathSegs = path.split("/")) {
            if (seg.length() <= 0) continue;
            encoded.append("/");
            try {
                encoded.append(URLEncoder.encode(seg, "UTF-8").replaceAll("\\+", "%20"));
                continue;
            }
            catch (UnsupportedEncodingException uee) {
                encoded.append(seg);
            }
        }
        return encoded.toString();
    }

    private String determineActualPath(ResourceResolver resolver, String path) {
        String actualPath = path;
        if (path != null) {
            String resolverPath = actualPath;
            String suffix = "";
            int sepPos = actualPath.indexOf("?");
            if (sepPos >= 0) {
                resolverPath = path.substring(0, sepPos);
                suffix = path.substring(sepPos);
            } else {
                sepPos = actualPath.indexOf("#");
                if (sepPos >= 0) {
                    resolverPath = path.substring(0, sepPos);
                    suffix = path.substring(sepPos);
                }
            }
            if (resolver != null) {
                String mapperPath = resolverPath;
                if (this.assumeEncodedPath) {
                    try {
                        mapperPath = URLDecoder.decode(resolverPath, "UTF-8");
                        mapperPath = Text.replace((String)mapperPath, (String)"?", (String)"\u0001");
                        mapperPath = Text.replace((String)mapperPath, (String)"#", (String)"\u0002");
                    }
                    catch (UnsupportedEncodingException uee) {
                        // empty catch block
                    }
                }
                actualPath = resolver.map(mapperPath) + suffix;
                if (this.assumeEncodedPath) {
                    actualPath = Text.replace((String)actualPath, (String)"%01", (String)"%3F");
                    actualPath = Text.replace((String)actualPath, (String)"%02", (String)"%23");
                }
            } else if (!this.assumeEncodedPath) {
                actualPath = this.encodePath(resolverPath) + suffix;
            }
        }
        return actualPath;
    }

    @Override
    public String relativeLink(SlingHttpServletRequest request, String path) {
        return request.getResourceResolver().map((HttpServletRequest)request, path);
    }

    @Override
    public String absoluteLink(SlingHttpServletRequest request, String scheme, String path) {
        return this.absoluteLink(request, null, scheme, path);
    }

    private String absoluteLink(SlingHttpServletRequest request, ResourceResolver resolver, String scheme, String path) {
        URI uri;
        if (request == null) {
            return this.externalLink(resolver, "local", scheme, path);
        }
        StringBuilder url = new StringBuilder();
        url.append(scheme).append("://");
        if (resolver == null) {
            resolver = request.getResourceResolver();
        }
        if ((uri = URI.create(this.determineActualPath(resolver, path))).getRawAuthority() == null) {
            url.append(ExternalizerImpl.getAuthority(scheme, request.getServerName(), request.getServerPort()));
        } else {
            url.append(uri.getRawAuthority());
        }
        url.append(request.getContextPath());
        url.append(uri.getRawPath());
        if (uri.getRawQuery() != null) {
            url.append("?");
            url.append(uri.getRawQuery());
        }
        if (uri.getRawFragment() != null) {
            url.append("#");
            url.append(uri.getRawFragment());
        }
        if (this.log.isDebugEnabled()) {
            this.log.debug("externalizing absolute link (request scope): {} -> {}", (Object)path, (Object)url);
        }
        return url.toString();
    }

    @Deprecated
    @Override
    public String absoluteLink(ResourceResolver resolver, String scheme, String path) {
        return this.externalLink(resolver, "local", scheme, path);
    }

    @Deprecated
    @Override
    public String absoluteLink(String scheme, String path) {
        return this.externalLink(null, "local", scheme, path);
    }

    @Override
    public String externalLink(ResourceResolver resolver, String domain, String path) {
        return this.externalLink(resolver, domain, null, path);
    }

    @Override
    public String externalLink(ResourceResolver resolver, String domain, String scheme, String path) {
        if (domain == null) {
            throw new NullPointerException("Argument 'domain' is null");
        }
        URI domainURI = this.domains.get(domain);
        if (domainURI == null) {
            throw new IllegalArgumentException("Could not find configuration for domain '" + domain + "'");
        }
        StringBuilder url = new StringBuilder();
        if (scheme == null && (scheme = domainURI.getScheme()) == null) {
            scheme = "http";
        }
        url.append(scheme).append("://");
        URI mapped = URI.create(this.determineActualPath(resolver, path));
        if (mapped.getRawAuthority() == null) {
            url.append(ExternalizerImpl.getAuthority(scheme, domainURI.getHost(), domainURI.getPort()));
        } else {
            url.append(mapped.getRawAuthority());
        }
        if (domainURI.getRawPath() != null) {
            url.append(domainURI.getRawPath());
        }
        url.append(mapped.getRawPath());
        if (mapped.getRawQuery() != null) {
            url.append("?");
            url.append(mapped.getRawQuery());
        }
        if (mapped.getRawFragment() != null) {
            url.append("#");
            url.append(mapped.getRawFragment());
        }
        if (this.log.isDebugEnabled()) {
            this.log.debug("externalizing link for '{}': {} -> {}", new Object[]{domain, path, url});
        }
        return url.toString();
    }

    @Override
    public String publishLink(ResourceResolver resolver, String path) {
        return this.externalLink(resolver, "publish", null, path);
    }

    @Override
    public String publishLink(ResourceResolver resolver, String scheme, String path) {
        return this.externalLink(resolver, "publish", scheme, path);
    }

    @Override
    public String authorLink(ResourceResolver resolver, String path) {
        return this.externalLink(resolver, "author", null, path);
    }

    @Override
    public String authorLink(ResourceResolver resolver, String scheme, String path) {
        return this.externalLink(resolver, "author", scheme, path);
    }
}