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.Collection;
021
022import javax.xml.bind.annotation.XmlAccessType;
023import javax.xml.bind.annotation.XmlAccessorType;
024import javax.xml.bind.annotation.XmlAttribute;
025import javax.xml.bind.annotation.XmlRootElement;
026
027import org.apache.camel.Processor;
028import org.apache.camel.processor.AOPProcessor;
029import org.apache.camel.spi.AsEndpointUri;
030import org.apache.camel.spi.Metadata;
031import org.apache.camel.spi.RouteContext;
032
033/**
034 * Does processing before and/or after the route is completed
035 *
036 * @deprecated will be removed in the future. You can for example use {@link Processor} and
037 * {@link org.apache.camel.spi.InterceptStrategy} to do AOP in Camel.
038 * @version 
039 */
040@Metadata(label = "configuration")
041@XmlRootElement(name = "aop")
042@XmlAccessorType(XmlAccessType.FIELD)
043@Deprecated
044public class AOPDefinition extends OutputDefinition<AOPDefinition> {
045    @XmlAttribute
046    private String beforeUri;
047    @XmlAttribute
048    private String afterUri;
049    @XmlAttribute
050    private String afterFinallyUri;
051
052    public AOPDefinition() {
053    }
054
055    @Override
056    public String toString() {
057        return "AOP[" + getOutputs() + "]";
058    }
059
060    public String getBeforeUri() {
061        return beforeUri;
062    }
063
064    /**
065     * Endpoint to call in AOP before.
066     */
067    public void setBeforeUri(String beforeUri) {
068        this.beforeUri = beforeUri;
069    }
070
071    public String getAfterUri() {
072        return afterUri;
073    }
074
075    /**
076     * Endpoint to call in AOP after.
077     * <p/>
078     * The difference between after and afterFinally is that afterFinally is invoked from a finally block
079     * so it will always be invoked no matter what, eg also in case of an exception occur.
080     */
081    public void setAfterUri(String afterUri) {
082        this.afterUri = afterUri;
083    }
084
085    public String getAfterFinallyUri() {
086        return afterFinallyUri;
087    }
088
089    /**
090     * Endpoint to call in AOP after finally.
091     * <p/>
092     * The difference between after and afterFinally is that afterFinally is invoked from a finally block
093     * so it will always be invoked no matter what, eg also in case of an exception occur.
094     */
095    public void setAfterFinallyUri(String afterFinallyUri) {
096        this.afterFinallyUri = afterFinallyUri;
097    }
098
099    @Override
100    public String getShortName() {
101        return "aop";
102    }
103
104    @Override
105    public String getLabel() {
106        return "aop";
107    }
108
109    @Override
110    public Processor createProcessor(final RouteContext routeContext) throws Exception {
111        // either before or after must be provided
112        if (beforeUri == null && afterUri == null && afterFinallyUri == null) {
113            throw new IllegalArgumentException("At least one of before, after or afterFinally must be provided on: " + this);
114        }
115
116        // use a pipeline to assemble the before and target processor
117        // and the after if not afterFinally
118        Collection<ProcessorDefinition<?>> pipe = new ArrayList<>();
119
120        Processor finallyProcessor = null;
121
122        if (beforeUri != null) {
123            pipe.add(new ToDefinition(beforeUri));
124        }
125        pipe.addAll(getOutputs());
126
127        if (afterUri != null) {
128            pipe.add(new ToDefinition(afterUri));
129        } else if (afterFinallyUri != null) {
130            finallyProcessor = createProcessor(routeContext, new ToDefinition(afterFinallyUri));
131        }
132
133        Processor tryProcessor = createOutputsProcessor(routeContext, pipe);
134
135        // the AOP processor is based on TryProcessor so we do not have any catches
136        return new AOPProcessor(tryProcessor, null, finallyProcessor);
137    }
138
139    /**
140     * Uses a AOP around.
141     *
142     * @param beforeUri the uri of the before endpoint
143     * @param afterUri  the uri of the after endpoint
144     * @return the builder
145     */
146    public AOPDefinition around(@AsEndpointUri String beforeUri, @AsEndpointUri String afterUri) {
147        this.beforeUri = beforeUri;
148        this.afterUri = afterUri;
149        this.afterFinallyUri = null;
150        return this;
151    }
152
153    /**
154     * Uses a AOP around with after being invoked in a finally block
155     *
156     * @param beforeUri the uri of the before endpoint
157     * @param afterUri  the uri of the after endpoint
158     * @return the builder
159     */
160    public AOPDefinition aroundFinally(@AsEndpointUri String beforeUri, @AsEndpointUri String afterUri) {
161        this.beforeUri = beforeUri;
162        this.afterUri = null;
163        this.afterFinallyUri = afterUri;
164        return this;
165    }
166
167    /**
168     * Uses a AOP before.
169     *
170     * @param beforeUri the uri of the before endpoint
171     * @return the builder
172     */
173    public AOPDefinition before(@AsEndpointUri String beforeUri) {
174        this.beforeUri = beforeUri;
175        this.afterUri = null;
176        this.afterFinallyUri = null;
177        return this;
178    }
179
180    /**
181     * Uses a AOP after.
182     *
183     * @param afterUri  the uri of the after endpoint
184     * @return the builder
185     */
186    public AOPDefinition after(@AsEndpointUri String afterUri) {
187        this.beforeUri = null;
188        this.afterUri = afterUri;
189        this.afterFinallyUri = null;
190        return this;
191    }
192
193    /**
194     * Uses a AOP after with after being invoked in a finally block.
195     *
196     * @param afterUri  the uri of the after endpoint
197     * @return the builder
198     */
199    public AOPDefinition afterFinally(@AsEndpointUri String afterUri) {
200        this.beforeUri = null;
201        this.afterUri = null;
202        this.afterFinallyUri = afterUri;
203        return this;
204    }
205}