2828import com .fasterxml .jackson .core .type .TypeReference ;
2929import com .fasterxml .jackson .databind .JavaType ;
3030import com .fasterxml .jackson .databind .module .SimpleModule ;
31+ import com .fasterxml .jackson .databind .node .ArrayNode ;
32+ import com .fasterxml .jackson .databind .node .ObjectNode ;
3133import com .fasterxml .jackson .databind .type .TypeFactory ;
3234import com .google .common .base .Strings ;
3335import org .glassfish .jersey .client .ClientProperties ;
34- import org .osiam .client .exception .ConflictException ;
35- import org .osiam .client .exception .ConnectionInitializationException ;
36- import org .osiam .client .exception .ForbiddenException ;
37- import org .osiam .client .exception .NoResultException ;
38- import org .osiam .client .exception .OAuthErrorMessage ;
39- import org .osiam .client .exception .OsiamClientException ;
40- import org .osiam .client .exception .OsiamRequestException ;
41- import org .osiam .client .exception .UnauthorizedException ;
36+ import org .osiam .client .exception .*;
4237import org .osiam .client .oauth .AccessToken ;
4338import org .osiam .client .query .Query ;
4439import org .osiam .client .query .QueryBuilder ;
4540import org .osiam .resources .helper .UserDeserializer ;
46- import org .osiam .resources .scim .ErrorResponse ;
47- import org .osiam .resources .scim .Resource ;
48- import org .osiam .resources .scim .SCIMSearchResult ;
49- import org .osiam .resources .scim .User ;
41+ import org .osiam .resources .scim .*;
5042
5143import javax .ws .rs .ProcessingException ;
5244import javax .ws .rs .client .Entity ;
@@ -80,6 +72,7 @@ abstract class AbstractOsiamService<T extends Resource> {
8072 private final String typeName ;
8173 private final int connectTimeout ;
8274 private final int readTimeout ;
75+ private final boolean legacySchemas ;
8376
8477 protected final WebTarget targetEndpoint ;
8578
@@ -88,9 +81,12 @@ protected AbstractOsiamService(Builder<T> builder) {
8881 typeName = builder .typeName ;
8982 connectTimeout = builder .connectTimeout ;
9083 readTimeout = builder .readTimeout ;
84+ legacySchemas = builder .legacySchemas ;
9185
86+ UserDeserializer userDeserializer =
87+ legacySchemas ? new UserDeserializer (OsiamUserService .LEGACY_SCHEMA ) : new UserDeserializer ();
9288 SimpleModule userDeserializerModule = new SimpleModule ("userDeserializerModule" , Version .unknownVersion ())
93- .addDeserializer (User .class , new UserDeserializer ( User . class ) );
89+ .addDeserializer (User .class , userDeserializer );
9490 objectMapper .registerModule (userDeserializerModule );
9591
9692 targetEndpoint = OsiamConnector .getClient ().target (builder .endpoint );
@@ -192,8 +188,8 @@ protected T createResource(T resource, AccessToken accessToken) {
192188
193189 String resourceAsString ;
194190 try {
195- resourceAsString = objectMapper . writeValueAsString (resource );
196- } catch (JsonProcessingException e ) {
191+ resourceAsString = mapToString (resource );
192+ } catch (JsonProcessingException | ClassCastException e ) {
197193 throw new ConnectionInitializationException (CONNECTION_SETUP_ERROR_STRING , e );
198194 }
199195
@@ -232,7 +228,7 @@ private T modifyResource(String id, T resource, String method, AccessToken acces
232228
233229 String resourceAsString ;
234230 try {
235- resourceAsString = objectMapper . writeValueAsString (resource );
231+ resourceAsString = mapToString (resource );
236232 } catch (JsonProcessingException e ) {
237233 throw new ConnectionInitializationException (CONNECTION_SETUP_ERROR_STRING , e );
238234 }
@@ -257,18 +253,48 @@ private T modifyResource(String id, T resource, String method, AccessToken acces
257253 return mapToResource (content );
258254 }
259255
260- protected T mapToResource (String content ) {
256+ private T mapToResource (String content ) {
261257 return mapToType (content , type );
262258 }
263259
264260 protected <U > U mapToType (String content , Class <U > type ) {
265261 try {
266- return objectMapper .readValue (content , type );
267- } catch (IOException e ) {
262+ if (legacySchemas && (type == User .class || type == Group .class )) {
263+ ObjectNode resourceNode = (ObjectNode ) objectMapper .readTree (content );
264+ switchToLegacySchema (resourceNode );
265+ return objectMapper .readValue (objectMapper .treeAsTokens (resourceNode ), type );
266+ } else {
267+ return objectMapper .readValue (content , type );
268+ }
269+ } catch (IOException | ClassCastException e ) {
268270 throw new OsiamClientException (String .format ("Unable to parse %s: %s" , typeName , content ), e );
269271 }
270272 }
271273
274+ private String mapToString (T resource ) throws JsonProcessingException {
275+ if (legacySchemas ) {
276+ ObjectNode resourceNode = objectMapper .valueToTree (resource );
277+ switchToLegacySchema (resourceNode );
278+ return resourceNode .toString ();
279+ } else {
280+ return objectMapper .writeValueAsString (resource );
281+ }
282+ }
283+
284+ private void switchToLegacySchema (ObjectNode resourceNode ) {
285+ ArrayNode schemas = (ArrayNode ) resourceNode .get ("schemas" );
286+ for (int i = 0 ; i < schemas .size (); i ++) {
287+ if (getSchema ().equals (schemas .get (i ).textValue ())) {
288+ schemas .remove (i );
289+ }
290+ }
291+ schemas .add (getLegacySchema ());
292+ }
293+
294+ protected abstract String getSchema ();
295+
296+ protected abstract String getLegacySchema ();
297+
272298 protected void checkAndHandleResponse (String content , StatusType status , AccessToken accessToken ) {
273299 if (status .getFamily () == Family .SUCCESSFUL ) {
274300 return ;
@@ -309,25 +335,29 @@ protected String extractErrorMessageDefault(String content, StatusType status) {
309335 }
310336
311337 protected String extractErrorMessage (String content , StatusType status ) {
312-
313- String message = getScimErrorMessageSinceOsiam3 (content );
314- if (message == null ) {
315- message = getScimErrorMessageUpToOsiam2 (content );
338+ String message ;
339+ if (legacySchemas ) {
340+ message = getScimErrorMessageLegacy (content );
341+ } else {
342+ message = getScimErrorMessage (content );
316343 }
344+
317345 if (message == null ) {
318346 message = getOAuthErrorMessage (content );
319347 }
348+
320349 if (message == null ) {
321350 message = String .format ("Could not deserialize the error response for the HTTP status '%s'." ,
322351 status .getReasonPhrase ());
323352 if (content != null ) {
324353 message += String .format (" Original response: %s" , content );
325354 }
326355 }
356+
327357 return message ;
328358 }
329359
330- private String getScimErrorMessageSinceOsiam3 (String content ) {
360+ private String getScimErrorMessage (String content ) {
331361 try {
332362 ErrorResponse error = objectMapper .readValue (content , ErrorResponse .class );
333363 return error .getDetail ();
@@ -336,7 +366,7 @@ private String getScimErrorMessageSinceOsiam3(String content) {
336366 }
337367 }
338368
339- private String getScimErrorMessageUpToOsiam2 (String content ) {
369+ private String getScimErrorMessageLegacy (String content ) {
340370 try {
341371 Map <String , String > error = objectMapper .readValue (content , new TypeReference <Map <String , String >>() {
342372 });
@@ -374,6 +404,7 @@ protected static class Builder<T> {
374404 private String typeName ;
375405 protected int connectTimeout = OsiamConnector .DEFAULT_CONNECT_TIMEOUT ;
376406 protected int readTimeout = OsiamConnector .DEFAULT_READ_TIMEOUT ;
407+ protected boolean legacySchemas = OsiamConnector .DEFAULT_LEGACY_SCHEMAS ;
377408
378409 @ SuppressWarnings ("unchecked" )
379410 protected Builder (String endpoint ) {
0 commit comments