001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.model;
018    
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    import javax.xml.bind.annotation.XmlAccessType;
023    import javax.xml.bind.annotation.XmlAccessorType;
024    import javax.xml.bind.annotation.XmlRootElement;
025    import javax.xml.bind.annotation.XmlTransient;
026    
027    import org.apache.camel.Processor;
028    import org.apache.camel.impl.RouteContext;
029    import org.apache.camel.processor.CatchProcessor;
030    import org.apache.camel.processor.TryProcessor;
031    
032    /**
033     * @version $Revision: 36507 $
034     */
035    @XmlRootElement(name = "try")
036    @XmlAccessorType(XmlAccessType.FIELD)
037    public class TryType extends OutputType<TryType> {
038        @XmlTransient
039        private List<CatchType> catchClauses;
040        @XmlTransient
041        private FinallyType finallyClause;
042        @XmlTransient
043        private boolean initialized;
044        @XmlTransient
045        private List<ProcessorType<?>> outputsWithoutCatches;
046    
047        @Override
048        public String toString() {
049            return "Try[ " + getOutputs() + "]";
050        }
051    
052        @Override
053        public Processor createProcessor(RouteContext routeContext) throws Exception {
054            Processor tryProcessor = createOutputsProcessor(routeContext, getOutputsWithoutCatches());
055    
056            Processor finallyProcessor = null;
057            if (finallyClause != null) {
058                finallyProcessor = finallyClause.createProcessor(routeContext);
059            }
060            List<CatchProcessor> catchProcessors = new ArrayList<CatchProcessor>();
061            if (catchClauses != null) {
062                for (CatchType catchClause : catchClauses) {
063                    catchProcessors.add(catchClause.createProcessor(routeContext));
064                }
065            }
066            return new TryProcessor(tryProcessor, catchProcessors, finallyProcessor);
067        }
068    
069        // Fluent API
070        // -------------------------------------------------------------------------
071        public TryType handle(Class<?> exceptionType) {
072            popBlock();
073            CatchType answer = new CatchType(exceptionType);
074            addOutput(answer);
075            pushBlock(answer);
076            return this;
077        }
078    
079        /**
080         * @deprecated Use {@link #finallyBlock()} instead, as the name
081         * is better. Current name sugests that it handles exception,
082         * while it mimics java finally keyword.
083         */
084        @Deprecated
085        public TryType handleAll() {
086            return finallyBlock();
087        }
088    
089        public TryType finallyBlock() {
090            popBlock();
091            FinallyType answer = new FinallyType();
092            addOutput(answer);
093            pushBlock(answer);
094            return this;
095        }
096    
097        @Override
098        public ProcessorType<? extends ProcessorType> end() {
099            popBlock();
100            return super.end();
101        }
102    
103        // Properties
104        // -------------------------------------------------------------------------
105    
106        public List<CatchType> getCatchClauses() {
107            if (catchClauses == null) {
108                checkInitialized();
109            }
110            return catchClauses;
111        }
112    
113        public FinallyType getFinallyClause() {
114            if (finallyClause == null) {
115                checkInitialized();
116            }
117            return finallyClause;
118        }
119    
120        public List<ProcessorType<?>> getOutputsWithoutCatches() {
121            if (outputsWithoutCatches == null) {
122                checkInitialized();
123            }
124            return outputsWithoutCatches;
125        }
126    
127        public void setOutputs(List<ProcessorType<?>> outputs) {
128            initialized = false;
129            super.setOutputs(outputs);
130        }
131    
132        @Override
133        public void addOutput(ProcessorType output) {
134            initialized = false;
135            super.addOutput(output);
136        }
137    
138        /**
139         * Checks whether or not this object has been initialized
140         */
141        protected void checkInitialized() {
142            if (!initialized) {
143                initialized = true;
144                outputsWithoutCatches = new ArrayList<ProcessorType<?>>();
145                catchClauses = new ArrayList<CatchType>();
146                finallyClause = null;
147    
148                for (ProcessorType output : outputs) {
149                    if (output instanceof CatchType) {
150                        catchClauses.add((CatchType)output);
151                    } else if (output instanceof FinallyType) {
152                        if (finallyClause != null) {
153                            throw new IllegalArgumentException("Multiple finally clauses added: " + finallyClause
154                                                               + " and " + output);
155                        } else {
156                            finallyClause = (FinallyType)output;
157                        }
158                    } else {
159                        outputsWithoutCatches.add(output);
160                    }
161                }
162            }
163        }
164    }