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 @SafeVarargs 092 public final TryDefinition doCatch(Class<? extends Throwable>... exceptionType) { 093 popBlock(); 094 List<Class<? extends Throwable>> list = Arrays.asList(exceptionType); 095 CatchDefinition answer = new CatchDefinition(list); 096 addOutput(answer); 097 pushBlock(answer); 098 return this; 099 } 100 101 /** 102 * The finally block for a given handle 103 * 104 * @return the try builder 105 */ 106 public TryDefinition doFinally() { 107 popBlock(); 108 FinallyDefinition answer = new FinallyDefinition(); 109 addOutput(answer); 110 pushBlock(answer); 111 return this; 112 } 113 114 /** 115 * Sets an additional predicate that should be true before the onCatch is 116 * triggered. 117 * <p/> 118 * To be used for fine grained controlling whether a thrown exception should 119 * be intercepted by this exception type or not. 120 * 121 * @param predicate predicate that determines true or false 122 * @return the builder 123 */ 124 public TryDefinition onWhen(@AsPredicate Predicate predicate) { 125 // we must use a delegate so we can use the fluent builder based on 126 // TryDefinition 127 // to configure all with try .. catch .. finally 128 // set the onWhen predicate on all the catch definitions 129 Iterator<CatchDefinition> it = ProcessorDefinitionHelper.filterTypeInOutputs(getOutputs(), CatchDefinition.class); 130 while (it.hasNext()) { 131 CatchDefinition doCatch = it.next(); 132 doCatch.setOnWhen(new WhenDefinition(predicate)); 133 } 134 return this; 135 } 136 137 // Properties 138 // ------------------------------------------------------------------------- 139 140 public List<CatchDefinition> getCatchClauses() { 141 if (catchClauses == null) { 142 checkInitialized(); 143 } 144 return catchClauses; 145 } 146 147 public FinallyDefinition getFinallyClause() { 148 if (finallyClause == null) { 149 checkInitialized(); 150 } 151 return finallyClause; 152 } 153 154 public List<ProcessorDefinition<?>> getOutputsWithoutCatches() { 155 if (outputsWithoutCatches == null) { 156 checkInitialized(); 157 } 158 return outputsWithoutCatches; 159 } 160 161 @Override 162 public List<ProcessorDefinition<?>> getOutputs() { 163 return super.getOutputs(); 164 } 165 166 @XmlElementRef 167 @Override 168 public void setOutputs(List<ProcessorDefinition<?>> outputs) { 169 initialized = false; 170 super.setOutputs(outputs); 171 } 172 173 @Override 174 public void addOutput(ProcessorDefinition<?> output) { 175 initialized = false; 176 super.addOutput(output); 177 } 178 179 @Override 180 public void preCreateProcessor() { 181 // force re-creating initialization to ensure its up-to-date 182 initialized = false; 183 checkInitialized(); 184 } 185 186 /** 187 * Checks whether or not this object has been initialized 188 */ 189 protected void checkInitialized() { 190 if (!initialized) { 191 initialized = true; 192 outputsWithoutCatches = new ArrayList<>(); 193 catchClauses = new ArrayList<>(); 194 finallyClause = null; 195 196 for (ProcessorDefinition<?> output : outputs) { 197 if (output instanceof CatchDefinition) { 198 catchClauses.add((CatchDefinition)output); 199 } else if (output instanceof FinallyDefinition) { 200 if (finallyClause != null) { 201 throw new IllegalArgumentException("Multiple finally clauses added: " + finallyClause + " and " + output); 202 } else { 203 finallyClause = (FinallyDefinition)output; 204 } 205 } else { 206 outputsWithoutCatches.add(output); 207 } 208 } 209 } 210 } 211}