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

org.springframework.web.util.DefaultUriBuilderFactory Maven / Gradle / Ivy

There is a newer version: 6.1.6
Show newest version
/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed 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.springframework.web.util;

import java.net.URI;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * {@code UriBuilderFactory} that relies on {@link UriComponentsBuilder} for
 * the actual building of the URI.
 *
 * 

Provides options to create {@link UriBuilder} instances with a common * base URI, alternative encoding mode strategies, among others. * * * @author Rossen Stoyanchev * @since 5.0 * @see UriComponentsBuilder */ public class DefaultUriBuilderFactory implements UriBuilderFactory { /** * Constants that represent different URI encoding strategies. * @see #setEncodingMode */ public enum EncodingMode { /** * The default way of encoding that {@link UriComponents} supports: *

    *
  1. Expand URI variables. *
  2. Encode individual URI components as described in * {@link UriComponents#encode(Charset)}. *
*

This mode does not encode all characters with * reserved meaning but only the ones that are illegal within a given * URI component as defined in RFC 396. This matches the way the * multi-argument {@link URI} constructor does encoding. */ URI_COMPONENT, /** * Comprehensive encoding of URI variable values prior to expanding: *

    *
  1. Apply {@link UriUtils#encode(String, Charset)} to each URI variable value. *
  2. Expand URI variable values. *
*

This mode encodes all characters with reserved meaning, therefore * ensuring that expanded URI variable do not have any impact on the * structure or meaning of the URI. */ VALUES_ONLY, /** * No encoding should be applied. */ NONE } private final UriComponentsBuilder baseUri; private final Map defaultUriVariables = new HashMap<>(); private EncodingMode encodingMode = EncodingMode.URI_COMPONENT; private boolean parsePath = true; /** * Default constructor without a base URI. *

The target address must be specified on each UriBuilder. */ public DefaultUriBuilderFactory() { this(UriComponentsBuilder.newInstance()); } /** * Constructor with a base URI. *

The given URI template is parsed via * {@link UriComponentsBuilder#fromUriString} and then applied as a base URI * to every UriBuilder via {@link UriComponentsBuilder#uriComponents} unless * the UriBuilder itself was created with a URI template that already has a * target address. * @param baseUriTemplate the URI template to use a base URL */ public DefaultUriBuilderFactory(String baseUriTemplate) { this(UriComponentsBuilder.fromUriString(baseUriTemplate)); } /** * Variant of {@link #DefaultUriBuilderFactory(String)} with a * {@code UriComponentsBuilder}. */ public DefaultUriBuilderFactory(UriComponentsBuilder baseUri) { Assert.notNull(baseUri, "'baseUri' is required"); this.baseUri = baseUri; } /** * Provide default URI variable values to use when expanding URI templates * with a Map of variables. * @param defaultUriVariables default URI variable values */ public void setDefaultUriVariables(@Nullable Map defaultUriVariables) { this.defaultUriVariables.clear(); if (defaultUriVariables != null) { this.defaultUriVariables.putAll(defaultUriVariables); } } /** * Return the configured default URI variable values. */ public Map getDefaultUriVariables() { return Collections.unmodifiableMap(this.defaultUriVariables); } /** * Specify the {@link EncodingMode EncodingMode} to use when building URIs. *

By default set to * {@link EncodingMode#URI_COMPONENT EncodingMode.URI_COMPONENT}. * @param encodingMode the encoding mode to use */ public void setEncodingMode(EncodingMode encodingMode) { this.encodingMode = encodingMode; } /** * Return the configured encoding mode. */ public EncodingMode getEncodingMode() { return this.encodingMode; } /** * Whether to parse the path into path segments for the URI string passed * into {@link #uriString(String)} or one of the expand methods. *

Setting this property to {@code true} ensures that URI variables * expanded into the path are subject to path segment encoding rules and * "/" characters are percent-encoded. If set to {@code false} the path is * kept as a full path and expanded URI variables will have "/" characters * preserved. *

By default this is set to {@code true}. * @param parsePath whether to parse the path into path segments */ public void setParsePath(boolean parsePath) { this.parsePath = parsePath; } /** * Whether the handler is configured to parse the path into path segments. */ public boolean shouldParsePath() { return this.parsePath; } // UriTemplateHandler public URI expand(String uriTemplate, Map uriVars) { return uriString(uriTemplate).build(uriVars); } public URI expand(String uriTemplate, Object... uriVars) { return uriString(uriTemplate).build(uriVars); } // UriBuilderFactory public UriBuilder uriString(String uriTemplate) { return new DefaultUriBuilder(uriTemplate); } @Override public UriBuilder builder() { return new DefaultUriBuilder(""); } /** * {@link DefaultUriBuilderFactory} specific implementation of UriBuilder. */ private class DefaultUriBuilder implements UriBuilder { private final UriComponentsBuilder uriComponentsBuilder; public DefaultUriBuilder(String uriTemplate) { this.uriComponentsBuilder = initUriComponentsBuilder(uriTemplate); } private UriComponentsBuilder initUriComponentsBuilder(String uriTemplate) { UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(uriTemplate); UriComponents uriComponents = uriComponentsBuilder.build(); UriComponentsBuilder result = (uriComponents.getHost() == null ? baseUri.cloneBuilder().uriComponents(uriComponents) : uriComponentsBuilder); if (shouldParsePath()) { UriComponents uric = result.build(); String path = uric.getPath(); List pathSegments = uric.getPathSegments(); result.replacePath(null); result.pathSegment(StringUtils.toStringArray(pathSegments)); if (path != null && path.endsWith("/")) { result.path("/"); } } return result; } @Override public DefaultUriBuilder scheme(@Nullable String scheme) { this.uriComponentsBuilder.scheme(scheme); return this; } @Override public DefaultUriBuilder userInfo(@Nullable String userInfo) { this.uriComponentsBuilder.userInfo(userInfo); return this; } @Override public DefaultUriBuilder host(@Nullable String host) { this.uriComponentsBuilder.host(host); return this; } @Override public DefaultUriBuilder port(int port) { this.uriComponentsBuilder.port(port); return this; } @Override public DefaultUriBuilder port(@Nullable String port) { this.uriComponentsBuilder.port(port); return this; } @Override public DefaultUriBuilder path(String path) { this.uriComponentsBuilder.path(path); return this; } @Override public DefaultUriBuilder replacePath(@Nullable String path) { this.uriComponentsBuilder.replacePath(path); return this; } @Override public DefaultUriBuilder pathSegment(String... pathSegments) { this.uriComponentsBuilder.pathSegment(pathSegments); return this; } @Override public DefaultUriBuilder query(String query) { this.uriComponentsBuilder.query(query); return this; } @Override public DefaultUriBuilder replaceQuery(@Nullable String query) { this.uriComponentsBuilder.replaceQuery(query); return this; } @Override public DefaultUriBuilder queryParam(String name, Object... values) { this.uriComponentsBuilder.queryParam(name, values); return this; } @Override public DefaultUriBuilder replaceQueryParam(String name, Object... values) { this.uriComponentsBuilder.replaceQueryParam(name, values); return this; } @Override public DefaultUriBuilder queryParams(MultiValueMap params) { this.uriComponentsBuilder.queryParams(params); return this; } @Override public DefaultUriBuilder replaceQueryParams(MultiValueMap params) { this.uriComponentsBuilder.replaceQueryParams(params); return this; } @Override public DefaultUriBuilder fragment(@Nullable String fragment) { this.uriComponentsBuilder.fragment(fragment); return this; } @Override public URI build(Map uriVars) { if (!defaultUriVariables.isEmpty()) { Map map = new HashMap<>(); map.putAll(defaultUriVariables); map.putAll(uriVars); uriVars = map; } if (encodingMode.equals(EncodingMode.VALUES_ONLY)) { uriVars = UriUtils.encodeUriVariables(uriVars); } UriComponents uriComponents = this.uriComponentsBuilder.build().expand(uriVars); if (encodingMode.equals(EncodingMode.URI_COMPONENT)) { uriComponents = uriComponents.encode(); } return URI.create(uriComponents.toString()); } @Override public URI build(Object... uriVars) { if (ObjectUtils.isEmpty(uriVars) && !defaultUriVariables.isEmpty()) { return build(Collections.emptyMap()); } if (encodingMode.equals(EncodingMode.VALUES_ONLY)) { uriVars = UriUtils.encodeUriVariables(uriVars); } UriComponents uriComponents = this.uriComponentsBuilder.build().expand(uriVars); if (encodingMode.equals(EncodingMode.URI_COMPONENT)) { uriComponents = uriComponents.encode(); } return URI.create(uriComponents.toString()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy