| /** |
| * 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); |
| } |
| } |