All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.UriResolver Maven / Gradle / Ivy

There is a newer version: 9.0.1
Show newest version
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau;

import static org.apache.juneau.UriRelativity.*;
import static org.apache.juneau.UriResolution.*;
import static org.apache.juneau.internal.StringUtils.*;

import java.io.*;
import java.net.*;

import org.apache.juneau.internal.*;

/**
 * Class used to create absolute and root-relative URIs based on your current URI 'location' and rules about how to
 * make such resolutions.
 *
 * 

* Combines a {@link UriContext} instance with rules for resolution ({@link UriResolution} and relativity * ({@link UriRelativity}) to define simple {@link #resolve(Object)} and {@link #append(Appendable, Object)} methods. * *

* Three special protocols are used to represent context-root-relative, servlet-relative, and request-path-relative * URIs: * "context:/", "servlet:/", and "request:/". * *

* The following list shows the protocols of URLs that can be resolved with this class: *

    *
  • "foo://foo" - Absolute URI. *
  • "/foo" - Root-relative URI. *
  • "/" - Root URI. *
  • "context:/foo" - Context-root-relative URI. *
  • "context:/" - Context-root URI. *
  • "servlet:/foo" - Servlet-path-relative URI. *
  • "servlet:/" - Servlet-path URI. *
  • "request:/foo" - Request-path-relative URI. *
  • "request:/" - Request-path URI. *
  • "foo" - Path-info-relative URI. *
  • "" - Path-info URI. *
*/ public class UriResolver { private final UriResolution resolution; private final UriRelativity relativity; private final String authority, contextRoot, servletPath, pathInfo, parentPath; /** * Constructor. * * @param resolution Rule on how URIs should be resolved. * @param relativity Rule on what relative URIs are relative to. * @param uriContext Current URI context (i.e. the current URI 'location'). */ public UriResolver(UriResolution resolution, UriRelativity relativity, UriContext uriContext) { this.resolution = resolution; this.relativity = relativity; this.authority = uriContext.authority; this.contextRoot = uriContext.contextRoot; this.servletPath = uriContext.servletPath; this.pathInfo = uriContext.pathInfo; this.parentPath = uriContext.parentPath; } /** * Converts the specified URI to absolute form based on values in this context. * * @param uri * The URI to convert to absolute form. * Can be any of the following: *
    *
  • {@link java.net.URI} *
  • {@link java.net.URL} *
  • {@link CharSequence} *
* URI can be any of the following forms: *
    *
  • "foo://foo" - Absolute URI. *
  • "/foo" - Root-relative URI. *
  • "/" - Root URI. *
  • "context:/foo" - Context-root-relative URI. *
  • "context:/" - Context-root URI. *
  • "servlet:/foo" - Servlet-path-relative URI. *
  • "servlet:/" - Servlet-path URI. *
  • "request:/foo" - Request-path-relative URI. *
  • "request:/" - Request-path URI. *
  • "foo" - Path-info-relative URI. *
  • "" - Path-info URI. *
* @return The converted URI. */ public String resolve(Object uri) { return resolve(uri, resolution); } private String resolve(Object uri, UriResolution res) { String s = StringUtils.toString(uri); if (isAbsoluteUri(s)) return hasDotSegments(s) && res != NONE ? normalize(s) : s; if (res == ROOT_RELATIVE && startsWith(s, '/')) return hasDotSegments(s) ? normalize(s) : s; if (res == NONE && ! isSpecialUri(s)) return s; return append(new StringBuilder(), s).toString(); } /** * Relativizes a URI. * *

* Similar to {@link URI#relativize(URI)}, except supports special protocols (e.g. "servlet:/") for both * the relativeTo and uri parameters. * *

* For example, to relativize a URI to its servlet-relative form: *

* // relativeUri == "path/foo" * String relativeUri = resolver.relativize("servlet:/", "/context/servlet/path/foo"); *

* * @param relativeTo The URI to relativize against. * @param uri The URI to relativize. * @return The relativized URI. */ public String relativize(Object relativeTo, Object uri) { String r = resolve(relativeTo, ABSOLUTE); String s = resolve(uri, ABSOLUTE); return URI.create(r).relativize(URI.create(s)).toString(); } /** * Same as {@link #resolve(Object)} except appends result to the specified appendable. * * @param a The appendable to append the URL to. * @param o The URI to convert to absolute form. * @return The same appendable passed in. */ public Appendable append(Appendable a, Object o) { try { String uri = StringUtils.toString(o); uri = nullIfEmpty(uri); boolean needsNormalize = hasDotSegments(uri) && resolution != null; // Absolute paths are not changed. if (isAbsoluteUri(uri)) return a.append(needsNormalize ? normalize(uri) : uri); if (resolution == NONE && ! isSpecialUri(uri)) return a.append(emptyIfNull(uri)); if (resolution == ROOT_RELATIVE && startsWith(uri, '/')) return a.append(needsNormalize ? normalize(uri) : uri); Appendable a2 = needsNormalize ? new StringBuilder() : a; // Root-relative path if (startsWith(uri, '/')) { if (authority != null) a2.append(authority); if (uri.length() != 1) a2.append(uri); else if (authority == null) a2.append('/'); } // Context-relative path else if (uri != null && uri.startsWith("context:/")) { if (resolution == ABSOLUTE && authority != null) a2.append(authority); if (contextRoot != null) a2.append('/').append(contextRoot); if (uri.length() > 9) a2.append('/').append(uri.substring(9)); else if (contextRoot == null && (authority == null || resolution != ABSOLUTE)) a2.append('/'); } // Resource-relative path else if (uri != null && uri.startsWith("servlet:/")) { if (resolution == ABSOLUTE && authority != null) a2.append(authority); if (contextRoot != null) a2.append('/').append(contextRoot); if (servletPath != null) a2.append('/').append(servletPath); if (uri.length() > 9) a2.append('/').append(uri.substring(9)); else if (servletPath == null && contextRoot == null && (authority == null || resolution != ABSOLUTE)) a2.append('/'); } // Request-relative path else if (uri != null && uri.startsWith("request:/")) { if (resolution == ABSOLUTE && authority != null) a2.append(authority); if (contextRoot != null) a2.append('/').append(contextRoot); if (servletPath != null) a2.append('/').append(servletPath); if (pathInfo != null) a2.append('/').append(pathInfo); if (uri.length() > 9) a2.append('/').append(uri.substring(9)); else if (servletPath == null && contextRoot == null && pathInfo == null && (authority == null || resolution != ABSOLUTE)) a2.append('/'); } // Relative path else { if (resolution == ABSOLUTE && authority != null) a2.append(authority); if (contextRoot != null) a2.append('/').append(contextRoot); if (servletPath != null) a2.append('/').append(servletPath); if (relativity == RESOURCE && uri != null) a2.append('/').append(uri); else if (relativity == PATH_INFO) { if (uri == null) { if (pathInfo != null) a2.append('/').append(pathInfo); } else { if (parentPath != null) a2.append('/').append(parentPath); a2.append('/').append(uri); } } else if (uri == null && contextRoot == null && servletPath == null && (authority == null || resolution != ABSOLUTE)) a2.append('/'); } if (needsNormalize) a.append(normalize(a2.toString())); return a; } catch (IOException e) { throw new RuntimeException(e); } } private static boolean isSpecialUri(String s) { if (s == null || s.length() == 0) return false; char c = s.charAt(0); if (c != 's' && c != 'c' && c != 'r') return false; return s.startsWith("servlet:/") || s.startsWith("context:/") || s.startsWith("request:/"); } private static String normalize(String s) { s = URI.create(s).normalize().toString(); if (s.length() > 1 && s.charAt(s.length()-1) == '/') s = s.substring(0, s.length()-1); return s; } private static boolean hasDotSegments(String s) { if (s == null) return false; for (int i = 0; i < s.length()-1; i++) { char c = s.charAt(i); if (i == 0 && c == '/') return true; if (c == '/' && s.charAt(i+1) == '.') return true; } return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy