| /* |
| * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| package com.sun.jaspic.config.helper; |
| |
| import com.sun.jaspic.config.delegate.MessagePolicyDelegate; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.concurrent.locks.Lock; |
| import java.util.concurrent.locks.ReentrantReadWriteLock; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.security.auth.Subject; |
| import javax.security.auth.callback.CallbackHandler; |
| import jakarta.security.auth.message.AuthException; |
| import jakarta.security.auth.message.MessageInfo; |
| |
| /** |
| * |
| * @author Ron Monzillo |
| */ |
| public abstract class AuthConfigHelper { |
| |
| String loggerName; |
| EpochCarrier providerEpoch; |
| long epoch; |
| MessagePolicyDelegate mpDelegate; |
| String layer; |
| String appContext; |
| CallbackHandler cbh; |
| private ReentrantReadWriteLock instanceReadWriteLock = new ReentrantReadWriteLock(); |
| private Lock instanceReadLock = instanceReadWriteLock.readLock(); |
| private Lock instanceWriteLock = instanceReadWriteLock.writeLock(); |
| |
| public AuthConfigHelper(String loggerName, EpochCarrier providerEpoch, |
| MessagePolicyDelegate mpDelegate, String layer, String appContext, |
| CallbackHandler cbh) throws AuthException { |
| |
| this.loggerName = loggerName; |
| this.providerEpoch = providerEpoch; |
| this.mpDelegate = mpDelegate; |
| this.layer = layer; |
| this.appContext = appContext; |
| this.cbh = cbh; |
| initialize(); |
| } |
| |
| private void initialize() throws AuthException { |
| instanceWriteLock.lock(); |
| try { |
| this.epoch = providerEpoch.getEpoch(); |
| initializeContextMap(); |
| } finally { |
| instanceWriteLock.unlock(); |
| } |
| } |
| |
| private void doRefreshIfNeeded() { |
| boolean hasChanged = false; |
| instanceReadLock.lock(); |
| try { |
| hasChanged = providerEpoch.hasChanged(epoch); |
| } finally { |
| instanceReadLock.unlock(); |
| } |
| if (hasChanged) { |
| refresh(); |
| } |
| } |
| |
| private Integer getHashCode(Map properties) { |
| if (properties == null) { |
| return Integer.valueOf("0"); |
| } |
| return Integer.valueOf(properties.hashCode()); |
| } |
| |
| private <M> M getContextFromMap(HashMap<String, HashMap<Integer, M>> contextMap, |
| String authContextID, Map properties) { |
| M rvalue = null; |
| HashMap<Integer, M> internalMap = contextMap.get(authContextID); |
| if (internalMap != null) { |
| rvalue = internalMap.get(getHashCode(properties)); |
| } |
| if (rvalue != null) { |
| if (isLoggable(Level.FINE)) { |
| logIfLevel(Level.FINE, null, "AuthContextID found in Map: ", authContextID); |
| } |
| } |
| return rvalue; |
| } |
| |
| protected final <M> M getContext( |
| HashMap<String, HashMap<Integer, M>> contextMap, String authContextID, |
| Subject subject, Map properties) throws AuthException { |
| |
| M rvalue = null; |
| |
| doRefreshIfNeeded(); |
| instanceReadLock.lock(); |
| try { |
| rvalue = getContextFromMap(contextMap, authContextID, properties); |
| if (rvalue != null) { |
| return rvalue; |
| } |
| } finally { |
| instanceReadLock.unlock(); |
| } |
| |
| instanceWriteLock.lock(); |
| try { |
| rvalue = getContextFromMap(contextMap, authContextID, properties); |
| if (rvalue == null) { |
| |
| rvalue = (M) createAuthContext(authContextID, properties); |
| |
| HashMap<Integer, M> internalMap = contextMap.get(authContextID); |
| if (internalMap == null) { |
| internalMap = new HashMap<Integer, M>(); |
| contextMap.put(authContextID, internalMap); |
| } |
| |
| internalMap.put(getHashCode(properties), rvalue); |
| } |
| return rvalue; |
| } finally { |
| instanceWriteLock.unlock(); |
| } |
| } |
| |
| protected boolean isLoggable(Level level) { |
| Logger logger = Logger.getLogger(loggerName); |
| return logger.isLoggable(level); |
| } |
| |
| protected void logIfLevel(Level level, Throwable t, String... msgParts) { |
| Logger logger = Logger.getLogger(loggerName); |
| if (logger.isLoggable(level)) { |
| StringBuffer msgB = new StringBuffer(""); |
| for (String m : msgParts) { |
| msgB.append(m); |
| } |
| String msg = msgB.toString(); |
| if ( !msg.isEmpty() && t != null) { |
| logger.log(level, msg, t); |
| } else if (!msg.isEmpty()) { |
| logger.log(level, msg); |
| } |
| } |
| } |
| |
| protected void checkMessageTypes(Class[] supportedMessageTypes) throws AuthException { |
| Class[] requiredMessageTypes = mpDelegate.getMessageTypes(); |
| for (Class requiredType : requiredMessageTypes) { |
| boolean supported = false; |
| for (Class supportedType : supportedMessageTypes) { |
| if (requiredType.isAssignableFrom(supportedType)) { |
| supported = true; |
| } |
| } |
| if (!supported) { |
| throw new AuthException("module does not support message type: " + requiredType.getName()); |
| } |
| } |
| } |
| |
| /** |
| * Only called from initialize (while lock is held). |
| */ |
| protected abstract void initializeContextMap(); |
| |
| protected abstract <M> M createAuthContext(final String authContextID, |
| final Map properties) throws AuthException; |
| |
| public String getAppContext() { |
| return appContext; |
| } |
| |
| public String getAuthContextID(MessageInfo messageInfo) { |
| return mpDelegate.getAuthContextID(messageInfo); |
| } |
| |
| public String getMessageLayer() { |
| return layer; |
| } |
| |
| public void refresh() { |
| try { |
| initialize(); |
| } catch (AuthException ae) { |
| throw new RuntimeException(ae); |
| } |
| } |
| } |