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.component.browse;
018
019import java.util.List;
020import java.util.concurrent.CopyOnWriteArrayList;
021
022import org.apache.camel.Component;
023import org.apache.camel.Consumer;
024import org.apache.camel.Exchange;
025import org.apache.camel.Processor;
026import org.apache.camel.Producer;
027import org.apache.camel.impl.DefaultEndpoint;
028import org.apache.camel.impl.DefaultProducer;
029import org.apache.camel.processor.loadbalancer.LoadBalancer;
030import org.apache.camel.processor.loadbalancer.LoadBalancerConsumer;
031import org.apache.camel.processor.loadbalancer.TopicLoadBalancer;
032import org.apache.camel.spi.BrowsableEndpoint;
033import org.apache.camel.spi.Metadata;
034import org.apache.camel.spi.UriEndpoint;
035import org.apache.camel.spi.UriPath;
036
037/**
038 * The browse component is used for viewing the messages received on endpoints that supports {@link BrowsableEndpoint}.
039 *
040 * This can be useful for testing, visualisation tools or debugging. he exchanges sent to the endpoint are all available to be browsed.
041 */
042@UriEndpoint(firstVersion = "1.3.0", scheme = "browse", title = "Browse", syntax = "browse:name", label = "core,monitoring")
043public class BrowseEndpoint extends DefaultEndpoint implements BrowsableEndpoint {
044
045    @UriPath(description = "A name which can be any string to uniquely identify the endpoint") @Metadata(required = "true")
046    private String name;
047
048    private List<Exchange> exchanges;
049    private final LoadBalancer loadBalancer = new TopicLoadBalancer();
050
051    public BrowseEndpoint() {
052    }
053
054    public BrowseEndpoint(String uri, Component component) {
055        super(uri, component);
056    }
057
058    public boolean isSingleton() {
059        return true;
060    }
061
062    public List<Exchange> getExchanges() {
063        if (exchanges == null) {
064            exchanges = createExchangeList();
065        }
066        return exchanges;
067    }
068
069    public Producer createProducer() throws Exception {
070        return new DefaultProducer(this) {
071            public void process(Exchange exchange) throws Exception {
072                onExchange(exchange);
073            }
074        };
075    }
076
077    public Consumer createConsumer(Processor processor) throws Exception {
078        Consumer answer = new LoadBalancerConsumer(this, processor, loadBalancer);
079        configureConsumer(answer);
080        return answer;
081    }
082
083    public String getName() {
084        return name;
085    }
086
087    public void setName(String name) {
088        this.name = name;
089    }
090
091    protected List<Exchange> createExchangeList() {
092        return new CopyOnWriteArrayList<Exchange>();
093    }
094
095    /**
096     * Invoked on a message exchange being sent by a producer
097     *
098     * @param exchange the exchange
099     * @throws Exception is thrown if failed to process the exchange
100     */
101    protected void onExchange(Exchange exchange) throws Exception {
102        getExchanges().add(exchange);
103
104        // now fire any consumers
105        loadBalancer.process(exchange);
106    }
107
108    @Override
109    protected void doStart() throws Exception {
110        exchanges = createExchangeList();
111        super.doStart();
112    }
113
114    @Override
115    protected void doStop() throws Exception {
116        if (exchanges != null) {
117            exchanges.clear();
118            exchanges = null;
119        }
120        super.doStop();
121    }
122}