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.processor.CatchProcessor;
029    import org.apache.camel.processor.TryProcessor;
030    import org.apache.camel.spi.RouteContext;
031    
032    /**
033     * Represents an XML <try/> element
034     *
035     * @version $Revision: 750806 $
036     */
037    @XmlRootElement(name = "try")
038    @XmlAccessorType(XmlAccessType.FIELD)
039    public class TryDefinition extends OutputDefinition<TryDefinition> {
040        @XmlTransient
041        private List<CatchDefinition> catchClauses;
042        @XmlTransient
043        private FinallyDefinition finallyClause;
044        @XmlTransient
045        private boolean initialized;
046        @XmlTransient
047        private List<ProcessorDefinition> outputsWithoutCatches;
048    
049        @Override
050        public String toString() {
051            return "Try[" + getOutputs() + "]";
052        }
053    
054        @Override
055        public String getShortName() {
056            return "try";
057        }
058    
059        @Override
060        public Processor createProcessor(RouteContext routeContext) throws Exception {
061            Processor tryProcessor = createOutputsProcessor(routeContext, getOutputsWithoutCatches());
062    
063            Processor finallyProcessor = null;
064            if (finallyClause != null) {
065                finallyProcessor = finallyClause.createProcessor(routeContext);
066            }
067            List<CatchProcessor> catchProcessors = new ArrayList<CatchProcessor>();
068            if (catchClauses != null) {
069                for (CatchDefinition catchClause : catchClauses) {
070                    catchProcessors.add(catchClause.createProcessor(routeContext));
071                }
072            }
073            return new TryProcessor(tryProcessor, catchProcessors, finallyProcessor);
074        }
075    
076        // Fluent API
077        // -------------------------------------------------------------------------
078    
079        /**
080         * Handles the given exception
081         *
082         * @param exceptionType  the exception
083         * @return the try builder
084         */
085        public TryDefinition handle(Class<?> exceptionType) {
086            popBlock();
087            CatchDefinition answer = new CatchDefinition(exceptionType);
088            addOutput(answer);
089            pushBlock(answer);
090            return this;
091        }
092    
093        /**
094         * The finally block for a given handle
095         *
096         * @return  the try builder
097         */
098        public TryDefinition finallyBlock() {
099            popBlock();
100            FinallyDefinition answer = new FinallyDefinition();
101            addOutput(answer);
102            pushBlock(answer);
103            return this;
104        }
105    
106        @Override
107        public ProcessorDefinition<? extends ProcessorDefinition> end() {
108            popBlock();
109            return super.end();
110        }
111    
112        // Properties
113        // -------------------------------------------------------------------------
114    
115        public List<CatchDefinition> getCatchClauses() {
116            if (catchClauses == null) {
117                checkInitialized();
118            }
119            return catchClauses;
120        }
121    
122        public FinallyDefinition getFinallyClause() {
123            if (finallyClause == null) {
124                checkInitialized();
125            }
126            return finallyClause;
127        }
128    
129        public List<ProcessorDefinition> getOutputsWithoutCatches() {
130            if (outputsWithoutCatches == null) {
131                checkInitialized();
132            }
133            return outputsWithoutCatches;
134        }
135    
136        public void setOutputs(List<ProcessorDefinition> outputs) {
137            initialized = false;
138            super.setOutputs(outputs);
139        }
140    
141        @Override
142        public void addOutput(ProcessorDefinition output) {
143            initialized = false;
144            super.addOutput(output);
145        }
146    
147        /**
148         * Checks whether or not this object has been initialized
149         */
150        protected void checkInitialized() {
151            if (!initialized) {
152                initialized = true;
153                outputsWithoutCatches = new ArrayList<ProcessorDefinition>();
154                catchClauses = new ArrayList<CatchDefinition>();
155                finallyClause = null;
156    
157                for (ProcessorDefinition output : outputs) {
158                    if (output instanceof CatchDefinition) {
159                        catchClauses.add((CatchDefinition)output);
160                    } else if (output instanceof FinallyDefinition) {
161                        if (finallyClause != null) {
162                            throw new IllegalArgumentException("Multiple finally clauses added: " + finallyClause
163                                                               + " and " + output);
164                        } else {
165                            finallyClause = (FinallyDefinition)output;
166                        }
167                    } else {
168                        outputsWithoutCatches.add(output);
169                    }
170                }
171            }
172        }
173    }