Package net.paoding.rose.web.portal.impl

Source Code of net.paoding.rose.web.portal.impl.PortalWaitInterceptor

/*
* Copyright 2007-2012 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 net.paoding.rose.web.portal.impl;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import net.paoding.rose.web.ControllerInterceptorAdapter;
import net.paoding.rose.web.Invocation;
import net.paoding.rose.web.portal.Portal;
import net.paoding.rose.web.portal.PortalUtils;
import net.paoding.rose.web.portal.Window;
import net.paoding.rose.web.portal.WindowListener;

/**
* 这个拦截器只拦截 Portal 控制器方法,用于等待所有该 portal 的窗口执行完成或进行超时取消。
*
* @author 王志亮 [qieqie.wang@gmail.com]
*
*/
public class PortalWaitInterceptor extends ControllerInterceptorAdapter {

    // 只拦截含有 Portal 的控制器方法
    @Override
    protected boolean isForAction(Method actionMethod, Class<?> controllerClazz) {
        for (Class<?> paramType : actionMethod.getParameterTypes()) {
            if (paramType == Portal.class) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Object after(Invocation inv, Object instruction) throws Exception {

        PortalImpl portal = (PortalImpl) PortalUtils.getPortal(inv);
        boolean debugEnabled = logger.isDebugEnabled();
        if (debugEnabled) {
            logger.debug(portal + " is going to wait windows.");
        }

        WindowListener listener = portal;
        long deadline;
        long begin = System.currentTimeMillis();
        if (portal.getTimeout() > 0) {
            deadline = begin + portal.getTimeout();
            if (debugEnabled) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
                logger.debug(portal + ".maxWait=" + portal.getTimeout() + "; deadline="
                        + sdf.format(new Date(deadline)));
            }
        } else {
            deadline = 0;
            if (debugEnabled) {
                logger.debug(portal + ".maxWait=(forever)");
            }
        }
        int winSize = portal.getWindows().size();
        int winIndex = 0;
        List<Window> windows = portal.getWindows();
        for (Window window : windows) {
            winIndex++;
            Future<?> future = window.getFuture();
            if (future.isDone()) {
                if (debugEnabled) {
                    if (future.isCancelled()) {
                        logger.debug("[" + winIndex + "/" + winSize + "] continue[cancelled]: "
                                + window.getName());
                    }
                    if (future.isDone()) {
                        logger.debug("[" + winIndex + "/" + winSize + "] continue[done]: "
                                + window.getName());
                    }
                }
                continue;
            }
            long awaitTime = 0;
            try {
                long begineWait = System.currentTimeMillis();
                if (deadline > 0) {
                    awaitTime = deadline - begineWait;
                    if (awaitTime > 0) {
                        if (debugEnabled) {
                            logger.debug("[" + winIndex + "/" + winSize + "] waiting[begin]: "
                                    + window.getName() + "; maxWait=" + awaitTime);
                        }
                        future.get(awaitTime, TimeUnit.MILLISECONDS);
                        if (debugEnabled) {
                            logger.debug("[" + winIndex + "/" + winSize + "] waiting[done]: "
                                    + window.getName() + "; actualWait="
                                    + (System.currentTimeMillis() - begineWait));
                        }
                    } else {
                        logger.error("[" + winIndex + "/" + winSize
                                + "] waiting[been timeout now]: " + window.getName());
                        listener.onWindowTimeout(window);
                        future.cancel(true);
                    }
                } else {
                    if (debugEnabled) {
                        logger.debug("[" + winIndex + "/" + winSize + "] waiting[begin]: "
                                + window.getName() + "; maxWait=(forever)");
                    }
                    future.get();
                    if (debugEnabled) {
                        logger.debug("[" + winIndex + "/" + winSize + "] waiting[done]: "
                                + window.getName() + "; actualWait="
                                + (System.currentTimeMillis() - begineWait));
                    }
                }
            } catch (InterruptedException e) {
                logger.error("x[" + winIndex + "/" + winSize + "] waiting[interrupted]: "
                        + window.getName());
            } catch (ExecutionException e) {
                logger.error("x[" + winIndex + "/" + winSize + "] waiting[error]: "
                        + window.getName(), e);
                window.setThrowable(e);
                listener.onWindowError(window);
            } catch (TimeoutException e) {
                logger.error("x[" + winIndex + "/" + winSize + "] waiting[timeout]: "
                        + window.getName(), e);
                listener.onWindowTimeout(window);
                future.cancel(true);
            }
        }
        if (debugEnabled) {
            logger.debug("[" + winIndex + "/" + winSize + "] size of simple windows = " + winIndex);
        }

        //
        if (logger.isDebugEnabled()) {
            logger.debug(portal + ".waitForWindows is done; cost="
                    + (System.currentTimeMillis() - begin));
        }

        return instruction;
    }

}
TOP

Related Classes of net.paoding.rose.web.portal.impl.PortalWaitInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.