/*
 * 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);
            }
        }
    }
}

