/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2013-2017 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * http://glassfish.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package org.glassfish.jersey.tests.e2e.server; import java.util.logging.Level; import java.util.logging.LogRecord; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.client.Entity; import javax.ws.rs.core.Application; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.internal.LocalizationMessages; import org.glassfish.jersey.spi.ExtendedExceptionMapper; import org.glassfish.jersey.test.JerseyTest; import org.glassfish.jersey.test.TestProperties; import org.junit.Assert; import org.junit.Test; import static org.junit.Assert.fail; /** * @author Miroslav Fuksa * */ public class ExtendedExceptionMapperTest extends JerseyTest { @Override protected Application configure() { set(TestProperties.RECORD_LOG_LEVEL, Level.FINE.intValue()); return new ResourceConfig( TestResource.class, ExceptionMapperA.class, ExceptionMapperB.class, ExceptionMapperC.class, ExceptionMapperD.class, ExceptionMapperE.class, ExceptionMapperX.class ); } public static class ExceptionA extends RuntimeException { public ExceptionA(String message) { super(message); } } public static class ExceptionB extends ExceptionA { public ExceptionB(String message) { super(message); } } public static class ExceptionC extends ExceptionB { public ExceptionC(String message) { super(message); } } public static class ExceptionD extends ExceptionC { public ExceptionD(String message) { super(message); } } public static class ExceptionE extends ExceptionD { public ExceptionE(String message) { super(message); } } public static class ExceptionX extends RuntimeException { public ExceptionX(String message) { super(message); } } public static class ExceptionMapperA implements ExtendedExceptionMapper<ExceptionA> { @Override public boolean isMappable(ExceptionA exception) { return exception.getMessage().substring(2).contains("A"); } @Override public Response toResponse(ExceptionA exception) { return Response.ok("A").build(); } } public static class ExceptionMapperB implements ExtendedExceptionMapper<ExceptionB> { @Override public boolean isMappable(ExceptionB exception) { return exception.getMessage().substring(2).contains("B"); } @Override public Response toResponse(ExceptionB exception) { return Response.ok("B").build(); } } public static class ExceptionMapperC implements ExceptionMapper<ExceptionC> { @Override public Response toResponse(ExceptionC exception) { return Response.ok("C").build(); } } public static class ExceptionMapperD implements ExtendedExceptionMapper<ExceptionD> { @Override public boolean isMappable(ExceptionD exception) { return exception.getMessage().substring(2).contains("D"); } @Override public Response toResponse(ExceptionD exception) { return Response.ok("D").build(); } } public static class ExceptionMapperE implements ExtendedExceptionMapper<ExceptionE> { @Override public boolean isMappable(ExceptionE exception) { return exception.getMessage().substring(2).contains("E"); } @Override public Response toResponse(ExceptionE exception) { return Response.ok("E").build(); } } public static class ExceptionMapperX implements ExtendedExceptionMapper<ExceptionX> { @Override public boolean isMappable(ExceptionX exception) { return exception.getMessage().substring(2).contains("X"); } @Override public Response toResponse(ExceptionX exception) { return Response.ok("X").build(); } } @Path("resource") public static class TestResource { @POST public String post(String e) { if (e.charAt(0) == 'A') { throw new ExceptionA(String.valueOf(e)); } else if (e.charAt(0) == 'B') { throw new ExceptionB(String.valueOf(e)); } else if (e.charAt(0) == 'C') { throw new ExceptionC(String.valueOf(e)); } else if (e.charAt(0) == 'D') { throw new ExceptionD(String.valueOf(e)); } else if (e.charAt(0) == 'E') { throw new ExceptionE(String.valueOf(e)); } else if (e.charAt(0) == 'X') { throw new ExceptionX(String.valueOf(e)); } return "get"; } } @Test public void test() { // Format of first param: [exception thrown]-[exception mappers which will return true in isMappable] _test("A-A", "A"); _test("A-AB", "A"); _test("A-ABC", "A"); _test("A-ABCD", "A"); _test("A-ABCDE", "A"); _test("A-ABCDEX", "A"); _test("A-C", null); _test("A-D", null); _test("A-E", null); _test("A-D", null); _test("A-BCDEX", null); _test("A-00000", null); _test("A-X", null); _test("B-A", "A"); _test("B-B", "B"); _test("B-AB", "B"); _test("B-ABC", "B"); _test("B-ABCD", "B"); _test("B-ABCDE", "B"); _test("B-ABCDEX", "B"); _test("B-C", null); _test("B-D", null); _test("B-E", null); _test("B-CDEX", null); _test("B-X", null); _test("B-000", null); // C is not an ExtendedExceptionMapper but just ExceptionMapper (always mappable) _test("C-C", "C"); _test("C-A", "C"); _test("C-AB", "C"); _test("C-ABC", "C"); _test("C-AEX", "C"); _test("C-00000", "C"); _test("C-ABCDEX", "C"); _test("C-E", "C"); _test("C-DE", "C"); _test("C-D", "C"); _test("C-X", "C"); _test("D-000", "C"); _test("D-A", "C"); _test("D-B", "C"); _test("D-C", "C"); _test("D-D", "D"); _test("D-E", "C"); _test("D-ABC", "C"); _test("D-ABCEX", "C"); _test("D-ABCDEX", "D"); _test("D-DE", "D"); _test("D-ABEX", "C"); _test("D-AEX", "C"); _test("D-X", "C"); _test("E-A", "C"); _test("E-B", "C"); _test("E-C", "C"); _test("E-D", "D"); _test("E-E", "E"); _test("E-ABC", "C"); _test("E-ABCD", "D"); _test("E-ABCDE", "E"); _test("E-ABCDEX", "E"); _test("E-DE", "E"); _test("E-X", "C"); _test("E-000000", "C"); _test("X-A", null); _test("X-ABCDE", null); _test("X-ABCDEX", "X"); _test("X-X", "X"); // Check logs. (??) for (final LogRecord logRecord : getLoggedRecords()) { // TODO: this test is fragile. if (logRecord.getLoggerName().contains("ClientExecutorProvidersConfigurator")) { continue; } for (final String message : new String[]{ LocalizationMessages.ERROR_EXCEPTION_MAPPING_ORIGINAL_EXCEPTION(), LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER()}) { if (logRecord.getMessage().contains(message) && logRecord.getLevel().intValue() > Level.FINE.intValue()) { fail("Log message should be logged at lower (FINE) level: " + message); } } } } private void _test(String input, String expectedMapper) { final Response response = target("resource").request().post(Entity.entity(input, MediaType.TEXT_PLAIN_TYPE)); if (expectedMapper == null) { Assert.assertEquals(500, response.getStatus()); } else { Assert.assertEquals(200, response.getStatus()); Assert.assertEquals(expectedMapper, response.readEntity(String.class)); } } }