/*
 * 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 flex.messaging.factories;

import flex.messaging.FlexFactory;
import flex.messaging.DestructibleFlexFactory;
import flex.messaging.FlexSession;
import flex.messaging.FlexContext;
import flex.messaging.FactoryInstance;
import flex.messaging.MessageBroker;
import flex.messaging.FlexSessionListener;
import flex.messaging.config.ConfigMap;
import flex.messaging.config.ConfigurationException;
import flex.messaging.services.ServiceException;

import flex.messaging.config.ConfigurationManager;
import flex.messaging.log.Log;
import flex.messaging.util.StringUtils;
import flex.messaging.util.ExceptionUtil;

import javax.servlet.ServletContext;

/**
 * This class implements the FlexFactory interface to constructs Flex messaging
 * components.  The JavaFactory uses the class name, specified as the source
 * attribute to determine the class for instances.   The scope attribute can be one of
 * session, application or request to determine its lifecycle.  If you
 * use application or session, you can specify the optional attribute-id
 * parameter to control the name of the key for storing the component.  Two destinations
 * using the same attribute-id will use the same component.  The component is stored
 * in the ServletContext (for application scoped components) and in the
 * session (for session scoped components) so you can use these components in your
 * JSP as well.
 */
public class JavaFactory implements FlexFactory, DestructibleFlexFactory
{
    private static final String ATTRIBUTE_ID = "attribute-id";

    private static final int SINGLETON_ERROR = 10656;
    private static final int SESSION_NOT_FOUND = 10652;
    private static final int INVALID_CLASS_FOUND = 10654;

    /**
     *
     * Default constructor
     */
    public JavaFactory()
    {
    }

    /**
     * This method can be used to provide additional configuration parameters
     * for the initializing this factory instance itself.
     */
    public void initialize(String id, ConfigMap configMap) {}

    /**
     * This method is called when we initialize the definition of an instance which
     * will be looked up by this factory.  It should validate that the properties
     * supplied are valid to define an instance.  Any valid properties used for
     * this configuration must be accessed to avoid warnings about unused
     * configuration elements.  If your factory is only used for application
     * scoped components, you do not need to implement this method as the lookup
     * method itself can be used to validate its configuration.
     */
    public FactoryInstance createFactoryInstance(String id, ConfigMap properties)
    {
        JavaFactoryInstance instance = new JavaFactoryInstance(this, id, properties);

        if (properties == null)
        {
            // Use destination id as the default attribute id to prevent unwanted sharing.
            instance.setSource(instance.getId());
            instance.setScope(SCOPE_REQUEST);
            instance.setAttributeId(id);
        }
        else
        {
            instance.setSource(properties.getPropertyAsString(SOURCE, instance.getId()));
            instance.setScope(properties.getPropertyAsString(SCOPE, SCOPE_REQUEST));
            // Use destination id as the default attribute id to prevent unwanted sharing.
            instance.setAttributeId(properties.getPropertyAsString(ATTRIBUTE_ID, id));
        }

        if (instance.getScope().equalsIgnoreCase(SCOPE_APPLICATION))
        {
            try
            {
                MessageBroker mb = FlexContext.getMessageBroker();
                ServletContext ctx = mb != null?  mb.getServletContext() : null;
                if (ctx == null) // Should not be the case; just in case.
                    return instance;

                synchronized (ctx)
                {
                    Object inst = ctx.getAttribute(instance.getAttributeId());
                    if (inst == null)
                    {
                        inst = instance.createInstance();
                        ctx.setAttribute(instance.getAttributeId(), inst);
                    }
                    else
                    {
                        Class configuredClass = instance.getInstanceClass();
                        Class instClass = inst.getClass();
                        if (configuredClass != instClass &&
                                !configuredClass.isAssignableFrom(instClass))
                        {
                            ServiceException e = new ServiceException();
                            e.setMessage(INVALID_CLASS_FOUND, new Object[] {
                                    instance.getAttributeId(), "application", instance.getId(),
                                    instance.getInstanceClass(), inst.getClass()});
                            e.setCode("Server.Processing");
                            throw e;
                        }
                    }
                    instance.applicationInstance = inst;

                    // increment attribute-id reference count on MB
                    mb.incrementAttributeIdRefCount(instance.getAttributeId());
                }
            }
            catch (Throwable t)
            {
                ConfigurationException ex = new ConfigurationException();
                ex.setMessage(SINGLETON_ERROR, new Object[] { instance.getSource(), id });
                ex.setRootCause(t);

                if (Log.isError())
                    Log.getLogger(ConfigurationManager.LOG_CATEGORY).error(ex.getMessage() + StringUtils.NEWLINE + ExceptionUtil.toString(t));

                throw ex;
            }
        }
        else if(instance.getScope().equalsIgnoreCase(SCOPE_SESSION))
        {
            // increment attribute-id reference count on MB for Session scoped instances
            MessageBroker mb = FlexContext.getMessageBroker();
            if (mb != null)
                mb.incrementAttributeIdRefCount(instance.getAttributeId());
        }
        return instance;
    }

    /**
     * Returns the instance specified by the source
     * and properties arguments.  For the factory, this may mean
     * constructing a new instance, optionally registering it in some other
     * name space such as the session or JNDI, and then returning it
     * or it may mean creating a new instance and returning it.
     * This method is called for each request to operate on the
     * given item by the system so it should be relatively efficient.
     * <p>
     * If your factory does not support the scope property, it report an error
     * if scope is supplied in the properties for this instance.
     * </p>
     *
     * @param inst the FactoryInstance to lookup.
     * @return the constructed and initialized component for this factory instance.
     */
    public Object lookup(FactoryInstance inst)
    {
        JavaFactoryInstance factoryInstance = (JavaFactoryInstance) inst;
        Object instance;

        if (factoryInstance.getScope().equalsIgnoreCase(SCOPE_APPLICATION))
        {
            instance = factoryInstance.applicationInstance;
        }
        else if (factoryInstance.getScope().equalsIgnoreCase(SCOPE_SESSION))
        {
            // See if an instance already exists in this http session first
            FlexSession session = FlexContext.getFlexSession();
            if (session != null)
            {
                instance = session.getAttribute(factoryInstance.getAttributeId());
                if (instance != null)
                {
                    Class configuredClass = factoryInstance.getInstanceClass();
                    Class instClass = instance.getClass();
                    if (configuredClass != instClass &&
                        !configuredClass.isAssignableFrom(instClass))
                    {
                        ServiceException e = new ServiceException();
                        e.setMessage(INVALID_CLASS_FOUND, new Object[] {
                                        factoryInstance.getAttributeId(),
                                        "session",
                                        factoryInstance.getId(),
                                        factoryInstance.getInstanceClass(), instance.getClass()});
                        e.setCode("Server.Processing");
                        throw e;
                    }
                }
                else
                {
                    // none exists - create it the first time for each session
                    instance = factoryInstance.createInstance();
                    session.setAttribute(factoryInstance.getAttributeId(), instance);
                }
            }
            else
                instance = null;

            if (instance == null)
            {
                ServiceException e = new ServiceException();
                e.setMessage(SESSION_NOT_FOUND, new Object[] {factoryInstance.getId()});
                e.setCode("Server.Processing");
                throw e;
            }
        }
        else
        {
            instance = factoryInstance.createInstance();
        }
        return instance;
    }

    /**
     * This method is called when a component using this factory is being destroyed.
     * When appropriate, it frees up resources that were used by the factory instance
     * and are no longer needed
     *
     * @param inst The FactoryInstance to be cleaned up
     */
    public void destroyFactoryInstance(FactoryInstance inst)
    {
        JavaFactoryInstance factoryInstance = (JavaFactoryInstance) inst;

        // if we are stopping a destination with an Application or Session scoped assembler, we may
        // have to remove the assembler from the ServletContext or Session
        if (factoryInstance != null)
        {
            MessageBroker mb = FlexContext.getMessageBroker();
            String attributeId = factoryInstance.getAttributeId();

            if (FlexFactory.SCOPE_APPLICATION.equals(factoryInstance.getScope()))
            {
                ServletContext ctx = mb.getServletContext();
                if (ctx == null) // Should never be the case, but just in case.
                    return;

                synchronized (ctx)
                {
                    // remove from ServletContext if reference count is zero
                    int refCount = (mb != null) ? mb.decrementAttributeIdRefCount(attributeId) : 0;
                    if (refCount <= 0)
                    {
                        // remove assembler from servlet context
                        ctx.removeAttribute(attributeId);
                    }
                }
            }
            else if (FlexFactory.SCOPE_SESSION.equals(factoryInstance.getScope()))
            {
                FlexSession session = FlexContext.getFlexSession();

                // if this is being stopped during runtime config, we should have a session available to us
                // However, if this is being stopped on MessageBroker shutdown, we will not have a session
                // but do not need to worry about clean up in that case as the entire session will be cleaned up
                if (session == null)
                    return;

                // remove from Session if reference count is zero
                int refCount = (mb != null) ? mb.decrementAttributeIdRefCount(attributeId) : 0;
                if (refCount <= 0)
                {
                    // remove assembler from servlet context
                    session.removeAttribute(attributeId);
                }
            }

            // Remove this instance from Session created listeners
            // Only helps if listener was created by the factory, but this is common (aka assembler classes)
            if (factoryInstance.applicationInstance instanceof FlexSessionListener)
            {
                FlexSession.removeSessionCreatedListener((FlexSessionListener) factoryInstance.applicationInstance);
            }
        }
    }
}

