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 */ 017package org.apache.camel.model; 018 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.Iterator; 022import java.util.List; 023 024import javax.xml.bind.annotation.XmlAccessType; 025import javax.xml.bind.annotation.XmlAccessorType; 026import javax.xml.bind.annotation.XmlElementRef; 027import javax.xml.bind.annotation.XmlRootElement; 028import javax.xml.bind.annotation.XmlTransient; 029 030import org.apache.camel.Predicate; 031import org.apache.camel.spi.AsPredicate; 032import org.apache.camel.spi.Metadata; 033 034/** 035 * Marks the beginning of a try, catch, finally block 036 */ 037@Metadata(label = "error") 038@XmlRootElement(name = "doTry") 039@XmlAccessorType(XmlAccessType.FIELD) 040public class TryDefinition extends OutputDefinition<TryDefinition> { 041 @XmlTransient 042 private List<CatchDefinition> catchClauses; 043 @XmlTransient 044 private FinallyDefinition finallyClause; 045 @XmlTransient 046 private boolean initialized; 047 @XmlTransient 048 private List<ProcessorDefinition<?>> outputsWithoutCatches; 049 050 public TryDefinition() { 051 } 052 053 @Override 054 public String toString() { 055 return "DoTry[" + getOutputs() + "]"; 056 } 057 058 @Override 059 public String getShortName() { 060 return "doTry"; 061 } 062 063 @Override 064 public String getLabel() { 065 return "doTry"; 066 } 067 068 // Fluent API 069 // ------------------------------------------------------------------------- 070 071 /** 072 * Handles the given exception 073 * 074 * @param exceptionType the exception 075 * @return the try builder 076 */ 077 @SuppressWarnings("unchecked") 078 public TryDefinition doCatch(Class<? extends Throwable> exceptionType) { 079 // this method is introduced to avoid compiler warnings about the 080 // generic Class arrays in the case we've got only one single Class 081 // to build a TryDefinition for 082 return doCatch(new Class[] {exceptionType}); 083 } 084 085 /** 086 * Handles the given exception(s) 087 * 088 * @param exceptionType the exception(s) 089 * @return the try builder 090 */ 091 public TryDefinition doCatch(Class<? extends Throwable>... exceptionType) { 092 popBlock(); 093 List<Class<? extends Throwable>> list = Arrays.asList(exceptionType); 094 CatchDefinition answer = new CatchDefinition(list); 095 addOutput(answer); 096 pushBlock(answer); 097 return this; 098 } 099 100 /** 101 * The finally block for a given handle 102 * 103 * @return the try builder 104 */ 105 public TryDefinition doFinally() { 106 popBlock(); 107 FinallyDefinition answer = new FinallyDefinition(); 108 addOutput(answer); 109 pushBlock(answer); 110 return this; 111 } 112 113 /** 114 * Sets an additional predicate that should be true before the onCatch is 115 * triggered. 116 * <p/> 117 * To be used for fine grained controlling whether a thrown exception should 118 * be intercepted by this exception type or not. 119 * 120 * @param predicate predicate that determines true or false 121 * @return the builder 122 */ 123 public TryDefinition onWhen(@AsPredicate Predicate predicate) { 124 // we must use a delegate so we can use the fluent builder based on 125 // TryDefinition 126 // to configure all with try .. catch .. finally 127 // set the onWhen predicate on all the catch definitions 128 Iterator<CatchDefinition> it = ProcessorDefinitionHelper.filterTypeInOutputs(getOutputs(), CatchDefinition.class); 129 while (it.hasNext()) { 130 CatchDefinition doCatch = it.next(); 131 doCatch.setOnWhen(new WhenDefinition(predicate)); 132 } 133 return this; 134 } 135 136 // Properties 137 // ------------------------------------------------------------------------- 138 139 public List<CatchDefinition> getCatchClauses() { 140 if (catchClauses == null) { 141 checkInitialized(); 142 } 143 return catchClauses; 144 } 145 146 public FinallyDefinition getFinallyClause() { 147 if (finallyClause == null) { 148 checkInitialized(); 149 } 150 return finallyClause; 151 } 152 153 public List<ProcessorDefinition<?>> getOutputsWithoutCatches() { 154 if (outputsWithoutCatches == null) { 155 checkInitialized(); 156 } 157 return outputsWithoutCatches; 158 } 159 160 @Override 161 public List<ProcessorDefinition<?>> getOutputs() { 162 return super.getOutputs(); 163 } 164 165 @XmlElementRef 166 @Override 167 public void setOutputs(List<ProcessorDefinition<?>> outputs) { 168 initialized = false; 169 super.setOutputs(outputs); 170 } 171 172 @Override 173 public void addOutput(ProcessorDefinition<?> output) { 174 initialized = false; 175 super.addOutput(output); 176 } 177 178 @Override 179 public void preCreateProcessor() { 180 // force re-creating initialization to ensure its up-to-date 181 initialized = false; 182 checkInitialized(); 183 } 184 185 /** 186 * Checks whether or not this object has been initialized 187 */ 188 protected void checkInitialized() { 189 if (!initialized) { 190 initialized = true; 191 outputsWithoutCatches = new ArrayList<>(); 192 catchClauses = new ArrayList<>(); 193 finallyClause = null; 194 195 for (ProcessorDefinition<?> output : outputs) { 196 if (output instanceof CatchDefinition) { 197 catchClauses.add((CatchDefinition)output); 198 } else if (output instanceof FinallyDefinition) { 199 if (finallyClause != null) { 200 throw new IllegalArgumentException("Multiple finally clauses added: " + finallyClause + " and " + output); 201 } else { 202 finallyClause = (FinallyDefinition)output; 203 } 204 } else { 205 outputsWithoutCatches.add(output); 206 } 207 } 208 } 209 } 210}