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.List;
021import java.util.concurrent.ExecutorService;
022import java.util.function.Supplier;
023
024import javax.xml.bind.annotation.XmlAccessType;
025import javax.xml.bind.annotation.XmlAccessorType;
026import javax.xml.bind.annotation.XmlAttribute;
027import javax.xml.bind.annotation.XmlElement;
028import javax.xml.bind.annotation.XmlElementRef;
029import javax.xml.bind.annotation.XmlRootElement;
030import javax.xml.bind.annotation.XmlTransient;
031
032import org.apache.camel.ExchangePattern;
033import org.apache.camel.Expression;
034import org.apache.camel.Processor;
035import org.apache.camel.spi.Metadata;
036
037/**
038 * Routes a copy of a message (or creates a new message) to a secondary
039 * destination while continue routing the original message.
040 */
041@Metadata(label = "eip,endpoint,routing")
042@XmlRootElement(name = "wireTap")
043@XmlAccessorType(XmlAccessType.FIELD)
044public class WireTapDefinition<Type extends ProcessorDefinition<Type>> extends ToDynamicDefinition implements ExecutorServiceAwareDefinition<WireTapDefinition<Type>> {
045    @XmlTransient
046    private Processor newExchangeProcessor;
047    @XmlAttribute(name = "processorRef")
048    private String newExchangeProcessorRef;
049    @XmlElement(name = "body")
050    private ExpressionSubElementDefinition newExchangeExpression;
051    @XmlElementRef
052    private List<SetHeaderDefinition> headers = new ArrayList<>();
053    @XmlTransient
054    private ExecutorService executorService;
055    @XmlAttribute
056    private String executorServiceRef;
057    @XmlAttribute
058    @Metadata(defaultValue = "true")
059    private Boolean copy;
060    @XmlAttribute
061    @Metadata(defaultValue = "true")
062    private Boolean dynamicUri;
063    @XmlAttribute
064    private String onPrepareRef;
065    @XmlTransient
066    private Processor onPrepare;
067
068    public WireTapDefinition() {
069    }
070
071    public boolean isDynamic() {
072        // its dynamic by default
073        return dynamicUri == null || dynamicUri;
074    }
075
076    @Override
077    public ExchangePattern getPattern() {
078        return ExchangePattern.InOnly;
079    }
080
081    @Override
082    public String toString() {
083        return "WireTap[" + getUri() + "]";
084    }
085
086    @Override
087    public String getShortName() {
088        return "wireTap";
089    }
090
091    @Override
092    public String getLabel() {
093        return "wireTap[" + getUri() + "]";
094    }
095
096    @Override
097    @SuppressWarnings("unchecked")
098    public Type end() {
099        // allow end() to return to previous type so you can continue in the DSL
100        return (Type)super.end();
101    }
102
103    @Override
104    public void addOutput(ProcessorDefinition<?> output) {
105        // add outputs on parent as this wiretap does not support outputs
106        getParent().addOutput(output);
107    }
108
109    // Fluent API
110    // -------------------------------------------------------------------------
111
112    /**
113     * Uses a custom thread pool
114     *
115     * @param executorService a custom {@link ExecutorService} to use as thread
116     *            pool for sending tapped exchanges
117     * @return the builder
118     */
119    @Override
120    public WireTapDefinition<Type> executorService(ExecutorService executorService) {
121        setExecutorService(executorService);
122        return this;
123    }
124
125    /**
126     * Uses a custom thread pool
127     *
128     * @param executorServiceRef reference to lookup a custom
129     *            {@link ExecutorService} to use as thread pool for sending
130     *            tapped exchanges
131     * @return the builder
132     */
133    @Override
134    public WireTapDefinition<Type> executorServiceRef(String executorServiceRef) {
135        setExecutorServiceRef(executorServiceRef);
136        return this;
137    }
138
139    /**
140     * Uses a copy of the original exchange
141     *
142     * @return the builder
143     */
144    public WireTapDefinition<Type> copy() {
145        setCopy(true);
146        return this;
147    }
148
149    /**
150     * Uses a copy of the original exchange
151     *
152     * @param copy if it is true camel will copy the original exchange, if it is
153     *            false camel will not copy the original exchange
154     * @return the builder
155     */
156    public WireTapDefinition<Type> copy(boolean copy) {
157        setCopy(copy);
158        return this;
159    }
160
161    /**
162     * Whether the uri is dynamic or static. If the uri is dynamic then the
163     * simple language is used to evaluate a dynamic uri to use as the wire-tap
164     * destination, for each incoming message. This works similar to how the
165     * <tt>toD</tt> EIP pattern works. If static then the uri is used as-is as
166     * the wire-tap destination.
167     *
168     * @param dynamicUri whether to use dynamic or static uris
169     * @return the builder
170     */
171    public WireTapDefinition<Type> dynamicUri(boolean dynamicUri) {
172        setDynamicUri(dynamicUri);
173        return this;
174    }
175
176    /**
177     * Sends a <i>new</i> Exchange, instead of tapping an existing, using
178     * {@link ExchangePattern#InOnly}
179     *
180     * @param expression expression that creates the new body to send
181     * @return the builder
182     * @see #newExchangeHeader(String, org.apache.camel.Expression)
183     */
184    public WireTapDefinition<Type> newExchangeBody(Expression expression) {
185        setNewExchangeExpression(new ExpressionSubElementDefinition(expression));
186        return this;
187    }
188
189    /**
190     * Sends a <i>new</i> Exchange, instead of tapping an existing, using
191     * {@link ExchangePattern#InOnly}
192     *
193     * @param ref reference to the {@link Processor} to lookup in the
194     *            {@link org.apache.camel.spi.Registry} to be used for preparing
195     *            the new exchange to send
196     * @return the builder
197     */
198    public WireTapDefinition<Type> newExchangeRef(String ref) {
199        setNewExchangeProcessorRef(ref);
200        return this;
201    }
202
203    /**
204     * Sends a <i>new</i> Exchange, instead of tapping an existing, using
205     * {@link ExchangePattern#InOnly}
206     *
207     * @param processor processor preparing the new exchange to send
208     * @return the builder
209     * @see #newExchangeHeader(String, org.apache.camel.Expression)
210     */
211    public WireTapDefinition<Type> newExchange(Processor processor) {
212        setNewExchangeProcessor(processor);
213        return this;
214    }
215
216    /**
217     * Sends a <i>new</i> Exchange, instead of tapping an existing, using
218     * {@link ExchangePattern#InOnly}
219     *
220     * @param processor processor preparing the new exchange to send
221     * @return the builder
222     * @see #newExchangeHeader(String, org.apache.camel.Expression)
223     */
224    public WireTapDefinition<Type> newExchange(Supplier<Processor> processor) {
225        setNewExchangeProcessor(processor.get());
226        return this;
227    }
228
229    /**
230     * Sets a header on the <i>new</i> Exchange, instead of tapping an existing,
231     * using {@link ExchangePattern#InOnly}.
232     * <p/>
233     * Use this together with the
234     * {@link #newExchangeBody(org.apache.camel.Expression)} or
235     * {@link #newExchange(org.apache.camel.Processor)} methods.
236     *
237     * @param headerName the header name
238     * @param expression the expression setting the header value
239     * @return the builder
240     */
241    public WireTapDefinition<Type> newExchangeHeader(String headerName, Expression expression) {
242        headers.add(new SetHeaderDefinition(headerName, expression));
243        return this;
244    }
245
246    /**
247     * Uses the {@link Processor} when preparing the
248     * {@link org.apache.camel.Exchange} to be send. This can be used to
249     * deep-clone messages that should be send, or any custom logic needed
250     * before the exchange is send.
251     *
252     * @param onPrepare the processor
253     * @return the builder
254     */
255    public WireTapDefinition<Type> onPrepare(Processor onPrepare) {
256        setOnPrepare(onPrepare);
257        return this;
258    }
259
260    /**
261     * Uses the {@link Processor} when preparing the
262     * {@link org.apache.camel.Exchange} to be send. This can be used to
263     * deep-clone messages that should be send, or any custom logic needed
264     * before the exchange is send.
265     *
266     * @param onPrepare the processor
267     * @return the builder
268     */
269    public WireTapDefinition<Type> onPrepare(Supplier<Processor> onPrepare) {
270        setOnPrepare(onPrepare.get());
271        return this;
272    }
273
274    /**
275     * Uses the {@link Processor} when preparing the
276     * {@link org.apache.camel.Exchange} to be send. This can be used to
277     * deep-clone messages that should be send, or any custom logic needed
278     * before the exchange is send.
279     *
280     * @param onPrepareRef reference to the processor to lookup in the
281     *            {@link org.apache.camel.spi.Registry}
282     * @return the builder
283     */
284    public WireTapDefinition<Type> onPrepareRef(String onPrepareRef) {
285        setOnPrepareRef(onPrepareRef);
286        return this;
287    }
288
289    /**
290     * Sets the maximum size used by the
291     * {@link org.apache.camel.spi.ProducerCache} which is used to cache and
292     * reuse producers, when uris are reused.
293     *
294     * @param cacheSize the cache size, use <tt>0</tt> for default cache size,
295     *            or <tt>-1</tt> to turn cache off.
296     * @return the builder
297     */
298    @Override
299    public WireTapDefinition<Type> cacheSize(int cacheSize) {
300        setCacheSize(cacheSize);
301        return this;
302    }
303
304    /**
305     * Ignore the invalidate endpoint exception when try to create a producer
306     * with that endpoint
307     *
308     * @return the builder
309     */
310    @Override
311    public WireTapDefinition<Type> ignoreInvalidEndpoint() {
312        setIgnoreInvalidEndpoint(true);
313        return this;
314    }
315
316    // Properties
317    // -------------------------------------------------------------------------
318
319    @Override
320    public String getUri() {
321        return super.getUri();
322    }
323
324    /**
325     * The uri of the endpoint to wiretap to. The uri can be dynamic computed
326     * using the {@link org.apache.camel.language.simple.SimpleLanguage}
327     * expression.
328     */
329    @Override
330    public void setUri(String uri) {
331        super.setUri(uri);
332    }
333
334    public Processor getNewExchangeProcessor() {
335        return newExchangeProcessor;
336    }
337
338    /**
339     * To use a Processor for creating a new body as the message to use for wire
340     * tapping
341     */
342    public void setNewExchangeProcessor(Processor processor) {
343        this.newExchangeProcessor = processor;
344    }
345
346    public String getNewExchangeProcessorRef() {
347        return newExchangeProcessorRef;
348    }
349
350    /**
351     * Reference to a Processor to use for creating a new body as the message to
352     * use for wire tapping
353     */
354    public void setNewExchangeProcessorRef(String ref) {
355        this.newExchangeProcessorRef = ref;
356    }
357
358    public ExpressionSubElementDefinition getNewExchangeExpression() {
359        return newExchangeExpression;
360    }
361
362    /**
363     * Uses the expression for creating a new body as the message to use for
364     * wire tapping
365     */
366    public void setNewExchangeExpression(ExpressionSubElementDefinition newExchangeExpression) {
367        this.newExchangeExpression = newExchangeExpression;
368    }
369
370    @Override
371    public ExecutorService getExecutorService() {
372        return executorService;
373    }
374
375    @Override
376    public void setExecutorService(ExecutorService executorService) {
377        this.executorService = executorService;
378    }
379
380    @Override
381    public String getExecutorServiceRef() {
382        return executorServiceRef;
383    }
384
385    @Override
386    public void setExecutorServiceRef(String executorServiceRef) {
387        this.executorServiceRef = executorServiceRef;
388    }
389
390    public Boolean getCopy() {
391        return copy;
392    }
393
394    public void setCopy(Boolean copy) {
395        this.copy = copy;
396    }
397
398    public Boolean getDynamicUri() {
399        return dynamicUri;
400    }
401
402    public void setDynamicUri(Boolean dynamicUri) {
403        this.dynamicUri = dynamicUri;
404    }
405
406    public String getOnPrepareRef() {
407        return onPrepareRef;
408    }
409
410    public void setOnPrepareRef(String onPrepareRef) {
411        this.onPrepareRef = onPrepareRef;
412    }
413
414    public Processor getOnPrepare() {
415        return onPrepare;
416    }
417
418    public void setOnPrepare(Processor onPrepare) {
419        this.onPrepare = onPrepare;
420    }
421
422    public List<SetHeaderDefinition> getHeaders() {
423        return headers;
424    }
425
426    public void setHeaders(List<SetHeaderDefinition> headers) {
427        this.headers = headers;
428    }
429
430}