001/* 002 * Copyright 2015-2024 Ping Identity Corporation 003 * 004 * This program is free software; you can redistribute it and/or modify 005 * it under the terms of the GNU General Public License (GPLv2 only) 006 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 007 * as published by the Free Software Foundation. 008 * 009 * This program is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU General Public License for more details. 013 * 014 * You should have received a copy of the GNU General Public License 015 * along with this program; if not, see <http://www.gnu.org/licenses>. 016 */ 017 018package com.unboundid.scim2.server.providers; 019 020import com.fasterxml.jackson.core.JsonParseException; 021import com.fasterxml.jackson.core.JsonProcessingException; 022import com.fasterxml.jackson.databind.JsonMappingException; 023import com.unboundid.scim2.common.annotations.NotNull; 024import com.unboundid.scim2.common.exceptions.BadRequestException; 025import com.unboundid.scim2.common.exceptions.ScimException; 026import com.unboundid.scim2.common.exceptions.ServerErrorException; 027import com.unboundid.scim2.common.messages.ErrorResponse; 028import com.unboundid.scim2.server.utils.ServerUtils; 029 030import jakarta.ws.rs.core.Context; 031import jakarta.ws.rs.core.HttpHeaders; 032import jakarta.ws.rs.core.Request; 033import jakarta.ws.rs.core.Response; 034import jakarta.ws.rs.ext.ExceptionMapper; 035import jakarta.ws.rs.ext.Provider; 036 037/** 038 * A JAX-RS ExceptionMapper for to convert Jackson JsonProcessingException to 039 * SCIM ErrorResponses. 040 */ 041@Provider 042public class JsonProcessingExceptionMapper implements 043 ExceptionMapper<JsonProcessingException> 044{ 045 @NotNull 046 @Context 047 private Request request; 048 049 @NotNull 050 @Context 051 private HttpHeaders headers; 052 053 /** 054 * {@inheritDoc} 055 */ 056 @NotNull 057 public Response toResponse(@NotNull final JsonProcessingException exception) 058 { 059 ErrorResponse errorResponse; 060 if((exception instanceof JsonParseException) || 061 (exception instanceof JsonMappingException)) 062 { 063 StringBuilder builder = new StringBuilder(); 064 builder.append("Unable to parse request: "); 065 builder.append(exception.getOriginalMessage()); 066 if(exception.getLocation() != null) 067 { 068 builder.append(" at line: "); 069 builder.append(exception.getLocation().getLineNr()); 070 builder.append(", column: "); 071 builder.append(exception.getLocation().getColumnNr()); 072 } 073 errorResponse = 074 BadRequestException.invalidSyntax(builder.toString()).getScimError(); 075 } 076 else 077 { 078 if(exception.getCause() != null && 079 exception.getCause() instanceof ScimException) 080 { 081 errorResponse = ((ScimException) exception.getCause()).getScimError(); 082 } 083 else 084 { 085 errorResponse = 086 new ServerErrorException(exception.getMessage()).getScimError(); 087 } 088 } 089 090 return ServerUtils.setAcceptableType( 091 Response.status(errorResponse.getStatus()).entity(errorResponse), 092 headers.getAcceptableMediaTypes()).build(); 093 } 094}