/** * 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.couchdb; import java.net.URI; import com.google.gson.JsonObject; 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.lightcouch.CouchDbClient; /** * The couchdb component is used for integrate with CouchDB databases. */ @UriEndpoint(firstVersion = "2.11.0", scheme = "couchdb", title = "CouchDB", syntax = "couchdb:protocol:hostname:port/database", consumerClass = CouchDbConsumer.class, label = "database,nosql") public class CouchDbEndpoint extends DefaultEndpoint { public static final String DEFAULT_STYLE = "main_only"; public static final long DEFAULT_HEARTBEAT = 30000; public static final int DEFAULT_PORT = 5984; private static final String URI_ERROR = "Invalid URI. Format must be of the form couchdb:http[s]://hostname[:port]/database?[options...]"; @UriPath(enums = "http,https") @Metadata(required = "true") private String protocol; @UriPath @Metadata(required = "true") private String hostname; @UriPath(defaultValue = "" + DEFAULT_PORT) private int port; @UriPath @Metadata(required = "true") private String database; @UriParam(label = "consumer", enums = "all_docs,main_only", defaultValue = DEFAULT_STYLE) private String style = DEFAULT_STYLE; @UriParam(label = "security", secret = true) private String username; @UriParam(label = "security", secret = true) private String password; @UriParam(label = "consumer", defaultValue = "" + DEFAULT_HEARTBEAT) private long heartbeat = DEFAULT_HEARTBEAT; @UriParam private boolean createDatabase; @UriParam(label = "consumer", defaultValue = "true") private boolean deletes = true; @UriParam(label = "consumer", defaultValue = "true") private boolean updates = true; @UriParam(label = "consumer") private String since; public CouchDbEndpoint() { } public CouchDbEndpoint(String endpointUri, String remaining, CouchDbComponent component) throws Exception { super(endpointUri, component); URI uri = new URI(remaining); protocol = uri.getScheme(); if (protocol == null) { throw new IllegalArgumentException(URI_ERROR); } port = uri.getPort() == -1 ? DEFAULT_PORT : uri.getPort(); if (uri.getPath() == null || uri.getPath().trim().length() == 0) { throw new IllegalArgumentException(URI_ERROR); } database = uri.getPath().substring(1); hostname = uri.getHost(); if (hostname == null) { throw new IllegalArgumentException(URI_ERROR); } } @Override public Consumer createConsumer(Processor processor) throws Exception { CouchDbConsumer answer = new CouchDbConsumer(this, createClient(), processor); configureConsumer(answer); return answer; } @Override public Producer createProducer() throws Exception { return new CouchDbProducer(this, createClient()); } @Override public boolean isSingleton() { return true; } public Exchange createExchange(String seq, String id, JsonObject obj, boolean deleted) { Exchange exchange = super.createExchange(); exchange.getIn().setHeader(CouchDbConstants.HEADER_DATABASE, database); exchange.getIn().setHeader(CouchDbConstants.HEADER_SEQ, seq); exchange.getIn().setHeader(CouchDbConstants.HEADER_DOC_ID, id); exchange.getIn().setHeader(CouchDbConstants.HEADER_DOC_REV, obj.get("_rev").getAsString()); exchange.getIn().setHeader(CouchDbConstants.HEADER_METHOD, deleted ? "DELETE" : "UPDATE"); exchange.getIn().setBody(obj); return exchange; } protected CouchDbClientWrapper createClient() { return new CouchDbClientWrapper(new CouchDbClient(database, createDatabase, protocol, hostname, port, username, password)); } public String getProtocol() { return protocol; } /** * The protocol to use for communicating with the database. */ public void setProtocol(String protocol) { this.protocol = protocol; } public String getHostname() { return hostname; } /** * Hostname of the running couchdb instance */ public void setHostname(String hostname) { this.hostname = hostname; } public String getStyle() { return style; } /** * Specifies how many revisions are returned in the changes array. * The default, main_only, will only return the current "winning" revision; all_docs will return all leaf revisions (including conflicts and deleted former conflicts.) */ public void setStyle(String style) { this.style = style; } public String getUsername() { return username; } /** * Username in case of authenticated databases */ public void setUsername(String username) { this.username = username; } public String getDatabase() { return database; } /** * Name of the database to use */ public void setDatabase(String database) { this.database = database; } public String getPassword() { return password; } /** * Password for authenticated databases */ public void setPassword(String password) { this.password = password; } public int getPort() { return port; } /** * Port number for the running couchdb instance */ public void setPort(int port) { this.port = port; } public long getHeartbeat() { return heartbeat; } /** * How often to send an empty message to keep socket alive in millis */ public void setHeartbeat(long heartbeat) { this.heartbeat = heartbeat; } public boolean isCreateDatabase() { return createDatabase; } /** * Creates the database if it does not already exist */ public void setCreateDatabase(boolean createDatabase) { this.createDatabase = createDatabase; } public boolean isDeletes() { return deletes; } /** * Document deletes are published as events */ public void setDeletes(boolean deletes) { this.deletes = deletes; } public boolean isUpdates() { return updates; } /** * Document inserts/updates are published as events */ public void setUpdates(boolean updates) { this.updates = updates; } public String getSince() { return since; } /** * Start tracking changes immediately after the given update sequence. * The default, null, will start monitoring from the latest sequence. */ public void setSince(String since) { this.since = since; } }