Merge branch 'eugenp:master' into master
This commit is contained in:
		
						commit
						66f5823c5d
					
				
							
								
								
									
										33
									
								
								core-java-modules/core-java-19/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								core-java-modules/core-java-19/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||||
|  |          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  |          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||
|  |     <modelVersion>4.0.0</modelVersion> | ||||||
|  |     <parent> | ||||||
|  |         <groupId>com.baeldung.core-java-modules</groupId> | ||||||
|  |         <artifactId>core-java-modules</artifactId> | ||||||
|  |         <version>0.0.1-SNAPSHOT</version> | ||||||
|  |     </parent> | ||||||
|  | 
 | ||||||
|  |     <artifactId>core-java-19</artifactId> | ||||||
|  | 
 | ||||||
|  |     <properties> | ||||||
|  |         <maven.compiler.source>19</maven.compiler.source> | ||||||
|  |         <maven.compiler.target>19</maven.compiler.target> | ||||||
|  |         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||||
|  |     </properties> | ||||||
|  |     <build> | ||||||
|  |         <plugins> | ||||||
|  |             <plugin> | ||||||
|  |                 <groupId>org.apache.maven.plugins</groupId> | ||||||
|  |                 <artifactId>maven-compiler-plugin</artifactId> | ||||||
|  |                 <configuration> | ||||||
|  |                     <source>19</source> | ||||||
|  |                     <target>19</target> | ||||||
|  |                     <compilerArgs>--enable-preview</compilerArgs> | ||||||
|  |                 </configuration> | ||||||
|  |             </plugin> | ||||||
|  |         </plugins> | ||||||
|  |     </build> | ||||||
|  | 
 | ||||||
|  | </project> | ||||||
| @ -0,0 +1,3 @@ | |||||||
|  | package com.baeldung.features.records; | ||||||
|  | 
 | ||||||
|  | public record GPSPoint (double lat, double lng) { } | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | package com.baeldung.features.records; | ||||||
|  | 
 | ||||||
|  | public sealed interface ILocation permits Location { | ||||||
|  |     default String getName() { | ||||||
|  |         return switch (this) { | ||||||
|  |             case Location(var name, var ignored) -> name; | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,5 @@ | |||||||
|  | package com.baeldung.features.records; | ||||||
|  | 
 | ||||||
|  | public record Location(String name, GPSPoint gpsPoint) implements ILocation { | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @ -0,0 +1,3 @@ | |||||||
|  | package com.baeldung.features.records; | ||||||
|  | 
 | ||||||
|  | public record LocationWrapper<T>(T t, String description) { } | ||||||
| @ -0,0 +1,99 @@ | |||||||
|  | package com.baeldung.features; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.features.records.GPSPoint; | ||||||
|  | import com.baeldung.features.records.Location; | ||||||
|  | import com.baeldung.features.records.LocationWrapper; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.AssertionsForClassTypes.assertThat; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | public class JEP405RecordPatternsUnitTest { | ||||||
|  | 
 | ||||||
|  |     Object object = new Location("Home", new GPSPoint(1.0, 2.0)); | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenObject_whenTestInstanceOfAndCastIdiom_shouldMatchNewInstanceOf() { | ||||||
|  |         // old Code | ||||||
|  |         if (object instanceof Location) { | ||||||
|  |             Location l = (Location) object; | ||||||
|  |             assertThat(l).isInstanceOf(Location.class); | ||||||
|  |         } | ||||||
|  |         // new code | ||||||
|  |         if (object instanceof Location l) { | ||||||
|  |             assertThat(l).isInstanceOf(Location.class); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenObject_whenTestDestruct_shouldMatch() { | ||||||
|  |         // when | ||||||
|  |         if (object instanceof Location(var name, var gpsPoint)) { | ||||||
|  |             // then | ||||||
|  |             assertThat(name).isEqualTo("Home"); | ||||||
|  |             assertThat(gpsPoint).isInstanceOf(GPSPoint.class); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (object instanceof Location(var name, GPSPoint(var lat, var lng))) { | ||||||
|  |             assertThat(lat).isEqualTo(1.0); | ||||||
|  |             assertThat(lng).isEqualTo(2.0); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenObjectIsNull_whenTestNullCheck_shouldNotMatch() { | ||||||
|  |         Location l = null; | ||||||
|  |         if (l instanceof Location location) { | ||||||
|  |             assertThat(location).isNotNull(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenObject_whenTestGenericTypeInstanceOf_shouldMatch() { | ||||||
|  |         LocationWrapper<Location> locationWrapper = new LocationWrapper<>(new Location("Home", new GPSPoint(1.0, 2.0)), "Description"); | ||||||
|  |         if (locationWrapper instanceof LocationWrapper<Location>(var ignored, var description)) { | ||||||
|  |             assertThat(description).isEqualTo("Description"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenObject_whenTestSwitchExpressionWithTypePattern_shouldMatch() { | ||||||
|  |         String result = switch (object) { | ||||||
|  |             case Location l -> l.name(); | ||||||
|  |             default -> "default"; | ||||||
|  |         }; | ||||||
|  |         assertThat(result).isEqualTo("Home"); | ||||||
|  |         Double result2 = switch (object) { | ||||||
|  |             case Location(var name, GPSPoint(var lat, var lng)) -> lat; | ||||||
|  |             default -> 0.0; | ||||||
|  |         }; | ||||||
|  |         assertThat(result2).isEqualTo(1.0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenObject_whenTestGuardedSwitchExpressionWithTypePattern_shouldMatchAndGuard() { | ||||||
|  |         String result = switch (object) { | ||||||
|  |             case Location(var name, var ignored) when name.equals("Home") -> "Test"; | ||||||
|  |             case Location(var name, var ignored) -> name; | ||||||
|  |             default -> "default"; | ||||||
|  |         }; | ||||||
|  |         assertThat(result).isEqualTo("Test"); | ||||||
|  | 
 | ||||||
|  |         String otherResult = switch (new Location("Other", new GPSPoint(1.0, 2.0))) { | ||||||
|  |             case Location(var name, var ignored) when name.equals("Home") -> "Test"; | ||||||
|  |             case Location(var name, var ignored) -> name; | ||||||
|  |             default -> "default"; | ||||||
|  |         }; | ||||||
|  |         assertThat(otherResult).isEqualTo("Other"); | ||||||
|  | 
 | ||||||
|  |         Object noLocation = new GPSPoint(1.0, 2.0); | ||||||
|  |         String noLocationResult = switch (noLocation) { | ||||||
|  |             case Location(var name, var ignored) when name.equals("Home") -> "Test"; | ||||||
|  |             case Location(var name, var ignored) -> name; | ||||||
|  |             default -> "default"; | ||||||
|  |         }; | ||||||
|  |         assertThat(noLocationResult).isEqualTo("default"); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | package com.baeldung.getclassfromstr; | ||||||
|  | 
 | ||||||
|  | public class MyNiceClass { | ||||||
|  |     public String greeting(){ | ||||||
|  |         return "Hi there, I wish you all the best!"; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,22 @@ | |||||||
|  | package com.baeldung.getclassfromstr; | ||||||
|  | 
 | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | 
 | ||||||
|  | import static org.junit.jupiter.api.Assertions.*; | ||||||
|  | 
 | ||||||
|  | public class GetClassObjectFromStringUnitTest { | ||||||
|  |     @Test | ||||||
|  |     void givenQualifiedClsName_whenUsingClassForName_shouldGetExpectedClassObject() throws ReflectiveOperationException { | ||||||
|  |         Class cls = Class.forName("com.baeldung.getclassfromstr.MyNiceClass"); | ||||||
|  |         assertNotNull(cls); | ||||||
|  | 
 | ||||||
|  |         MyNiceClass myNiceObject = (MyNiceClass) cls.getDeclaredConstructor().newInstance(); | ||||||
|  |         assertNotNull(myNiceObject); | ||||||
|  |         assertEquals("Hi there, I wish you all the best!", myNiceObject.greeting()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenSimpleName_whenUsingClassForName_shouldGetExpectedException() { | ||||||
|  |         assertThrows(ClassNotFoundException.class, () -> Class.forName("MyNiceClass")); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								pom.xml
									
									
									
									
									
								
							| @ -1130,6 +1130,7 @@ | |||||||
|                  <!-- <module>core-java-modules/core-java-15</module> --> <!-- uses preview features, to be decided how to handle --> |                  <!-- <module>core-java-modules/core-java-15</module> --> <!-- uses preview features, to be decided how to handle --> | ||||||
|                  <!-- <module>core-java-modules/core-java-16</module> --> <!-- uses preview features, to be decided how to handle --> |                  <!-- <module>core-java-modules/core-java-16</module> --> <!-- uses preview features, to be decided how to handle --> | ||||||
|                  <!-- <module>core-java-modules/core-java-17</module> --> <!-- uses preview features, to be decided how to handle --> |                  <!-- <module>core-java-modules/core-java-17</module> --> <!-- uses preview features, to be decided how to handle --> | ||||||
|  |                  <!-- <module>core-java-modules/core-java-19</module> --> <!-- uses preview features, to be decided how to handle --> | ||||||
|                  <module>core-java-modules/core-java-collections-set</module> |                  <module>core-java-modules/core-java-collections-set</module> | ||||||
|                  <module>core-java-modules/core-java-collections-list-4</module> |                  <module>core-java-modules/core-java-collections-list-4</module> | ||||||
|                  <module>core-java-modules/core-java-collections-maps-4</module> |                  <module>core-java-modules/core-java-collections-maps-4</module> | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ | |||||||
|         <module>stripe</module> |         <module>stripe</module> | ||||||
|         <module>twilio</module> |         <module>twilio</module> | ||||||
|         <module>twitter4j</module> |         <module>twitter4j</module> | ||||||
|  |         <module>sentry-servlet</module> | ||||||
|     </modules> |     </modules> | ||||||
| 
 | 
 | ||||||
|     <build> |     <build> | ||||||
|  | |||||||
							
								
								
									
										49
									
								
								saas-modules/sentry-servlet/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								saas-modules/sentry-servlet/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  |     xmlns="http://maven.apache.org/POM/4.0.0" | ||||||
|  |     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||
|  |     <modelVersion>4.0.0</modelVersion> | ||||||
|  |     <parent> | ||||||
|  |         <groupId>com.baeldung</groupId> | ||||||
|  |         <artifactId>saas-modules</artifactId> | ||||||
|  |         <version>1.0.0-SNAPSHOT</version> | ||||||
|  |     </parent> | ||||||
|  |     <artifactId>sentry-servlet</artifactId> | ||||||
|  |     <name>sentry-servlet</name> | ||||||
|  |     <packaging>war</packaging> | ||||||
|  |      | ||||||
|  |     <properties> | ||||||
|  |       <sentry.version>6.11.0</sentry.version> | ||||||
|  |       <cargo.version>1.10.4</cargo.version> | ||||||
|  |     </properties> | ||||||
|  |      | ||||||
|  |     <dependencies> | ||||||
|  |       <dependency> | ||||||
|  |         <groupId>io.sentry</groupId> | ||||||
|  |         <artifactId>sentry-servlet</artifactId> | ||||||
|  |         <version>${sentry.version}</version> | ||||||
|  |       </dependency> | ||||||
|  | 
 | ||||||
|  |       <dependency> | ||||||
|  |         <groupId>javax.servlet</groupId> | ||||||
|  |         <artifactId>javax.servlet-api</artifactId> | ||||||
|  |         <scope>provided</scope> | ||||||
|  |       </dependency> | ||||||
|  |     </dependencies> | ||||||
|  |      | ||||||
|  |     <build> | ||||||
|  |       <plugins> | ||||||
|  |         <plugin> | ||||||
|  |           <groupId>org.codehaus.cargo</groupId> | ||||||
|  |           <artifactId>cargo-maven3-plugin</artifactId> | ||||||
|  |           <version>${cargo.version}</version> | ||||||
|  |           <configuration> | ||||||
|  |             <container> | ||||||
|  |               <containerId>tomcat9x</containerId> | ||||||
|  |               <type>embedded</type> | ||||||
|  |             </container> | ||||||
|  |           </configuration> | ||||||
|  |         </plugin> | ||||||
|  |       </plugins> | ||||||
|  |     </build> | ||||||
|  | </project> | ||||||
| @ -0,0 +1,32 @@ | |||||||
|  | package com.baeldung.sentry.servlet; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | 
 | ||||||
|  | import javax.servlet.ServletException; | ||||||
|  | import javax.servlet.annotation.WebServlet; | ||||||
|  | import javax.servlet.http.HttpServlet; | ||||||
|  | import javax.servlet.http.HttpServletRequest; | ||||||
|  | import javax.servlet.http.HttpServletResponse; | ||||||
|  | 
 | ||||||
|  | @WebServlet(urlPatterns = "/fault", loadOnStartup = 1) | ||||||
|  | public class FaultyServlet extends HttpServlet { | ||||||
|  | 
 | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |      | ||||||
|  |     @Override | ||||||
|  |     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||||
|  |          | ||||||
|  |         String op = req.getParameter("op"); | ||||||
|  |         if( "fault".equals(op) ) { | ||||||
|  |             resp.sendError(500, "Something bad happened !"); | ||||||
|  |         } | ||||||
|  |         else if ( "exception".equals(op) ) { | ||||||
|  |             throw new IllegalArgumentException("Internal error"); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             resp.setStatus(200); | ||||||
|  |             resp.setContentType("text/plain"); | ||||||
|  |             resp.getWriter().println("OK"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,39 @@ | |||||||
|  | package com.baeldung.sentry.support; | ||||||
|  | 
 | ||||||
|  | import javax.servlet.ServletContext; | ||||||
|  | import javax.servlet.ServletContextEvent; | ||||||
|  | import javax.servlet.ServletContextListener; | ||||||
|  | import javax.servlet.annotation.WebListener; | ||||||
|  | 
 | ||||||
|  | import io.sentry.Sentry; | ||||||
|  | import io.sentry.SentryLevel; | ||||||
|  | 
 | ||||||
|  | @WebListener | ||||||
|  | public class SentryContextListener implements ServletContextListener { | ||||||
|  |     @Override | ||||||
|  |     public void contextInitialized(ServletContextEvent sce) { | ||||||
|  |          | ||||||
|  |         // Besides standard supported locations, let's also allow the DSN to be | ||||||
|  |         // passed using servlet container managed parameters. This can be useful if your app | ||||||
|  |         // is hosted in a shared application server. | ||||||
|  |         ServletContext context = sce.getServletContext(); | ||||||
|  |         String sentryDsn = context.getInitParameter("sentry.dsn"); | ||||||
|  |          | ||||||
|  |         if ( sentryDsn != null ) { | ||||||
|  |             context.log("[I21] sentry.dsn init parameter found. Configuring Sentry SDK..."); | ||||||
|  |             Sentry.init(sentryDsn); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             context.log("[I25] sentry.dsn init parameter not found. Configuring Sentry SDK with defaults"); | ||||||
|  |             Sentry.init(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void contextDestroyed(ServletContextEvent sce) { | ||||||
|  |         sce.getServletContext().log("[I34] shutting down context"); | ||||||
|  |         Sentry.captureMessage("[I35] contextDestroyed", SentryLevel.INFO); | ||||||
|  |         Sentry.close(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,32 @@ | |||||||
|  | package com.baeldung.sentry.support; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | 
 | ||||||
|  | import javax.servlet.Filter; | ||||||
|  | import javax.servlet.FilterChain; | ||||||
|  | import javax.servlet.ServletException; | ||||||
|  | import javax.servlet.ServletRequest; | ||||||
|  | import javax.servlet.ServletResponse; | ||||||
|  | import javax.servlet.annotation.WebFilter; | ||||||
|  | import javax.servlet.http.HttpServletResponse; | ||||||
|  | 
 | ||||||
|  | import io.sentry.Sentry; | ||||||
|  | import io.sentry.SentryLevel; | ||||||
|  | 
 | ||||||
|  | @WebFilter(urlPatterns = "/*") | ||||||
|  | public class SentryFilter implements Filter { | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { | ||||||
|  |         try { | ||||||
|  |             chain.doFilter(request, response); | ||||||
|  |             int rc = ((HttpServletResponse) response).getStatus(); | ||||||
|  |             if (rc/100 == 5) { | ||||||
|  |                 Sentry.captureMessage("Application error: code=" + rc, SentryLevel.ERROR); | ||||||
|  |             } | ||||||
|  |         } catch (Throwable t) { | ||||||
|  |             Sentry.captureException(t); | ||||||
|  |             throw t; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,3 @@ | |||||||
|  | # Sentry configuration file | ||||||
|  | # put your DSN here | ||||||
|  | dsn=https://xxxxxxxxxxxxxxxx@zzzzzzz.ingest.sentry.io/wwww | ||||||
							
								
								
									
										14
									
								
								saas-modules/sentry-servlet/src/main/webapp/WEB-INF/web.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								saas-modules/sentry-servlet/src/main/webapp/WEB-INF/web.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <web-app  | ||||||
|  |   xmlns="http://xmlns.jcp.org/xml/ns/javaee" | ||||||
|  |   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  |   xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" | ||||||
|  |   version="4.0"> | ||||||
|  |    | ||||||
|  |   <!--  | ||||||
|  |   <context-param> | ||||||
|  |   	<param-name>sentry.dsn</param-name> | ||||||
|  |   	<param-value>https://093dbb121a584893b17677bd87c5ec1f@o75061.ingest.sentry.io/4504352731627520</param-value> | ||||||
|  |   </context-param> | ||||||
|  | --> | ||||||
|  | </web-app> | ||||||
| @ -0,0 +1,46 @@ | |||||||
|  | package com.baeldung.sentry.servlet; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | 
 | ||||||
|  | import java.net.HttpURLConnection; | ||||||
|  | import java.net.URL; | ||||||
|  | 
 | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | 
 | ||||||
|  | class FaultyServletLiveTest { | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void testGivenFaultyRequestWithNoQueryString_thenSuccess() throws Exception { | ||||||
|  |          | ||||||
|  |         //int port = getServerPort(); | ||||||
|  |         URL u = new URL("http://localhost:8080/sentry-servlet/fault"); | ||||||
|  |         HttpURLConnection conn = (HttpURLConnection)u.openConnection(); | ||||||
|  |         int rc = conn.getResponseCode(); | ||||||
|  |         assertThat(rc) | ||||||
|  |           .isEqualTo(200); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void testGivenFaultyRequestWithFaultString_thenFail() throws Exception { | ||||||
|  |          | ||||||
|  |         //int port = getServerPort(); | ||||||
|  |         URL u = new URL("http://localhost:8080/sentry-servlet/fault?fault=true"); | ||||||
|  |         HttpURLConnection conn = (HttpURLConnection)u.openConnection(); | ||||||
|  |         int rc = conn.getResponseCode(); | ||||||
|  |         assertThat(rc) | ||||||
|  |           .isEqualTo(500); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void testGivenFaultyRequestWithExceptionString_thenFail() throws Exception { | ||||||
|  |          | ||||||
|  |         //int port = getServerPort(); | ||||||
|  |         URL u = new URL("http://localhost:8080/sentry-servlet/fault?exception=true"); | ||||||
|  |         HttpURLConnection conn = (HttpURLConnection)u.openConnection(); | ||||||
|  |         int rc = conn.getResponseCode(); | ||||||
|  |         assertThat(rc) | ||||||
|  |           .isEqualTo(500); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user