/**
 * 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.geronimo.components.jaspi;

import org.apache.geronimo.components.jaspi.model.ConfigProviderType;
import org.apache.geronimo.components.jaspi.model.JaspiType;
import org.apache.geronimo.components.jaspi.model.JaspiXmlUtil;
import org.xml.sax.SAXException;

import javax.security.auth.AuthPermission;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.message.config.AuthConfigFactory;
import javax.security.auth.message.config.AuthConfigProvider;
import javax.security.auth.message.config.RegistrationListener;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Implementation of the AuthConfigFactory.
 *
 * @version $Rev: $ $Date: $
 */
public class AuthConfigFactoryImpl extends AuthConfigFactory {

    public static final String JASPI_CONFIGURATION_FILE = "org.apache.geronimo.jaspic.configurationFile";
    private static final File DEFAULT_CONFIG_FILE = new File("var/config/security/jaspic/jaspic.xml");
    public static CallbackHandler staticCallbackHandler;

    private static ClassLoader contextClassLoader;
    private JaspiType jaspiType = new JaspiType();

    private final CallbackHandler callbackHandler;
    private final File configFile;

    static {
        contextClassLoader = java.security.AccessController
                .doPrivileged(new java.security.PrivilegedAction<ClassLoader>() {
                    public ClassLoader run() {
                        return Thread.currentThread().getContextClassLoader();
                    }
                });
    }

    public AuthConfigFactoryImpl(CallbackHandler callbackHandler, File configFile) {
        JaspiXmlUtil.initialize(callbackHandler);
        this.callbackHandler = callbackHandler;
        this.configFile = configFile;
        loadConfig();
    }

    public AuthConfigFactoryImpl() {
        this(staticCallbackHandler, getConfigFile());
    }

    private static File getConfigFile() {
        String fileLocation = java.security.AccessController
                .doPrivileged(new java.security.PrivilegedAction<String>() {
                    public String run() {
                        return System.getProperty(JASPI_CONFIGURATION_FILE);
                    }
                });
        File file;
        if (fileLocation == null) {
            file = DEFAULT_CONFIG_FILE;
        } else {
            file = new File(fileLocation);
        }
        return file;
    }

    public synchronized String[] detachListener(RegistrationListener listener, String layer, String appContext) throws SecurityException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new AuthPermission("detachAuthListener"));
        }
        List<String> ids = new ArrayList<String>();
        for (Map.Entry<String, ConfigProviderType> entry : getRegistrations().entrySet()) {
            ConfigProviderType ctx = entry.getValue();
            if ((layer == null || layer.equals(ctx.getMessageLayer())) &&
                    (appContext == null || appContext.equals(ctx.getAppContext()))) {
                if (ctx.getListeners().remove(listener)) {
                    ids.add(entry.getKey());
                }
            }
        }
        return ids.toArray(new String[ids.size()]);
    }

    private Map<String, ConfigProviderType> getRegistrations() {
        return jaspiType.getConfigProvider();
    }

    public synchronized AuthConfigProvider getConfigProvider(String layer, String appContext, RegistrationListener listener) {
        if (layer == null) {
            throw new NullPointerException("messageLayer");
        }
        if (appContext == null) {
            throw new NullPointerException("appContext");
        }
        ConfigProviderType ctx = getRegistrations().get(ConfigProviderType.getRegistrationKey(layer, appContext));
        if (ctx == null) {
            ctx = getRegistrations().get(ConfigProviderType.getRegistrationKey(null, appContext));
        }
        if (ctx == null) {
            ctx = getRegistrations().get(ConfigProviderType.getRegistrationKey(layer, null));
        }
        if (ctx == null) {
            ctx = getRegistrations().get(ConfigProviderType.getRegistrationKey(null, null));
        }
        if (ctx != null) {
            if (listener != null) {
                ctx.getListeners().add(listener);
            }
            return ctx.getProvider();
        }
        return null;
    }

    public synchronized RegistrationContext getRegistrationContext(String registrationID) {
        return getRegistrations().get(registrationID);
    }

    public synchronized String[] getRegistrationIDs(AuthConfigProvider provider) {
        List<String> ids = new ArrayList<String>();
        for (Map.Entry<String, ConfigProviderType> entry : getRegistrations().entrySet()) {
            ConfigProviderType ctx = entry.getValue();
            if (provider == null ||
                    provider.getClass().getName().equals(ctx.getProvider().getClass().getName())) {
                ids.add(entry.getKey());
            }
        }
        return ids.toArray(new String[ids.size()]);
    }

    public synchronized void refresh() throws SecurityException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new AuthPermission("refreshAuth"));
        }
        loadConfig();
    }

    public String registerConfigProvider(AuthConfigProvider authConfigProvider, String layer, String appContext, String description) throws SecurityException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new AuthPermission("registerAuthConfigProvider"));
        }
        return registerConfigProvider(authConfigProvider, layer, appContext, description, false, null, null);
    }

    public synchronized String registerConfigProvider(final String className, final Map constructorParam, String layer, String appContext, String description) throws SecurityException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new AuthPermission("registerAuthConfigProvider"));
        }
        String key = registerConfigProvider(null, layer, appContext, description, true, constructorParam, className);
        saveConfig();
        return key;
    }

    private String registerConfigProvider(AuthConfigProvider provider, String layer, String appContext, String description, boolean persistent, Map<String, String> constructorParam, String className) {
        String key = ConfigProviderType.getRegistrationKey(layer, appContext);
        // Get or create context
        ConfigProviderType ctx = getRegistrations().get(key);
        if (ctx == null) {
            ctx = new ConfigProviderType(layer, appContext, persistent, persistent? null: this);
            getRegistrations().put(key, ctx);
        } else {
            if (persistent != ctx.isPersistent()) {
                throw new IllegalArgumentException("Cannot change the persistence state");
            }
        }
        // Create provider
        ctx.setDescription(description);
        if (persistent) {
            if (provider != null) {
                throw new IllegalStateException("Config provider supplied but should be created");
            }
            ctx.setClassName(className);
            ctx.setProperties(constructorParam);
            ctx.initialize(callbackHandler);
        } else {
            if (provider == null) {
                throw new IllegalStateException("No config provider to set");
            }
            ctx.setProvider(provider);
        }

        // Notify listeners
        List<RegistrationListener> listeners = ctx.getListeners();
        for (RegistrationListener listener : listeners) {
            listener.notify(ctx.getMessageLayer(), ctx.getAppContext());
        }
        // Return registration Id
        return key;
    }

    public synchronized boolean removeRegistration(String registrationID) throws SecurityException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new AuthPermission("removeAuthRegistration"));
        }
        ConfigProviderType ctx = getRegistrations().remove(registrationID);
        saveConfig();
        if (ctx != null) {
            List<RegistrationListener> listeners = ctx.getListeners();
            for (RegistrationListener listener : listeners) {
                listener.notify(ctx.getMessageLayer(), ctx.getAppContext());
            }
            return true;
        }
        return false;
    }

    private void loadConfig() {
        if (configFile != null && configFile.length() > 0) {
            try {
                FileReader in = new FileReader(configFile);
                try {
                    jaspiType = JaspiXmlUtil.loadJaspi(in);
                } finally {
                    in.close();
                }
            } catch (ParserConfigurationException e) {
                throw new SecurityException("Could not read config", e);
            } catch (IOException e) {
                throw new SecurityException("Could not read config", e);
            } catch (SAXException e) {
                throw new SecurityException("Could not read config", e);
            } catch (JAXBException e) {
                throw new SecurityException("Could not read config", e);
            } catch (XMLStreamException e) {
                throw new SecurityException("Could not read config", e);
            }
        }
    }

    private void saveConfig() {
        if (configFile != null) {
            try {
                FileWriter out = new FileWriter(configFile);
                try {
                    JaspiXmlUtil.writeJaspi(jaspiType, out);
                } finally {
                    out.close();
                }
            } catch (IOException e) {
                throw new SecurityException("Could not write config", e);
            } catch (XMLStreamException e) {
                throw new SecurityException("Could not write config", e);
            } catch (JAXBException e) {
                throw new SecurityException("Could not write config", e);
            }
        }
    }


}
