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.data;
20  
21  import java.net.URI;
22  import java.util.Collection;
23  import java.util.Collections;
24  import java.util.List;
25  import org.apache.commons.lang3.tuple.Pair;
26  import org.apache.syncope.common.lib.SyncopeClientException;
27  import org.apache.syncope.common.lib.to.ConnInstanceTO;
28  import org.apache.syncope.common.lib.to.ConnPoolConfTO;
29  import org.apache.syncope.common.lib.types.ClientExceptionType;
30  import org.apache.syncope.common.lib.types.ConnConfPropSchema;
31  import org.apache.syncope.common.lib.types.ConnConfProperty;
32  import org.apache.syncope.core.persistence.api.dao.ConnInstanceDAO;
33  import org.apache.syncope.core.persistence.api.dao.NotFoundException;
34  import org.apache.syncope.core.persistence.api.dao.RealmDAO;
35  import org.apache.syncope.core.persistence.api.entity.ConnInstance;
36  import org.apache.syncope.core.persistence.api.entity.EntityFactory;
37  import org.apache.syncope.core.persistence.api.entity.Realm;
38  import org.apache.syncope.core.provisioning.api.ConnIdBundleManager;
39  import org.apache.syncope.core.provisioning.api.data.ConnInstanceDataBinder;
40  import org.apache.syncope.core.provisioning.api.utils.ConnPoolConfUtils;
41  import org.identityconnectors.framework.api.ConfigurationProperties;
42  import org.identityconnectors.framework.api.ConfigurationProperty;
43  import org.identityconnectors.framework.api.ConnectorInfo;
44  import org.identityconnectors.framework.impl.api.ConfigurationPropertyImpl;
45  import org.slf4j.Logger;
46  import org.slf4j.LoggerFactory;
47  
48  public class ConnInstanceDataBinderImpl implements ConnInstanceDataBinder {
49  
50      protected static final Logger LOG = LoggerFactory.getLogger(ConnInstanceDataBinder.class);
51  
52      protected final ConnIdBundleManager connIdBundleManager;
53  
54      protected final ConnInstanceDAO connInstanceDAO;
55  
56      protected final RealmDAO realmDAO;
57  
58      protected final EntityFactory entityFactory;
59  
60      public ConnInstanceDataBinderImpl(
61              final ConnIdBundleManager connIdBundleManager,
62              final ConnInstanceDAO connInstanceDAO,
63              final RealmDAO realmDAO,
64              final EntityFactory entityFactory) {
65  
66          this.connIdBundleManager = connIdBundleManager;
67          this.connInstanceDAO = connInstanceDAO;
68          this.realmDAO = realmDAO;
69          this.entityFactory = entityFactory;
70      }
71  
72      @Override
73      public ConnInstance getConnInstance(final ConnInstanceTO connInstanceTO) {
74          SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
75  
76          if (connInstanceTO.getLocation() == null) {
77              sce.getElements().add("location");
78          }
79  
80          if (connInstanceTO.getBundleName() == null) {
81              sce.getElements().add("bundlename");
82          }
83  
84          if (connInstanceTO.getVersion() == null) {
85              sce.getElements().add("bundleversion");
86          }
87  
88          if (connInstanceTO.getConnectorName() == null) {
89              sce.getElements().add("connectorname");
90          }
91  
92          if (connInstanceTO.getConf().isEmpty()) {
93              sce.getElements().add("configuration");
94          }
95  
96          ConnInstance connInstance = entityFactory.newEntity(ConnInstance.class);
97  
98          connInstance.setBundleName(connInstanceTO.getBundleName());
99          connInstance.setConnectorName(connInstanceTO.getConnectorName());
100         connInstance.setVersion(connInstanceTO.getVersion());
101         connInstance.setDisplayName(connInstanceTO.getDisplayName());
102         connInstance.setConnRequestTimeout(connInstanceTO.getConnRequestTimeout());
103         connInstance.getCapabilities().addAll(connInstanceTO.getCapabilities());
104 
105         if (connInstanceTO.getAdminRealm() != null) {
106             connInstance.setAdminRealm(realmDAO.findByFullPath(connInstanceTO.getAdminRealm()));
107         }
108         if (connInstance.getAdminRealm() == null) {
109             sce.getElements().add("Invalid or null realm specified: " + connInstanceTO.getAdminRealm());
110         }
111         if (connInstanceTO.getLocation() != null) {
112             connInstance.setLocation(connInstanceTO.getLocation());
113         }
114         connInstance.setConf(connInstanceTO.getConf());
115         if (connInstanceTO.getPoolConf() != null) {
116             connInstance.setPoolConf(
117                     ConnPoolConfUtils.getConnPoolConf(connInstanceTO.getPoolConf(), entityFactory.newConnPoolConf()));
118         }
119 
120         // Throw exception if there is at least one element set
121         if (!sce.isEmpty()) {
122             throw sce;
123         }
124 
125         return connInstance;
126     }
127 
128     @Override
129     public ConnInstance update(final ConnInstanceTO connInstanceTO) {
130         ConnInstance connInstance = connInstanceDAO.authFind(connInstanceTO.getKey());
131         if (connInstance == null) {
132             throw new NotFoundException("Connector '" + connInstanceTO.getKey() + '\'');
133         }
134 
135         connInstance.getCapabilities().clear();
136         connInstance.getCapabilities().addAll(connInstanceTO.getCapabilities());
137 
138         if (connInstanceTO.getAdminRealm() != null) {
139             Realm realm = realmDAO.findByFullPath(connInstanceTO.getAdminRealm());
140             if (realm == null) {
141                 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
142                 sce.getElements().add("Invalid or null realm specified: " + connInstanceTO.getAdminRealm());
143                 throw sce;
144             }
145             connInstance.setAdminRealm(realm);
146         }
147 
148         if (connInstanceTO.getLocation() != null) {
149             connInstance.setLocation(connInstanceTO.getLocation());
150         }
151 
152         if (connInstanceTO.getBundleName() != null) {
153             connInstance.setBundleName(connInstanceTO.getBundleName());
154         }
155 
156         if (connInstanceTO.getVersion() != null) {
157             connInstance.setVersion(connInstanceTO.getVersion());
158         }
159 
160         if (connInstanceTO.getConnectorName() != null) {
161             connInstance.setConnectorName(connInstanceTO.getConnectorName());
162         }
163 
164         if (connInstanceTO.getConf() != null && !connInstanceTO.getConf().isEmpty()) {
165             connInstance.setConf(connInstanceTO.getConf());
166         }
167 
168         if (connInstanceTO.getDisplayName() != null) {
169             connInstance.setDisplayName(connInstanceTO.getDisplayName());
170         }
171 
172         if (connInstanceTO.getConnRequestTimeout() != null) {
173             connInstance.setConnRequestTimeout(connInstanceTO.getConnRequestTimeout());
174         }
175 
176         if (connInstanceTO.getPoolConf() == null) {
177             connInstance.setPoolConf(null);
178         } else {
179             connInstance.setPoolConf(
180                     ConnPoolConfUtils.getConnPoolConf(connInstanceTO.getPoolConf(), entityFactory.newConnPoolConf()));
181         }
182 
183         return connInstance;
184     }
185 
186     @Override
187     public ConnConfPropSchema build(final ConfigurationProperty property) {
188         ConnConfPropSchema connConfPropSchema = new ConnConfPropSchema();
189 
190         connConfPropSchema.setName(property.getName());
191         connConfPropSchema.setDisplayName(property.getDisplayName(property.getName()));
192         connConfPropSchema.setHelpMessage(property.getHelpMessage(property.getName()));
193         connConfPropSchema.setRequired(property.isRequired());
194         connConfPropSchema.setType(property.getType().getName());
195         connConfPropSchema.setOrder(((ConfigurationPropertyImpl) property).getOrder());
196         connConfPropSchema.setConfidential(property.isConfidential());
197 
198         if (property.getValue() != null) {
199             if (property.getValue().getClass().isArray()) {
200                 connConfPropSchema.getDefaultValues().addAll(List.of((Object[]) property.getValue()));
201             } else if (property.getValue() instanceof Collection<?>) {
202                 connConfPropSchema.getDefaultValues().addAll((Collection<?>) property.getValue());
203             } else {
204                 connConfPropSchema.getDefaultValues().add(property.getValue());
205             }
206         }
207 
208         return connConfPropSchema;
209     }
210 
211     @Override
212     public ConnInstanceTO getConnInstanceTO(final ConnInstance connInstance) {
213         ConnInstanceTO connInstanceTO = new ConnInstanceTO();
214         connInstanceTO.setKey(connInstance.getKey());
215         connInstanceTO.setBundleName(connInstance.getBundleName());
216         connInstanceTO.setConnectorName(connInstance.getConnectorName());
217         connInstanceTO.setVersion(connInstance.getVersion());
218         connInstanceTO.setDisplayName(connInstance.getDisplayName());
219         connInstanceTO.setConnRequestTimeout(connInstance.getConnRequestTimeout());
220         connInstanceTO.setAdminRealm(connInstance.getAdminRealm().getFullPath());
221         connInstanceTO.getCapabilities().addAll(connInstance.getCapabilities());
222         connInstanceTO.getConf().addAll(connInstance.getConf());
223 
224         try {
225             Pair<URI, ConnectorInfo> info = connIdBundleManager.getConnectorInfo(connInstance);
226 
227             connInstanceTO.setLocation(info.getLeft().toASCIIString());
228 
229             // refresh stored properties in the given connInstance with direct information from underlying connector
230             ConfigurationProperties properties = connIdBundleManager.getConfigurationProperties(info.getRight());
231             properties.getPropertyNames().forEach(propName -> {
232                 ConnConfPropSchema schema = build(properties.getProperty(propName));
233 
234                 ConnConfProperty property = connInstanceTO.getConf(propName).
235                         orElseGet(() -> {
236                             ConnConfProperty p = new ConnConfProperty();
237                             connInstanceTO.getConf().add(p);
238                             return p;
239                         });
240                 property.setSchema(schema);
241             });
242         } catch (Exception e) {
243             LOG.error("Could not get ConnId information for {} / {}#{}#{}",
244                     connInstance.getLocation(), connInstance.getBundleName(), connInstance.getConnectorName(),
245                     connInstance.getVersion(), e);
246 
247             connInstanceTO.setErrored(true);
248             connInstanceTO.setLocation(connInstance.getLocation());
249         }
250 
251         Collections.sort(connInstanceTO.getConf());
252 
253         // pool configuration
254         if (connInstance.getPoolConf() != null
255                 && (connInstance.getPoolConf().getMaxIdle() != null
256                 || connInstance.getPoolConf().getMaxObjects() != null
257                 || connInstance.getPoolConf().getMaxWait() != null
258                 || connInstance.getPoolConf().getMinEvictableIdleTimeMillis() != null
259                 || connInstance.getPoolConf().getMinIdle() != null)) {
260 
261             ConnPoolConfTO poolConf = new ConnPoolConfTO();
262             poolConf.setMaxIdle(connInstance.getPoolConf().getMaxIdle());
263             poolConf.setMaxObjects(connInstance.getPoolConf().getMaxObjects());
264             poolConf.setMaxWait(connInstance.getPoolConf().getMaxWait());
265             poolConf.setMinEvictableIdleTimeMillis(connInstance.getPoolConf().getMinEvictableIdleTimeMillis());
266             poolConf.setMinIdle(connInstance.getPoolConf().getMinIdle());
267             connInstanceTO.setPoolConf(poolConf);
268         }
269 
270         return connInstanceTO;
271     }
272 }