Package com.alibaba.citrus.service.pipeline.impl

Source Code of com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl

/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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.alibaba.citrus.service.pipeline.impl;

import static com.alibaba.citrus.util.Assert.ExceptionType.*;
import static com.alibaba.citrus.util.Assert.*;
import static com.alibaba.citrus.util.BasicConstant.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static com.alibaba.citrus.util.ObjectUtil.*;
import static com.alibaba.citrus.util.StringUtil.*;

import java.util.Map;

import com.alibaba.citrus.service.AbstractService;
import com.alibaba.citrus.service.pipeline.LabelNotDefinedException;
import com.alibaba.citrus.service.pipeline.Pipeline;
import com.alibaba.citrus.service.pipeline.PipelineContext;
import com.alibaba.citrus.service.pipeline.PipelineException;
import com.alibaba.citrus.service.pipeline.PipelineInvocationHandle;
import com.alibaba.citrus.service.pipeline.Valve;
import com.alibaba.citrus.util.ToStringBuilder;
import org.slf4j.Logger;

/**
* 对<code>Pipeline</code>的实现。
*
* @author Michael Zhou
*/
public class PipelineImpl extends AbstractService<Pipeline> implements Pipeline {
    private Valve[] valves;
    private String  label;

    public Valve[] getValves() {
        return valves;
    }

    public void setValves(Valve[] valves) {
        this.valves = valves;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = trimToNull(label);
    }

    @Override
    protected void init() {
        if (valves == null) {
            valves = new Valve[0];
        }

        for (int i = 0; i < valves.length; i++) {
            assertNotNull(valves[i], "valves[%d] == null", i);
        }
    }

    public PipelineInvocationHandle newInvocation() {
        return new PipelineContextImpl(null);
    }

    public PipelineInvocationHandle newInvocation(PipelineContext parentContext) {
        return new PipelineContextImpl(assertNotNull(parentContext, "no parent PipelineContext"));
    }

    @Override
    public String toString() {
        return new ToStringBuilder().append(getBeanDescription()).append(valves).toString();
    }

    /** 实现<code>PipelineContext</code>。 */
    private final class PipelineContextImpl implements PipelineContext, PipelineInvocationHandle {
        private final Logger log = getLogger();
        private final PipelineContext parentContext;
        private final int             level;
        private int executedIndex  = -1;
        private int executingIndex = -1;
        private boolean             broken;
        private Map<String, Object> attributes;

        public PipelineContextImpl(PipelineContext parentContext) {
            this.parentContext = parentContext;

            if (parentContext == null) {
                this.level = 1;
            } else {
                this.level = parentContext.level() + 1;
            }
        }

        public int level() {
            return level;
        }

        public int index() {
            return executingIndex + 1;
        }

        public int findLabel(String label) throws LabelNotDefinedException {
            label = assertNotNull(trimToNull(label), "no label");
            boolean isTop = TOP_LABEL.equals(label);

            if (isTop && parentContext == null) {
                return 0;
            } else if (label.equals(getLabel())) {
                return 0;
            } else if (parentContext != null) {
                return parentContext.findLabel(label) + 1;
            } else {
                throw new LabelNotDefinedException("Could not find pipeline or sub-pipeline with label \"" + label
                                                   + "\" in the pipeline invocation stack");
            }
        }

        public void invokeNext() {
            assertInitialized();

            if (broken) {
                return;
            }

            try {
                executingIndex++;

                if (executingIndex <= executedIndex) {
                    throw new IllegalStateException(descCurrentValve() + " has already been invoked: "
                                                    + valves[executingIndex]);
                }

                executedIndex++;

                if (executingIndex < valves.length) {
                    Valve valve = valves[executingIndex];

                    try {
                        if (log.isTraceEnabled()) {
                            log.trace("Entering {}: {}", descCurrentValve(), valve);
                        }

                        valve.invoke(this);
                    } catch (PipelineException e) {
                        throw e;
                    } catch (Exception e) {
                        throw new PipelineException("Failed to invoke " + descCurrentValve() + ": " + valve, e);
                    } finally {
                        if (log.isTraceEnabled()) {
                            log.trace("...Exited {}: {}", descCurrentValve(), valve);
                        }
                    }

                    if (executedIndex < valves.length && executedIndex == executingIndex) {
                        if (log.isTraceEnabled()) {
                            log.trace("{} execution was interrupted by {}: {}", new Object[] { descCurrentPipeline(),
                                                                                               descCurrentValve(), valve });
                        }
                    }
                } else {
                    if (log.isTraceEnabled()) {
                        log.trace("{} reaches its end.", descCurrentPipeline());
                    }
                }
            } finally {
                executingIndex--;
            }
        }

        public void breakPipeline(int levels) {
            assertTrue(levels >= 0 && levels < level, "invalid break levels: %d, should be in range of [0, %d)",
                       levels, level);

            broken = true;

            if (levels > 0) {
                parentContext.breakPipeline(levels - 1);
            }
        }

        public void breakPipeline(String label) throws LabelNotDefinedException {
            breakPipeline(findLabel(label));
        }

        public boolean isBroken() {
            return broken;
        }

        public boolean isFinished() {
            return !broken && executedIndex >= valves.length;
        }

        public void invoke() throws IllegalStateException {
            assertTrue(!isBroken(), ILLEGAL_STATE, "cannot reinvoke a broken pipeline");
            executingIndex = executedIndex = -1;
            invokeNext();
        }

        public Object getAttribute(String key) {
            Object value = null;

            if (attributes != null) {
                value = attributes.get(key);
            }

            if (value == null && parentContext != null) {
                value = parentContext.getAttribute(key);
            }

            return value == NULL_PLACEHOLDER ? null : value;
        }

        public void setAttribute(String key, Object value) {
            if (attributes == null) {
                attributes = createHashMap();
            }

            attributes.put(key, defaultIfNull(value, NULL_PLACEHOLDER));
        }

        @Override
        public String toString() {
            return "Executing Pipeline " + descCurrentValve();
        }

        private String descCurrentPipeline() {
            return "Pipeline[level " + level() + "]";
        }

        private String descCurrentValve() {
            return "Valve[#" + index() + "/" + valves.length + ", level " + level() + "]";
        }
    }
}
TOP

Related Classes of com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl

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.