Polishing

This commit is contained in:
Juergen Hoeller 2019-06-11 20:57:27 +02:00
parent 1956cb1e57
commit 7dc92aa05d
30 changed files with 82 additions and 106 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -169,7 +169,7 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
}
/**
* Set the converted value of the constructor argument,
* Set the converted value of this property value,
* after processed type conversion.
*/
public synchronized void setConvertedValue(@Nullable Object value) {
@ -178,7 +178,7 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
}
/**
* Return the converted value of the constructor argument,
* Return the converted value of this property value,
* after processed type conversion.
*/
@Nullable

View File

@ -180,7 +180,7 @@ public class InjectionPoint {
if (this == other) {
return true;
}
if (getClass() != other.getClass()) {
if (other == null || getClass() != other.getClass()) {
return false;
}
InjectionPoint otherPoint = (InjectionPoint) other;

View File

@ -234,7 +234,7 @@ public class BeanDefinitionVisitor {
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
protected void visitList(List listVal) {
for (int i = 0; i < listVal.size(); i++) {
Object elem = listVal.get(i);
@ -245,7 +245,7 @@ public class BeanDefinitionVisitor {
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
protected void visitSet(Set setVal) {
Set newContent = new LinkedHashSet();
boolean entriesModified = false;
@ -262,7 +262,7 @@ public class BeanDefinitionVisitor {
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
protected void visitMap(Map<?, ?> mapVal) {
Map newContent = new LinkedHashMap();
boolean entriesModified = false;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2019 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.
@ -26,7 +26,7 @@ import org.springframework.util.Assert;
* @author Rod Johnson
* @author Juergen Hoeller
* @see BeanDefinition#getPropertyValues()
* @see org.springframework.beans.factory.BeanFactory#getBean
* @see org.springframework.beans.factory.BeanFactory#getBean(String)
*/
public class RuntimeBeanReference implements BeanReference {
@ -39,9 +39,7 @@ public class RuntimeBeanReference implements BeanReference {
/**
* Create a new RuntimeBeanReference to the given bean name,
* without explicitly marking it as reference to a bean in
* the parent factory.
* Create a new RuntimeBeanReference to the given bean name.
* @param beanName name of the target bean
*/
public RuntimeBeanReference(String beanName) {
@ -50,11 +48,10 @@ public class RuntimeBeanReference implements BeanReference {
/**
* Create a new RuntimeBeanReference to the given bean name,
* with the option to mark it as reference to a bean in
* the parent factory.
* with the option to mark it as reference to a bean in the parent factory.
* @param beanName name of the target bean
* @param toParent whether this is an explicit reference to
* a bean in the parent factory
* @param toParent whether this is an explicit reference to a bean in the
* parent factory
*/
public RuntimeBeanReference(String beanName, boolean toParent) {
Assert.hasText(beanName, "'beanName' must not be empty");
@ -69,8 +66,7 @@ public class RuntimeBeanReference implements BeanReference {
}
/**
* Return whether this is an explicit reference to a bean
* in the parent factory.
* Return whether this is an explicit reference to a bean in the parent factory.
*/
public boolean isToParent() {
return this.toParent;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -117,7 +117,7 @@ public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map
* case of a shared singleton; else, on each {@link #getObject()} call.
* <p>The default implementation returns the merged {@code Map} instance.
* @return the object returned by this factory
* @see #process(java.util.Map, MatchCallback)
* @see #process(MatchCallback)
*/
protected Map<String, Object> createMap() {
Map<String, Object> result = new LinkedHashMap<>();
@ -125,7 +125,7 @@ public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map
return result;
}
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
private void merge(Map<String, Object> output, Map<String, Object> map) {
map.forEach((key, value) -> {
Object existing = output.get(key);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -128,7 +128,7 @@ public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryB
* <p>Invoked lazily the first time {@link #getObject()} is invoked in
* case of a shared singleton; else, on each {@link #getObject()} call.
* @return the object returned by this factory
* @see #process(MatchCallback) ()
* @see #process(MatchCallback)
*/
protected Properties createProperties() {
Properties result = CollectionFactory.createStringAdaptingProperties();

View File

@ -65,7 +65,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
public static final String SCOPE_DEFAULT = "";
/**
* Constant that indicates no autowiring at all.
* Constant that indicates no external autowiring at all.
* @see #setAutowireMode
*/
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -1648,7 +1648,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -180,6 +180,8 @@ public final class BeanDefinitionBuilder {
/**
* Set the name of a non-static factory method to use for this definition,
* including the bean name of the factory instance to call the method on.
* @param factoryMethod the name of the factory method
* @param factoryBean the name of the bean to call the specified factory method on
* @since 4.3.6
*/
public BeanDefinitionBuilder setFactoryMethodOnBean(String factoryMethod, String factoryBean) {
@ -209,7 +211,7 @@ public final class BeanDefinitionBuilder {
}
/**
* Add the supplied property value under the given name.
* Add the supplied property value under the given property name.
*/
public BeanDefinitionBuilder addPropertyValue(String name, @Nullable Object value) {
this.beanDefinition.getPropertyValues().add(name, value);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -385,8 +385,7 @@ class BeanDefinitionValueResolver {
private Object resolveManagedArray(Object argName, List<?> ml, Class<?> elementType) {
Object resolved = Array.newInstance(elementType, ml.size());
for (int i = 0; i < ml.size(); i++) {
Array.set(resolved, i,
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
Array.set(resolved, i, resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
@ -397,8 +396,7 @@ class BeanDefinitionValueResolver {
private List<?> resolveManagedList(Object argName, List<?> ml) {
List<Object> resolved = new ArrayList<>(ml.size());
for (int i = 0; i < ml.size(); i++) {
resolved.add(
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -176,7 +176,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
@Override
public boolean equals(Object other) {
return (getClass() == other.getClass() &&
return (other != null && getClass() == other.getClass() &&
this.beanDefinition.equals(((CglibIdentitySupport) other).beanDefinition));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2019 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.
@ -23,7 +23,9 @@ import org.junit.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.tests.sample.beans.TestBean;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Rod Johnson
@ -36,9 +38,9 @@ public class BeanDefinitionBuilderTests {
String[] dependsOn = new String[] { "A", "B", "C" };
BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
bdb.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bdb.addPropertyReference("age", "15");
for (int i = 0; i < dependsOn.length; i++) {
bdb.addDependsOn(dependsOn[i]);
bdb.addPropertyValue("age", "15");
for (String dependsOnEntry : dependsOn) {
bdb.addDependsOn(dependsOnEntry);
}
RootBeanDefinition rbd = (RootBeanDefinition) bdb.getBeanDefinition();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2019 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.
@ -61,8 +61,6 @@ public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOt
private ITestBean spouse;
protected ITestBean[] spouses;
private String touchy;
private String[] stringArray;

View File

@ -166,7 +166,7 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);

View File

@ -241,7 +241,7 @@ public final class CollectionFactory {
* @see java.util.TreeMap
* @see java.util.LinkedHashMap
*/
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
public static <K, V> Map<K, V> createApproximateMap(@Nullable Object map, int capacity) {
if (map instanceof EnumMap) {
EnumMap enumMap = new EnumMap((EnumMap) map);
@ -294,7 +294,7 @@ public final class CollectionFactory {
* {@code null}; or if the desired {@code mapType} is {@link EnumMap} and
* the supplied {@code keyType} is not a subtype of {@link Enum}
*/
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
public static <K, V> Map<K, V> createMap(Class<?> mapType, @Nullable Class<?> keyType, int capacity) {
Assert.notNull(mapType, "Map type must not be null");
if (mapType.isInterface()) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2019 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.
@ -26,7 +26,7 @@ import org.springframework.core.convert.converter.ConverterFactory;
* @author Stephane Nicoll
* @since 4.3
*/
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
final class IntegerToEnumConverterFactory implements ConverterFactory<Integer, Enum> {
@Override

View File

@ -26,7 +26,7 @@ import org.springframework.core.convert.converter.ConverterFactory;
* @author Stephane Nicoll
* @since 3.0
*/
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -383,7 +383,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
public Map<String, Object> getSystemProperties() {
try {
return (Map) System.getProperties();
@ -409,7 +409,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
public Map<String, Object> getSystemEnvironment() {
if (suppressGetenvAccess()) {
return Collections.emptyMap();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -75,8 +75,10 @@ public class StandardEnvironment extends AbstractEnvironment {
*/
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
propertySources.addLast(
new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -84,10 +84,9 @@ public enum TypeCode {
public static TypeCode forName(String name) {
String searchingFor = name.toUpperCase();
TypeCode[] tcs = values();
for (int i = 1; i < tcs.length; i++) {
if (tcs[i].name().equals(searchingFor)) {
if (tcs[i].name().equalsIgnoreCase(name)) {
return tcs[i];
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2019 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.
@ -62,7 +62,7 @@ public class ReflectiveConstructorResolver implements ConstructorResolver {
Arrays.sort(ctors, (c1, c2) -> {
int c1pl = c1.getParameterCount();
int c2pl = c2.getParameterCount();
return (c1pl < c2pl ? -1 : (c1pl > c2pl ? 1 : 0));
return Integer.compare(c1pl, c2pl);
});
Constructor<?> closeMatch = null;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2019 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.
@ -83,20 +83,16 @@ public class StandardTypeComparator implements TypeComparator {
return leftBigInteger.compareTo(rightBigInteger);
}
else if (leftNumber instanceof Long || rightNumber instanceof Long) {
// Don't call Long.compare here - only available on JDK 1.7+
return compare(leftNumber.longValue(), rightNumber.longValue());
return Long.compare(leftNumber.longValue(), rightNumber.longValue());
}
else if (leftNumber instanceof Integer || rightNumber instanceof Integer) {
// Don't call Integer.compare here - only available on JDK 1.7+
return compare(leftNumber.intValue(), rightNumber.intValue());
return Integer.compare(leftNumber.intValue(), rightNumber.intValue());
}
else if (leftNumber instanceof Short || rightNumber instanceof Short) {
// Don't call Short.compare here - only available on JDK 1.7+
return compare(leftNumber.shortValue(), rightNumber.shortValue());
return leftNumber.shortValue() - rightNumber.shortValue();
}
else if (leftNumber instanceof Byte || rightNumber instanceof Byte) {
// Don't call Short.compare here - only available on JDK 1.7+
return compare(leftNumber.byteValue(), rightNumber.byteValue());
return leftNumber.byteValue() - rightNumber.byteValue();
}
else {
// Unknown Number subtypes -> best guess is double multiplication
@ -116,21 +112,4 @@ public class StandardTypeComparator implements TypeComparator {
throw new SpelEvaluationException(SpelMessage.NOT_COMPARABLE, left.getClass(), right.getClass());
}
private static int compare(long x, long y) {
return (x < y ? -1 : (x > y ? 1 : 0));
}
private static int compare(int x, int y) {
return (x < y ? -1 : (x > y ? 1 : 0));
}
private static int compare(short x, short y) {
return x - y;
}
private static int compare(byte x, byte y) {
return x - y;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -272,7 +272,7 @@ public class PreparedStatementCreatorFactory {
Collection<?> entries = (Collection<?>) in;
for (Object entry : entries) {
if (entry instanceof Object[]) {
Object[] valueArray = ((Object[])entry);
Object[] valueArray = (Object[]) entry;
for (Object argValue : valueArray) {
StatementCreatorUtils.setParameterValue(ps, sqlColIndx++, declaredParameter, argValue);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -92,10 +92,11 @@ public class SimpleJmsHeaderMapper extends AbstractHeaderMapper<Message> impleme
logger.debug("Failed to set JMSType - skipping", ex);
}
}
Set<String> headerNames = headers.keySet();
for (String headerName : headerNames) {
Set<Map.Entry<String, Object>> entries = headers.entrySet();
for (Map.Entry<String, Object> entry : entries) {
String headerName = entry.getKey();
if (StringUtils.hasText(headerName) && !headerName.startsWith(JmsHeaders.PREFIX)) {
Object value = headers.get(headerName);
Object value = entry.getValue();
if (value != null && SUPPORTED_PROPERTY_TYPES.contains(value.getClass())) {
try {
String propertyName = this.fromHeaderName(headerName);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -180,9 +180,9 @@ public class DefaultContextCache implements ContextCache {
}
// Remove empty entries from the hierarchy map.
for (MergedContextConfiguration currentKey : this.hierarchyMap.keySet()) {
if (this.hierarchyMap.get(currentKey).isEmpty()) {
this.hierarchyMap.remove(currentKey);
for (Map.Entry<MergedContextConfiguration, Set<MergedContextConfiguration>> entry : this.hierarchyMap.entrySet()) {
if (entry.getValue().isEmpty()) {
this.hierarchyMap.remove(entry.getKey());
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -142,7 +142,7 @@ public abstract class ModelAndViewAssert {
* @param comparator the comparator to use (may be {@code null}). If not
* specifying the comparator, both lists will be sorted not using any comparator.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
public static void assertSortAndCompareListModelAttribute(
ModelAndView mav, String modelName, List expectedList, Comparator comparator) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -253,7 +253,7 @@ public final class WebAsyncManager {
* @see #getConcurrentResult()
* @see #getConcurrentResultContext()
*/
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
public void startCallableProcessing(Callable<?> callable, Object... processingContext) throws Exception {
Assert.notNull(callable, "Callable must not be null");
startCallableProcessing(new WebAsyncTask(callable), processingContext);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -60,7 +60,7 @@ public class MapMethodProcessor implements HandlerMethodArgumentResolver, Handle
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes", "unchecked"})
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -113,8 +113,7 @@ class SessionAttributesHandler {
* @param attributes candidate attributes for session storage
*/
public void storeAttributes(WebSession session, Map<String, ?> attributes) {
attributes.keySet().forEach(name -> {
Object value = attributes.get(name);
attributes.forEach((name, value) -> {
if (value != null && isHandlerSessionAttribute(name, value.getClass())) {
session.getAttributes().put(name, value);
}

View File

@ -390,7 +390,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
result.append(UriUtils.encodePathSegment(value.toString(), encodingScheme));
endLastMatch = matcher.end();
}
result.append(targetUrl.substring(endLastMatch, targetUrl.length()));
result.append(targetUrl.substring(endLastMatch));
return result;
}