/*
* Copyright 2011-2017 the original author or authors.
*
* Licensed 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.springframework.data.mongodb.gridfs;
import static org.springframework.data.mongodb.core.query.Query.*;
import static org.springframework.data.mongodb.gridfs.GridFsCriteria.*;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.bson.BsonObjectId;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.convert.QueryMapper;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import com.mongodb.client.gridfs.GridFSFindIterable;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.mongodb.client.gridfs.model.GridFSUploadOptions;
/**
* {@link GridFsOperations} implementation to store content into MongoDB GridFS.
*
* @author Oliver Gierke
* @author Philipp Schneider
* @author Thomas Darimont
* @author Martin Baumgartner
* @author Christoph Strobl
* @author Mark Paluch
*/
public class GridFsTemplate implements GridFsOperations, ResourcePatternResolver {
private final MongoDbFactory dbFactory;
private final String bucket;
private final MongoConverter converter;
private final QueryMapper queryMapper;
/**
* Creates a new {@link GridFsTemplate} using the given {@link MongoDbFactory} and {@link MongoConverter}.
*
* @param dbFactory must not be {@literal null}.
* @param converter must not be {@literal null}.
*/
public GridFsTemplate(MongoDbFactory dbFactory, MongoConverter converter) {
this(dbFactory, converter, null);
}
/**
* Creates a new {@link GridFsTemplate} using the given {@link MongoDbFactory} and {@link MongoConverter}.
*
* @param dbFactory must not be {@literal null}.
* @param converter must not be {@literal null}.
* @param bucket
*/
public GridFsTemplate(MongoDbFactory dbFactory, MongoConverter converter, String bucket) {
Assert.notNull(dbFactory, "MongoDbFactory must not be null!");
Assert.notNull(converter, "MongoConverter must not be null!");
this.dbFactory = dbFactory;
this.converter = converter;
this.bucket = bucket;
this.queryMapper = new QueryMapper(converter);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String)
*/
public ObjectId store(InputStream content, String filename) {
return store(content, filename, (Object) null);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.Object)
*/
@Override
public ObjectId store(InputStream content, Object metadata) {
return store(content, null, metadata);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, com.mongodb.Document)
*/
@Override
public ObjectId store(InputStream content, Document metadata) {
return store(content, null, metadata);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.String)
*/
public ObjectId store(InputStream content, String filename, String contentType) {
return store(content, filename, contentType, (Object) null);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.Object)
*/
public ObjectId store(InputStream content, String filename, Object metadata) {
return store(content, filename, null, metadata);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.String, java.lang.Object)
*/
public ObjectId store(InputStream content, String filename, String contentType, Object metadata) {
Document document = null;
if (metadata != null) {
document = new Document();
converter.write(metadata, document);
}
return store(content, filename, contentType, document);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, com.mongodb.Document)
*/
public ObjectId store(InputStream content, String filename, Document metadata) {
return this.store(content, filename, null, metadata);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, com.mongodb.Document)
*/
public ObjectId store(InputStream content, String filename, String contentType, Document metadata) {
Assert.notNull(content, "InputStream must not be null!");
GridFSUploadOptions opts = new GridFSUploadOptions();
Document mData = new Document();
if (StringUtils.hasText(contentType)) {
mData.put("type", contentType);
}
if (metadata != null) {
mData.putAll(metadata);
}
opts.metadata(mData);
return getGridFs().uploadFromStream(filename, content, opts);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#find(com.mongodb.Document)
*/
public GridFSFindIterable find(Query query) {
if (query == null) {
return getGridFs().find(new Document());
}
Document queryObject = getMappedQuery(query.getQueryObject());
Document sortObject = getMappedQuery(query.getSortObject());
return getGridFs().find(queryObject).sort(sortObject);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#findOne(com.mongodb.Document)
*/
public GridFSFile findOne(Query query) {
return find(query).first();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#delete(org.springframework.data.mongodb.core.query.Query)
*/
public void delete(Query query) {
for (GridFSFile x : find(query)) {
getGridFs().delete(((BsonObjectId) x.getId()).getValue());
}
}
/*
* (non-Javadoc)
* @see org.springframework.core.io.ResourceLoader#getClassLoader()
*/
public ClassLoader getClassLoader() {
return dbFactory.getClass().getClassLoader();
}
/*
* (non-Javadoc)
* @see org.springframework.core.io.ResourceLoader#getResource(java.lang.String)
*/
public GridFsResource getResource(String location) {
GridFSFile file = findOne(query(whereFilename().is(location)));
return file != null ? new GridFsResource(file, getGridFs().openDownloadStreamByName(location)) : null;
}
/*
* (non-Javadoc)
* @see org.springframework.core.io.support.ResourcePatternResolver#getResources(java.lang.String)
*/
public GridFsResource[] getResources(String locationPattern) {
if (!StringUtils.hasText(locationPattern)) {
return new GridFsResource[0];
}
AntPath path = new AntPath(locationPattern);
if (path.isPattern()) {
GridFSFindIterable files = find(query(whereFilename().regex(path.toRegex())));
List<GridFsResource> resources = new ArrayList<GridFsResource>();
for (GridFSFile file : files) {
resources.add(new GridFsResource(file, getGridFs().openDownloadStreamByName(file.getFilename())));
}
return resources.toArray(new GridFsResource[resources.size()]);
}
return new GridFsResource[] { getResource(locationPattern) };
}
private Document getMappedQuery(Query query) {
return query == null ? new Query().getQueryObject() : getMappedQuery(query.getQueryObject());
}
private Document getMappedQuery(Document query) {
return query == null ? null : queryMapper.getMappedObject(query, Optional.empty());
}
private GridFSBucket getGridFs() {
MongoDatabase db = dbFactory.getDb();
return bucket == null ? GridFSBuckets.create(db) : GridFSBuckets.create(db, bucket);
}
}