/** * 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.cassandra; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.ConsistencyLevel; import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Session; import org.apache.camel.Component; import org.apache.camel.Consumer; import org.apache.camel.Message; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; import org.apache.camel.util.CamelContextHelper; import org.apache.camel.utils.cassandra.CassandraLoadBalancingPolicies; import org.apache.camel.utils.cassandra.CassandraSessionHolder; /** * The cql component aims at integrating Cassandra 2.0+ using the CQL3 API (not the Thrift API). * * It's based on Cassandra Java Driver provided by DataStax. */ @UriEndpoint(firstVersion = "2.15.0", scheme = "cql", title = "Cassandra CQL", syntax = "cql:beanRef:hosts:port/keyspace", consumerClass = CassandraConsumer.class, label = "database,nosql") public class CassandraEndpoint extends DefaultEndpoint { private volatile CassandraSessionHolder sessionHolder; @UriPath(description = "beanRef is defined using bean:id") private String beanRef; @UriPath private String hosts; @UriPath private Integer port; @UriPath private String keyspace; @UriParam private String cql; @UriParam(defaultValue = "true") private boolean prepareStatements = true; @UriParam private String clusterName; @UriParam private String username; @UriParam private String password; @UriParam private Cluster cluster; @UriParam private Session session; @UriParam private ConsistencyLevel consistencyLevel; @UriParam private String loadBalancingPolicy; @UriParam(javaType = "java.lang.String") private ResultSetConversionStrategy resultSetConversionStrategy = ResultSetConversionStrategies.all(); public CassandraEndpoint(String endpointUri, Component component) { super(endpointUri, component); } public CassandraEndpoint(String uri, CassandraComponent component, Cluster cluster, Session session, String keyspace) { super(uri, component); this.cluster = cluster; this.session = session; this.keyspace = keyspace; } public Producer createProducer() throws Exception { return new CassandraProducer(this); } public Consumer createConsumer(Processor processor) throws Exception { return new CassandraConsumer(this, processor); } public boolean isSingleton() { return true; } @Override protected void doStart() throws Exception { super.doStart(); // we can get the cluster using various ways if (cluster == null && beanRef != null) { Object bean = CamelContextHelper.mandatoryLookup(getCamelContext(), beanRef); if (bean instanceof Session) { session = (Session) bean; cluster = session.getCluster(); keyspace = session.getLoggedKeyspace(); } else if (bean instanceof Cluster) { cluster = (Cluster) bean; session = null; } else { throw new IllegalArgumentException("CQL Bean type should be of type Session or Cluster but was " + bean); } } if (cluster == null && hosts != null) { // use the cluster builder to create the cluster cluster = createClusterBuilder().build(); } if (cluster != null) { sessionHolder = new CassandraSessionHolder(cluster, keyspace); } else { sessionHolder = new CassandraSessionHolder(session); } sessionHolder.start(); } @Override protected void doStop() throws Exception { super.doStop(); sessionHolder.stop(); } protected CassandraSessionHolder getSessionHolder() { return sessionHolder; } protected Cluster.Builder createClusterBuilder() throws Exception { CassandraLoadBalancingPolicies cassLoadBalancingPolicies = new CassandraLoadBalancingPolicies(); Cluster.Builder clusterBuilder = Cluster.builder(); for (String host : hosts.split(",")) { clusterBuilder = clusterBuilder.addContactPoint(host); } if (port != null) { clusterBuilder = clusterBuilder.withPort(port); } if (clusterName != null) { clusterBuilder = clusterBuilder.withClusterName(clusterName); } if (username != null && !username.isEmpty() && password != null) { clusterBuilder.withCredentials(username, password); } if (loadBalancingPolicy != null && !loadBalancingPolicy.isEmpty()) { clusterBuilder.withLoadBalancingPolicy(cassLoadBalancingPolicies.getLoadBalancingPolicy(loadBalancingPolicy)); } return clusterBuilder; } /** * Create and configure a Prepared CQL statement */ protected PreparedStatement prepareStatement(String cql) { PreparedStatement preparedStatement = getSessionHolder().getSession().prepare(cql); if (consistencyLevel != null) { preparedStatement.setConsistencyLevel(consistencyLevel); } return preparedStatement; } /** * Create and configure a Prepared CQL statement */ protected PreparedStatement prepareStatement() { return prepareStatement(cql); } /** * Copy ResultSet into Message. */ protected void fillMessage(ResultSet resultSet, Message message) { message.setBody(resultSetConversionStrategy.getBody(resultSet)); } public String getBean() { return beanRef; } /** * Instead of using a hostname:port, refer to an existing configured Session or Cluster from the Camel registry to be used. */ public void setBean(String beanRef) { this.beanRef = beanRef; } @Deprecated public String getBeanRef() { return beanRef; } @Deprecated public void setBeanRef(String beanRef) { this.beanRef = beanRef; } public String getHosts() { return hosts; } /** * Hostname(s) cassansdra server(s). Multiple hosts can be separated by comma. */ public void setHosts(String hosts) { this.hosts = hosts; } public Integer getPort() { return port; } /** * Port number of cassansdra server(s) */ public void setPort(Integer port) { this.port = port; } public String getKeyspace() { return keyspace; } /** * Keyspace to use */ public void setKeyspace(String keyspace) { this.keyspace = keyspace; } public String getCql() { return cql; } /** * CQL query to perform. Can be overridden with the message header with key CamelCqlQuery. */ public void setCql(String cql) { this.cql = cql; } public Cluster getCluster() { return cluster; } /** * To use the Cluster instance (you would normally not use this option) */ public void setCluster(Cluster cluster) { this.cluster = cluster; } public Session getSession() { if (session == null) { return sessionHolder.getSession(); } else { return session; } } /** * To use the Session instance (you would normally not use this option) */ public void setSession(Session session) { this.session = session; } public String getClusterName() { return clusterName; } /** * Cluster name */ public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getUsername() { return username; } /** * Username for session authentication */ public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } /** * Password for session authentication */ public void setPassword(String password) { this.password = password; } public ConsistencyLevel getConsistencyLevel() { return consistencyLevel; } /** * Consistency level to use */ public void setConsistencyLevel(ConsistencyLevel consistencyLevel) { this.consistencyLevel = consistencyLevel; } public ResultSetConversionStrategy getResultSetConversionStrategy() { return resultSetConversionStrategy; } /** * To use a custom class that implements logic for converting ResultSet into message body ALL, ONE, LIMIT_10, LIMIT_100... */ public void setResultSetConversionStrategy(ResultSetConversionStrategy resultSetConversionStrategy) { this.resultSetConversionStrategy = resultSetConversionStrategy; } public boolean isPrepareStatements() { return prepareStatements; } /** * Whether to use PreparedStatements or regular Statements */ public void setPrepareStatements(boolean prepareStatements) { this.prepareStatements = prepareStatements; } /** * To use a specific LoadBalancingPolicy */ public String getLoadBalancingPolicy() { return loadBalancingPolicy; } public void setLoadBalancingPolicy(String loadBalancingPolicy) { this.loadBalancingPolicy = loadBalancingPolicy; } }