/** 
 * 
 * Copyright 2004 Protique Ltd
 * 
 * Licensed 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.activemq.jca;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;

import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.UnavailableException;
import javax.resource.spi.XATerminator;
import javax.resource.spi.work.WorkManager;
import java.util.Timer;

/**
 * Represents a Spring based JCA container for a single JCA {@link ResourceAdapter}
 * which provides <i>Message Driven POJO</i> support to Spring, providing all
 * the features of MDBs but using a lightweight container.
 *
 * @version $Revision: 1.1.1.1 $
 */
public class JCAContainer implements BootstrapContext, InitializingBean, DisposableBean, BeanFactoryAware {
    private WorkManager workManager;
    private XATerminator xaTerminator;
    private ResourceAdapter resourceAdapter;
    private BeanFactory beanFactory;
    private boolean lazyLoad = false;

    public Timer createTimer() throws UnavailableException {
        return new Timer();
    }

    public JCAConnector addConnector() {
        return new JCAConnector(this, resourceAdapter);
    }

    public void afterPropertiesSet() throws Exception {
        if (workManager == null) {
            throw new IllegalArgumentException("workManager property must be set");
        }
        if (resourceAdapter == null) {
            throw new IllegalArgumentException("bootstrapContext must be set");

        }
        resourceAdapter.start(this);

        // now lets start all of the JCAConnector instances
        if (beanFactory == null) {
            throw new IllegalArgumentException("beanFactory should have been set by Spring");
        }
        else if (!lazyLoad && beanFactory instanceof ListableBeanFactory) {
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
            String[] names = listableBeanFactory.getBeanDefinitionNames();
            for (int i = 0; i < names.length; i++) {
                // TODO one day we could be smart to only pre-load the correct
                // types of bean, based on the definitions?
                String name = names[i];
                beanFactory.getBean(name);
            }
        }
    }

    public void destroy() throws Exception {
        if (resourceAdapter != null) {
            resourceAdapter.stop();
        }
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    // Properties
    //-------------------------------------------------------------------------
    public WorkManager getWorkManager() {
        return workManager;
    }

    public XATerminator getXATerminator() {
        return xaTerminator;
    }

    public void setXaTerminator(XATerminator xaTerminator) {
        this.xaTerminator = xaTerminator;
    }

    public void setWorkManager(WorkManager workManager) {
        this.workManager = workManager;
    }

    public ResourceAdapter getResourceAdapter() {
        return resourceAdapter;
    }

    public void setResourceAdapter(ResourceAdapter resourceAdapter) {
        this.resourceAdapter = resourceAdapter;
    }
}
