polishing
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2011 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -50,6 +50,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
|||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(ResourceDatabasePopulator.class);
|
private static final Log logger = LogFactory.getLog(ResourceDatabasePopulator.class);
|
||||||
|
|
||||||
|
|
||||||
private List<Resource> scripts = new ArrayList<Resource>();
|
private List<Resource> scripts = new ArrayList<Resource>();
|
||||||
|
|
||||||
private String sqlScriptEncoding;
|
private String sqlScriptEncoding;
|
||||||
@@ -62,6 +63,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
|||||||
|
|
||||||
private String separator = null;
|
private String separator = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param separator the statement separator
|
* @param separator the statement separator
|
||||||
*/
|
*/
|
||||||
@@ -121,6 +123,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
|||||||
this.ignoreFailedDrops = ignoreFailedDrops;
|
this.ignoreFailedDrops = ignoreFailedDrops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void populate(Connection connection) throws SQLException {
|
public void populate(Connection connection) throws SQLException {
|
||||||
for (Resource script : this.scripts) {
|
for (Resource script : this.scripts) {
|
||||||
executeSqlScript(connection, applyEncodingIfNecessary(script), this.continueOnError, this.ignoreFailedDrops);
|
executeSqlScript(connection, applyEncodingIfNecessary(script), this.continueOnError, this.ignoreFailedDrops);
|
||||||
@@ -130,7 +133,8 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
|||||||
private EncodedResource applyEncodingIfNecessary(Resource script) {
|
private EncodedResource applyEncodingIfNecessary(Resource script) {
|
||||||
if (script instanceof EncodedResource) {
|
if (script instanceof EncodedResource) {
|
||||||
return (EncodedResource) script;
|
return (EncodedResource) script;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return new EncodedResource(script, this.sqlScriptEncoding);
|
return new EncodedResource(script, this.sqlScriptEncoding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,22 +181,26 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
|||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(rowsAffected + " rows affected by SQL: " + statement);
|
logger.debug(rowsAffected + " rows affected by SQL: " + statement);
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
}
|
||||||
|
catch (SQLException ex) {
|
||||||
boolean dropStatement = StringUtils.startsWithIgnoreCase(statement.trim(), "drop");
|
boolean dropStatement = StringUtils.startsWithIgnoreCase(statement.trim(), "drop");
|
||||||
if (continueOnError || (dropStatement && ignoreFailedDrops)) {
|
if (continueOnError || (dropStatement && ignoreFailedDrops)) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Failed to execute SQL script statement at line " + lineNumber
|
logger.debug("Failed to execute SQL script statement at line " + lineNumber
|
||||||
+ " of resource " + resource + ": " + statement, ex);
|
+ " of resource " + resource + ": " + statement, ex);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
throw new ScriptStatementFailedException(statement, lineNumber, resource, ex);
|
throw new ScriptStatementFailedException(statement, lineNumber, resource, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
}
|
||||||
|
finally {
|
||||||
try {
|
try {
|
||||||
stmt.close();
|
stmt.close();
|
||||||
} catch (Throwable ex) {
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
logger.debug("Could not close JDBC Statement", ex);
|
logger.debug("Could not close JDBC Statement", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,8 +221,8 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
|||||||
String currentStatement = lnr.readLine();
|
String currentStatement = lnr.readLine();
|
||||||
StringBuilder scriptBuilder = new StringBuilder();
|
StringBuilder scriptBuilder = new StringBuilder();
|
||||||
while (currentStatement != null) {
|
while (currentStatement != null) {
|
||||||
if (StringUtils.hasText(currentStatement)
|
if (StringUtils.hasText(currentStatement) &&
|
||||||
&& (this.commentPrefix != null && !currentStatement.startsWith(this.commentPrefix))) {
|
this.commentPrefix != null && !currentStatement.startsWith(this.commentPrefix)) {
|
||||||
if (scriptBuilder.length() > 0) {
|
if (scriptBuilder.length() > 0) {
|
||||||
scriptBuilder.append('\n');
|
scriptBuilder.append('\n');
|
||||||
}
|
}
|
||||||
@@ -227,13 +235,16 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void maybeAddSeparatorToScript(StringBuilder scriptBuilder) {
|
private void maybeAddSeparatorToScript(StringBuilder scriptBuilder) {
|
||||||
if (separator==null || separator.trim().length()==separator.length()) {
|
if (this.separator == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String trimmed = this.separator.trim();
|
||||||
|
if (trimmed.length() == this.separator.length()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String trimmed = separator.trim();
|
|
||||||
// separator ends in whitespace, so we might want to see if the script is trying to end the same way
|
// separator ends in whitespace, so we might want to see if the script is trying to end the same way
|
||||||
if (scriptBuilder.lastIndexOf(trimmed)==scriptBuilder.length()-trimmed.length()) {
|
if (scriptBuilder.lastIndexOf(trimmed) == scriptBuilder.length() - trimmed.length()) {
|
||||||
scriptBuilder.append(separator.substring(trimmed.length()));
|
scriptBuilder.append(this.separator.substring(trimmed.length()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +303,8 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
|||||||
}
|
}
|
||||||
i += delim.length() - 1;
|
i += delim.length() - 1;
|
||||||
continue;
|
continue;
|
||||||
} else if (c == '\n' || c == '\t') {
|
}
|
||||||
|
else if (c == '\n' || c == '\t') {
|
||||||
c = ' ';
|
c = ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2011 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -27,7 +27,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -105,19 +104,16 @@ import org.springframework.web.context.request.NativeWebRequest;
|
|||||||
import org.springframework.web.context.request.RequestScope;
|
import org.springframework.web.context.request.RequestScope;
|
||||||
import org.springframework.web.context.request.ServletWebRequest;
|
import org.springframework.web.context.request.ServletWebRequest;
|
||||||
import org.springframework.web.context.request.WebRequest;
|
import org.springframework.web.context.request.WebRequest;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
|
||||||
import org.springframework.web.multipart.MultipartRequest;
|
import org.springframework.web.multipart.MultipartRequest;
|
||||||
import org.springframework.web.servlet.HandlerAdapter;
|
import org.springframework.web.servlet.HandlerAdapter;
|
||||||
import org.springframework.web.servlet.HandlerMapping;
|
import org.springframework.web.servlet.HandlerMapping;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
import org.springframework.web.servlet.View;
|
import org.springframework.web.servlet.View;
|
||||||
import org.springframework.web.servlet.mvc.LastModified;
|
|
||||||
import org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver;
|
import org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver;
|
||||||
import org.springframework.web.servlet.mvc.multiaction.MethodNameResolver;
|
import org.springframework.web.servlet.mvc.multiaction.MethodNameResolver;
|
||||||
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
|
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
|
||||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||||
import org.springframework.web.servlet.support.WebContentGenerator;
|
import org.springframework.web.servlet.support.WebContentGenerator;
|
||||||
import org.springframework.web.util.UriTemplate;
|
|
||||||
import org.springframework.web.util.UrlPathHelper;
|
import org.springframework.web.util.UrlPathHelper;
|
||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
|
|
||||||
@@ -663,11 +659,9 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!allowedMethods.isEmpty()) {
|
if (!allowedMethods.isEmpty()) {
|
||||||
throw new HttpRequestMethodNotSupportedException(request.getMethod(),
|
throw new HttpRequestMethodNotSupportedException(request.getMethod(), StringUtils.toStringArray(allowedMethods));
|
||||||
StringUtils.toStringArray(allowedMethods));
|
|
||||||
}
|
}
|
||||||
throw new NoSuchRequestHandlingMethodException(lookupPath, request.getMethod(),
|
throw new NoSuchRequestHandlingMethodException(lookupPath, request.getMethod(), request.getParameterMap());
|
||||||
request.getParameterMap());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -675,17 +669,17 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||||||
if (!hasTypeLevelMapping() || ObjectUtils.isEmpty(getTypeLevelMapping().value())) {
|
if (!hasTypeLevelMapping() || ObjectUtils.isEmpty(getTypeLevelMapping().value())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (Boolean) request.getAttribute(
|
return (Boolean) request.getAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING);
|
||||||
HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the combined pattern for the given methodLevelPattern and path.
|
* Determines the combined pattern for the given methodLevelPattern and path.
|
||||||
* <p>Uses the following algorithm: <ol>
|
* <p>Uses the following algorithm:
|
||||||
|
* <ol>
|
||||||
* <li>If there is a type-level mapping with path information, it is {@linkplain
|
* <li>If there is a type-level mapping with path information, it is {@linkplain
|
||||||
* PathMatcher#combine(String, String) combined} with the method-level pattern.</li>
|
* PathMatcher#combine(String, String) combined} with the method-level pattern.</li>
|
||||||
* <li>If there is a {@linkplain HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE best matching pattern} in the
|
* <li>If there is a {@linkplain HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE best matching pattern}
|
||||||
* request, it is combined with the method-level pattern.</li>
|
* in the request, it is combined with the method-level pattern.</li>
|
||||||
* <li>Otherwise, the method-level pattern is returned.</li>
|
* <li>Otherwise, the method-level pattern is returned.</li>
|
||||||
* </ol>
|
* </ol>
|
||||||
*/
|
*/
|
||||||
@@ -708,7 +702,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||||||
if (StringUtils.hasText(bestMatchingPattern) && bestMatchingPattern.endsWith("*")) {
|
if (StringUtils.hasText(bestMatchingPattern) && bestMatchingPattern.endsWith("*")) {
|
||||||
String combinedPattern = pathMatcher.combine(bestMatchingPattern, methodLevelPattern);
|
String combinedPattern = pathMatcher.combine(bestMatchingPattern, methodLevelPattern);
|
||||||
String matchingPattern = getMatchingPattern(combinedPattern, lookupPath);
|
String matchingPattern = getMatchingPattern(combinedPattern, lookupPath);
|
||||||
if ((matchingPattern != null) && !matchingPattern.equals(bestMatchingPattern)) {
|
if (matchingPattern != null && !matchingPattern.equals(bestMatchingPattern)) {
|
||||||
return matchingPattern;
|
return matchingPattern;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -720,31 +714,31 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
boolean hasSuffix = pattern.indexOf('.') != -1;
|
boolean hasSuffix = pattern.indexOf('.') != -1;
|
||||||
if (!hasSuffix && pathMatcher.match(pattern + ".*", lookupPath)) {
|
if (!hasSuffix) {
|
||||||
return pattern + ".*";
|
String patternWithSuffix = pattern + ".*";
|
||||||
|
if (pathMatcher.match(patternWithSuffix, lookupPath)) {
|
||||||
|
return patternWithSuffix;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pathMatcher.match(pattern, lookupPath)) {
|
if (pathMatcher.match(pattern, lookupPath)) {
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
boolean endsWithSlash = pattern.endsWith("/");
|
boolean endsWithSlash = pattern.endsWith("/");
|
||||||
if (!endsWithSlash && pathMatcher.match(pattern + "/", lookupPath)) {
|
if (!endsWithSlash) {
|
||||||
return pattern + "/";
|
String patternWithSlash = pattern + "/";
|
||||||
|
if (pathMatcher.match(patternWithSlash, lookupPath)) {
|
||||||
|
return patternWithSlash;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void extractHandlerMethodUriTemplates(String mappedPattern,
|
private void extractHandlerMethodUriTemplates(String mappedPattern, String lookupPath, HttpServletRequest request) {
|
||||||
String lookupPath,
|
|
||||||
HttpServletRequest request) {
|
|
||||||
|
|
||||||
Map<String, String> variables =
|
Map<String, String> variables =
|
||||||
(Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
(Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||||
|
|
||||||
int patternVariableCount = StringUtils.countOccurrencesOf(mappedPattern, "{");
|
int patternVariableCount = StringUtils.countOccurrencesOf(mappedPattern, "{");
|
||||||
|
if ((variables == null || patternVariableCount != variables.size()) && pathMatcher.match(mappedPattern, lookupPath)) {
|
||||||
if ( (variables == null || patternVariableCount != variables.size())
|
|
||||||
&& pathMatcher.match(mappedPattern, lookupPath)) {
|
|
||||||
variables = pathMatcher.extractUriTemplateVariables(mappedPattern, lookupPath);
|
variables = pathMatcher.extractUriTemplateVariables(mappedPattern, lookupPath);
|
||||||
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, variables);
|
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, variables);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2011 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -23,7 +23,6 @@ import java.util.Date;
|
|||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
@@ -43,7 +42,12 @@ import org.springframework.web.context.support.GenericWebApplicationContext;
|
|||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
import org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping;
|
import org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping;
|
||||||
|
|
||||||
/** @author Arjen Poutsma */
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Arjen Poutsma
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
*/
|
||||||
public class UriTemplateServletAnnotationControllerTests {
|
public class UriTemplateServletAnnotationControllerTests {
|
||||||
|
|
||||||
private DispatcherServlet servlet;
|
private DispatcherServlet servlet;
|
||||||
@@ -309,9 +313,7 @@ public class UriTemplateServletAnnotationControllerTests {
|
|||||||
assertEquals("test-42", response.getContentAsString());
|
assertEquals("test-42", response.getContentAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// SPR-6640
|
||||||
* See SPR-6640
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void menuTree() throws Exception {
|
public void menuTree() throws Exception {
|
||||||
initServlet(MenuTreeController.class);
|
initServlet(MenuTreeController.class);
|
||||||
@@ -322,9 +324,7 @@ public class UriTemplateServletAnnotationControllerTests {
|
|||||||
assertEquals("M5", response.getContentAsString());
|
assertEquals("M5", response.getContentAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// SPR-6876
|
||||||
* See SPR-6876
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void variableNames() throws Exception {
|
public void variableNames() throws Exception {
|
||||||
initServlet(VariableNamesController.class);
|
initServlet(VariableNamesController.class);
|
||||||
@@ -340,9 +340,7 @@ public class UriTemplateServletAnnotationControllerTests {
|
|||||||
assertEquals("bar-bar", response.getContentAsString());
|
assertEquals("bar-bar", response.getContentAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// SPR-8543
|
||||||
* See SPR-8543
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void variableNamesWithUrlExtension() throws Exception {
|
public void variableNamesWithUrlExtension() throws Exception {
|
||||||
initServlet(VariableNamesController.class);
|
initServlet(VariableNamesController.class);
|
||||||
@@ -353,9 +351,7 @@ public class UriTemplateServletAnnotationControllerTests {
|
|||||||
assertEquals("foo-foo", response.getContentAsString());
|
assertEquals("foo-foo", response.getContentAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// SPR-6906
|
||||||
* See SPR-6906
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void controllerClassName() throws Exception {
|
public void controllerClassName() throws Exception {
|
||||||
servlet = new DispatcherServlet() {
|
servlet = new DispatcherServlet() {
|
||||||
@@ -389,9 +385,7 @@ public class UriTemplateServletAnnotationControllerTests {
|
|||||||
assertEquals("plain-bar", response.getContentAsString());
|
assertEquals("plain-bar", response.getContentAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// SPR-6978
|
||||||
* See SPR-6978
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void doIt() throws Exception {
|
public void doIt() throws Exception {
|
||||||
initServlet(Spr6978Controller.class);
|
initServlet(Spr6978Controller.class);
|
||||||
@@ -419,10 +413,7 @@ public class UriTemplateServletAnnotationControllerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Controllers
|
||||||
/*
|
|
||||||
* Controllers
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public static class SimpleUriTemplateController {
|
public static class SimpleUriTemplateController {
|
||||||
@@ -561,7 +552,6 @@ public class UriTemplateServletAnnotationControllerTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping("hotels")
|
@RequestMapping("hotels")
|
||||||
public static class CrudController {
|
public static class CrudController {
|
||||||
@@ -689,5 +679,4 @@ public class UriTemplateServletAnnotationControllerTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user