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     * Beware that when using dynamic endpoints then it affects how well the cache can be utilized.
286     * If each dynamic endpoint is unique then its best to turn of caching by setting this to -1, which
287     * allows Camel to not cache both the producers and endpoints; they are regarded as prototype scoped
288     * and will be stopped and discarded after use. This reduces memory usage as otherwise producers/endpoints
289     * are stored in memory in the caches.
290     *
291     * However if there are a high degree of dynamic endpoints that have been used before, then it can
292     * benefit to use the cache to reuse both producers and endpoints and therefore the cache size
293     * can be set accordingly or rely on the default size (1000).
294     *
295     * If there is a mix of unique and used before dynamic endpoints, then setting a reasonable cache size
296     * can help reduce memory usage to avoid storing too many non frequent used producers.
297     *
298     * @param cacheSize the cache size, use <tt>0</tt> for default cache size,
299     *            or <tt>-1</tt> to turn cache off.
300     * @return the builder
301     */
302    @Override
303    public WireTapDefinition<Type> cacheSize(int cacheSize) {
304        return cacheSize(Integer.toString(cacheSize));
305    }
306
307    /**
308     * Sets the maximum size used by the
309     * {@link org.apache.camel.spi.ProducerCache} which is used to cache and
310     * reuse producers, when uris are reused.
311     *
312     * Beware that when using dynamic endpoints then it affects how well the cache can be utilized.
313     * If each dynamic endpoint is unique then its best to turn of caching by setting this to -1, which
314     * allows Camel to not cache both the producers and endpoints; they are regarded as prototype scoped
315     * and will be stopped and discarded after use. This reduces memory usage as otherwise producers/endpoints
316     * are stored in memory in the caches.
317     *
318     * However if there are a high degree of dynamic endpoints that have been used before, then it can
319     * benefit to use the cache to reuse both producers and endpoints and therefore the cache size
320     * can be set accordingly or rely on the default size (1000).
321     *
322     * If there is a mix of unique and used before dynamic endpoints, then setting a reasonable cache size
323     * can help reduce memory usage to avoid storing too many non frequent used producers.
324     *
325     * @param cacheSize the cache size, use <tt>0</tt> for default cache size,
326     *            or <tt>-1</tt> to turn cache off.
327     * @return the builder
328     */
329    @Override
330    public WireTapDefinition<Type> cacheSize(String cacheSize) {
331        setCacheSize(cacheSize);
332        return this;
333    }
334
335    /**
336     * Ignore the invalidate endpoint exception when try to create a producer
337     * with that endpoint
338     *
339     * @return the builder
340     */
341    public WireTapDefinition<Type> ignoreInvalidEndpoint() {
342        setIgnoreInvalidEndpoint(Boolean.toString(true));
343        return this;
344    }
345
346    // Properties
347    // -------------------------------------------------------------------------
348
349    @Override
350    public String getUri() {
351        return super.getUri();
352    }
353
354    /**
355     * The uri of the endpoint to wiretap to. The uri can be dynamic computed
356     * using the {@link org.apache.camel.language.simple.SimpleLanguage}
357     * expression.
358     */
359    @Override
360    public void setUri(String uri) {
361        super.setUri(uri);
362    }
363
364    public Processor getNewExchangeProcessor() {
365        return newExchangeProcessor;
366    }
367
368    /**
369     * To use a Processor for creating a new body as the message to use for wire
370     * tapping
371     */
372    public void setNewExchangeProcessor(Processor processor) {
373        this.newExchangeProcessor = processor;
374    }
375
376    public String getNewExchangeProcessorRef() {
377        return newExchangeProcessorRef;
378    }
379
380    /**
381     * Reference to a Processor to use for creating a new body as the message to
382     * use for wire tapping
383     */
384    public void setNewExchangeProcessorRef(String ref) {
385        this.newExchangeProcessorRef = ref;
386    }
387
388    public ExpressionSubElementDefinition getNewExchangeExpression() {
389        return newExchangeExpression;
390    }
391
392    /**
393     * Uses the expression for creating a new body as the message to use for
394     * wire tapping
395     */
396    public void setNewExchangeExpression(ExpressionSubElementDefinition newExchangeExpression) {
397        this.newExchangeExpression = newExchangeExpression;
398    }
399
400    @Override
401    public ExecutorService getExecutorService() {
402        return executorService;
403    }
404
405    @Override
406    public void setExecutorService(ExecutorService executorService) {
407        this.executorService = executorService;
408    }
409
410    @Override
411    public String getExecutorServiceRef() {
412        return executorServiceRef;
413    }
414
415    @Override
416    public void setExecutorServiceRef(String executorServiceRef) {
417        this.executorServiceRef = executorServiceRef;
418    }
419
420    public String getCopy() {
421        return copy;
422    }
423
424    public void setCopy(String copy) {
425        this.copy = copy;
426    }
427
428    public String getDynamicUri() {
429        return dynamicUri;
430    }
431
432    public void setDynamicUri(String dynamicUri) {
433        this.dynamicUri = dynamicUri;
434    }
435
436    public String getOnPrepareRef() {
437        return onPrepareRef;
438    }
439
440    public void setOnPrepareRef(String onPrepareRef) {
441        this.onPrepareRef = onPrepareRef;
442    }
443
444    public Processor getOnPrepare() {
445        return onPrepare;
446    }
447
448    public void setOnPrepare(Processor onPrepare) {
449        this.onPrepare = onPrepare;
450    }
451
452    public List<SetHeaderDefinition> getHeaders() {
453        return headers;
454    }
455
456    public void setHeaders(List<SetHeaderDefinition> headers) {
457        this.headers = headers;
458    }
459
460}