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);
}
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;
}
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);
}
}
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>");
}
}
Aggregations