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.core.provisioning.java;
20  
21  import java.util.Set;
22  import java.util.concurrent.Future;
23  import org.identityconnectors.common.security.GuardedString;
24  import org.identityconnectors.framework.api.ConnectorFacade;
25  import org.identityconnectors.framework.common.objects.Attribute;
26  import org.identityconnectors.framework.common.objects.AttributeDelta;
27  import org.identityconnectors.framework.common.objects.ConnectorObject;
28  import org.identityconnectors.framework.common.objects.ObjectClass;
29  import org.identityconnectors.framework.common.objects.ObjectClassInfo;
30  import org.identityconnectors.framework.common.objects.OperationOptions;
31  import org.identityconnectors.framework.common.objects.SearchResult;
32  import org.identityconnectors.framework.common.objects.SyncToken;
33  import org.identityconnectors.framework.common.objects.Uid;
34  import org.identityconnectors.framework.common.objects.filter.FilterBuilder;
35  import org.identityconnectors.framework.spi.SearchResultsHandler;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  import org.springframework.scheduling.annotation.Async;
39  import org.springframework.scheduling.annotation.AsyncResult;
40  
41  /**
42   * Intercept calls to ConnectorFacade's methods and check if the corresponding connector instance has been configured to
43   * allow every single operation: if not, simply do nothing.
44   */
45  public class AsyncConnectorFacade {
46  
47      private static final Logger LOG = LoggerFactory.getLogger(AsyncConnectorFacade.class);
48  
49      @Async
50      public Future<Uid> authenticate(
51              final ConnectorFacade connector,
52              final String username,
53              final GuardedString password,
54              final OperationOptions options) {
55  
56          return new AsyncResult<>(connector.authenticate(ObjectClass.ACCOUNT, username, password, options));
57      }
58  
59      @Async
60      public Future<Uid> create(
61              final ConnectorFacade connector,
62              final ObjectClass objectClass,
63              final Set<Attribute> attrs,
64              final OperationOptions options) {
65  
66          return new AsyncResult<>(connector.create(objectClass, attrs, options));
67      }
68  
69      @Async
70      public Future<Uid> update(
71              final ConnectorFacade connector,
72              final ObjectClass objectClass,
73              final Uid uid,
74              final Set<Attribute> attrs,
75              final OperationOptions options) {
76  
77          return new AsyncResult<>(connector.update(objectClass, uid, attrs, options));
78      }
79  
80      @Async
81      public Future<Set<AttributeDelta>> updateDelta(
82              final ConnectorFacade connector,
83              final ObjectClass objectClass,
84              final Uid uid,
85              final Set<AttributeDelta> modifications,
86              final OperationOptions options) {
87  
88          return new AsyncResult<>(connector.updateDelta(objectClass, uid, modifications, options));
89      }
90  
91      @Async
92      public Future<Uid> delete(
93              final ConnectorFacade connector,
94              final ObjectClass objectClass,
95              final Uid uid,
96              final OperationOptions options) {
97  
98          connector.delete(objectClass, uid, options);
99          return new AsyncResult<>(uid);
100     }
101 
102     @Async
103     public Future<SyncToken> getLatestSyncToken(
104             final ConnectorFacade connector, final ObjectClass objectClass) {
105 
106         return new AsyncResult<>(connector.getLatestSyncToken(objectClass));
107     }
108 
109     @Async
110     public Future<ConnectorObject> getObject(
111             final ConnectorFacade connector,
112             final ObjectClass objectClass,
113             final Attribute connObjectKey,
114             final boolean ignoreCaseMatch,
115             final OperationOptions options) {
116 
117         ConnectorObject[] objects = new ConnectorObject[1];
118         connector.search(
119                 objectClass,
120                 ignoreCaseMatch ? FilterBuilder.equalsIgnoreCase(connObjectKey) : FilterBuilder.equalTo(connObjectKey),
121                 new SearchResultsHandler() {
122 
123             @Override
124             public boolean handle(final ConnectorObject connectorObject) {
125                 objects[0] = connectorObject;
126                 return false;
127             }
128 
129             @Override
130             public void handleResult(final SearchResult sr) {
131                 // do nothing
132             }
133         },
134                 options);
135 
136         return new AsyncResult<>(objects[0]);
137     }
138 
139     @Async
140     public Future<Set<ObjectClassInfo>> getObjectClassInfo(final ConnectorFacade connector) {
141         Set<ObjectClassInfo> result = Set.of();
142 
143         try {
144             result = connector.schema().getObjectClassInfo();
145         } catch (Exception e) {
146             // catch exception in order to manage unpredictable behaviors
147             LOG.debug("While reading schema on connector {}", connector, e);
148         }
149 
150         return new AsyncResult<>(result);
151     }
152 
153     @Async
154     public Future<String> validate(final ConnectorFacade connector) {
155         connector.validate();
156         return new AsyncResult<>("OK");
157     }
158 
159     @Async
160     public Future<String> test(final ConnectorFacade connector) {
161         connector.test();
162         return new AsyncResult<>("OK");
163     }
164 }