View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.fit.core;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertNull;
25  import static org.junit.jupiter.api.Assertions.assertThrows;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  import static org.junit.jupiter.api.Assertions.fail;
28  
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.util.Collection;
32  import java.util.EnumSet;
33  import java.util.HashSet;
34  import java.util.List;
35  import java.util.Locale;
36  import java.util.Properties;
37  import java.util.Set;
38  import java.util.UUID;
39  import java.util.stream.Collectors;
40  import javax.ws.rs.core.Response;
41  import org.apache.commons.lang3.exception.ExceptionUtils;
42  import org.apache.syncope.client.lib.SyncopeClient;
43  import org.apache.syncope.common.lib.SyncopeClientException;
44  import org.apache.syncope.common.lib.SyncopeConstants;
45  import org.apache.syncope.common.lib.to.ConnIdBundle;
46  import org.apache.syncope.common.lib.to.ConnIdObjectClass;
47  import org.apache.syncope.common.lib.to.ConnInstanceTO;
48  import org.apache.syncope.common.lib.to.ConnPoolConfTO;
49  import org.apache.syncope.common.lib.to.Item;
50  import org.apache.syncope.common.lib.to.Mapping;
51  import org.apache.syncope.common.lib.to.Provision;
52  import org.apache.syncope.common.lib.to.ResourceTO;
53  import org.apache.syncope.common.lib.types.AnyTypeKind;
54  import org.apache.syncope.common.lib.types.ClientExceptionType;
55  import org.apache.syncope.common.lib.types.ConnConfPropSchema;
56  import org.apache.syncope.common.lib.types.ConnConfProperty;
57  import org.apache.syncope.common.lib.types.ConnectorCapability;
58  import org.apache.syncope.common.rest.api.service.ConnectorService;
59  import org.apache.syncope.common.rest.api.service.ResourceService;
60  import org.apache.syncope.fit.AbstractITCase;
61  import org.identityconnectors.common.security.GuardedString;
62  import org.identityconnectors.framework.common.objects.ObjectClass;
63  import org.junit.jupiter.api.Assertions;
64  import org.junit.jupiter.api.BeforeAll;
65  import org.junit.jupiter.api.Test;
66  
67  public class ConnectorITCase extends AbstractITCase {
68  
69      private static String CONNECTOR_SERVER_LOCATION;
70  
71      private static String CONNID_SOAP_VERSION;
72  
73      private static String CONNID_DB_VERSION;
74  
75      private static String TEST_JDBC_URL;
76  
77      @BeforeAll
78      public static void setUpConnIdBundles() throws IOException {
79          try (InputStream propStream = ConnectorITCase.class.getResourceAsStream("/test.properties")) {
80              Properties props = new Properties();
81              props.load(propStream);
82  
83              CONNID_SOAP_VERSION = props.getProperty("connid.soap.version");
84              CONNID_DB_VERSION = props.getProperty("connid.db.version");
85  
86              TEST_JDBC_URL = props.getProperty("testdb.url");
87          } catch (Exception e) {
88              LOG.error("Could not load /test.properties", e);
89          }
90  
91          try (InputStream propStream = ConnectorITCase.class.getResourceAsStream("/core-embedded.properties")) {
92              Properties props = new Properties();
93              props.load(propStream);
94  
95              for (String location : props.getProperty("provisioning.connIdLocation").split(",")) {
96                  if (!location.startsWith("file")) {
97                      CONNECTOR_SERVER_LOCATION = location;
98                  }
99              }
100         } catch (Exception e) {
101             LOG.error("Could not load /core-embedded.properties", e);
102         }
103 
104         assertNotNull(CONNECTOR_SERVER_LOCATION);
105         assertNotNull(CONNID_SOAP_VERSION);
106         assertNotNull(CONNID_DB_VERSION);
107         assertNotNull(TEST_JDBC_URL);
108     }
109 
110     @Test
111     public void createWithException() {
112         assertThrows(SyncopeClientException.class, () -> {
113             ConnInstanceTO connectorTO = new ConnInstanceTO();
114 
115             Response response = CONNECTOR_SERVICE.create(connectorTO);
116             if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
117                 throw (RuntimeException) CLIENT_FACTORY.getExceptionMapper().fromResponse(response);
118             }
119         });
120     }
121 
122     @Test
123     public void create() {
124         ConnInstanceTO connectorTO = new ConnInstanceTO();
125         connectorTO.setAdminRealm(SyncopeConstants.ROOT_REALM);
126         connectorTO.setLocation(CONNECTOR_SERVICE.read(
127                 "88a7a819-dab5-46b4-9b90-0b9769eabdb8", Locale.ENGLISH.getLanguage()).getLocation());
128         connectorTO.setVersion(CONNID_SOAP_VERSION);
129         connectorTO.setConnectorName("net.tirasa.connid.bundles.soap.WebServiceConnector");
130         connectorTO.setBundleName("net.tirasa.connid.bundles.soap");
131         connectorTO.setDisplayName("Display name");
132         connectorTO.setConnRequestTimeout(15);
133 
134         // set the connector configuration using PropertyTO
135         Set<ConnConfProperty> conf = new HashSet<>();
136 
137         ConnConfPropSchema endpointSchema = new ConnConfPropSchema();
138         endpointSchema.setName("endpoint");
139         endpointSchema.setType(String.class.getName());
140         endpointSchema.setRequired(true);
141         ConnConfProperty endpoint = new ConnConfProperty();
142         endpoint.setSchema(endpointSchema);
143         endpoint.getValues().add("http://localhost:8888/syncope-fit-build-tools/cxf/soap");
144         endpoint.getValues().add("Provisioning");
145         conf.add(endpoint);
146 
147         ConnConfPropSchema servicenameSchema = new ConnConfPropSchema();
148         servicenameSchema.setName("servicename");
149         servicenameSchema.setType(String.class.getName());
150         servicenameSchema.setRequired(true);
151         ConnConfProperty servicename = new ConnConfProperty();
152         servicename.setSchema(servicenameSchema);
153         conf.add(servicename);
154 
155         // set connector configuration
156         connectorTO.getConf().addAll(conf);
157 
158         // set connector capabilities
159         connectorTO.getCapabilities().add(ConnectorCapability.CREATE);
160         connectorTO.getCapabilities().add(ConnectorCapability.UPDATE);
161 
162         // set connector pool conf
163         ConnPoolConfTO cpc = new ConnPoolConfTO();
164         cpc.setMaxObjects(1534);
165         connectorTO.setPoolConf(cpc);
166 
167         Response response = CONNECTOR_SERVICE.create(connectorTO);
168         if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
169             throw (RuntimeException) CLIENT_FACTORY.getExceptionMapper().fromResponse(response);
170         }
171 
172         ConnInstanceTO actual = getObject(
173                 response.getLocation(), ConnectorService.class, ConnInstanceTO.class);
174         assertNotNull(actual);
175 
176         assertEquals(actual.getBundleName(), connectorTO.getBundleName());
177         assertEquals(actual.getConnectorName(), connectorTO.getConnectorName());
178         assertEquals(actual.getVersion(), connectorTO.getVersion());
179         assertEquals("Display name", actual.getDisplayName());
180         assertEquals(Integer.valueOf(15), actual.getConnRequestTimeout());
181         assertEquals(connectorTO.getCapabilities(), actual.getCapabilities());
182         assertNotNull(actual.getPoolConf());
183         assertEquals(1534, actual.getPoolConf().getMaxObjects().intValue());
184         assertEquals(10, actual.getPoolConf().getMaxIdle().intValue());
185 
186         Throwable t = null;
187 
188         // check update
189         actual.getCapabilities().remove(ConnectorCapability.UPDATE);
190         actual.getPoolConf().setMaxObjects(null);
191 
192         try {
193             CONNECTOR_SERVICE.update(actual);
194             actual = CONNECTOR_SERVICE.read(actual.getKey(), Locale.ENGLISH.getLanguage());
195         } catch (SyncopeClientException e) {
196             LOG.error("update failed", e);
197             t = e;
198         }
199 
200         assertNull(t);
201         assertNotNull(actual);
202         assertEquals(EnumSet.of(ConnectorCapability.CREATE), actual.getCapabilities());
203         assertEquals(10, actual.getPoolConf().getMaxObjects().intValue());
204 
205         // check also for the deletion of the created object
206         try {
207             CONNECTOR_SERVICE.delete(actual.getKey());
208         } catch (SyncopeClientException e) {
209             LOG.error("delete failed", e);
210             t = e;
211         }
212 
213         assertNull(t);
214 
215         // check the non existence
216         try {
217             CONNECTOR_SERVICE.read(actual.getKey(), Locale.ENGLISH.getLanguage());
218         } catch (SyncopeClientException e) {
219             assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
220         }
221     }
222 
223     @Test
224     public void update() {
225         ConnInstanceTO connectorTO = new ConnInstanceTO();
226         connectorTO.setAdminRealm(SyncopeConstants.ROOT_REALM);
227 
228         // set connector instance key
229         connectorTO.setKey("fcf9f2b0-f7d6-42c9-84a6-61b28255a42b");
230 
231         // set connector version
232         connectorTO.setVersion(CONNID_SOAP_VERSION);
233 
234         // set connector name
235         connectorTO.setConnectorName("net.tirasa.connid.bundles.soap.WebServiceConnector");
236 
237         // set bundle name
238         connectorTO.setBundleName("net.tirasa.connid.bundles.soap");
239 
240         connectorTO.setConnRequestTimeout(20);
241 
242         // set the connector configuration using PropertyTO
243         Set<ConnConfProperty> conf = new HashSet<>();
244 
245         ConnConfPropSchema endpointSchema = new ConnConfPropSchema();
246         endpointSchema.setName("endpoint");
247         endpointSchema.setType(String.class.getName());
248         endpointSchema.setRequired(true);
249         ConnConfProperty endpoint = new ConnConfProperty();
250         endpoint.setSchema(endpointSchema);
251         endpoint.getValues().add("http://localhost:8888/syncope-fit-build-tools/cxf/soap");
252         conf.add(endpoint);
253 
254         ConnConfPropSchema servicenameSchema = new ConnConfPropSchema();
255         servicenameSchema.setName("servicename");
256         servicenameSchema.setType(String.class.getName());
257         servicenameSchema.setRequired(true);
258         ConnConfProperty servicename = new ConnConfProperty();
259         servicename.setSchema(servicenameSchema);
260         servicename.getValues().add("Provisioning");
261         conf.add(servicename);
262 
263         // set connector configuration
264         connectorTO.getConf().addAll(conf);
265 
266         CONNECTOR_SERVICE.update(connectorTO);
267         ConnInstanceTO actual = CONNECTOR_SERVICE.read(connectorTO.getKey(), Locale.ENGLISH.getLanguage());
268 
269         assertNotNull(actual);
270 
271         actual = CONNECTOR_SERVICE.read(actual.getKey(), Locale.ENGLISH.getLanguage());
272 
273         assertNotNull(actual);
274         assertEquals(actual.getBundleName(), connectorTO.getBundleName());
275         assertEquals(actual.getConnectorName(), connectorTO.getConnectorName());
276         assertEquals(actual.getVersion(), connectorTO.getVersion());
277         assertEquals(Integer.valueOf(20), actual.getConnRequestTimeout());
278     }
279 
280     @Test
281     public void reload() {
282         CONNECTOR_SERVICE.reload();
283     }
284 
285     @Test
286     public void deleteWithException() {
287         try {
288             CONNECTOR_SERVICE.delete(UUID.randomUUID().toString());
289         } catch (SyncopeClientException e) {
290             assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
291         }
292     }
293 
294     @Test
295     public void list() {
296         List<ConnInstanceTO> connInstances = CONNECTOR_SERVICE.list(null);
297         assertNotNull(connInstances);
298         assertFalse(connInstances.isEmpty());
299         connInstances.forEach(Assertions::assertNotNull);
300     }
301 
302     @Test
303     public void read() {
304         ConnInstanceTO connInstance = CONNECTOR_SERVICE.read(
305                 "88a7a819-dab5-46b4-9b90-0b9769eabdb8", Locale.ENGLISH.getLanguage());
306         assertNotNull(connInstance);
307         assertFalse(connInstance.isErrored());
308         assertNotNull(connInstance.getLocation());
309         assertFalse(connInstance.getConf().isEmpty());
310 
311         connInstance = CONNECTOR_SERVICE.read(
312                 "413bf072-678a-41d3-9d20-8c453b3a39d1", Locale.ENGLISH.getLanguage());
313         assertNotNull(connInstance);
314         assertTrue(connInstance.isErrored());
315         assertNotNull(connInstance.getLocation());
316         assertTrue(connInstance.getConf().isEmpty());
317     }
318 
319     @Test
320     public void getBundles() {
321         List<ConnIdBundle> bundles = CONNECTOR_SERVICE.getBundles(Locale.ENGLISH.getLanguage());
322         assertNotNull(bundles);
323         assertFalse(bundles.isEmpty());
324         bundles.forEach(Assertions::assertNotNull);
325     }
326 
327     @Test
328     public void getConnectorConfiguration() {
329         List<ConnConfProperty> props = CONNECTOR_SERVICE.read(
330                 "6c2acf1b-b052-46f0-8c56-7a8ad6905edf", Locale.ENGLISH.getLanguage()).getConf();
331         assertNotNull(props);
332         assertFalse(props.isEmpty());
333     }
334 
335     @Test
336     public void checkHiddenProperty() {
337         ConnInstanceTO connInstanceTO = CONNECTOR_SERVICE.read(
338                 "88a7a819-dab5-46b4-9b90-0b9769eabdb8", Locale.ENGLISH.getLanguage());
339 
340         boolean check = false;
341 
342         for (ConnConfProperty prop : connInstanceTO.getConf()) {
343             if ("receiveTimeout".equals(prop.getSchema().getName())) {
344                 check = true;
345             }
346         }
347         assertTrue(check);
348     }
349 
350     @Test
351     public void checkSelectedLanguage() {
352         // 1. Check Italian
353         assertTrue(CONNECTOR_SERVICE.list("it").stream().
354                 filter(i -> "net.tirasa.connid.bundles.db.table.DatabaseTableConnector".equals(i.getConnectorName())).
355                 allMatch(i -> "Utente".equals(i.getConf("user").get().getSchema().getDisplayName())));
356 
357         // 2. Check English (default)
358         assertTrue(CONNECTOR_SERVICE.list(null).stream().
359                 filter(i -> "net.tirasa.connid.bundles.db.table.DatabaseTableConnector".equals(i.getConnectorName())).
360                 allMatch(i -> "User".equals(i.getConf("user").get().getSchema().getDisplayName())));
361     }
362 
363     @Test
364     public void validate() {
365         ConnInstanceTO connectorTO = new ConnInstanceTO();
366         connectorTO.setAdminRealm(SyncopeConstants.ROOT_REALM);
367         connectorTO.setLocation(CONNECTOR_SERVER_LOCATION);
368         connectorTO.setVersion(CONNID_DB_VERSION);
369         connectorTO.setConnectorName("net.tirasa.connid.bundles.db.table.DatabaseTableConnector");
370         connectorTO.setBundleName("net.tirasa.connid.bundles.db");
371         connectorTO.setDisplayName("H2Test");
372 
373         // set the connector configuration using PropertyTO
374         Set<ConnConfProperty> conf = new HashSet<>();
375 
376         ConnConfPropSchema jdbcDriverSchema = new ConnConfPropSchema();
377         jdbcDriverSchema.setName("jdbcDriver");
378         jdbcDriverSchema.setType(String.class.getName());
379         jdbcDriverSchema.setRequired(true);
380         ConnConfProperty jdbcDriver = new ConnConfProperty();
381         jdbcDriver.setSchema(jdbcDriverSchema);
382         jdbcDriver.getValues().add("org.h2.Driver");
383         conf.add(jdbcDriver);
384 
385         ConnConfPropSchema jdbcUrlTemplateSchema = new ConnConfPropSchema();
386         jdbcUrlTemplateSchema.setName("jdbcUrlTemplate");
387         jdbcUrlTemplateSchema.setType(String.class.getName());
388         jdbcUrlTemplateSchema.setRequired(true);
389         ConnConfProperty jdbcUrlTemplate = new ConnConfProperty();
390         jdbcUrlTemplate.setSchema(jdbcUrlTemplateSchema);
391         jdbcUrlTemplate.getValues().add(TEST_JDBC_URL);
392         conf.add(jdbcUrlTemplate);
393 
394         ConnConfPropSchema userSchema = new ConnConfPropSchema();
395         userSchema.setName("user");
396         userSchema.setType(String.class.getName());
397         userSchema.setRequired(false);
398         ConnConfProperty user = new ConnConfProperty();
399         user.setSchema(userSchema);
400         user.getValues().add("sa");
401         conf.add(user);
402 
403         ConnConfPropSchema passwordSchema = new ConnConfPropSchema();
404         passwordSchema.setName("password");
405         passwordSchema.setType(GuardedString.class.getName());
406         passwordSchema.setRequired(true);
407         ConnConfProperty password = new ConnConfProperty();
408         password.setSchema(passwordSchema);
409         password.getValues().add("sa");
410         conf.add(password);
411 
412         ConnConfPropSchema tableSchema = new ConnConfPropSchema();
413         tableSchema.setName("table");
414         tableSchema.setType(String.class.getName());
415         tableSchema.setRequired(true);
416         ConnConfProperty table = new ConnConfProperty();
417         table.setSchema(tableSchema);
418         table.getValues().add("test");
419         conf.add(table);
420 
421         ConnConfPropSchema keyColumnSchema = new ConnConfPropSchema();
422         keyColumnSchema.setName("keyColumn");
423         keyColumnSchema.setType(String.class.getName());
424         keyColumnSchema.setRequired(true);
425         ConnConfProperty keyColumn = new ConnConfProperty();
426         keyColumn.setSchema(keyColumnSchema);
427         keyColumn.getValues().add("id");
428         conf.add(keyColumn);
429 
430         ConnConfPropSchema passwordColumnSchema = new ConnConfPropSchema();
431         passwordColumnSchema.setName("passwordColumn");
432         passwordColumnSchema.setType(String.class.getName());
433         passwordColumnSchema.setRequired(true);
434         ConnConfProperty passwordColumn = new ConnConfProperty();
435         passwordColumn.setSchema(passwordColumnSchema);
436         passwordColumn.getValues().add("password");
437         conf.add(passwordColumn);
438 
439         // set connector configuration
440         connectorTO.getConf().addAll(conf);
441 
442         try {
443             CONNECTOR_SERVICE.check(connectorTO);
444         } catch (Exception e) {
445             fail(ExceptionUtils.getStackTrace(e));
446         }
447 
448         conf.remove(password);
449         password.getValues().clear();
450         password.getValues().add("password");
451         conf.add(password);
452 
453         try {
454             CONNECTOR_SERVICE.check(connectorTO);
455             fail("This should not happen");
456         } catch (Exception e) {
457             assertNotNull(e);
458         }
459     }
460 
461     @Test
462     public void buildObjectClassInfo() {
463         ConnInstanceTO db = CONNECTOR_SERVICE.read(
464                 "5aa5b8be-7521-481a-9651-c557aea078c1", Locale.ENGLISH.getLanguage());
465         assertNotNull(db);
466 
467         List<ConnIdObjectClass> objectClassInfo = CONNECTOR_SERVICE.buildObjectClassInfo(db, true);
468         assertNotNull(objectClassInfo);
469         assertEquals(1, objectClassInfo.size());
470         assertEquals(ObjectClass.ACCOUNT_NAME, objectClassInfo.get(0).getType());
471         assertTrue(objectClassInfo.get(0).getAttributes().stream().anyMatch(schema -> "ID".equals(schema.getKey())));
472 
473         ConnInstanceTO ldap = CONNECTOR_SERVICE.read(
474                 "74141a3b-0762-4720-a4aa-fc3e374ef3ef", Locale.ENGLISH.getLanguage());
475         assertNotNull(ldap);
476 
477         objectClassInfo = CONNECTOR_SERVICE.buildObjectClassInfo(ldap, true);
478         assertNotNull(objectClassInfo);
479 
480         Collection<String> objectClasses = objectClassInfo.stream().
481                 map(ConnIdObjectClass::getType).collect(Collectors.toSet());
482         assertTrue(objectClasses.contains(ObjectClass.ACCOUNT_NAME));
483         assertTrue(objectClasses.contains(ObjectClass.GROUP_NAME));
484     }
485 
486     @Test
487     public void authorizations() {
488         SyncopeClient puccini = CLIENT_FACTORY.create("puccini", ADMIN_PWD);
489         ConnectorService pcs = puccini.getService(ConnectorService.class);
490 
491         // 1. list connectors: get only the ones allowed
492         List<ConnInstanceTO> connInstances = pcs.list(null);
493         assertEquals(2, connInstances.size());
494 
495         assertTrue(connInstances.stream().allMatch(connInstance
496                 -> "a6d017fd-a705-4507-bb7c-6ab6a6745997".equals(connInstance.getKey())
497                 || "44c02549-19c3-483c-8025-4919c3283c37".equals(connInstance.getKey())));
498 
499         // 2. attempt to read a connector with a different admin realm: fail
500         try {
501             pcs.read("88a7a819-dab5-46b4-9b90-0b9769eabdb8", null);
502             fail("This should not happen");
503         } catch (SyncopeClientException e) {
504             assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
505         }
506 
507         // 3. read and upate a connector in the realm for which entitlements are owned: succeed
508         try {
509             ConnInstanceTO scriptedsql = pcs.read("a6d017fd-a705-4507-bb7c-6ab6a6745997", null);
510             ConnConfProperty reloadScriptOnExecution = scriptedsql.getConf("reloadScriptOnExecution").get();
511             assertEquals("true", reloadScriptOnExecution.getValues().get(0).toString());
512 
513             reloadScriptOnExecution.getValues().set(0, "false");
514             pcs.update(scriptedsql);
515 
516             scriptedsql = pcs.read(scriptedsql.getKey(), null);
517             reloadScriptOnExecution = scriptedsql.getConf("reloadScriptOnExecution").get();
518             assertEquals("false", reloadScriptOnExecution.getValues().get(0).toString());
519         } finally {
520             ConnInstanceTO scriptedsql = CONNECTOR_SERVICE.read("a6d017fd-a705-4507-bb7c-6ab6a6745997", null);
521             ConnConfProperty reloadScriptOnExecution = scriptedsql.getConf("reloadScriptOnExecution").get();
522             reloadScriptOnExecution.getValues().set(0, "true");
523             CONNECTOR_SERVICE.update(scriptedsql);
524         }
525     }
526 
527     @Test
528     public void issueSYNCOPE10() {
529         // ----------------------------------
530         // Copy resource and connector in order to create new objects.
531         // ----------------------------------
532         // Retrieve a connector instance template.
533         ConnInstanceTO connInstanceTO = CONNECTOR_SERVICE.read(
534                 "fcf9f2b0-f7d6-42c9-84a6-61b28255a42b", Locale.ENGLISH.getLanguage());
535         assertNotNull(connInstanceTO);
536 
537         // check for resource
538         List<ResourceTO> resources = RESOURCE_SERVICE.list().stream().
539                 filter(resource -> "fcf9f2b0-f7d6-42c9-84a6-61b28255a42b".equals(resource.getConnector())).
540                 collect(Collectors.toList());
541         assertEquals(4, resources.size());
542 
543         // Retrieve a resource TO template.
544         ResourceTO resourceTO = resources.get(0);
545 
546         // Make it new.
547         resourceTO.setKey("newAbout103" + getUUIDString());
548 
549         // Make it new.
550         connInstanceTO.setKey(null);
551         connInstanceTO.setDisplayName("newDisplayName" + getUUIDString());
552         // ----------------------------------
553 
554         // ----------------------------------
555         // Create a new connector instance.
556         // ----------------------------------
557         Response response = CONNECTOR_SERVICE.create(connInstanceTO);
558         if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
559             throw (RuntimeException) CLIENT_FACTORY.getExceptionMapper().fromResponse(response);
560         }
561 
562         connInstanceTO = getObject(response.getLocation(), ConnectorService.class, ConnInstanceTO.class);
563         assertNotNull(connInstanceTO);
564         assertFalse(connInstanceTO.getCapabilities().contains(ConnectorCapability.AUTHENTICATE));
565 
566         final String connKey = connInstanceTO.getKey();
567 
568         // Link resourceTO to the new connector instance.
569         resourceTO.setConnector(connKey);
570         // ----------------------------------
571 
572         // ----------------------------------
573         // Check for connector instance update after resource creation.
574         // ----------------------------------
575         response = RESOURCE_SERVICE.create(resourceTO);
576         resourceTO = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
577 
578         assertNotNull(resourceTO);
579 
580         resources = RESOURCE_SERVICE.list().stream().
581                 filter(resource -> connKey.equals(resource.getConnector())).collect(Collectors.toList());
582         assertEquals(1, resources.size());
583         // ----------------------------------
584 
585         // ----------------------------------
586         // Check for spring bean.
587         // ----------------------------------
588         ConnInstanceTO connInstanceBean = CONNECTOR_SERVICE.readByResource(
589                 resourceTO.getKey(), Locale.ENGLISH.getLanguage());
590         assertNotNull(connInstanceBean);
591         assertFalse(connInstanceBean.getCapabilities().contains(ConnectorCapability.AUTHENTICATE));
592         // ----------------------------------
593 
594         // ----------------------------------
595         // Check for spring bean update after connector instance update.
596         // ----------------------------------
597         connInstanceTO.getCapabilities().add(ConnectorCapability.AUTHENTICATE);
598 
599         CONNECTOR_SERVICE.update(connInstanceTO);
600         ConnInstanceTO actual = CONNECTOR_SERVICE.read(connInstanceTO.getKey(), Locale.ENGLISH.getLanguage());
601         assertNotNull(actual);
602         assertTrue(connInstanceTO.getCapabilities().contains(ConnectorCapability.AUTHENTICATE));
603 
604         // check for spring bean update
605         connInstanceBean = CONNECTOR_SERVICE.readByResource(resourceTO.getKey(), Locale.ENGLISH.getLanguage());
606         assertTrue(connInstanceBean.getCapabilities().contains(ConnectorCapability.AUTHENTICATE));
607         // ----------------------------------
608     }
609 
610     @Test
611     public void issueSYNCOPE112() {
612         // ----------------------------------------
613         // Create a new connector
614         // ----------------------------------------
615         ConnInstanceTO connectorTO = new ConnInstanceTO();
616         connectorTO.setAdminRealm(SyncopeConstants.ROOT_REALM);
617 
618         connectorTO.setLocation(CONNECTOR_SERVICE.read(
619                 "88a7a819-dab5-46b4-9b90-0b9769eabdb8", Locale.ENGLISH.getLanguage()).getLocation());
620 
621         // set connector version
622         connectorTO.setVersion(CONNID_SOAP_VERSION);
623 
624         // set connector name
625         connectorTO.setConnectorName("net.tirasa.connid.bundles.soap.WebServiceConnector");
626 
627         // set bundle name
628         connectorTO.setBundleName("net.tirasa.connid.bundles.soap");
629 
630         // set display name
631         connectorTO.setDisplayName("WSSoap");
632 
633         // set the connector configuration using PropertyTO
634         Set<ConnConfProperty> conf = new HashSet<>();
635 
636         ConnConfPropSchema userSchema = new ConnConfPropSchema();
637         userSchema.setName("endpoint");
638         userSchema.setType(String.class.getName());
639         userSchema.setRequired(true);
640         ConnConfProperty endpoint = new ConnConfProperty();
641         endpoint.setSchema(userSchema);
642         endpoint.getValues().add("http://localhost:9080/does_not_work");
643         endpoint.setOverridable(true);
644 
645         ConnConfPropSchema keyColumnSchema = new ConnConfPropSchema();
646         keyColumnSchema.setName("servicename");
647         keyColumnSchema.setType(String.class.getName());
648         keyColumnSchema.setRequired(true);
649         ConnConfProperty servicename = new ConnConfProperty();
650         servicename.setSchema(keyColumnSchema);
651         servicename.getValues().add("net.tirasa.connid.bundles.soap.provisioning.interfaces.Provisioning");
652         servicename.setOverridable(false);
653 
654         conf.add(endpoint);
655         conf.add(servicename);
656 
657         // set connector configuration
658         connectorTO.getConf().addAll(conf);
659 
660         try {
661             try {
662                 CONNECTOR_SERVICE.check(connectorTO);
663                 fail("This should not happen");
664             } catch (Exception e) {
665                 assertNotNull(e);
666             }
667 
668             Response response = CONNECTOR_SERVICE.create(connectorTO);
669             if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
670                 throw (RuntimeException) CLIENT_FACTORY.getExceptionMapper().fromResponse(response);
671             }
672 
673             connectorTO = getObject(response.getLocation(), ConnectorService.class, ConnInstanceTO.class);
674             assertNotNull(connectorTO);
675             // ----------------------------------------
676 
677             // ----------------------------------------
678             // create a resourceTO
679             // ----------------------------------------
680             String resourceName = "checkForPropOverriding";
681             ResourceTO resourceTO = new ResourceTO();
682 
683             resourceTO.setKey(resourceName);
684             resourceTO.setConnector(connectorTO.getKey());
685 
686             conf = new HashSet<>();
687             endpoint.getValues().clear();
688             endpoint.getValues().add(BUILD_TOOLS_ADDRESS + "/soap/provisioning");
689             conf.add(endpoint);
690 
691             resourceTO.getConfOverride().addAll(conf);
692 
693             Provision provisionTO = new Provision();
694             provisionTO.setAnyType(AnyTypeKind.USER.name());
695             provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
696             resourceTO.getProvisions().add(provisionTO);
697 
698             Mapping mapping = new Mapping();
699             provisionTO.setMapping(mapping);
700 
701             Item mapItem = new Item();
702             mapItem.setExtAttrName("uid");
703             mapItem.setIntAttrName("userId");
704             mapItem.setConnObjectKey(true);
705             mapping.setConnObjectKeyItem(mapItem);
706             // ----------------------------------------
707 
708             // ----------------------------------------
709             // Check connection without saving the resource ....
710             // ----------------------------------------
711             try {
712                 RESOURCE_SERVICE.check(resourceTO);
713             } catch (Exception e) {
714                 fail(ExceptionUtils.getStackTrace(e));
715             }
716             // ----------------------------------------
717         } finally {
718             // Remove connector from db to make test re-runnable
719             CONNECTOR_SERVICE.delete(connectorTO.getKey());
720         }
721     }
722 
723     @Test
724     public void issueSYNCOPE605() {
725         ConnInstanceTO connInstance = CONNECTOR_SERVICE.read(
726                 "fcf9f2b0-f7d6-42c9-84a6-61b28255a42b", Locale.ENGLISH.getLanguage());
727         assertTrue(connInstance.getCapabilities().isEmpty());
728 
729         connInstance.getCapabilities().add(ConnectorCapability.SEARCH);
730         CONNECTOR_SERVICE.update(connInstance);
731 
732         ConnInstanceTO updatedCapabilities = CONNECTOR_SERVICE.read(
733                 connInstance.getKey(), Locale.ENGLISH.getLanguage());
734         assertNotNull(updatedCapabilities.getCapabilities());
735         assertTrue(updatedCapabilities.getCapabilities().size() == 1);
736     }
737 }