/*
 * 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.factory;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.sun.jaspic.config.helper.JASPICLogManager;

import jakarta.security.auth.message.config.AuthConfigFactory;
import jakarta.security.auth.message.config.AuthConfigProvider;
import jakarta.security.auth.message.config.RegistrationListener;
import jakarta.security.auth.message.module.ServerAuthModule;


/**
 * This class implements methods in the abstract class AuthConfigFactory.
 * @author  Shing Wai Chan
 */
public abstract class BaseAuthConfigFactory extends AuthConfigFactory {

    private static final Logger logger = Logger.getLogger(JASPICLogManager.JASPIC_LOGGER, JASPICLogManager.RES_BUNDLE);

    private static final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
    public static final Lock rLock = rwLock.readLock();
    public static final Lock wLock = rwLock.writeLock();

    private static Map<String, AuthConfigProvider> id2ProviderMap;
    private static Map<String, RegistrationContext> id2RegisContextMap;
    private static Map<String, List<RegistrationListener>> id2RegisListenersMap;
    private static Map<AuthConfigProvider, List<String>> provider2IdsMap;

    protected static final String CONF_FILE_NAME = "auth.conf";

    abstract protected RegStoreFileParser getRegStore();

    /**
     * Get a registered AuthConfigProvider from the factory.
     *
     * Get the provider of ServerAuthConfig and/or
     * ClientAuthConfig objects registered for the identified message
     * layer and application context.
     *
     * @param layer a String identifying the message layer
     *        for which the registered AuthConfigProvider is
     *          to be returned. This argument may be null.
     *
     * @param appContext a String that identifies the application messaging
     *          context for which the registered AuthConfigProvider
     *          is to be returned. This argument may be null.
     *
     * @param listener the RegistrationListener whose
     *          <code>notify</code> method is to be invoked
     *          if the corresponding registration is unregistered or
     *          replaced. The value of this argument may be null.
     *
     * @return the implementation of the AuthConfigProvider interface
     *          registered at the factory for the layer and appContext
     *          or null if no AuthConfigProvider is selected.
     *
     * <p>All factories shall employ the following precedence rules to select
     * the registered AuthConfigProvider that matches (via matchConstructors) the
     * layer and appContext arguments:
     *<ul>
     * <li> The provider that is specifically registered for both the
     * corresponding message layer and appContext
     * shall be selected.
     * <li> if no provider is selected according to the preceding rule,
     * the provider specifically registered for the
     * corresponding appContext and for all message layers
     * shall be selected.
     * <li> if no provider is selected according to the preceding rules,
     * the provider specifically registered for the
     * corresponding message layer and for all appContexts
     * shall be selected.
     * <li> if no provider is selected according to the preceding rules,
     * the provider registered for all message layers and for all
     * appContexts shall be selected.
     * <li> if no provider is selected according to the preceding rules,
     * the factory shall terminate its search for a registered provider.
     *</ul>
     */
    @Override
    public AuthConfigProvider getConfigProvider(String layer, String appContext, RegistrationListener listener) {
        AuthConfigProvider provider = null;
        if (listener == null) {
            rLock.lock();
            try {
                provider = getConfigProviderUnderLock(layer,appContext,null);
            } finally {
                rLock.unlock();
            }
        } else {
            wLock.lock();
            try {
                provider = getConfigProviderUnderLock(layer,appContext,listener);
            } finally {
                wLock.unlock();
            }
        }
        return provider;
    }

    /**
     * Registers within the factory, a provider
     * of ServerAuthConfig and/or ClientAuthConfig objects for a
     * message layer and application context identifier.
     *
     * <P>At most one registration may exist within the factory for a
     * given combination of message layer
     * and appContext. Any pre-existing
     * registration with identical values for layer and appContext is replaced
     * by a subsequent registration. When replacement occurs, the registration
     * identifier, layer, and appContext identifier remain unchanged,
     * and the AuthConfigProvider (with initialization properties) and
     * description are replaced.
     *
     *<p>Within the lifetime of its Java process, a factory must assign unique
     * registration identifiers to registrations, and must never
     * assign a previously used registration identifier to a registration
     * whose message layer and or appContext identifier differ from
     * the previous use.
     *
     * <p>Programmatic registrations performed via this method must update
     * (according to the replacement rules described above), the persistent
     * declarative representation of provider registrations employed by the
     * factory constructor.
     *
     * @param className the fully qualified name of an AuthConfigProvider
     *          implementation class. This argument must not be null.
     *
     * @param properties a Map object containing the initialization
     *          properties to be passed to the provider constructor.
     *          This argument may be null. When this argument is not null,
     *          all the values and keys occuring in the Map must be of
     *          type String.
     *
     * @param layer a String identifying the message layer
     *        for which the provider will be registered at the factory.
     *          A null value may be passed as an argument for this parameter,
     *          in which case, the provider is registered at all layers.
     *
     * @param appContext a String value that may be used by a runtime
     *          to request a configuration object from this provider.
     *          A null value may be passed as an argument for this parameter,
     *          in which case, the provider is registered for all
     *          configuration ids (at the indicated layers).
     *
     * @param description a text String describing the provider.
     *          this value may be null.
     *
     * @return a String identifier assigned by
     *          the factory to the provider registration, and that may be
     *          used to remove the registration from the provider.
     *
     * @exception SecurityException if the caller does not have
     *        permission to register a provider at the factory.
     */
    @Override
    public String registerConfigProvider(String className, Map properties, String layer, String appContext,
        String description) {
        //XXX factory must check permission
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(AuthConfigFactory.providerRegistrationSecurityPermission);
        }
        //XXX do we need doPrivilege here
        AuthConfigProvider provider = _constructProvider(className, properties, null);
        return _register(provider, properties, layer, appContext, description, true);
    }

    @Override
    public String registerConfigProvider(AuthConfigProvider provider,
            String layer, String appContext, String description) {
        //XXX factory must check permission
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(AuthConfigFactory.providerRegistrationSecurityPermission);
        }
        return _register(provider, null, layer, appContext, description, false);
    }

    /**
     * Remove the identified provider registration from the factory
     * and invoke any listeners associated with the removed registration.
     *
     * @param registrationID a String that identifies a provider registration
     *          at the factory
     *
     * @return true if there was a registration with the specified identifier
     *          and it was removed. Return false if the registraionID was
     *          invalid.
     *
     * @exception SecurityException if the caller does not have
     *        permission to unregister the provider at the factory.
     *
     */
    @Override
    public boolean removeRegistration(String registrationID) {
        //XXX factory must check permission
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(AuthConfigFactory.providerRegistrationSecurityPermission);
        }
        return _unRegister(registrationID);
    }

    /**
     * Disassociate the listener from all the provider
     * registrations whose layer and appContext values are matched
     * by the corresponding arguments to this method.
     *
     * @param listener the RegistrationListener to be detached.
     *
     * @param layer a String identifying the message layer or null.
     *
     * @param appContext a String value identifying the application context
     *          or null.
     *
     * @return an array of String values where each value identifies a
     *          provider registration from which the listener was removed.
     *          This method never returns null; it returns an empty array if
     *          the listener was not removed from any registrations.
     *
     * @exception SecurityException if the caller does not have
     *        permission to detach the listener from the factory.
     *
     */
    @Override
    public String[] detachListener(RegistrationListener listener, String layer, String appContext) {
        //XXX factory must check permission
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(AuthConfigFactory.providerRegistrationSecurityPermission);
        }
        ArrayList<String> list = new ArrayList<>();
        String regisID = getRegistrationID(layer, appContext);
        wLock.lock();
        try {
            Set<String> targets = id2RegisListenersMap.keySet();
            for (String targetID : targets) {
                if (regIdImplies(regisID, targetID)) {
                    List<RegistrationListener> listeners =
                            id2RegisListenersMap.get(targetID);
                    if (listeners != null && listeners.remove(listener)) {
                        list.add(targetID);
                    }
                }
            }
        } finally {
            wLock.unlock();
        }
        return list.toArray(new String[list.size()]);
    }

    /**
     * Get the registration identifiers for all registrations of the
     * provider instance at the factory.
     *
     * @param provider the AuthConfigurationProvider whose registration
     *          identifiers are to be returned. This argument may be
     *          null, in which case, it indicates that the the id's of
     *          all active registration within the factory are returned.
     *
     * @return an array of String values where each value identifies a
     * provider registration at the factory. This method never returns null;
     * it returns an empty array when their are no registrations at the
     * factory for the identified provider.
     */
    @Override
    public String[] getRegistrationIDs(AuthConfigProvider provider) {
        rLock.lock();
        try {
            Collection<String> regisIDs = null;
            if (provider != null) {
                regisIDs = provider2IdsMap.get(provider);
            } else {
                Collection<List<String>> collList = provider2IdsMap.values();
                if (collList != null) {
                    regisIDs = new HashSet<>();
                    for (List<String> listIds : collList) {
                         if (listIds != null) {
                             regisIDs.addAll(listIds);
                         }
                    }
                }
            }
            return ((regisIDs != null) ? regisIDs.toArray(new String[regisIDs.size()]) : new String[0]);
        } finally {
            rLock.unlock();
        }
    }

    /**
     * Get the the registration context for the identified registration.
     *
     * @param registrationID a String that identifies a provider registration
     *          at the factory
     *
     * @return a RegistrationContext or null. When a Non-null value is
     * returned, it is a copy of the registration context corresponding to the
     * registration. Null is returned when the registration identifier does
     * not correspond to an active registration
     */
    @Override
    public RegistrationContext getRegistrationContext(String registrationID) {
        rLock.lock();
        try {
            return id2RegisContextMap.get(registrationID);
        } finally {
            rLock.unlock();
        }
    }

   /**
     * Cause the factory to reprocess its persistent declarative
     * representation of provider registrations.
     *
     * <p> A factory should only replace an existing registration when
     * a change of provider implementation class or initialization
     * properties has occurred.
     *
     * @exception SecurityException if the caller does not have permission
     *        to refresh the factory.
     */
    @Override
    public void refresh() {
        //XXX factory must check permission
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(AuthConfigFactory.providerRegistrationSecurityPermission);
        }
        Map<String, List<RegistrationListener>> preExistingListenersMap;
        wLock.lock();
        try {
            preExistingListenersMap = id2RegisListenersMap;
            _loadFactory();
        } finally {
            wLock.unlock();
        }

        // notify pre-existing listeners after (re)loading factory
        if (preExistingListenersMap != null) {
            notifyListeners(preExistingListenersMap);
        }
    }

    @Override
    public String registerServerAuthModule(ServerAuthModule serverAuthModule, Object context) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void removeServerAuthModule(Object context) {
        // TODO Auto-generated method stub

    }


    private AuthConfigProvider getConfigProviderUnderLock(String layer, String appContext,
        RegistrationListener listener) {
        AuthConfigProvider provider = null;
        String regisID = getRegistrationID(layer, appContext);
        String matchedID = null;
        boolean providerFound = false;
        if (id2ProviderMap.containsKey(regisID)) {
            provider = id2ProviderMap.get(regisID);
            providerFound = true;
        }
        if (!providerFound) {
            matchedID = getRegistrationID(null, appContext);
            if (id2ProviderMap.containsKey(matchedID)) {
                provider = id2ProviderMap.get(matchedID);
                providerFound = true;
            }
        }
        if (!providerFound) {
            matchedID = getRegistrationID(layer, null);
            if (id2ProviderMap.containsKey(matchedID)) {
                provider = id2ProviderMap.get(matchedID);
                providerFound = true;
            }
        }
        if (!providerFound) {
            matchedID = getRegistrationID(null, null);
            if (id2ProviderMap.containsKey(matchedID)) {
                provider = id2ProviderMap.get(matchedID);
            }
        }
        if (listener != null) {
            List<RegistrationListener> listeners = id2RegisListenersMap.get(regisID);
            if (listeners == null) {
                listeners = new ArrayList<>();
                id2RegisListenersMap.put(regisID, listeners);
            }
            if (!listeners.contains(listener)) {
                listeners.add(listener);
            }
        }

        return provider;
    }


    private static String getRegistrationID(String layer, String appContext) {
        String regisID = null;

        // __0                          (null, null)
        // __1<appContext>              (null, appContext)
        // __2<layer>                   (layer, null)
        // __3<nn>_<layer><appContext>  (layer, appContext)

        if (layer != null) {
            regisID = (appContext != null) ?
                "__3" + layer.length() + "_" + layer + appContext :
                "__2" + layer;
        } else {
            regisID = (appContext != null) ?
                "__1" + appContext :
                "__0";
        }
        return regisID;
    }

    /**
     * This API decomposes the given regisID into layer and appContext.
     * @param regisID
     * @return a String array with layer and appContext
     */
    private static String[] decomposeRegisID(String regisID) {
        String layer = null;
        String appContext = null;
        if (regisID.equals("__0")) {
            // null, null
        } else if (regisID.startsWith("__1")) {
            appContext = (regisID.length() == 3)?
                   "" : regisID.substring(3);
        } else if (regisID.startsWith("__2")) {
            layer = (regisID.length() == 3)?
                   "" : regisID.substring(3);
        } else if (regisID.startsWith("__3")) {
            int ind = regisID.indexOf('_', 3);
            if (regisID.length() > 3 && ind > 0) {
                String numberString = regisID.substring(3, ind);
                int n;
                try {
                    n = Integer.parseInt(numberString);
                } catch (Exception ex) {
                    throw new IllegalArgumentException();
                }
                layer = regisID.substring(ind + 1, ind + 1 + n);
                appContext = regisID.substring(ind + 1 + n);
            } else {
                throw new IllegalArgumentException();
            }
        } else {
            throw new IllegalArgumentException();
        }

        return new String[]{layer, appContext};
    }

    private static AuthConfigProvider _constructProvider(String className, Map properties, AuthConfigFactory factory) {
        //XXX do we need doPrivilege here
        AuthConfigProvider provider = null;
        if (className != null) {
            try {
                ClassLoader loader = Thread.currentThread().getContextClassLoader();
                Class c = Class.forName(className, true, loader);
                Constructor<AuthConfigProvider> constr = c.getConstructor(Map.class, AuthConfigFactory.class);
                provider = constr.newInstance(new Object[] {properties, factory});
            } catch (Throwable t) {
                Throwable cause = t.getCause();
                logger.log(Level.WARNING,
                        "jmac.factory_unable_to_load_provider",
                        new Object[]{ className, t.toString(), (cause == null ? "cannot determine" : cause.toString())});
            }
        }
        return provider;
    }

    //XXX need to update persistent state and notify effected listeners
    private String _register(AuthConfigProvider provider,
            Map<String, Object> properties,
            String layer,
            String appContext,
            String description,
            boolean persistent) {

        String regisID = getRegistrationID(layer, appContext);
        RegistrationContext rc =
                new RegistrationContextImpl(layer, appContext, description, persistent);
        RegistrationContext prevRegisContext = null;
        Map<String, List<RegistrationListener>> listenerMap;
        wLock.lock();
        try {
            prevRegisContext = id2RegisContextMap.get(regisID);
            AuthConfigProvider prevProvider = id2ProviderMap.get(regisID);

            // handle the persistence first - so that any exceptions occur before
            // the actual registration happens
            if (persistent) {
                _storeRegistration(regisID, rc, provider, properties);
            } else if (prevRegisContext != null && prevRegisContext.isPersistent()) {
                _deleteStoredRegistration(regisID, prevRegisContext);
            }

            boolean wasRegistered = id2ProviderMap.containsKey(regisID);

            if (wasRegistered) {
                List<String> prevRegisIDs = provider2IdsMap.get(prevProvider);
                prevRegisIDs.remove(regisID);
                if (prevRegisIDs.isEmpty()) {
                    provider2IdsMap.remove(prevProvider);
                }
            }

            id2ProviderMap.put(regisID, provider);
            id2RegisContextMap.put(regisID, rc);

            List<String> regisIDs = provider2IdsMap.get(provider);
            if (regisIDs == null) {
                regisIDs = new ArrayList<>();
                provider2IdsMap.put(provider, regisIDs);
            }

            if (!regisIDs.contains(regisID)) {
                regisIDs.add(regisID);
            }

            listenerMap = getEffectedListeners(regisID);

        } finally {
            wLock.unlock();
        }

        // outside wLock to prevent dead lock
        notifyListeners(listenerMap);

        return regisID;
    }

    //XXX need to update persistent state and notify effected listeners
    private boolean _unRegister(String regisID) {
        boolean rvalue = false;
        RegistrationContext rc = null;
        Map<String, List<RegistrationListener>> listenerMap;
        wLock.lock();
        try {
            rc = id2RegisContextMap.remove(regisID);
            rvalue = id2ProviderMap.containsKey(regisID);
            AuthConfigProvider provider = id2ProviderMap.remove(regisID);
            List<String> regisIDs = provider2IdsMap.get(provider);
            if (regisIDs != null) {
                regisIDs.remove(regisID);
            }
            if (regisIDs == null || regisIDs.isEmpty()) {
                provider2IdsMap.remove(provider);
            }
            if (!rvalue) {
                return false;
            }
            listenerMap = getEffectedListeners(regisID);
            if (rc != null && rc.isPersistent()) {
                    _deleteStoredRegistration(regisID, rc);
            }
        } finally {
            wLock.unlock();
        }

        // outside wLock to prevent dead lock
        notifyListeners(listenerMap);
        return rvalue;
    }

// the following methods implement the factory's persistence layer
    protected void _loadFactory() {
        try {
            initializeMaps();

            List<EntryInfo> entryList = getRegStore().getPersistedEntries();

            for (EntryInfo info : entryList) {
                if (info.isConstructorEntry()) {
                    _constructProvider(info.getClassName(), info.getProperties(), this);
                } else {
                    boolean first = true;
                    AuthConfigProvider p = null;
                    List<RegistrationContext> contexts = (info.getRegContexts());
                    for (RegistrationContext ctx : contexts) {
                        if (first) {
                            p = _constructProvider(info.getClassName(), info.getProperties(), null);
                        }
                        _loadRegistration(p, ctx.getMessageLayer(), ctx.getAppContext(), ctx.getDescription());
                    }
                }
            }
        } catch (Exception e) {
            if (logger.isLoggable(Level.WARNING)) {
                logger.log(Level.WARNING,
                        "jmac.factory_auth_config_loader_failure", e);
            }
        }
    }

    /**
     * Initialize the static maps in a static method
     */
    private static void initializeMaps() {
        id2ProviderMap = new HashMap<>();
        id2RegisContextMap = new HashMap<>();
        id2RegisListenersMap = new HashMap<>();
        provider2IdsMap = new HashMap<>();
    }

    private static String _loadRegistration(AuthConfigProvider provider,
            String layer,
            String appContext,
            String description) {

        RegistrationContext rc = new RegistrationContextImpl(layer, appContext, description, true);
        String regisID = getRegistrationID(layer, appContext);
        id2RegisContextMap.get(regisID);
        AuthConfigProvider prevProvider = id2ProviderMap.get(regisID);
        boolean wasRegistered = id2ProviderMap.containsKey(regisID);
        if (wasRegistered) {
            List<String> prevRegisIDs = provider2IdsMap.get(prevProvider);
            prevRegisIDs.remove(regisID);
            if (prevRegisIDs.isEmpty()) {
                provider2IdsMap.remove(prevProvider);
            }
        }

        id2ProviderMap.put(regisID, provider);
        id2RegisContextMap.put(regisID, rc);

        List<String> regisIDs = provider2IdsMap.get(provider);
        if (regisIDs == null) {
            regisIDs = new ArrayList<>();
            provider2IdsMap.put(provider, regisIDs);
        }

        if (!regisIDs.contains(regisID)) {
            regisIDs.add(regisID);
        }

        return regisID;
    }


    private void _storeRegistration(String regId, RegistrationContext ctx, AuthConfigProvider p, Map properties) {

        String className = null;
        if (p != null) {
            className = p.getClass().getName();
        }
        if (propertiesContainAnyNonStringValues(properties)) {
            throw new IllegalArgumentException("AuthConfigProvider cannot be registered - properties must all be of type String.");
        }
        if (ctx.isPersistent()) {
            getRegStore().store(className, ctx, properties);
        }
    }


    private boolean propertiesContainAnyNonStringValues(Map<String,Object> props) {
        if (props != null) {
            for(Map.Entry<String, Object> entry : props.entrySet()) {
                if (!(entry.getValue() instanceof String)) {
                    return true;
                }
            }
        }
        return false;
    }


    private void _deleteStoredRegistration(String regId, RegistrationContext ctx) {
        if (ctx.isPersistent()) {
            getRegStore().delete(ctx);
        }
    }

    private static boolean regIdImplies(String reference, String target) {

        boolean rvalue = true;

        String[] refID = decomposeRegisID(reference);
        String[] targetID = decomposeRegisID(target);

        if (refID[0] != null && !refID[0].equals(targetID[0])) {
            rvalue = false;
        } else if (refID[1] != null && !refID[1].equals(targetID[1])) {
            rvalue = false;
        }
        return rvalue;
    }

    /* will return some extra listeners. iow, effected listeners could be reduced
     * by removing any associated with a provider registration id that is
     * more specific than the one being added or removed.l
     */
    private static Map<String, List<RegistrationListener>> getEffectedListeners(String regisID) {
        Map<String, List<RegistrationListener>> effectedListeners = new HashMap<>();
        Set<String> listenerRegistrations = new HashSet<>(id2RegisListenersMap.keySet());

        for (String listenerID : listenerRegistrations) {
            if (regIdImplies(regisID, listenerID)) {
                if (!effectedListeners.containsKey(listenerID)) {
                    effectedListeners.put(listenerID, new ArrayList<RegistrationListener>());
                }
                effectedListeners.get(listenerID).addAll(id2RegisListenersMap.remove(listenerID));
            }
        }
        return effectedListeners;
    }

    private static void notifyListeners(Map<String, List<RegistrationListener>> map) {
        Set<Map.Entry<String, List<RegistrationListener>>> entrySet = map.entrySet();
        for (Map.Entry<String, List<RegistrationListener>> entry : entrySet) {
            List<RegistrationListener> listeners = map.get(entry.getKey());

            if (listeners != null && listeners.size() > 0) {
                String[] dIds = decomposeRegisID(entry.getKey());

                for (RegistrationListener listener : listeners) {
                    listener.notify(dIds[0], dIds[1]);
                }
            }
        }
    }
}
