<commit_before>/*
 * Copyright 2002-2004 the original author or authors.
 * 
 * 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.springframework.richclient.application;

import javax.swing.SwingUtilities;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.richclient.application.splash.SplashScreen;
import org.springframework.richclient.progress.ProgressMonitor;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * The main driver for a Spring Rich Client application. This class displays a
 * configurable splash screen and instantiates the rich client <code>Application</code>
 * instance.
 * 
 * @author <NAME>
 * @see Application
 */
public class ApplicationLauncher {
    public static final String SPLASH_SCREEN_BEAN_ID = "splashScreen";

    public static final String APPLICATION_BEAN_ID = "application";

    private final Log logger = LogFactory.getLog(getClass());

    private ApplicationContext startupContext;

    private SplashScreen splashScreen;

    private ApplicationContext rootApplicationContext;

    /**
     * Launch the application using the spring application context at the provided path
     * for configuration.
     * 
     * @param rootContextPath the classpath application context path
     */
    public ApplicationLauncher(String rootContextPath) {
        this(new String[] {rootContextPath});
    }

    /**
     * Launch the application using the spring application context at the provided paths
     * for configuration.
     * 
     * @param rootContextPath the classpath application context paths
     */
    public ApplicationLauncher(String[] rootContextPath) {
        this(null, rootContextPath);
    }

    /**
     * Launch the application using the spring application context at the provided paths
     * for configuration. The startup context path is loaded first to allow for quick
     * loading of the application splash screen.
     * 
     * @param startupContext the startup context classpath
     * @param rootContextPath the classpath application context path
     */
    public ApplicationLauncher(String startupContext, String rootContextPath) {
        this(startupContext, new String[] {rootContextPath});
    }

    /**
     * Launch the application using the spring application context at the provided paths
     * for configuration. The startup context path is loaded first to allow for quick
     * loading of the application splash screen.
     * 
     * @param startupContextPath the startup context classpath
     * @param rootContextPath the classpath application context paths
     */
    public ApplicationLauncher(String startupContextPath, String[] rootContextPath) {
        Assert.notEmpty(rootContextPath, "One or more root rich client application context paths must be provided");
        this.startupContext = loadStartupContext(startupContextPath);
        if (startupContext != null) {
            displaySplashScreen(startupContext);
        }
        try {
            setRootApplicationContext(loadRootApplicationContext(rootContextPath));
            launchMyRichClient();
        } finally {
            destroySplashScreen();
        }
    }

    /**
     * Launch the application from the pre-loaded application context.
     *
     * @param rootApplicationContext the application context.
     */
    public ApplicationLauncher(ApplicationContext rootApplicationContext) {
        this(null, rootApplicationContext);
    }

    /**
     * Launch the application from the pre-loaded application context.
     *
     * @param rootApplicationContext the application context.
     */
    public ApplicationLauncher(String startupContextPath, ApplicationContext rootApplicationContext) {
        this.startupContext = loadStartupContext(startupContextPath);
        if (startupContext != null) {
            displaySplashScreen(startupContext);
        }
        try {
            setRootApplicationContext(rootApplicationContext);
            launchMyRichClient();
        } finally {
            destroySplashScreen();
        }
    }

    private ApplicationContext loadStartupContext(String startupContextPath) {
        if (StringUtils.hasText(startupContextPath)) {
            logger.info("Loading startup context...");
            return new ClassPathXmlApplicationContext(startupContextPath);
        } else {
            return null;
        }
    }

    private ApplicationContext loadRootApplicationContext(String[] contextPaths) {
        final ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(contextPaths,
                false);

        final ProgressMonitor tracker = splashScreen.getProgressMonitor();

        applicationContext.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
            public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
                    private int max = -1;

                    public Object postProcessBeforeInitialization(Object bean, String beanName)
                            throws BeansException {
                        if (max == -1) {
                            max = 0;
                            ConfigurableListableBeanFactory configurableListBeanFactory = applicationContext.getBeanFactory();
                            String[] beanNames = applicationContext.getBeanDefinitionNames();
                            for (int i = 0; i < beanNames.length; i++) {
                                // using beanDefinition to check singleton property because when accessing through
                                // context (applicationContext.isSingleton(beanName)), bean will be created already,
                                // possibly bypassing other BeanFactoryPostProcessors
                                if (configurableListBeanFactory.getBeanDefinition(beanNames[i]).isSingleton())
                                    max++;
                            }
                            tracker.taskStarted("Loading Application Context ...", max);
                        }

                        if (applicationContext.containsLocalBean(beanName)) {
                            tracker.subTaskStarted("Loading " + beanName + " ...");
                            tracker.worked(1);
                        }

                        return bean;
                    }

                    public Object postProcessAfterInitialization(Object bean, String beanName)
                            throws BeansException {
                        return bean;
                    }
                });
            }
        });

        applicationContext.refresh();

        return applicationContext;
    }

    private void setRootApplicationContext(ApplicationContext context) {
        Assert.notNull(context, "The root rich client application context is required");
        this.rootApplicationContext = context;
    }

    /**
     * Launch this rich client application; with the startup context loading first, built
     * from the <code>startupContextPath</code> location in the classpath.
     * <p>
     * It is recommended that the startup context contain contain a splash screen
     * definition for quick loading & display.
     * <p>
     * Once the splash screen is displayed, the main application context is then
     * initialized, built from the <code>contextPaths</code> location(s) in the
     * classpath. The root application bean is retrieved and the startup lifecycle begins.
     */
    private void launchMyRichClient() {
        if (startupContext == null) {
            displaySplashScreen(rootApplicationContext);
        }

        Application application;
        try {
            application = (Application)rootApplicationContext.getBean(APPLICATION_BEAN_ID, Application.class);
        }
        catch (NoSuchBeanDefinitionException e) {
            throw new IllegalArgumentException(
                    "A single org.springframework.richclient.Application bean definition must be defined "
                    + "in the main application context", e);
        }
        application.start();
        logger.debug("Launcher thread exiting...");
    }

    private void displaySplashScreen(BeanFactory beanFactory) {
        if (beanFactory.containsBean(SPLASH_SCREEN_BEAN_ID)) {
            this.splashScreen = (SplashScreen)beanFactory.getBean(SPLASH_SCREEN_BEAN_ID, SplashScreen.class);
            logger.debug("Displaying application splash screen...");
            this.splashScreen.splash();
        } else {
            logger.info("No splash screen bean found to display. Continuing...");
        }
    }

    private void destroySplashScreen() {
        if (splashScreen != null) {
            logger.debug("Closing splash screen...");

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    splashScreen.dispose();
                    splashScreen = null;
                }
            });
        }
    }
}
<commit_msg>fix for RCP-411: Added check for splashScreen, avoiding NPE<commit_after>/*
 * Copyright 2002-2004 the original author or authors.
 * 
 * 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.springframework.richclient.application;

import javax.swing.SwingUtilities;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.richclient.application.splash.SplashScreen;
import org.springframework.richclient.progress.ProgressMonitor;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * The main driver for a Spring Rich Client application. This class displays a
 * configurable splash screen and instantiates the rich client <code>Application</code>
 * instance.
 * 
 * @author <NAME>
 * @see Application
 */
public class ApplicationLauncher {
    public static final String SPLASH_SCREEN_BEAN_ID = "splashScreen";

    public static final String APPLICATION_BEAN_ID = "application";

    private final Log logger = LogFactory.getLog(getClass());

    private ApplicationContext startupContext;

    private SplashScreen splashScreen;

    private ApplicationContext rootApplicationContext;

    /**
     * Launch the application using the spring application context at the provided path
     * for configuration.
     * 
     * @param rootContextPath the classpath application context path
     */
    public ApplicationLauncher(String rootContextPath) {
        this(new String[] {rootContextPath});
    }

    /**
     * Launch the application using the spring application context at the provided paths
     * for configuration.
     * 
     * @param rootContextPath the classpath application context paths
     */
    public ApplicationLauncher(String[] rootContextPath) {
        this(null, rootContextPath);
    }

    /**
     * Launch the application using the spring application context at the provided paths
     * for configuration. The startup context path is loaded first to allow for quick
     * loading of the application splash screen.
     * 
     * @param startupContext the startup context classpath
     * @param rootContextPath the classpath application context path
     */
    public ApplicationLauncher(String startupContext, String rootContextPath) {
        this(startupContext, new String[] {rootContextPath});
    }

    /**
     * Launch the application using the spring application context at the provided paths
     * for configuration. The startup context path is loaded first to allow for quick
     * loading of the application splash screen.
     * 
     * @param startupContextPath the startup context classpath
     * @param rootContextPath the classpath application context paths
     */
    public ApplicationLauncher(String startupContextPath, String[] rootContextPath) {
        Assert.notEmpty(rootContextPath, "One or more root rich client application context paths must be provided");
        this.startupContext = loadStartupContext(startupContextPath);
        if (startupContext != null) {
            displaySplashScreen(startupContext);
        }
        try {
            setRootApplicationContext(loadRootApplicationContext(rootContextPath));
            launchMyRichClient();
        } finally {
            destroySplashScreen();
        }
    }

    /**
     * Launch the application from the pre-loaded application context.
     *
     * @param rootApplicationContext the application context.
     */
    public ApplicationLauncher(ApplicationContext rootApplicationContext) {
        this(null, rootApplicationContext);
    }

    /**
     * Launch the application from the pre-loaded application context.
     *
     * @param rootApplicationContext the application context.
     */
    public ApplicationLauncher(String startupContextPath, ApplicationContext rootApplicationContext) {
        this.startupContext = loadStartupContext(startupContextPath);
        if (startupContext != null) {
            displaySplashScreen(startupContext);
        }
        try {
            setRootApplicationContext(rootApplicationContext);
            launchMyRichClient();
        } finally {
            destroySplashScreen();
        }
    }

    private ApplicationContext loadStartupContext(String startupContextPath) {
        if (StringUtils.hasText(startupContextPath)) {
            logger.info("Loading startup context...");
            return new ClassPathXmlApplicationContext(startupContextPath);
        } else {
            return null;
        }
    }

    private ApplicationContext loadRootApplicationContext(String[] contextPaths) {
        final ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(contextPaths,
                false);

        if (splashScreen != null)
        {
                
            final ProgressMonitor tracker = splashScreen.getProgressMonitor();
    
            applicationContext.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
                public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                    beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
                        private int max = -1;
    
                        public Object postProcessBeforeInitialization(Object bean, String beanName)
                                throws BeansException {
                            if (max == -1) {
                                max = 0;
                                ConfigurableListableBeanFactory configurableListBeanFactory = applicationContext.getBeanFactory();
                                String[] beanNames = applicationContext.getBeanDefinitionNames();
                                for (int i = 0; i < beanNames.length; i++) {
                                    // using beanDefinition to check singleton property because when accessing through
                                    // context (applicationContext.isSingleton(beanName)), bean will be created already,
                                    // possibly bypassing other BeanFactoryPostProcessors
                                    if (configurableListBeanFactory.getBeanDefinition(beanNames[i]).isSingleton())
                                        max++;
                                }
                                tracker.taskStarted("Loading Application Context ...", max);
                            }
    
                            if (applicationContext.containsLocalBean(beanName)) {
                                tracker.subTaskStarted("Loading " + beanName + " ...");
                                tracker.worked(1);
                            }
    
                            return bean;
                        }
    
                        public Object postProcessAfterInitialization(Object bean, String beanName)
                                throws BeansException {
                            return bean;
                        }
                    });
                }
            });

        }
        
        applicationContext.refresh();

        return applicationContext;
    }

    private void setRootApplicationContext(ApplicationContext context) {
        Assert.notNull(context, "The root rich client application context is required");
        this.rootApplicationContext = context;
    }

    /**
     * Launch this rich client application; with the startup context loading first, built
     * from the <code>startupContextPath</code> location in the classpath.
     * <p>
     * It is recommended that the startup context contain contain a splash screen
     * definition for quick loading & display.
     * <p>
     * Once the splash screen is displayed, the main application context is then
     * initialized, built from the <code>contextPaths</code> location(s) in the
     * classpath. The root application bean is retrieved and the startup lifecycle begins.
     */
    private void launchMyRichClient() {
        if (startupContext == null) {
            displaySplashScreen(rootApplicationContext);
        }

        Application application;
        try {
            application = (Application)rootApplicationContext.getBean(APPLICATION_BEAN_ID, Application.class);
        }
        catch (NoSuchBeanDefinitionException e) {
            throw new IllegalArgumentException(
                    "A single org.springframework.richclient.Application bean definition must be defined "
                    + "in the main application context", e);
        }
        application.start();
        logger.debug("Launcher thread exiting...");
    }

    private void displaySplashScreen(BeanFactory beanFactory) {
        if (beanFactory.containsBean(SPLASH_SCREEN_BEAN_ID)) {
            this.splashScreen = (SplashScreen)beanFactory.getBean(SPLASH_SCREEN_BEAN_ID, SplashScreen.class);
            logger.debug("Displaying application splash screen...");
            this.splashScreen.splash();
        } else {
            logger.info("No splash screen bean found to display. Continuing...");
        }
    }

    private void destroySplashScreen() {
        if (splashScreen != null) {
            logger.debug("Closing splash screen...");

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    splashScreen.dispose();
                    splashScreen = null;
                }
            });
        }
    }
}

{'fraction_non_alphanumeric': 0.07039868395587381, 'fraction_numerical': 0.0017902070834139733, 'mean_word_length': 2.412978863936592, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 13, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4828248', 'n_tokens_mistral': 4766, 'n_tokens_neox': 4545, 'n_words': 1369}