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.direct;
018
019import java.util.HashMap;
020import java.util.Map;
021
022import org.apache.camel.Component;
023import org.apache.camel.Consumer;
024import org.apache.camel.Processor;
025import org.apache.camel.Producer;
026import org.apache.camel.impl.DefaultEndpoint;
027import org.apache.camel.spi.Metadata;
028import org.apache.camel.spi.UriEndpoint;
029import org.apache.camel.spi.UriParam;
030import org.apache.camel.spi.UriPath;
031import org.apache.camel.util.ObjectHelper;
032
033/**
034 * Represents a direct endpoint that synchronously invokes the consumer of the
035 * endpoint when a producer sends a message to it.
036 *
037 * @version 
038 */
039@UriEndpoint(scheme = "direct", title = "Direct", syntax = "direct:name", consumerClass = DirectConsumer.class, label = "core,endpoint")
040public class DirectEndpoint extends DefaultEndpoint {
041
042    private volatile Map<String, DirectConsumer> consumers;
043
044    @UriPath(description = "Name of direct endpoint") @Metadata(required = "true")
045    private String name;
046
047    @UriParam(label = "producer")
048    private boolean block;
049    @UriParam(label = "producer", defaultValue = "30000")
050    private long timeout = 30000L;
051    @UriParam(label = "producer")
052    private boolean failIfNoConsumers = true;
053
054    public DirectEndpoint() {
055        this.consumers = new HashMap<String, DirectConsumer>();
056    }
057
058    public DirectEndpoint(String endpointUri, Component component) {
059        this(endpointUri, component, new HashMap<String, DirectConsumer>());
060    }
061
062    public DirectEndpoint(String uri, Component component, Map<String, DirectConsumer> consumers) {
063        super(uri, component);
064        this.consumers = consumers;
065    }
066
067    public Producer createProducer() throws Exception {
068        if (block) {
069            return new DirectBlockingProducer(this);
070        } else {
071            return new DirectProducer(this);
072        }
073    }
074
075    public Consumer createConsumer(Processor processor) throws Exception {
076        Consumer answer = new DirectConsumer(this, processor);
077        configureConsumer(answer);
078        return answer;
079    }
080
081    public boolean isSingleton() {
082        return true;
083    }
084
085    public void addConsumer(DirectConsumer consumer) {
086        String key = consumer.getEndpoint().getKey();
087        consumers.put(key, consumer);
088    }
089
090    public void removeConsumer(DirectConsumer consumer) {
091        String key = consumer.getEndpoint().getKey();
092        consumers.remove(key);
093    }
094
095    public boolean hasConsumer(DirectConsumer consumer) {
096        String key = consumer.getEndpoint().getKey();
097        return consumers.containsKey(key);
098    }
099
100    public DirectConsumer getConsumer() {
101        String key = getKey();
102        return consumers.get(key);
103    }
104
105    public boolean isBlock() {
106        return block;
107    }
108
109    /**
110     * If sending a message to a direct endpoint which has no active consumer,
111     * then we can tell the producer to block and wait for the consumer to become active.
112     */
113    public void setBlock(boolean block) {
114        this.block = block;
115    }
116
117    public long getTimeout() {
118        return timeout;
119    }
120
121    /**
122     * The timeout value to use if block is enabled.
123     *
124     * @param timeout the timeout value
125     */
126    public void setTimeout(long timeout) {
127        this.timeout = timeout;
128    }
129
130    public boolean isFailIfNoConsumers() {
131        return failIfNoConsumers;
132    }
133
134    /**
135     * Whether the producer should fail by throwing an exception, when sending to a DIRECT endpoint with no active consumers.
136     */
137    public void setFailIfNoConsumers(boolean failIfNoConsumers) {
138        this.failIfNoConsumers = failIfNoConsumers;
139    }
140
141    protected String getKey() {
142        String uri = getEndpointUri();
143        if (uri.indexOf('?') != -1) {
144            return ObjectHelper.before(uri, "?");
145        } else {
146            return uri;
147        }
148    }
149}