added support for SERVER_SERVLET_CONTEXT_PATH. Could be used in some cases Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
|||||||
import org.eclipse.hawkbit.api.ArtifactUrlHandlerProperties;
|
import org.eclipse.hawkbit.api.ArtifactUrlHandlerProperties;
|
||||||
import org.eclipse.hawkbit.api.HostnameResolver;
|
import org.eclipse.hawkbit.api.HostnameResolver;
|
||||||
import org.eclipse.hawkbit.api.PropertyBasedArtifactUrlHandler;
|
import org.eclipse.hawkbit.api.PropertyBasedArtifactUrlHandler;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -58,8 +59,9 @@ public class PropertyHostnameResolverAutoConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(ArtifactUrlHandler.class)
|
@ConditionalOnMissingBean(ArtifactUrlHandler.class)
|
||||||
PropertyBasedArtifactUrlHandler propertyBasedArtifactUrlHandler(
|
PropertyBasedArtifactUrlHandler propertyBasedArtifactUrlHandler(
|
||||||
final ArtifactUrlHandlerProperties urlHandlerProperties) {
|
final ArtifactUrlHandlerProperties urlHandlerProperties,
|
||||||
return new PropertyBasedArtifactUrlHandler(urlHandlerProperties);
|
@Value("${server.servlet.context-path:}") final String contextPath) {
|
||||||
|
return new PropertyBasedArtifactUrlHandler(urlHandlerProperties, contextPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,9 +31,12 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
*/
|
*/
|
||||||
private final Map<String, UrlProtocol> protocols = new HashMap<>();
|
private final Map<String, UrlProtocol> protocols = new HashMap<>();
|
||||||
|
|
||||||
|
public Map<String, UrlProtocol> getProtocols() {
|
||||||
|
return protocols;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol specific properties to generate URLs accordingly.
|
* Protocol specific properties to generate URLs accordingly.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public static class UrlProtocol {
|
public static class UrlProtocol {
|
||||||
|
|
||||||
@@ -50,15 +53,10 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
private String rel = "download-http";
|
private String rel = "download-http";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hypermedia ref pattern for this protocol. Supported place holders are
|
* Hypermedia ref pattern for this protocol. Supported placeholders are the properties
|
||||||
* protocol,controllerId,targetId,targetIdBase62,ip,port,hostname,
|
* supported by {@link PropertyBasedArtifactUrlHandler}.
|
||||||
* artifactFileName,artifactSHA1,
|
|
||||||
* artifactIdBase62,artifactId,tenant,softwareModuleId,
|
|
||||||
* softwareModuleIdBase62.
|
|
||||||
*
|
|
||||||
* The update server itself supports
|
|
||||||
*/
|
*/
|
||||||
private String ref = "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}";
|
private String ref = PropertyBasedArtifactUrlHandler.DEFAULT_URL_PROTOCOL_REF;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol name placeholder that can be used in ref pattern.
|
* Protocol name placeholder that can be used in ref pattern.
|
||||||
@@ -150,11 +148,5 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
public void setProtocol(final String protocol) {
|
public void setProtocol(final String protocol) {
|
||||||
this.protocol = protocol;
|
this.protocol = protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, UrlProtocol> getProtocols() {
|
|
||||||
return protocols;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.api;
|
package org.eclipse.hawkbit.api;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -23,8 +22,7 @@ import java.util.Set;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.api.ArtifactUrlHandlerProperties.UrlProtocol;
|
import org.eclipse.hawkbit.api.ArtifactUrlHandlerProperties.UrlProtocol;
|
||||||
import org.slf4j.Logger;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,25 +34,24 @@ import org.springframework.util.StringUtils;
|
|||||||
* well in the following {@link UrlProtocol#getRef()} patterns:
|
* well in the following {@link UrlProtocol#getRef()} patterns:
|
||||||
*
|
*
|
||||||
* Default:
|
* Default:
|
||||||
* {protocol}://{hostname}:{port}/{tenant}/controller/v1/{controllerId}/
|
* {protocol}://{hostname}:{port}{contextPath}/{tenant}/controller/v1/{controllerId}/
|
||||||
* softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}
|
* softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}
|
||||||
*
|
*
|
||||||
* Default (MD5SUM files):
|
* Default (MD5SUM files):
|
||||||
* {protocol}://{hostname}:{port}/{tenant}/controller/v1/{controllerId}/
|
* {protocol}://{hostname}:{port}{contextPath}/{tenant}/controller/v1/{controllerId}/
|
||||||
* softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}.MD5SUM
|
* softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}.MD5SUM
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(PropertyBasedArtifactUrlHandler.class);
|
|
||||||
|
|
||||||
private static final String PROTOCOL_PLACEHOLDER = "protocol";
|
private static final String PROTOCOL_PLACEHOLDER = "protocol";
|
||||||
|
private static final String HOSTNAME_PLACEHOLDER = "hostname";
|
||||||
|
private static final String IP_PLACEHOLDER = "ip";
|
||||||
|
private static final String PORT_PLACEHOLDER = "port";
|
||||||
|
private static final String CONTEXT_PATH = "contextPath";
|
||||||
private static final String CONTROLLER_ID_PLACEHOLDER = "controllerId";
|
private static final String CONTROLLER_ID_PLACEHOLDER = "controllerId";
|
||||||
private static final String TARGET_ID_BASE10_PLACEHOLDER = "targetId";
|
private static final String TARGET_ID_BASE10_PLACEHOLDER = "targetId";
|
||||||
private static final String TARGET_ID_BASE62_PLACEHOLDER = "targetIdBase62";
|
private static final String TARGET_ID_BASE62_PLACEHOLDER = "targetIdBase62";
|
||||||
private static final String IP_PLACEHOLDER = "ip";
|
|
||||||
private static final String PORT_PLACEHOLDER = "port";
|
|
||||||
private static final String HOSTNAME_PLACEHOLDER = "hostname";
|
|
||||||
private static final String HOSTNAME_REQUEST_PLACEHOLDER = "hostnameRequest";
|
private static final String HOSTNAME_REQUEST_PLACEHOLDER = "hostnameRequest";
|
||||||
private static final String PORT_REQUEST_PLACEHOLDER = "portRequest";
|
private static final String PORT_REQUEST_PLACEHOLDER = "portRequest";
|
||||||
private static final String HOSTNAME_WITH_DOMAIN_REQUEST_PLACEHOLDER = "domainRequest";
|
private static final String HOSTNAME_WITH_DOMAIN_REQUEST_PLACEHOLDER = "domainRequest";
|
||||||
@@ -68,14 +65,18 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
private static final String SOFTWARE_MODULE_ID_BASE10_PLACDEHOLDER = "softwareModuleId";
|
private static final String SOFTWARE_MODULE_ID_BASE10_PLACDEHOLDER = "softwareModuleId";
|
||||||
private static final String SOFTWARE_MODULE_ID_BASE62_PLACDEHOLDER = "softwareModuleIdBase62";
|
private static final String SOFTWARE_MODULE_ID_BASE62_PLACDEHOLDER = "softwareModuleIdBase62";
|
||||||
|
|
||||||
|
final static String DEFAULT_URL_PROTOCOL_REF = "{" + PROTOCOL_PLACEHOLDER + "}://{" + HOSTNAME_PLACEHOLDER + "}:{" + PORT_PLACEHOLDER + "}{" + CONTEXT_PATH + "}/{" + TENANT_PLACEHOLDER + "}/controller/v1/{" + CONTROLLER_ID_PLACEHOLDER + "}/softwaremodules/{" + SOFTWARE_MODULE_ID_BASE10_PLACDEHOLDER + "}/artifacts/{" + ARTIFACT_FILENAME_PLACEHOLDER + "}";
|
||||||
|
|
||||||
private final ArtifactUrlHandlerProperties urlHandlerProperties;
|
private final ArtifactUrlHandlerProperties urlHandlerProperties;
|
||||||
|
private final String contextPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param urlHandlerProperties
|
* @param urlHandlerProperties
|
||||||
* for URL generation configuration
|
* for URL generation configuration
|
||||||
*/
|
*/
|
||||||
public PropertyBasedArtifactUrlHandler(final ArtifactUrlHandlerProperties urlHandlerProperties) {
|
public PropertyBasedArtifactUrlHandler(final ArtifactUrlHandlerProperties urlHandlerProperties, final String contextPath) {
|
||||||
this.urlHandlerProperties = urlHandlerProperties;
|
this.urlHandlerProperties = urlHandlerProperties;
|
||||||
|
this.contextPath = contextPath == null || "/".equals(contextPath) ? "" : contextPath; // normalize
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -85,7 +86,6 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ArtifactUrl> getUrls(final URLPlaceholder placeholder, final ApiType api, final URI requestUri) {
|
public List<ArtifactUrl> getUrls(final URLPlaceholder placeholder, final ApiType api, final URI requestUri) {
|
||||||
|
|
||||||
return urlHandlerProperties.getProtocols().values().stream()
|
return urlHandlerProperties.getProtocols().values().stream()
|
||||||
.filter(urlProtocol -> urlProtocol.getSupports().contains(api) && urlProtocol.isEnabled())
|
.filter(urlProtocol -> urlProtocol.getSupports().contains(api) && urlProtocol.isEnabled())
|
||||||
.map(urlProtocol -> new ArtifactUrl(urlProtocol.getProtocol().toUpperCase(), urlProtocol.getRel(),
|
.map(urlProtocol -> new ArtifactUrl(urlProtocol.getProtocol().toUpperCase(), urlProtocol.getRel(),
|
||||||
@@ -94,7 +94,7 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String generateUrl(final UrlProtocol protocol, final URLPlaceholder placeholder,
|
private String generateUrl(final UrlProtocol protocol, final URLPlaceholder placeholder,
|
||||||
final URI requestUri) {
|
final URI requestUri) {
|
||||||
final Set<Entry<String, String>> entrySet = getReplaceMap(protocol, placeholder, requestUri).entrySet();
|
final Set<Entry<String, String>> entrySet = getReplaceMap(protocol, placeholder, requestUri).entrySet();
|
||||||
|
|
||||||
@@ -103,17 +103,18 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
for (final Entry<String, String> entry : entrySet) {
|
for (final Entry<String, String> entry : entrySet) {
|
||||||
if (entry.getKey().equals(PORT_PLACEHOLDER)) {
|
if (entry.getKey().equals(PORT_PLACEHOLDER)) {
|
||||||
urlPattern = urlPattern.replace(":{" + entry.getKey() + "}",
|
urlPattern = urlPattern.replace(":{" + entry.getKey() + "}",
|
||||||
StringUtils.isEmpty(entry.getValue()) ? "" : (":" + entry.getValue()));
|
ObjectUtils.isEmpty(entry.getValue()) ? "" : (":" + entry.getValue()));
|
||||||
} else {
|
} else {
|
||||||
if(entry.getValue() != null) {
|
if(entry.getValue() != null) {
|
||||||
urlPattern = urlPattern.replace("{" + entry.getKey() + "}", entry.getValue());
|
urlPattern = urlPattern.replace("{" + entry.getKey() + "}", entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return urlPattern;
|
return urlPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, String> getReplaceMap(final UrlProtocol protocol, final URLPlaceholder placeholder,
|
private Map<String, String> getReplaceMap(final UrlProtocol protocol, final URLPlaceholder placeholder,
|
||||||
final URI requestUri) {
|
final URI requestUri) {
|
||||||
final Map<String, String> replaceMap = new HashMap<>();
|
final Map<String, String> replaceMap = new HashMap<>();
|
||||||
replaceMap.put(IP_PLACEHOLDER, protocol.getIp());
|
replaceMap.put(IP_PLACEHOLDER, protocol.getIp());
|
||||||
@@ -123,12 +124,10 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
replaceMap.put(PORT_REQUEST_PLACEHOLDER, getRequestPort(protocol, requestUri));
|
replaceMap.put(PORT_REQUEST_PLACEHOLDER, getRequestPort(protocol, requestUri));
|
||||||
replaceMap.put(HOSTNAME_WITH_DOMAIN_REQUEST_PLACEHOLDER, computeHostWithRequestDomain(protocol, requestUri));
|
replaceMap.put(HOSTNAME_WITH_DOMAIN_REQUEST_PLACEHOLDER, computeHostWithRequestDomain(protocol, requestUri));
|
||||||
|
|
||||||
try {
|
replaceMap.put(CONTEXT_PATH, contextPath);
|
||||||
replaceMap.put(ARTIFACT_FILENAME_PLACEHOLDER,
|
|
||||||
URLEncoder.encode(placeholder.getSoftwareData().getFilename(), StandardCharsets.UTF_8.toString()));
|
replaceMap.put(ARTIFACT_FILENAME_PLACEHOLDER,
|
||||||
} catch (final UnsupportedEncodingException e) {
|
URLEncoder.encode(placeholder.getSoftwareData().getFilename(), StandardCharsets.UTF_8));
|
||||||
LOG.error("Could not encode {}", placeholder.getSoftwareData().getFilename(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
replaceMap.put(ARTIFACT_SHA1_PLACEHOLDER, placeholder.getSoftwareData().getSha1Hash());
|
replaceMap.put(ARTIFACT_SHA1_PLACEHOLDER, placeholder.getSoftwareData().getSha1Hash());
|
||||||
replaceMap.put(PROTOCOL_PLACEHOLDER, protocol.getProtocol());
|
replaceMap.put(PROTOCOL_PLACEHOLDER, protocol.getProtocol());
|
||||||
@@ -138,7 +137,7 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
replaceMap.put(TENANT_ID_BASE62_PLACEHOLDER, Base62Util.fromBase10(placeholder.getTenantId()));
|
replaceMap.put(TENANT_ID_BASE62_PLACEHOLDER, Base62Util.fromBase10(placeholder.getTenantId()));
|
||||||
replaceMap.put(CONTROLLER_ID_PLACEHOLDER, placeholder.getControllerId());
|
replaceMap.put(CONTROLLER_ID_PLACEHOLDER, placeholder.getControllerId());
|
||||||
replaceMap.put(TARGET_ID_BASE10_PLACEHOLDER, String.valueOf(placeholder.getTargetId()));
|
replaceMap.put(TARGET_ID_BASE10_PLACEHOLDER, String.valueOf(placeholder.getTargetId()));
|
||||||
if(placeholder.getTargetId() != null) {
|
if (placeholder.getTargetId() != null) {
|
||||||
replaceMap.put(TARGET_ID_BASE62_PLACEHOLDER, Base62Util.fromBase10(placeholder.getTargetId()));
|
replaceMap.put(TARGET_ID_BASE62_PLACEHOLDER, Base62Util.fromBase10(placeholder.getTargetId()));
|
||||||
}
|
}
|
||||||
replaceMap.put(ARTIFACT_ID_BASE62_PLACEHOLDER,
|
replaceMap.put(ARTIFACT_ID_BASE62_PLACEHOLDER,
|
||||||
@@ -168,7 +167,7 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String getPort(final UrlProtocol protocol) {
|
private static String getPort(final UrlProtocol protocol) {
|
||||||
return protocol.getPort() == null ? null : String.valueOf(protocol.getPort());
|
return ObjectUtils.isEmpty(protocol.getPort()) ? null : String.valueOf(protocol.getPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String computeHostWithRequestDomain(final UrlProtocol protocol, final URI requestUri) {
|
private static String computeHostWithRequestDomain(final UrlProtocol protocol, final URI requestUri) {
|
||||||
@@ -188,7 +187,7 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
final String domain = StringUtils.collectionToDelimitedString(domainElements.subList(1, domainElements.size()),
|
final String domain = StringUtils.collectionToDelimitedString(domainElements.subList(1, domainElements.size()),
|
||||||
".");
|
".");
|
||||||
|
|
||||||
if (StringUtils.isEmpty(domain)) {
|
if (ObjectUtils.isEmpty(domain)) {
|
||||||
return protocol.getHostname();
|
return protocol.getHostname();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class PropertyBasedArtifactUrlHandlerTest {
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setup() {
|
public void setup() {
|
||||||
properties = new ArtifactUrlHandlerProperties();
|
properties = new ArtifactUrlHandlerProperties();
|
||||||
urlHandlerUnderTest = new PropertyBasedArtifactUrlHandler(properties);
|
urlHandlerUnderTest = new PropertyBasedArtifactUrlHandler(properties, "");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ public class PropertyBasedArtifactUrlHandlerTest {
|
|||||||
proto.setPort(5683);
|
proto.setPort(5683);
|
||||||
proto.setProtocol(TEST_PROTO);
|
proto.setProtocol(TEST_PROTO);
|
||||||
proto.setRel(TEST_REL);
|
proto.setRel(TEST_REL);
|
||||||
proto.setSupports(Arrays.asList(ApiType.DMF));
|
proto.setSupports(List.of(ApiType.DMF));
|
||||||
proto.setRef("{protocol}://{ip}:{port}/fw/{tenant}/{controllerId}/sha1/{artifactSHA1}");
|
proto.setRef("{protocol}://{ip}:{port}/fw/{tenant}/{controllerId}/sha1/{artifactSHA1}");
|
||||||
properties.getProtocols().put(TEST_PROTO, proto);
|
properties.getProtocols().put(TEST_PROTO, proto);
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ public class PropertyBasedArtifactUrlHandlerTest {
|
|||||||
proto.setPort(5683);
|
proto.setPort(5683);
|
||||||
proto.setProtocol(TEST_PROTO);
|
proto.setProtocol(TEST_PROTO);
|
||||||
proto.setRel(TEST_REL);
|
proto.setRel(TEST_REL);
|
||||||
proto.setSupports(Arrays.asList(ApiType.DMF));
|
proto.setSupports(List.of(ApiType.DMF));
|
||||||
proto.setRef("{protocol}://{ip}:{port}/fws/{tenant}/{targetIdBase62}/{artifactIdBase62}");
|
proto.setRef("{protocol}://{ip}:{port}/fws/{tenant}/{targetIdBase62}/{artifactIdBase62}");
|
||||||
properties.getProtocols().put("ftp", proto);
|
properties.getProtocols().put("ftp", proto);
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ public class PropertyBasedArtifactUrlHandlerTest {
|
|||||||
proto.setPort(5683);
|
proto.setPort(5683);
|
||||||
proto.setProtocol(TEST_PROTO);
|
proto.setProtocol(TEST_PROTO);
|
||||||
proto.setRel(TEST_REL);
|
proto.setRel(TEST_REL);
|
||||||
proto.setSupports(Arrays.asList(ApiType.DDI));
|
proto.setSupports(List.of(ApiType.DDI));
|
||||||
proto.setRef("{protocol}://{hostnameRequest}:{port}/fws/{tenant}/{targetIdBase62}/{artifactIdBase62}");
|
proto.setRef("{protocol}://{hostnameRequest}:{port}/fws/{tenant}/{targetIdBase62}/{artifactIdBase62}");
|
||||||
properties.getProtocols().put("ftp", proto);
|
properties.getProtocols().put("ftp", proto);
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ public class TestConfiguration implements AsyncConfigurer {
|
|||||||
@Bean
|
@Bean
|
||||||
PropertyBasedArtifactUrlHandler testPropertyBasedArtifactUrlHandler(
|
PropertyBasedArtifactUrlHandler testPropertyBasedArtifactUrlHandler(
|
||||||
final ArtifactUrlHandlerProperties urlHandlerProperties) {
|
final ArtifactUrlHandlerProperties urlHandlerProperties) {
|
||||||
return new PropertyBasedArtifactUrlHandler(urlHandlerProperties);
|
return new PropertyBasedArtifactUrlHandler(urlHandlerProperties, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
Reference in New Issue
Block a user