com.laxser.blitz.web.impl.module.ErrorHandlerDispatcher.java Source code

Java tutorial

Introduction

Here is the source code for com.laxser.blitz.web.impl.module.ErrorHandlerDispatcher.java

Source

/*
 * Copyright 2007-2009 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 com.laxser.blitz.web.impl.module;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.laxser.blitz.web.ControllerErrorHandler;
import com.laxser.blitz.web.Invocation;

/**
 * 
 * @author zhiliang.wang
 * 
 */
public class ErrorHandlerDispatcher implements ControllerErrorHandler {

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

    private static final int INVOCATION_INDEX = 0;

    private static final int THROWABLE_INDEX = 1;

    private ControllerErrorHandler errorHandler;

    private List<ErrorHandlerDelegate> delegates = new ArrayList<ErrorHandlerDelegate>(8);

    public ErrorHandlerDispatcher(ControllerErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
        Method[] methods = this.errorHandler.getClass().getMethods();
        for (final Method method : methods) {
            if (Modifier.isAbstract(method.getModifiers()) || Modifier.isStatic(method.getModifiers())) {
                continue;
            }
            if (method.getName().equals("onError")) {
                final Class<?>[] parameterClasses = method.getParameterTypes();
                if (parameterClasses.length == 2 && parameterClasses[INVOCATION_INDEX] == Invocation.class
                        && Throwable.class.isAssignableFrom(parameterClasses[THROWABLE_INDEX])) {
                    delegates.add(new ErrorHandlerDelegate() {

                        @Override
                        public Method getMethod() {
                            return method;
                        }

                        @Override
                        public Object onError(Invocation inv, Throwable ex) throws Throwable {
                            Object[] args = new Object[] { inv, ex };
                            try {
                                return method.invoke(ErrorHandlerDispatcher.this.errorHandler, args);
                            } catch (Throwable e) {
                                logger.error("error happened when handling error " + ex.getClass() + " at "
                                        + ErrorHandlerDispatcher.this.toString());
                                throw e;
                            }
                        }
                    });
                }
            }
        }
        Collections.sort(delegates, new Comparator<ErrorHandlerDelegate>() {

            @Override
            public int compare(ErrorHandlerDelegate o1, ErrorHandlerDelegate o2) {
                if (o1.getMethod().getParameterTypes()[THROWABLE_INDEX]
                        .isAssignableFrom(o2.getMethod().getParameterTypes()[THROWABLE_INDEX])) {
                    return 1;
                } else if (o2.getMethod().getParameterTypes()[THROWABLE_INDEX]
                        .isAssignableFrom(o1.getMethod().getParameterTypes()[THROWABLE_INDEX])) {
                    return -1;
                } else {
                    return o1.getMethod().getParameterTypes()[THROWABLE_INDEX].getName()
                            .compareTo(o2.getMethod().getParameterTypes()[THROWABLE_INDEX].getName());
                }
            }
        });
    }

    @Override
    public Object onError(Invocation inv, Throwable ex) throws Throwable {
        for (ErrorHandlerDelegate delegate : delegates) {
            if (delegate.getMethod().getParameterTypes()[THROWABLE_INDEX].isAssignableFrom(ex.getClass())) {
                return delegate.onError(inv, ex);
            }
        }
        throw new Error("not found errorHandlerMethod for exceptionClass" + ex.getClass().getName(), ex);
    }

    @Override
    public String toString() {
        return errorHandler.toString() + delegates.toString();
    }

    static abstract class ErrorHandlerDelegate {

        abstract Method getMethod();

        abstract Object onError(Invocation inv, Throwable ex) throws Throwable;

        @Override
        public String toString() {
            return getMethod().getParameterTypes()[THROWABLE_INDEX].getSimpleName();
        }
    }

}