blob: 84db10542fb201f2f3f557ec8f437dafdf642d30 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.syncope.core.provisioning.java;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
import org.apache.syncope.core.persistence.api.entity.Any;
import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
import org.apache.syncope.core.persistence.api.entity.LinkingMappingItem;
import org.apache.syncope.core.persistence.api.entity.Membership;
import org.apache.syncope.core.persistence.api.entity.VirSchema;
import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.provisioning.api.ConnectorManager;
import org.apache.syncope.core.provisioning.api.VirAttrHandler;
import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheKey;
import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
import org.apache.syncope.core.provisioning.java.pushpull.OutboundMatcher;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.ConnectorObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
@Transactional(readOnly = true)
public class DefaultVirAttrHandler implements VirAttrHandler {
protected static final Logger LOG = LoggerFactory.getLogger(VirAttrHandler.class);
protected final ConnectorManager connectorManager;
protected final VirAttrCache virAttrCache;
protected final OutboundMatcher outboundMatcher;
protected final AnyUtilsFactory anyUtilsFactory;
public DefaultVirAttrHandler(
final ConnectorManager connectorManager,
final VirAttrCache virAttrCache,
final OutboundMatcher outboundMatcher,
final AnyUtilsFactory anyUtilsFactory) {
this.connectorManager = connectorManager;
this.virAttrCache = virAttrCache;
this.outboundMatcher = outboundMatcher;
this.anyUtilsFactory = anyUtilsFactory;
}
@Override
public void setValues(final Any<?> any, final ConnectorObject connObj) {
if (any == null) {
LOG.debug("Null any passed, ignoring");
return;
}
AllowedSchemas<VirSchema> schemas =
anyUtilsFactory.getInstance(any).dao().findAllowedSchemas(any, VirSchema.class);
Stream.concat(
schemas.getForSelf().stream(),
schemas.getForMemberships().values().stream().flatMap(Set::stream)).forEach(schema -> {
VirAttrCacheKey cacheKey = new VirAttrCacheKey(any.getType().getKey(), any.getKey(), schema.getKey());
Attribute attr = connObj.getAttributeByName(schema.getExtAttrName());
if (attr == null) {
virAttrCache.expire(cacheKey);
LOG.debug("Evicted from cache: {}", cacheKey);
} else {
VirAttrCacheValue cacheValue = new VirAttrCacheValue(attr.getValue());
virAttrCache.put(cacheKey, cacheValue);
LOG.debug("Set in cache: {}={}", cacheKey, cacheValue);
}
});
}
protected Map<VirSchema, List<String>> getValues(final Any<?> any, final Set<VirSchema> schemas) {
Set<ExternalResource> resources = anyUtilsFactory.getInstance(any).getAllResources(any);
Map<VirSchema, List<String>> result = new HashMap<>();
Map<Provision, Set<VirSchema>> toRead = new HashMap<>();
schemas.stream().filter(schema -> resources.contains(schema.getProvision().getResource())).forEach(schema -> {
VirAttrCacheKey cacheKey = new VirAttrCacheKey(any.getType().getKey(), any.getKey(), schema.getKey());
VirAttrCacheValue cacheValue = virAttrCache.get(cacheKey);
if (cacheValue != null) {
LOG.debug("Found in cache: {}={}", cacheKey, cacheValue);
result.put(schema, cacheValue.getValues());
} else if (schema.getProvision().getAnyType().equals(any.getType())) {
Set<VirSchema> schemasToRead = toRead.get(schema.getProvision());
if (schemasToRead == null) {
schemasToRead = new HashSet<>();
toRead.put(schema.getProvision(), schemasToRead);
}
schemasToRead.add(schema);
}
});
toRead.forEach((provision, schemasToRead) -> {
LOG.debug("About to read from {}: {}", provision, schemasToRead);
outboundMatcher.match(
connectorManager.getConnector(provision.getResource()),
any,
provision,
Optional.empty(),
schemasToRead.stream().map(VirSchema::asLinkingMappingItem).toArray(LinkingMappingItem[]::new)).
forEach(connObj -> schemasToRead.forEach(schema -> {
Attribute attr = connObj.getAttributeByName(schema.getExtAttrName());
if (attr != null) {
VirAttrCacheKey cacheKey =
new VirAttrCacheKey(any.getType().getKey(), any.getKey(), schema.getKey());
VirAttrCacheValue cacheValue = virAttrCache.put(cacheKey, new VirAttrCacheValue(attr.getValue()));
LOG.debug("Set in cache: {}={}", cacheKey, cacheValue);
result.put(schema, cacheValue.getValues());
}
}));
});
return result;
}
@Override
public List<String> getValues(final Any<?> any, final VirSchema schema) {
if (!anyUtilsFactory.getInstance(any).dao().
findAllowedSchemas(any, VirSchema.class).forSelfContains(schema)) {
LOG.debug("{} not allowed for {}", schema, any);
return List.of();
}
List<String> result = getValues(any, Set.of(schema)).get(schema);
return result == null ? List.of() : result;
}
@Override
public List<String> getValues(final Any<?> any, final Membership<?> membership, final VirSchema schema) {
if (!anyUtilsFactory.getInstance(any).dao().
findAllowedSchemas(any, VirSchema.class).getForMembership(membership.getRightEnd()).contains(schema)) {
LOG.debug("{} not allowed for {}", schema, any);
return List.of();
}
List<String> result = getValues(any, Set.of(schema)).get(schema);
return result == null ? List.of() : result;
}
@Override
public Map<VirSchema, List<String>> getValues(final Any<?> any) {
return getValues(
any,
anyUtilsFactory.getInstance(any).dao().findAllowedSchemas(any, VirSchema.class).getForSelf());
}
@Override
public Map<VirSchema, List<String>> getValues(final Any<?> any, final Membership<?> membership) {
return getValues(
any,
anyUtilsFactory.getInstance(any).dao().findAllowedSchemas(any, VirSchema.class).
getForMembership(membership.getRightEnd()));
}
}