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