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.event;
018
019import org.apache.camel.Category;
020import org.apache.camel.Exchange;
021import org.apache.camel.Processor;
022import org.apache.camel.Producer;
023import org.apache.camel.processor.loadbalancer.LoadBalancer;
024import org.apache.camel.processor.loadbalancer.TopicLoadBalancer;
025import org.apache.camel.spi.UriEndpoint;
026import org.apache.camel.spi.UriPath;
027import org.apache.camel.support.DefaultEndpoint;
028import org.apache.camel.support.DefaultProducer;
029import org.apache.camel.util.ObjectHelper;
030import org.springframework.beans.BeansException;
031import org.springframework.context.ApplicationContext;
032import org.springframework.context.ApplicationContextAware;
033import org.springframework.context.ApplicationEvent;
034
035import static org.apache.camel.RuntimeCamelException.wrapRuntimeCamelException;
036
037/**
038 * Listen for Spring Application Events.
039 */
040@UriEndpoint(firstVersion = "1.4.0", scheme = "spring-event", title = "Spring Event", syntax = "spring-event:name",
041             category = { Category.SPRING, Category.EVENTBUS })
042public class EventEndpoint extends DefaultEndpoint implements ApplicationContextAware {
043    private LoadBalancer loadBalancer;
044    private ApplicationContext applicationContext;
045
046    @UriPath(description = "Name of endpoint")
047    private String name;
048
049    public EventEndpoint(String endpointUri, EventComponent component, String name) {
050        super(endpointUri, component);
051        this.applicationContext = component.getApplicationContext();
052        this.name = name;
053    }
054
055    @Override
056    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
057        this.applicationContext = applicationContext;
058    }
059
060    public ApplicationContext getApplicationContext() {
061        return applicationContext;
062    }
063
064    public String getName() {
065        return name;
066    }
067
068    public void setName(String name) {
069        this.name = name;
070    }
071
072    @Override
073    public Producer createProducer() throws Exception {
074        ObjectHelper.notNull(applicationContext, "applicationContext");
075        return new DefaultProducer(this) {
076            public void process(Exchange exchange) throws Exception {
077                ApplicationEvent event = toApplicationEvent(exchange);
078                applicationContext.publishEvent(event);
079            }
080        };
081    }
082
083    @Override
084    public EventConsumer createConsumer(Processor processor) throws Exception {
085        ObjectHelper.notNull(applicationContext, "applicationContext");
086        EventConsumer answer = new EventConsumer(this, processor);
087        configureConsumer(answer);
088        return answer;
089    }
090
091    public void onApplicationEvent(ApplicationEvent event) {
092        Exchange exchange = createExchange();
093        exchange.getIn().setBody(event);
094        try {
095            getLoadBalancer().process(exchange);
096        } catch (Exception e) {
097            throw wrapRuntimeCamelException(e);
098        }
099    }
100
101    public LoadBalancer getLoadBalancer() {
102        if (loadBalancer == null) {
103            loadBalancer = createLoadBalancer();
104        }
105        return loadBalancer;
106    }
107
108    public void setLoadBalancer(LoadBalancer loadBalancer) {
109        this.loadBalancer = loadBalancer;
110    }
111
112    @Override
113    public EventComponent getComponent() {
114        return (EventComponent) super.getComponent();
115    }
116
117    // Implementation methods
118    // -------------------------------------------------------------------------
119    public synchronized void consumerStarted(EventConsumer consumer) {
120        getComponent().consumerStarted(this);
121        getLoadBalancer().addProcessor(consumer.getAsyncProcessor());
122    }
123
124    public synchronized void consumerStopped(EventConsumer consumer) {
125        getComponent().consumerStopped(this);
126        getLoadBalancer().removeProcessor(consumer.getAsyncProcessor());
127    }
128
129    protected LoadBalancer createLoadBalancer() {
130        return new TopicLoadBalancer();
131    }
132
133    protected ApplicationEvent toApplicationEvent(Exchange exchange) {
134        ApplicationEvent event = exchange.getIn().getBody(ApplicationEvent.class);
135        if (event != null) {
136            return event;
137        }
138        return new CamelEvent(this, exchange);
139    }
140}