/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2010, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jboss.as.ejb3.component.singleton;

import org.jboss.as.ee.component.ComponentConfiguration;
import org.jboss.as.ee.component.EEModuleConfiguration;
import org.jboss.as.ee.component.ViewConfiguration;
import org.jboss.as.ee.component.ViewConfigurator;
import org.jboss.as.ee.component.ViewDescription;
import org.jboss.as.ejb3.component.session.ComponentTypeIdentityInterceptorFactory;
import org.jboss.as.ejb3.component.session.SessionBeanComponentDescription;
import org.jboss.as.ejb3.deployment.EjbJarDescription;
import org.jboss.as.server.deployment.DeploymentPhaseContext;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.invocation.ImmediateInterceptorFactory;
import org.jboss.msc.service.ServiceName;

/**
 * Component description for a singleton bean
 *
 * @author Jaikiran Pai
 */
public class SingletonComponentDescription extends SessionBeanComponentDescription {

    /**
     * Flag to indicate whether the singleton bean is a @Startup (a.k.a init-on-startup) bean
     */
    private boolean initOnStartup;

    /**
     * Construct a new instance.
     *
     * @param componentName      the component name
     * @param componentClassName the component instance class name
     * @param ejbJarDescription  the module description
     */
    public SingletonComponentDescription(final String componentName, final String componentClassName, final EjbJarDescription ejbJarDescription,
                                         final ServiceName deploymentUnitServiceName) {
        super(componentName, componentClassName, ejbJarDescription, deploymentUnitServiceName);
    }

    @Override
    public ComponentConfiguration createConfiguration(EEModuleConfiguration moduleConfiguration) {

        ComponentConfiguration singletonComponentConfiguration = new ComponentConfiguration(this, moduleConfiguration.getClassConfiguration(getComponentClassName()));
        // setup the component create service
        singletonComponentConfiguration.setComponentCreateServiceFactory(new SingletonComponentCreateServiceFactory(this.isInitOnStartup()));

        return singletonComponentConfiguration;
    }

    /**
     * Returns true if the singleton bean is marked for init-on-startup (a.k.a @Startup). Else
     * returns false
     * <p/>
     *
     * @return
     */
    public boolean isInitOnStartup() {
        return this.initOnStartup;
    }

    /**
     * Marks the singleton bean for init-on-startup
     */
    public void initOnStartup() {
        this.initOnStartup = true;

    }

    @Override
    public boolean allowsConcurrentAccess() {
        return true;
    }

    @Override
    public SessionBeanType getSessionBeanType() {
        return SessionBeanComponentDescription.SessionBeanType.SINGLETON;
    }

    @Override
    protected void setupViewInterceptors(ViewDescription view) {
        // let super do its job first
        super.setupViewInterceptors(view);

        // add instance associating interceptor at the start of the interceptor chain
        view.getConfigurators().addFirst(new ViewConfigurator() {
            @Override
            public void configure(DeploymentPhaseContext context, ComponentConfiguration componentConfiguration, ViewDescription description, ViewConfiguration configuration) throws DeploymentUnitProcessingException {

                //add equals/hashCode interceptor
                configuration.addViewInterceptorToFront(ComponentTypeIdentityInterceptorFactory.INSTANCE);

                // add the singleton component instance associating interceptor
                configuration.addViewInterceptorToFront(new ImmediateInterceptorFactory(new SingletonComponentInstanceAssociationInterceptor()));
            }
        });

    }
}

@@ -1107,29 +1107,135 @@
 omponent
-Configuration
+;%0Aimport org.jboss.as.ee.component.ComponentConfiguration;%0Aimport org.jboss.as.ee.component.ComponentInterceptorFactory
 ;%0Aimport
@@ -1865,30 +1865,171 @@
 oss.
-msc.service.ServiceNam
+invocation.Interceptor;%0Aimport org.jboss.invocation.InterceptorFactoryContext;%0Aimport org.jboss.msc.service.ServiceName;%0A%0Aimport javax.ejb.TransactionManagementTyp
 e;%0A%0A
@@ -5019,20 +5019,1396 @@
        %7D);%0A%0A
+%0A        // add the bmt interceptor%0A        if (TransactionManagementType.BEAN.equals(this.getTransactionManagementType())) %7B%0A            view.getConfigurators().add(new ViewConfigurator() %7B%0A                @Override%0A                public void configure(DeploymentPhaseContext context, ComponentConfiguration componentConfiguration, ViewDescription description, ViewConfiguration configuration) throws DeploymentUnitProcessingException %7B%0A                    final ComponentInterceptorFactory slsbBmtInterceptorFactory = new ComponentInterceptorFactory() %7B%0A                        @Override%0A                        protected Interceptor create(Component component, InterceptorFactoryContext context) %7B%0A                            if (component instanceof SingletonComponent == false) %7B%0A                                throw new IllegalArgumentException(%22Component %22 + component + %22 with component class: %22 + component.getComponentClass() +%0A                                        %22 isn't a singleton component%22);%0A                            %7D%0A                            return new SingletonBMTInterceptor((SingletonComponent) component);%0A                        %7D%0A                    %7D;%0A                    // add the bmt interceptor factory%0A                    configuration.addViewInterceptorToFront(slsbBmtInterceptorFactory);%0A                %7D%0A            %7D);%0A        %7D%0A%0A
     %7D%0A%7D%0A

Add singleton BMT interceptor