blob: b506fe1a0694c87bcf72206a6363a50f98f0a4a9 [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.kerby.kerberos.kerb.identity;
import org.apache.kerby.config.Config;
import org.apache.kerby.config.Configured;
import org.apache.kerby.kerberos.kerb.KrbException;
import org.apache.kerby.kerberos.kerb.request.KdcClientRequest;
import org.apache.kerby.kerberos.kerb.request.KrbIdentity;
import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationData;
import org.apache.kerby.kerberos.kerb.type.ticket.EncTicketPart;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* A cacheable identity backend that provides a cache with FIFO and size limit.
* Note only limited recently active identities are kept in the cache, and other
* identities are meant to be loaded from the underlying backend like memory,
* file, SQL DB, LDAP, and etc.
*/
public class CacheableIdentityService
extends Configured implements IdentityService {
private static final int DEFAULT_CACHE_SIZE = 1000;
private Map<String, KrbIdentity> idCache;
private int cacheSize = DEFAULT_CACHE_SIZE;
private IdentityService underlying;
public CacheableIdentityService(Config config, IdentityService underlying) {
super(config);
this.underlying = underlying;
init();
}
/**
* {@inheritDoc}
*/
@Override
public boolean supportBatchTrans() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public BatchTrans startBatchTrans() throws KrbException {
throw new KrbException("Transaction isn't supported");
}
private void init() {
Map<String, KrbIdentity> tmpMap =
new LinkedHashMap<String, KrbIdentity>(cacheSize) {
private static final long serialVersionUID = -6911200685333503214L;
@Override
protected boolean removeEldestEntry(Map.Entry<String, KrbIdentity> eldest) {
return size() > cacheSize;
}
};
idCache = new ConcurrentHashMap<>(tmpMap);
}
/**
* {@inheritDoc}
*/
@Override
public Iterable<String> getIdentities() throws KrbException {
return underlying.getIdentities();
}
/**
* {@inheritDoc}
*/
@Override
public KrbIdentity getIdentity(String principalName) throws KrbException {
if (idCache.containsKey(principalName)) {
return idCache.get(principalName);
}
KrbIdentity identity = underlying.getIdentity(principalName);
if (identity != null) {
idCache.put(principalName, identity);
}
return identity;
}
/**
* {@inheritDoc}
*/
@Override
public KrbIdentity addIdentity(KrbIdentity identity) throws KrbException {
KrbIdentity added = underlying.addIdentity(identity);
if (added != null) {
idCache.put(added.getPrincipalName(), added);
}
return added;
}
/**
* {@inheritDoc}
*/
@Override
public KrbIdentity updateIdentity(KrbIdentity identity) throws KrbException {
KrbIdentity updated = underlying.updateIdentity(identity);
if (updated != null) {
idCache.put(updated.getPrincipalName(), updated);
}
return updated;
}
/**
* {@inheritDoc}
*/
@Override
public void deleteIdentity(String principalName) throws KrbException {
if (idCache.containsKey(principalName)) {
idCache.remove(principalName);
}
underlying.deleteIdentity(principalName);
}
/**
* {@inheritDoc}
*/
@Override
public AuthorizationData getIdentityAuthorizationData(KdcClientRequest kdcClientRequest,
EncTicketPart encTicketPart) throws KrbException {
return underlying.getIdentityAuthorizationData(kdcClientRequest,
encTicketPart);
}
}