/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.component.jgroups; import java.util.concurrent.atomic.AtomicInteger; import org.apache.camel.Component; import org.apache.camel.Consumer; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; import org.jgroups.JChannel; import org.jgroups.Message; import org.jgroups.View; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The jgroups component provides exchange of messages between Camel and JGroups clusters. */ @UriEndpoint(firstVersion = "2.13.0", scheme = "jgroups", title = "JGroups", syntax = "jgroups:clusterName", consumerClass = JGroupsConsumer.class, label = "clustering,messaging") public class JGroupsEndpoint extends DefaultEndpoint { public static final String HEADER_JGROUPS_ORIGINAL_MESSAGE = "JGROUPS_ORIGINAL_MESSAGE"; public static final String HEADER_JGROUPS_SRC = "JGROUPS_SRC"; public static final String HEADER_JGROUPS_DEST = "JGROUPS_DEST"; public static final String HEADER_JGROUPS_CHANNEL_ADDRESS = "JGROUPS_CHANNEL_ADDRESS"; private static final Logger LOG = LoggerFactory.getLogger(JGroupsEndpoint.class); private AtomicInteger connectCount = new AtomicInteger(0); private JChannel channel; private JChannel resolvedChannel; @UriPath @Metadata(required = "true") private String clusterName; @UriParam private String channelProperties; @UriParam(label = "consumer") private boolean enableViewMessages; public JGroupsEndpoint(String endpointUri, Component component, JChannel channel, String clusterName, String channelProperties, boolean enableViewMessages) { super(endpointUri, component); this.channel = channel; this.clusterName = clusterName; this.channelProperties = channelProperties; this.enableViewMessages = enableViewMessages; } @Override public Producer createProducer() throws Exception { return new JGroupsProducer(this, resolvedChannel, clusterName); } @Override public Consumer createConsumer(Processor processor) throws Exception { return new JGroupsConsumer(this, processor, resolvedChannel, clusterName); } @Override public boolean isSingleton() { return true; } public Exchange createExchange(Message message) { Exchange exchange = createExchange(); exchange.getIn().setHeader(HEADER_JGROUPS_ORIGINAL_MESSAGE, message); exchange.getIn().setHeader(HEADER_JGROUPS_SRC, message.getSrc()); exchange.getIn().setHeader(HEADER_JGROUPS_DEST, message.getDest()); exchange.getIn().setBody(message.getObject()); return exchange; } public Exchange createExchange(View view) { Exchange exchange = createExchange(); exchange.getIn().setBody(view); return exchange; } @Override public Exchange createExchange() { Exchange exchange = super.createExchange(); exchange.getIn().setHeader(HEADER_JGROUPS_CHANNEL_ADDRESS, resolvedChannel.getAddress()); return exchange; } @Override protected void doStart() throws Exception { super.doStart(); resolvedChannel = resolveChannel(); } @Override protected void doStop() throws Exception { LOG.trace("Closing JGroups Channel {}", getEndpointUri()); resolvedChannel.close(); super.doStop(); } private JChannel resolveChannel() throws Exception { if (channel != null) { return channel; } if (channelProperties != null && !channelProperties.isEmpty()) { return new JChannel(channelProperties); } return new JChannel(); } /** * Connect shared channel, called by producer and consumer. * @throws Exception */ public void connect() throws Exception { connectCount.incrementAndGet(); LOG.trace("Connecting JGroups Channel {}", getEndpointUri()); resolvedChannel.connect(clusterName); } /** * Disconnect shared channel, called by producer and consumer. */ public void disconnect() { if (connectCount.decrementAndGet() == 0) { LOG.trace("Disconnecting JGroups Channel {}", getEndpointUri()); resolvedChannel.disconnect(); } } public JChannel getChannel() { return channel; } /** * The channel to use */ public void setChannel(JChannel channel) { this.channel = channel; } public String getClusterName() { return clusterName; } /** * The name of the JGroups cluster the component should connect to. */ public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getChannelProperties() { return channelProperties; } /** * Specifies configuration properties of the JChannel used by the endpoint. */ public void setChannelProperties(String channelProperties) { this.channelProperties = channelProperties; } JChannel getResolvedChannel() { return resolvedChannel; } public boolean isEnableViewMessages() { return enableViewMessages; } /** * If set to true, the consumer endpoint will receive org.jgroups.View messages as well (not only org.jgroups.Message instances). * By default only regular messages are consumed by the endpoint. */ public void setEnableViewMessages(boolean enableViewMessages) { this.enableViewMessages = enableViewMessages; } }