/** * 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.mongodb.gridfs; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.Mongo; import com.mongodb.MongoClient; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; import com.mongodb.gridfs.GridFS; import org.apache.camel.Consumer; 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.apache.camel.util.CamelContextHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Component for working with MongoDB GridFS. */ @UriEndpoint(firstVersion = "2.18.0", scheme = "mongodb-gridfs", title = "MongoDB GridFS", syntax = "mongodb-gridfs:connectionBean", label = "database,nosql") public class GridFsEndpoint extends DefaultEndpoint { public static final String GRIDFS_OPERATION = "gridfs.operation"; public static final String GRIDFS_METADATA = "gridfs.metadata"; public static final String GRIDFS_CHUNKSIZE = "gridfs.chunksize"; public static final String GRIDFS_FILE_ID_PRODUCED = "gridfs.fileid"; private static final Logger LOG = LoggerFactory.getLogger(GridFsEndpoint.class); @UriPath @Metadata(required = "true") private String connectionBean; @UriParam @Metadata(required = "true") private String database; @UriParam(defaultValue = GridFS.DEFAULT_BUCKET) private String bucket; @UriParam(enums = "ACKNOWLEDGED,W1,W2,W3,UNACKNOWLEDGED,JOURNALED,MAJORITY,SAFE") private WriteConcern writeConcern; @UriParam private WriteConcern writeConcernRef; @UriParam private ReadPreference readPreference; @UriParam(label = "producer") private String operation; @UriParam(label = "consumer") private String query; @UriParam(label = "consumer", defaultValue = "1000") private long initialDelay = 1000; @UriParam(label = "consumer", defaultValue = "500") private long delay = 500; @UriParam(label = "consumer", defaultValue = "TimeStamp") private QueryStrategy queryStrategy = QueryStrategy.TimeStamp; @UriParam(label = "consumer", defaultValue = "camel-timestamps") private String persistentTSCollection = "camel-timestamps"; @UriParam(label = "consumer", defaultValue = "camel-timestamp") private String persistentTSObject = "camel-timestamp"; @UriParam(label = "consumer", defaultValue = "camel-processed") private String fileAttributeName = "camel-processed"; private Mongo mongoConnection; private DB db; private GridFS gridFs; private DBCollection filesCollection; public GridFsEndpoint(String uri, GridFsComponent component) { super(uri, component); } @Override public Producer createProducer() throws Exception { initializeConnection(); return new GridFsProducer(this); } @Override public Consumer createConsumer(Processor processor) throws Exception { initializeConnection(); return new GridFsConsumer(this, processor); } public boolean isSingleton() { return true; } @SuppressWarnings("deprecation") public void initializeConnection() throws Exception { LOG.info("Initialize GridFS endpoint: {}", this.toString()); if (database == null) { throw new IllegalStateException("Missing required endpoint configuration: database"); } db = mongoConnection.getDB(database); if (db == null) { throw new IllegalStateException("Could not initialize GridFsComponent. Database " + database + " does not exist."); } gridFs = new GridFS(db, bucket == null ? GridFS.DEFAULT_BUCKET : bucket) { { filesCollection = getFilesCollection(); } }; } @Override protected void doStart() throws Exception { if (writeConcern != null && writeConcernRef != null) { String msg = "Cannot set both writeConcern and writeConcernRef at the same time. Respective values: " + writeConcern + ", " + writeConcernRef + ". Aborting initialization."; throw new IllegalArgumentException(msg); } mongoConnection = CamelContextHelper.mandatoryLookup(getCamelContext(), connectionBean, MongoClient.class); LOG.debug("Resolved the connection with the name {} as {}", connectionBean, mongoConnection); setWriteReadOptionsOnConnection(); super.doStart(); } @Override protected void doStop() throws Exception { super.doStop(); if (mongoConnection != null) { LOG.debug("Closing connection"); mongoConnection.close(); } } private void setWriteReadOptionsOnConnection() { // Set the WriteConcern if (writeConcern != null) { mongoConnection.setWriteConcern(writeConcern); } else if (writeConcernRef != null) { mongoConnection.setWriteConcern(writeConcernRef); } // Set the ReadPreference if (readPreference != null) { mongoConnection.setReadPreference(readPreference); } } // ======= Getters and setters =============================================== public String getConnectionBean() { return connectionBean; } /** * Name of {@link com.mongodb.Mongo} to use. */ public void setConnectionBean(String connectionBean) { this.connectionBean = connectionBean; } public Mongo getMongoConnection() { return mongoConnection; } /** * Sets the Mongo instance that represents the backing connection * * @param mongoConnection the connection to the database */ public void setMongoConnection(Mongo mongoConnection) { this.mongoConnection = mongoConnection; } public DB getDB() { return db; } public String getDatabase() { return database; } /** * Sets the name of the MongoDB database to target * * @param database name of the MongoDB database */ public void setDatabase(String database) { this.database = database; } /** * Sets the name of the GridFS bucket within the database. Default is "fs". * * @param database name of the MongoDB database */ public String getBucket() { return bucket; } public void setBucket(String bucket) { this.bucket = bucket; } public String getQuery() { return query; } /** * Additional query parameters (in JSON) that are used to configure the query used for finding * files in the GridFsConsumer * @param query */ public void setQuery(String query) { this.query = query; } public long getDelay() { return delay; } /** * Sets the delay between polls within the Consumer. Default is 500ms * @param delay */ public void setDelay(long delay) { this.delay = delay; } public long getInitialDelay() { return initialDelay; } /** * Sets the initialDelay before the consumer will start polling. Default is 1000ms * @param initialDelay */ public void setInitialDelay(long initialDelay) { this.initialDelay = delay; } /** * Sets the QueryStrategy that is used for polling for new files. Default is Timestamp * @see QueryStrategy * @param s */ public void setQueryStrategy(String s) { queryStrategy = QueryStrategy.valueOf(s); } public QueryStrategy getQueryStrategy() { return queryStrategy; } /** * If the QueryType uses a persistent timestamp, this sets the name of the collection within * the DB to store the timestamp. * @param s */ public void setPersistentTSCollection(String s) { persistentTSCollection = s; } public String getPersistentTSCollection() { return persistentTSCollection; } /** * If the QueryType uses a persistent timestamp, this is the ID of the object in the collection * to store the timestamp. * @param s */ public void setPersistentTSObject(String id) { persistentTSObject = id; } public String getPersistentTSObject() { return persistentTSObject; } /** * If the QueryType uses a FileAttribute, this sets the name of the attribute that is used. Default is "camel-processed". * @param f */ public void setFileAttributeName(String f) { fileAttributeName = f; } public String getFileAttributeName() { return fileAttributeName; } /** * Set the {@link WriteConcern} for write operations on MongoDB using the standard ones. * Resolved from the fields of the WriteConcern class by calling the {@link WriteConcern#valueOf(String)} method. * * @param writeConcern the standard name of the WriteConcern * @see <a href="http://api.mongodb.org/java/current/com/mongodb/WriteConcern.html#valueOf(java.lang.String)">possible options</a> */ public void setWriteConcern(String writeConcern) { this.writeConcern = WriteConcern.valueOf(writeConcern); } public WriteConcern getWriteConcern() { return writeConcern; } /** * Set the {@link WriteConcern} for write operations on MongoDB, passing in the bean ref to a custom WriteConcern which exists in the Registry. * You can also use standard WriteConcerns by passing in their key. See the {@link #setWriteConcern(String) setWriteConcern} method. * * @param writeConcernRef the name of the bean in the registry that represents the WriteConcern to use */ public void setWriteConcernRef(String writeConcernRef) { WriteConcern wc = this.getCamelContext().getRegistry().lookupByNameAndType(writeConcernRef, WriteConcern.class); if (wc == null) { String msg = "Camel MongoDB component could not find the WriteConcern in the Registry. Verify that the " + "provided bean name (" + writeConcernRef + ") is correct. Aborting initialization."; throw new IllegalArgumentException(msg); } this.writeConcernRef = wc; } public WriteConcern getWriteConcernRef() { return writeConcernRef; } /** * Sets a MongoDB {@link ReadPreference} on the Mongo connection. Read preferences set directly on the connection will be * overridden by this setting. * <p/> * The {@link com.mongodb.ReadPreference#valueOf(String)} utility method is used to resolve the passed {@code readPreference} * value. Some examples for the possible values are {@code nearest}, {@code primary} or {@code secondary} etc. * * @param readPreference the name of the read preference to set */ public void setReadPreference(String readPreference) { this.readPreference = ReadPreference.valueOf(readPreference); } public ReadPreference getReadPreference() { return readPreference; } /** * Sets the operation this endpoint will execute against GridRS. */ public void setOperation(String operation) { this.operation = operation; } public String getOperation() { return operation; } public GridFS getGridFs() { return gridFs; } public void setGridFs(GridFS gridFs) { this.gridFs = gridFs; } public DBCollection getFilesCollection() { return filesCollection; } }