/** * 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.couchbase; import java.util.Map; import java.util.concurrent.Future; import com.couchbase.client.CouchbaseClientIF; import net.spy.memcached.PersistTo; import net.spy.memcached.ReplicateTo; import net.spy.memcached.internal.OperationFuture; import org.apache.camel.Exchange; import org.apache.camel.impl.DefaultProducer; import static org.apache.camel.component.couchbase.CouchbaseConstants.COUCHBASE_DELETE; import static org.apache.camel.component.couchbase.CouchbaseConstants.COUCHBASE_GET; import static org.apache.camel.component.couchbase.CouchbaseConstants.COUCHBASE_PUT; import static org.apache.camel.component.couchbase.CouchbaseConstants.DEFAULT_TTL; import static org.apache.camel.component.couchbase.CouchbaseConstants.HEADER_ID; import static org.apache.camel.component.couchbase.CouchbaseConstants.HEADER_TTL; /** * Couchbase producer generates various type of operations. PUT, GET, and DELETE * are currently supported */ public class CouchbaseProducer extends DefaultProducer { private CouchbaseEndpoint endpoint; private CouchbaseClientIF client; private long startId; private PersistTo persistTo; private ReplicateTo replicateTo; private int producerRetryAttempts; private int producerRetryPause; public CouchbaseProducer(CouchbaseEndpoint endpoint, CouchbaseClientIF client, int persistTo, int replicateTo) throws Exception { super(endpoint); this.endpoint = endpoint; this.client = client; if (endpoint.isAutoStartIdForInserts()) { this.startId = endpoint.getStartingIdForInsertsFrom(); } this.producerRetryAttempts = endpoint.getProducerRetryAttempts(); this.producerRetryPause = endpoint.getProducerRetryPause(); switch (persistTo) { case 0: this.persistTo = PersistTo.ZERO; break; case 1: this.persistTo = PersistTo.MASTER; break; case 2: this.persistTo = PersistTo.TWO; break; case 3: this.persistTo = PersistTo.THREE; break; case 4: this.persistTo = PersistTo.FOUR; break; default: throw new IllegalArgumentException("Unsupported persistTo parameter. Supported values are 0 to 4. Currently provided: " + persistTo); } switch (replicateTo) { case 0: this.replicateTo = ReplicateTo.ZERO; break; case 1: this.replicateTo = ReplicateTo.ONE; break; case 2: this.replicateTo = ReplicateTo.TWO; break; case 3: this.replicateTo = ReplicateTo.THREE; break; default: throw new IllegalArgumentException("Unsupported replicateTo parameter. Supported values are 0 to 3. Currently provided: " + replicateTo); } } @Override public void process(Exchange exchange) throws Exception { Map<String, Object> headers = exchange.getIn().getHeaders(); String id = (headers.containsKey(HEADER_ID)) ? exchange.getIn().getHeader(HEADER_ID, String.class) : endpoint.getId(); int ttl = (headers.containsKey(HEADER_TTL)) ? Integer.parseInt(exchange.getIn().getHeader(HEADER_TTL, String.class)) : DEFAULT_TTL; if (endpoint.isAutoStartIdForInserts()) { id = Long.toString(startId); startId++; } else if (id == null) { throw new CouchbaseException(HEADER_ID + " is not specified in message header or endpoint URL.", exchange); } if (endpoint.getOperation().equals(COUCHBASE_PUT)) { log.info("Type of operation: PUT"); Object obj = exchange.getIn().getBody(); exchange.getOut().setBody(setDocument(id, ttl, obj, persistTo, replicateTo)); } else if (endpoint.getOperation().equals(COUCHBASE_GET)) { log.info("Type of operation: GET"); Object result = client.get(id); exchange.getOut().setBody(result); } else if (endpoint.getOperation().equals(COUCHBASE_DELETE)) { log.info("Type of operation: DELETE"); Future<Boolean> result = client.delete(id); exchange.getOut().setBody(result.get()); } // cleanup the cache headers exchange.getIn().removeHeader(HEADER_ID); } private Boolean setDocument(String id, int expiry, Object obj, PersistTo persistTo, ReplicateTo replicateTo) throws Exception { return setDocument(id, expiry, obj, producerRetryAttempts, persistTo, replicateTo); } private Boolean setDocument(String id, int expiry, Object obj, int retryAttempts, PersistTo persistTo, ReplicateTo replicateTo) throws Exception { OperationFuture<Boolean> result = client.set(id, expiry, obj, persistTo, replicateTo); try { if (!result.get()) { throw new Exception("Unable to save Document. " + id); } return true; } catch (Exception e) { if (retryAttempts <= 0) { throw e; } else { log.info("Unable to save Document, retrying in " + producerRetryPause + "ms (" + retryAttempts + ")"); Thread.sleep(producerRetryPause); return setDocument(id, expiry, obj, retryAttempts - 1, persistTo, replicateTo); } } } }