1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.client.lib;
20
21 import java.security.AccessControlException;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Set;
25 import javax.ws.rs.BadRequestException;
26 import javax.ws.rs.ForbiddenException;
27 import javax.ws.rs.core.GenericType;
28 import javax.ws.rs.core.Response;
29 import javax.ws.rs.ext.Provider;
30 import javax.xml.ws.WebServiceException;
31 import org.apache.commons.lang3.StringUtils;
32 import org.apache.cxf.jaxrs.client.ResponseExceptionMapper;
33 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
34 import org.apache.syncope.common.lib.SyncopeClientException;
35 import org.apache.syncope.common.lib.to.ErrorTO;
36 import org.apache.syncope.common.lib.types.ClientExceptionType;
37 import org.apache.syncope.common.rest.api.RESTHeaders;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 @Provider
42 public class RestClientExceptionMapper implements ResponseExceptionMapper<Exception> {
43
44 private static final Logger LOG = LoggerFactory.getLogger(RestClientExceptionMapper.class);
45
46 @Override
47 public Exception fromResponse(final Response response) {
48 int statusCode = response.getStatus();
49 String message = response.getHeaderString(RESTHeaders.ERROR_INFO);
50
51 Exception ex;
52 SyncopeClientCompositeException scce = checkSyncopeClientCompositeException(response);
53 if (scce != null) {
54
55 ex = scce.getExceptions().size() == 1
56 ? scce.getExceptions().iterator().next()
57 : scce;
58 } else if (statusCode == Response.Status.UNAUTHORIZED.getStatusCode()) {
59
60 ex = new AccessControlException(StringUtils.isBlank(message)
61 ? "Remote unauthorized exception"
62 : message);
63 } else if (statusCode == Response.Status.FORBIDDEN.getStatusCode()) {
64
65 ex = new ForbiddenException(StringUtils.isBlank(message)
66 ? "Remote forbidden exception"
67 : message);
68 } else if (statusCode == Response.Status.BAD_REQUEST.getStatusCode()) {
69
70 ex = StringUtils.isBlank(message)
71 ? new BadRequestException()
72 : new BadRequestException(message);
73 } else {
74
75 ex = new WebServiceException(String.format("Remote exception with status code: %s",
76 Response.Status.fromStatusCode(statusCode).name()));
77 }
78 LOG.error("Exception thrown", ex);
79 return ex;
80 }
81
82 private static SyncopeClientCompositeException checkSyncopeClientCompositeException(final Response response) {
83 SyncopeClientCompositeException compException = SyncopeClientException.buildComposite();
84
85
86 List<ErrorTO> errors = null;
87 try {
88 ErrorTO error = response.readEntity(ErrorTO.class);
89 if (error != null) {
90 errors = List.of(error);
91 }
92 } catch (Exception e) {
93 LOG.debug("Could not read {}, attempting to read composite...", ErrorTO.class.getName(), e);
94 }
95 if (errors == null) {
96 try {
97 errors = response.readEntity(new GenericType<>() {
98 });
99 } catch (Exception e) {
100 LOG.debug("Could not read {} list, attempting to read headers...", ErrorTO.class.getName(), e);
101 }
102 }
103
104
105 if (errors == null) {
106 List<String> exTypesInHeaders = response.getStringHeaders().get(RESTHeaders.ERROR_CODE);
107 if (exTypesInHeaders == null) {
108 LOG.debug("No " + RESTHeaders.ERROR_CODE + " provided");
109 return null;
110 }
111 List<String> exInfos = response.getStringHeaders().get(RESTHeaders.ERROR_INFO);
112
113 Set<String> handledExceptions = new HashSet<>();
114 exTypesInHeaders.forEach(exTypeAsString -> {
115 ClientExceptionType exceptionType = null;
116 try {
117 exceptionType = ClientExceptionType.fromHeaderValue(exTypeAsString);
118 } catch (IllegalArgumentException e) {
119 LOG.error("Unexpected value of " + RESTHeaders.ERROR_CODE + ": " + exTypeAsString, e);
120 }
121 if (exceptionType != null) {
122 handledExceptions.add(exTypeAsString);
123
124 SyncopeClientException clientException = SyncopeClientException.build(exceptionType);
125 if (exInfos != null && !exInfos.isEmpty()) {
126 for (String element : exInfos) {
127 if (element.startsWith(exceptionType.name())) {
128 clientException.getElements().add(StringUtils.substringAfter(element, ":"));
129 }
130 }
131 }
132 compException.addException(clientException);
133 }
134 });
135
136 exTypesInHeaders.removeAll(handledExceptions);
137 if (!exTypesInHeaders.isEmpty()) {
138 LOG.error("Unmanaged exceptions: " + exTypesInHeaders);
139 }
140 } else {
141 for (ErrorTO error : errors) {
142 SyncopeClientException clientException = SyncopeClientException.build(error.getType());
143 clientException.getElements().addAll(error.getElements());
144 compException.addException(clientException);
145 }
146 }
147
148 if (compException.hasExceptions()) {
149 return compException;
150 }
151
152 return null;
153 }
154 }