/*
 * Copyright (c) 2008-2013 Haulmont. All rights reserved.
 * Use is subject to license terms, see http://www.cuba-platform.com/license for details.
 */
package com.haulmont.cuba.web.exception;

import com.haulmont.bali.util.ReflectionHelper;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.web.App;
import com.vaadin.terminal.Terminal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.LinkedList;
import java.util.Map;

/**
 * Class that holds the collection of exception handlers and delegates unhandled exception processing to them. Handlers
 * form the chain of responsibility.
 *
 * <p>A set of exception handlers is configured by defining <code>ExceptionHandlersConfiguration</code> beans
 * in spring.xml. If a project needs specific handlers, it should define a bean of such type with its own
 * <strong>id</strong>, e.g. <code>refapp_ExceptionHandlersConfiguration</code></p>
 *
 * <p>An instance of this class is bound to {@link App}.</p>
 *
 * <p>$Id$</p>
 *
 * @author krivopustov
 */
public class ExceptionHandlers {

    protected App app;

    protected LinkedList<ExceptionHandler> handlers = new LinkedList<ExceptionHandler>();

    protected ExceptionHandler defaultHandler;

    private Log log = LogFactory.getLog(getClass());

    public ExceptionHandlers(App app) {
        this.app = app;
        this.defaultHandler = new DefaultExceptionHandler();
    }

    /**
     * Adds new handler if it is not yet registered.
     * @param handler   handler instance
     */
    public void addHandler(ExceptionHandler handler) {
        if (!handlers.contains(handler))
            handlers.add(handler);
    }

    /**
     * Return all registered handlers.
     * @return  modifiable handlers list
     */
    public LinkedList<ExceptionHandler> getHandlers() {
        return handlers;
    }

    /**
     * Delegates exception handling to registered handlers.
     * @param event error event generated by Vaadin
     */
    public void handle(Terminal.ErrorEvent event) {
        for (ExceptionHandler handler : handlers) {
            if (handler.handle(event, app))
                return;
        }
        defaultHandler.handle(event, app);
    }

    /**
     * Create all handlers defined by <code>ExceptionHandlersConfiguration</code> beans in spring.xml.
     */
    public void createByConfiguration() {
        Map<String, ExceptionHandlersConfiguration> map = AppBeans.getAll(ExceptionHandlersConfiguration.class);
        for (ExceptionHandlersConfiguration conf : map.values()) {
            for (Class aClass : conf.getHandlerClasses()) {
                try {
                    addHandler(ReflectionHelper.<ExceptionHandler>newInstance(aClass));
                } catch (NoSuchMethodException e) {
                    log.error("Unable to instantiate " + aClass, e);
                }
            }
        }
    }

    /**
     * Remove all handlers.
     */
    public void removeAll() {
        handlers.clear();
    }
}

@@ -1490,32 +1490,531 @@
 er();%0D%0A    %7D%0D%0A%0D%0A
+    /**%0D%0A     * @return default exception handler which is used when none of registered handlers have handled an exception%0D%0A     */%0D%0A    public ExceptionHandler getDefaultHandler() %7B%0D%0A        return defaultHandler;%0D%0A    %7D%0D%0A%0D%0A    /**%0D%0A     * Set the default handler instead of initialized in constructor.%0D%0A     * @param defaultHandler     default handler instance%0D%0A     */%0D%0A    public void setDefaultHandler(ExceptionHandler defaultHandler) %7B%0D%0A        this.defaultHandler = defaultHandler;%0D%0A    %7D%0D%0A%0D%0A
     /**%0D%0A     * 

Replace RuntimeException throwing with special DevelopmentException (default handlers) (merge to web6) #PL-2074