com.laxser.blitz.web.portal.impl.PipeImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.laxser.blitz.web.portal.impl.PipeImpl.java

Source

/*
 * 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 com.laxser.blitz.web.portal.impl;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

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

import com.laxser.blitz.web.Invocation;
import com.laxser.blitz.web.portal.Pipe;
import com.laxser.blitz.web.portal.Window;
import com.laxser.blitz.web.portal.WindowListener;
import com.laxser.blitz.web.portal.WindowListenerAdapter;

/**
 * 
 *@author laxser  Date 2012-3-23 ?4:54:31
@contact [duqifan@gmail.com]
@PipeImpl.java
     
 */
// TODO: pipewindow cancle?
public class PipeImpl extends GenericWindowContainer implements Pipe {

    public static final String WINDIW_JS = "$$blitz-portal.pipe.js";

    public static final String WINDOW_CSS = "$$blitz-portal.pipe.css";

    private static final Log logger = LogFactory.getLog(PipeImpl.class);

    private static final DefaultPipeRender defaultPipeRender = new DefaultPipeRender();

    private int state = 0;

    private CountDownLatch latch;

    // ?
    private List<Window> blocking;

    private Writer out;

    public PipeImpl(Invocation inv, ExecutorService executorService, WindowListener portalListener) {
        super(inv, executorService, portalListener);
        setWindowRender(defaultPipeRender);
        addListener(new FireListener());
    }

    private class FireListener extends WindowListenerAdapter {

        @Override
        public void onWindowDone(Window window) {
            try {
                PipeImpl.this.fire(window);
            } catch (IOException e) {
                logger.error("", e);
            }
        }
    }

    @Override
    public void addCssTo(String windowName, String css) {
        for (Window window : windows) {
            if (window.getName().equals(windowName)) {
                addCssTo(window, css);
                return;
            }
        }
    }

    protected void addCssTo(Window window, String css) {
        @SuppressWarnings("unchecked")
        List<Object> list = (List<Object>) window.get(WINDOW_CSS);
        if (list == null) {
            list = new ArrayList<Object>(4);
            window.set(WINDOW_CSS, list);
        }
        list.add(css);
    }

    @Override
    public void addJsTo(String windowName, String js) {
        for (Window window : windows) {
            if (window.getName().equals(windowName)) {
                addJsTo(window, js);
                return;
            }
        }
    }

    protected void addJsTo(Window window, String js) {
        @SuppressWarnings("unchecked")
        List<Object> list = (List<Object>) window.get(WINDIW_JS);
        if (list == null) {
            list = new ArrayList<Object>(4);
            window.set(WINDIW_JS, list);
        }
        list.add(js);
    }

    public synchronized boolean isStarted() {
        return out != null;
    }

    public void write(Writer out) throws IOException {
        if (isStarted()) {
            if (logger.isDebugEnabled()) {
                logger.debug(this + " has been started yet.");
            }
            return;
        }
        doStart(out);
        if (getTimeout() >= 0) {
            if (logger.isDebugEnabled()) {
                logger.debug("waiting for pipe windows up to " + getTimeout() + "ms");
            }
            long start = System.currentTimeMillis();
            try {
                await(getTimeout());
            } catch (InterruptedException e) {
                logger.error("pipe was interrupted", e);
            }
            long cost = System.currentTimeMillis() - start;

            if (logger.isDebugEnabled()) {
                logger.debug("it takes " + cost + "ms for pipe windows.");
            }
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("there's no time to wait pipe windows.");
            }
        }
    }

    private synchronized void doStart(Writer writer) throws IOException {
        if (this.out != null) {
            throw new IllegalStateException("has been started.");
        }
        this.out = writer;
        if (logger.isDebugEnabled()) {
            logger.debug("start pipe " + getInvocation().getRequestPath().getUri());
        }
        writer.flush();
        latch = new CountDownLatch(windows.size());
        state = 1;
        if (blocking != null) {
            for (Window window : blocking) {
                doFire(window);
            }
            blocking = null;
        }
    }

    private void await(long timeout) throws InterruptedException {
        if (timeout > 0) {
            latch.await(timeout, TimeUnit.MILLISECONDS);
        } else {
            latch.await();
        }
    }

    private synchronized void fire(Window window) throws IOException {
        if (!super.windows.contains(window)) {
            throw new IllegalArgumentException(//
                    "not a register piped window '" + window.getName() + "'");
        }
        if (state < 0) {
            if (logger.isDebugEnabled()) {
                logger.debug("firing '" + window.getName() + "' but pipe is closed");
            }
            return;
        } else if (state == 0) {
            if (blocking == null) {
                blocking = new ArrayList<Window>(windows.size());
            } else {
                if (blocking.contains(window)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("firing '" + window.getName() + "' : has been add to waiting list");
                    }
                    return;
                }
            }
            blocking.add(window);
            if (logger.isDebugEnabled()) {
                logger.debug("firing '" + window.getName() + "' : add to waiting list");
            }
        } else {
            doFire(window);
        }
    }

    private synchronized void doFire(Window window) throws IOException {
        if (state != 1) {
            throw new IllegalStateException("only avalabled when started.");
        }
        try {
            // ?responseencoding?encoding
            render(out, window);
            out.flush();
        } finally {
            latch.countDown();
        }
        if (logger.isDebugEnabled()) {
            logger.debug(//
                    "firing '" + window.getName() + "' : done  content=" + window.getContent());
        }
    }

    //-------------toString()---------------F

    @Override
    public String toString() {
        return "pipe ['" + getInvocation().getRequestPath().getUri() + "']";
    }

    @Override
    public void addModel(String name, Object value) {
        // TODO Auto-generated method stub

    }

}