Search in sources :

Example 1 with MapEntry

use of org.apache.sling.resourceresolver.impl.mapping.MapEntry in project sling by apache.

the class ResourceResolverImpl method resolveInternal.

private Resource resolveInternal(final HttpServletRequest request, String absPath) {
    // make sure abspath is not null and is absolute
    if (absPath == null) {
        absPath = "/";
    } else if (!absPath.startsWith("/")) {
        absPath = "/" + absPath;
    }
    // check for special namespace prefix treatment
    absPath = unmangleNamespaces(absPath);
    // Assume http://localhost:80 if request is null
    String[] realPathList = { absPath };
    String requestPath;
    if (request != null) {
        requestPath = getMapPath(request.getScheme(), request.getServerName(), request.getServerPort(), absPath);
    } else {
        requestPath = getMapPath("http", "localhost", 80, absPath);
    }
    logger.debug("resolve: Resolving request path {}", requestPath);
    // TODO: might do better to be able to log the loop and help the user
    for (int i = 0; i < 100; i++) {
        String[] mappedPath = null;
        final Iterator<MapEntry> mapEntriesIterator = this.factory.getMapEntries().getResolveMapsIterator(requestPath);
        while (mapEntriesIterator.hasNext()) {
            final MapEntry mapEntry = mapEntriesIterator.next();
            mappedPath = mapEntry.replace(requestPath);
            if (mappedPath != null) {
                if (logger.isDebugEnabled()) {
                    logger.debug("resolve: MapEntry {} matches, mapped path is {}", mapEntry, Arrays.toString(mappedPath));
                }
                if (mapEntry.isInternal()) {
                    // internal redirect
                    logger.debug("resolve: Redirecting internally");
                    break;
                }
                // external redirect
                logger.debug("resolve: Returning external redirect");
                return this.factory.getResourceDecoratorTracker().decorate(new RedirectResource(this, absPath, mappedPath[0], mapEntry.getStatus()));
            }
        }
        // and use the original realPath
        if (mappedPath == null) {
            logger.debug("resolve: Request path {} does not match any MapEntry", requestPath);
            break;
        }
        // if the mapped path is not an URL, use this path to continue
        if (!mappedPath[0].contains("://")) {
            logger.debug("resolve: Mapped path is for resource tree");
            realPathList = mappedPath;
            break;
        }
        // resolve that URI now, using the URI's path as the real path
        try {
            final URI uri = new URI(mappedPath[0], false);
            requestPath = getMapPath(uri.getScheme(), uri.getHost(), uri.getPort(), uri.getPath());
            realPathList = new String[] { uri.getPath() };
            logger.debug("resolve: Mapped path is an URL, using new request path {}", requestPath);
        } catch (final URIException use) {
            // TODO: log and fail
            throw new ResourceNotFoundException(absPath);
        }
    }
    // now we have the real path resolved from virtual host mapping
    // this path may be absolute or relative, in which case we try
    // to resolve it against the search path
    Resource res = null;
    for (int i = 0; res == null && i < realPathList.length; i++) {
        final ParsedParameters parsedPath = new ParsedParameters(realPathList[i]);
        final String realPath = parsedPath.getRawPath();
        // first check whether the requested resource is a StarResource
        if (StarResource.appliesTo(realPath)) {
            logger.debug("resolve: Mapped path {} is a Star Resource", realPath);
            res = new StarResource(this, ensureAbsPath(realPath));
        } else {
            if (realPath.startsWith("/")) {
                // let's check it with a direct access first
                logger.debug("resolve: Try absolute mapped path {}", realPath);
                res = resolveInternal(realPath, parsedPath.getParameters());
            } else {
                final String[] searchPath = getSearchPath();
                for (int spi = 0; res == null && spi < searchPath.length; spi++) {
                    logger.debug("resolve: Try relative mapped path with search path entry {}", searchPath[spi]);
                    res = resolveInternal(searchPath[spi] + realPath, parsedPath.getParameters());
                }
            }
        }
    }
    // if no resource has been found, use a NonExistingResource
    if (res == null) {
        final ParsedParameters parsedPath = new ParsedParameters(realPathList[0]);
        final String resourcePath = ensureAbsPath(parsedPath.getRawPath());
        logger.debug("resolve: Path {} does not resolve, returning NonExistingResource at {}", absPath, resourcePath);
        res = new NonExistingResource(this, resourcePath);
        // SLING-864: if the path contains a dot we assume this to be
        // the start for any selectors, extension, suffix, which may be
        // used for further request processing.
        // the resolution path must be the full path and is already set within
        // the non existing resource
        final int index = resourcePath.indexOf('.');
        if (index != -1) {
            res.getResourceMetadata().setResolutionPathInfo(resourcePath.substring(index));
        }
        res.getResourceMetadata().setParameterMap(parsedPath.getParameters());
    } else {
        logger.debug("resolve: Path {} resolves to Resource {}", absPath, res);
    }
    return this.factory.getResourceDecoratorTracker().decorate(res);
}
Also used : MapEntry(org.apache.sling.resourceresolver.impl.mapping.MapEntry) RedirectResource(org.apache.sling.resourceresolver.impl.helper.RedirectResource) StarResource(org.apache.sling.resourceresolver.impl.helper.StarResource) RedirectResource(org.apache.sling.resourceresolver.impl.helper.RedirectResource) NonExistingResource(org.apache.sling.api.resource.NonExistingResource) Resource(org.apache.sling.api.resource.Resource) StringUtils.defaultString(org.apache.commons.lang3.StringUtils.defaultString) URI(org.apache.sling.resourceresolver.impl.helper.URI) StarResource(org.apache.sling.resourceresolver.impl.helper.StarResource) URIException(org.apache.sling.resourceresolver.impl.helper.URIException) ParsedParameters(org.apache.sling.resourceresolver.impl.params.ParsedParameters) NonExistingResource(org.apache.sling.api.resource.NonExistingResource) ResourceNotFoundException(org.apache.sling.api.resource.ResourceNotFoundException)

Example 2 with MapEntry

use of org.apache.sling.resourceresolver.impl.mapping.MapEntry in project sling by apache.

the class ResourceResolverImpl method map.

/**
     * full implementation - apply sling:alias from the resource path - apply
     * /etc/map mappings (inkl. config backwards compat) - return absolute uri
     * if possible
     *
     * @see org.apache.sling.api.resource.ResourceResolver#map(javax.servlet.http.HttpServletRequest,
     *      java.lang.String)
     */
@Override
public String map(final HttpServletRequest request, final String resourcePath) {
    checkClosed();
    // find a fragment or query
    int fragmentQueryMark = resourcePath.indexOf('#');
    if (fragmentQueryMark < 0) {
        fragmentQueryMark = resourcePath.indexOf('?');
    }
    // cut fragment or query off the resource path
    String mappedPath;
    final String fragmentQuery;
    if (fragmentQueryMark >= 0) {
        fragmentQuery = resourcePath.substring(fragmentQueryMark);
        mappedPath = resourcePath.substring(0, fragmentQueryMark);
        logger.debug("map: Splitting resource path '{}' into '{}' and '{}'", new Object[] { resourcePath, mappedPath, fragmentQuery });
    } else {
        fragmentQuery = null;
        mappedPath = resourcePath;
    }
    // cut off scheme and host, if the same as requested
    final String schemehostport;
    final String schemePrefix;
    if (request != null) {
        schemehostport = MapEntry.getURI(request.getScheme(), request.getServerName(), request.getServerPort(), "/");
        schemePrefix = request.getScheme().concat("://");
        logger.debug("map: Mapping path {} for {} (at least with scheme prefix {})", new Object[] { resourcePath, schemehostport, schemePrefix });
    } else {
        schemehostport = null;
        schemePrefix = null;
        logger.debug("map: Mapping path {} for default", resourcePath);
    }
    ParsedParameters parsed = new ParsedParameters(mappedPath);
    final Resource res = resolveInternal(parsed.getRawPath(), parsed.getParameters());
    if (res != null) {
        // keep, what we might have cut off in internal resolution
        final String resolutionPathInfo = res.getResourceMetadata().getResolutionPathInfo();
        logger.debug("map: Path maps to resource {} with path info {}", res, resolutionPathInfo);
        // find aliases for segments. we can't walk the parent chain
        // since the request session might not have permissions to
        // read all parents SLING-2093
        final LinkedList<String> names = new LinkedList<>();
        Resource current = res;
        String path = res.getPath();
        while (path != null) {
            String alias = null;
            if (current != null && !path.endsWith(JCR_CONTENT_LEAF)) {
                if (factory.isOptimizeAliasResolutionEnabled()) {
                    logger.debug("map: Optimize Alias Resolution is Enabled");
                    String parentPath = ResourceUtil.getParent(path);
                    if (parentPath != null) {
                        final Map<String, String> aliases = factory.getMapEntries().getAliasMap(parentPath);
                        if (aliases != null && aliases.containsValue(current.getName())) {
                            for (String key : aliases.keySet()) {
                                if (current.getName().equals(aliases.get(key))) {
                                    alias = key;
                                    break;
                                }
                            }
                        }
                    }
                } else {
                    logger.debug("map: Optimize Alias Resolution is Disabled");
                    alias = ResourceResolverControl.getProperty(current, PROP_ALIAS);
                }
            }
            if (alias == null || alias.length() == 0) {
                alias = ResourceUtil.getName(path);
            }
            names.add(alias);
            path = ResourceUtil.getParent(path);
            if ("/".equals(path)) {
                path = null;
            } else if (path != null) {
                current = res.getResourceResolver().resolve(path);
            }
        }
        // build path from segment names
        final StringBuilder buf = new StringBuilder();
        // construct the path from the segments (or root if none)
        if (names.isEmpty()) {
            buf.append('/');
        } else {
            while (!names.isEmpty()) {
                buf.append('/');
                buf.append(names.removeLast());
            }
        }
        // reappend the resolutionPathInfo
        if (resolutionPathInfo != null) {
            buf.append(resolutionPathInfo);
        }
        // and then we have the mapped path to work on
        mappedPath = buf.toString();
        logger.debug("map: Alias mapping resolves to path {}", mappedPath);
    }
    boolean mappedPathIsUrl = false;
    for (final MapEntry mapEntry : this.factory.getMapEntries().getMapMaps()) {
        final String[] mappedPaths = mapEntry.replace(mappedPath);
        if (mappedPaths != null) {
            logger.debug("map: Match for Entry {}", mapEntry);
            mappedPathIsUrl = !mapEntry.isInternal();
            if (mappedPathIsUrl && schemehostport != null) {
                mappedPath = null;
                for (final String candidate : mappedPaths) {
                    if (candidate.startsWith(schemehostport)) {
                        mappedPath = candidate.substring(schemehostport.length() - 1);
                        mappedPathIsUrl = false;
                        logger.debug("map: Found host specific mapping {} resolving to {}", candidate, mappedPath);
                        break;
                    } else if (candidate.startsWith(schemePrefix) && mappedPath == null) {
                        mappedPath = candidate;
                    }
                }
                if (mappedPath == null) {
                    mappedPath = mappedPaths[0];
                }
            } else {
                // we can only go with assumptions selecting the first entry
                mappedPath = mappedPaths[0];
            }
            logger.debug("resolve: MapEntry {} matches, mapped path is {}", mapEntry, mappedPath);
            break;
        }
    }
    // this should not be the case, since mappedPath is primed
    if (mappedPath == null) {
        mappedPath = resourcePath;
    }
    // [scheme:][//authority][path][?query][#fragment]
    try {
        // use commons-httpclient's URI instead of java.net.URI, as it can
        // actually accept *unescaped* URIs, such as the "mappedPath" and
        // return them in proper escaped form, including the path, via
        // toString()
        final URI uri = new URI(mappedPath, false);
        // 1. mangle the namespaces in the path
        String path = mangleNamespaces(uri.getPath());
        // 2. prepend servlet context path if we have a request
        if (request != null && request.getContextPath() != null && request.getContextPath().length() > 0) {
            path = request.getContextPath().concat(path);
        }
        // update the path part of the URI
        uri.setPath(path);
        mappedPath = uri.toString();
    } catch (final URIException e) {
        logger.warn("map: Unable to mangle namespaces for " + mappedPath + " returning unmangled", e);
    }
    logger.debug("map: Returning URL {} as mapping for path {}", mappedPath, resourcePath);
    // reappend fragment and/or query
    if (fragmentQuery != null) {
        mappedPath = mappedPath.concat(fragmentQuery);
    }
    return mappedPath;
}
Also used : MapEntry(org.apache.sling.resourceresolver.impl.mapping.MapEntry) StarResource(org.apache.sling.resourceresolver.impl.helper.StarResource) RedirectResource(org.apache.sling.resourceresolver.impl.helper.RedirectResource) NonExistingResource(org.apache.sling.api.resource.NonExistingResource) Resource(org.apache.sling.api.resource.Resource) StringUtils.defaultString(org.apache.commons.lang3.StringUtils.defaultString) URI(org.apache.sling.resourceresolver.impl.helper.URI) LinkedList(java.util.LinkedList) URIException(org.apache.sling.resourceresolver.impl.helper.URIException) ParsedParameters(org.apache.sling.resourceresolver.impl.params.ParsedParameters)

Example 3 with MapEntry

use of org.apache.sling.resourceresolver.impl.mapping.MapEntry in project sling by apache.

the class ResourceResolverWebConsolePlugin method dumpMapText.

private void dumpMapText(PrintWriter pw, String title, Collection<MapEntry> list) {
    pw.println(title);
    final String format = "%25s%25s%15s\r\n";
    pw.printf(format, "Pattern", "Replacement", "Redirect");
    for (MapEntry entry : list) {
        final List<String> redir = Arrays.asList(entry.getRedirect());
        final String status = entry.isInternal() ? "internal" : "external: " + entry.getStatus();
        pw.printf(format, entry.getPattern(), redir, status);
    }
}
Also used : MapEntry(org.apache.sling.resourceresolver.impl.mapping.MapEntry)

Example 4 with MapEntry

use of org.apache.sling.resourceresolver.impl.mapping.MapEntry in project sling by apache.

the class ResourceResolverWebConsolePlugin method dumpMapHtml.

// ---------- internal
private void dumpMapHtml(PrintWriter pw, String title, String description, Collection<MapEntry> list) {
    titleHtml(pw, title, description);
    pw.println("<tr class='content'>");
    pw.println("<th class='content'>Pattern</th>");
    pw.println("<th class='content'>Replacement</th>");
    pw.println("<th class='content'>Redirect</th>");
    pw.println("</tr>");
    final Set<String> usedPatterns = new HashSet<String>();
    for (final MapEntry entry : list) {
        final String pattern = entry.getPattern();
        pw.print("<tr class='content");
        if (!usedPatterns.add(pattern)) {
            pw.print(" duplicate");
        }
        pw.println("'>");
        pw.println("<td class='content' style='vertical-align: top'>");
        pw.print(ResponseUtil.escapeXml(pattern));
        pw.print("</td>");
        pw.print("<td class='content' style='vertical-align: top'>");
        final String[] repls = entry.getRedirect();
        for (final String repl : repls) {
            pw.print(ResponseUtil.escapeXml(repl));
            pw.print("<br/>");
        }
        pw.print("</td>");
        pw.print("<td class='content' style='vertical-align: top'>");
        if (entry.isInternal()) {
            pw.print("internal");
        } else {
            pw.print("external: ");
            pw.print(String.valueOf(entry.getStatus()));
        }
        pw.println("</td></tr>");
    }
}
Also used : MapEntry(org.apache.sling.resourceresolver.impl.mapping.MapEntry) HashSet(java.util.HashSet)

Aggregations

MapEntry (org.apache.sling.resourceresolver.impl.mapping.MapEntry)4 StringUtils.defaultString (org.apache.commons.lang3.StringUtils.defaultString)2 NonExistingResource (org.apache.sling.api.resource.NonExistingResource)2 Resource (org.apache.sling.api.resource.Resource)2 RedirectResource (org.apache.sling.resourceresolver.impl.helper.RedirectResource)2 StarResource (org.apache.sling.resourceresolver.impl.helper.StarResource)2 URI (org.apache.sling.resourceresolver.impl.helper.URI)2 URIException (org.apache.sling.resourceresolver.impl.helper.URIException)2 ParsedParameters (org.apache.sling.resourceresolver.impl.params.ParsedParameters)2 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 ResourceNotFoundException (org.apache.sling.api.resource.ResourceNotFoundException)1