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