package org.springframework.security.config

import groovy.xml.MarkupBuilder
import org.springframework.context.support.AbstractXmlApplicationContext
import org.springframework.security.config.util.InMemoryXmlApplicationContext
import org.springframework.security.core.context.SecurityContextHolder
import spock.lang.Specification
import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML
import org.springframework.context.ApplicationListener
import org.springframework.context.ApplicationEvent
import org.springframework.security.authentication.event.AbstractAuthenticationEvent
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent
import org.springframework.security.access.event.AbstractAuthorizationEvent
import org.springframework.security.CollectingAppListener

/**
 *
 * @author Luke Taylor
 */
abstract class AbstractXmlConfigTests extends Specification {
    AbstractXmlApplicationContext appContext;
    Writer writer;
    MarkupBuilder xml;
    ApplicationListener appListener;

    def setup() {
        writer = new StringWriter()
        xml = new MarkupBuilder(writer)
        appListener = new CollectingAppListener()
    }

    def cleanup() {
        if (appContext != null) {
            appContext.close();
            appContext = null;
        }
        SecurityContextHolder.clearContext();
    }

    def bean(String name, Class clazz) {
        xml.'b:bean'(id: name, 'class': clazz.name)
    }

    def bean(String name, String clazz) {
        xml.'b:bean'(id: name, 'class': clazz)
    }

    def bean(String name, String clazz, List constructorArgs) {
        xml.'b:bean'(id: name, 'class': clazz) {
            constructorArgs.each { val ->
                'b:constructor-arg'(value: val)
            }
        }
    }

    def bean(String name, String clazz, Map properties, Map refs) {
        xml.'b:bean'(id: name, 'class': clazz) {
            properties.each {key, val ->
                'b:property'(name: key, value: val)
            }
            refs.each {key, val ->
                'b:property'(name: key, ref: val)
            }
        }
    }

    def createAppContext() {
        createAppContext(AUTH_PROVIDER_XML)
    }

    def createAppContext(String extraXml) {
        appContext = new InMemoryXmlApplicationContext(writer.toString() + extraXml);
        appContext.addApplicationListener(appListener);
    }
}
