package com.github.mongorest.service;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import com.github.mongorest.exception.AuthenticationException;
import com.github.mongorest.exception.AuthorizationException;
import com.github.mongorest.security.Credentials;
import com.github.mongorest.util.Configuration;
import com.github.mongorest.util.HttpStatusMapper;
import com.github.mongorest.util.Utils;
import com.github.mongorest.util.HttpStatusMapper.ClientError;
import com.github.mongorest.util.HttpStatusMapper.ServerError;
import com.github.mongorest.util.HttpStatusMapper.Successful;
import com.github.mongorest.util.Utils.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.MongoException.DuplicateKey;
import com.mongodb.WriteConcern;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSInputFile;
import com.mongodb.util.JSON;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.spi.resource.Singleton;
@Singleton
@Path("/api/mongo")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class MongoRestServiceImpl implements MongoRestService {
private Logger logger = LoggerFactory.getLogger(MongoRestServiceImpl.class);
private static final String STATS_DB = "stats";
private static final String STATS_USER_COLLECTION = "byUser";
private static final String STATS_USER_KEY = "user";
private static final String STATS_OP_KEY = "op";
private static final String STATS_COUNT_KEY = "count";
private static final String SYS_INDEXES_COLLECTION = "system.indexes";
private static final String FILTERED_INDEX = "_id_";
private volatile boolean shutdown;
private Configuration configuration;
private Mongo mongo;
private GridFS gridFs;
private DBCollection statsByUser;
@POST
@Path("/databases")
@Override
public Response createDatabase(com.github.mongorest.to.request.Database database, @Context HttpHeaders headers,
@Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbName = constructDbNamespace(credentials.getUserName(), database.getName());
if (mongo.getDatabaseNames().contains(dbName)) {
return Response.status(HttpStatusMapper.ClientError.ALREADY_EXISTS.code()).build();
}
DB db = mongo.getDB(dbName);
authServiceAgainstMongo(db);
if (database.getWriteConcern() != null) {
db.setWriteConcern(database.getWriteConcern().getMongoWriteConcern());
} else {
db.setWriteConcern(WriteConcern.FSYNC_SAFE);
}
DBCollection localStats = db.getCollection(STATS_USER_COLLECTION);
DBObject statsIndex = new BasicDBObject();
statsIndex.put(STATS_OP_KEY, 1);
localStats.ensureIndex(statsIndex, null, true);
URI statusSubResource = uriInfo.getBaseUriBuilder().path(MongoRestServiceImpl.class)
.path("/databases/" + database.getName()).build();
response = Response.created(statusSubResource).build();
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "createDatabase");
}
return response;
}
@PUT
@Path("/databases/{dbName}")
@Override
public Response updateDatabase(com.github.mongorest.to.request.Database database,
@PathParam("dbName") String dbName, @Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
boolean created = true;
if (mongo.getDatabaseNames().contains(dbNamespace)) {
created = false;
}
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (database.getWriteConcern() != null) {
db.setWriteConcern(database.getWriteConcern().getMongoWriteConcern());
}
URI statusSubResource = uriInfo.getBaseUriBuilder().path(MongoRestServiceImpl.class)
.path("/databases/" + dbName).build();
if (created) {
DBCollection localStats = db.getCollection(STATS_USER_COLLECTION);
DBObject statsIndex = new BasicDBObject();
statsIndex.put(STATS_OP_KEY, 1);
localStats.ensureIndex(statsIndex, null, true);
response = Response.created(statusSubResource).build();
} else {
response = Response.ok(statusSubResource).build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "updateDatabase");
}
return response;
}
@DELETE
@Path("/databases/{dbName}")
@Override
public Response deleteDatabase(@PathParam("dbName") String dbName, @Context HttpHeaders headers,
@Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
mongo.dropDatabase(dbNamespace);
response = Response.ok().build();
} else {
response = Response.status(ClientError.NOT_FOUND.code()).build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "deleteDatabase");
}
return response;
}
@GET
@Path("/databases/{dbName}")
@Override
public Response findDatabase(@PathParam("dbName") String dbName,
@QueryParam("collDetails") @DefaultValue("false") boolean collDetails, @Context HttpHeaders headers,
@Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
com.github.mongorest.to.response.Database database = searchDatabase(dbName, dbNamespace, collDetails);
response = Response.ok(database).build();
} else {
response = Response.status(ClientError.NOT_FOUND.code()).build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "findDatabase");
}
return response;
}
@GET
@Path("/databases")
@Override
public Response findDatabases(@QueryParam("collDetails") @DefaultValue("false") boolean collDetails,
@Context HttpHeaders headers, @Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
List<com.github.mongorest.to.response.Database> databases = new ArrayList<com.github.mongorest.to.response.Database>();
String dbNamePrefix = "dbs:" + credentials.getUserName();
for (String dbName : mongo.getDatabaseNames()) {
if (dbName.startsWith(dbNamePrefix)) {
com.github.mongorest.to.response.Database database = searchDatabase(
dbName.substring(dbNamePrefix.length() + 1), dbName, collDetails);
databases.add(database);
}
}
response = Response.ok(databases).build();
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "findDatabases");
}
return response;
}
@DELETE
@Path("/databases")
@Override
public Response deleteDatabases(@Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
List<String> databases = new ArrayList<String>();
String dbNamePrefix = "dbs:" + credentials.getUserName();
for (String dbName : mongo.getDatabaseNames()) {
if (dbName.startsWith(dbNamePrefix)) {
mongo.dropDatabase(dbName);
databases.add(dbName.substring(dbNamePrefix.length() + 1));
}
}
response = Response.ok("Deleted databases: " + databases).build();
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "deleteDatabases");
}
return response;
}
@POST
@Path("/databases/{dbName}/collections")
@Override
public Response createCollection(@PathParam("dbName") String dbName,
com.github.mongorest.to.request.Collection collection, @Context HttpHeaders headers,
@Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
DBObject options = new BasicDBObject();
options.put("max", configuration.getMaxDocsPerCollection());
DBCollection dbCollection = db.createCollection(collection.getName(), options);
if (collection.getWriteConcern() != null) {
dbCollection.setWriteConcern(collection.getWriteConcern().getMongoWriteConcern());
}
URI statusSubResource = uriInfo.getBaseUriBuilder().path(MongoRestServiceImpl.class)
.path("/databases/" + dbName + "/collections/" + collection.getName()).build();
response = Response.created(statusSubResource).build();
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "createCollection");
}
return response;
}
@GET
@Path("/databases/{dbName}/collections/{collName}")
@Override
public Response findCollection(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@Context HttpHeaders headers, @Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
com.github.mongorest.to.response.Collection collection = searchCollection(collName, dbName, db);
response = Response.ok(collection).build();
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "findCollection");
}
return response;
}
@PUT
@Path("/databases/{dbName}/collections/{collName}")
@Override
public Response updateCollection(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
com.github.mongorest.to.request.Collection collection, @Context HttpHeaders headers,
@Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
DBCollection dbCollection = null;
if (mongo.getDatabaseNames().contains(dbNamespace)) {
URI statusSubResource = uriInfo.getBaseUriBuilder().path(MongoRestServiceImpl.class)
.path("/databases/" + dbName + "/collections/" + collection.getName()).build();
if (db.getCollectionNames().contains(collection.getName())) {
dbCollection = db.getCollection(collection.getName());
if (collection.getWriteConcern() != null) {
dbCollection.setWriteConcern(collection.getWriteConcern().getMongoWriteConcern());
}
response = Response.ok(statusSubResource).build();
} else {
DBObject options = new BasicDBObject();
options.put("max", configuration.getMaxDocsPerCollection());
dbCollection = db.createCollection(collection.getName(), options);
if (collection.getWriteConcern() != null) {
dbCollection.setWriteConcern(collection.getWriteConcern().getMongoWriteConcern());
}
response = Response.created(statusSubResource).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "updateCollection");
}
return response;
}
@DELETE
@Path("/databases/{dbName}/collections/{collName}")
@Override
public Response deleteCollection(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@Context HttpHeaders headers, @Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection collection = db.getCollection(collName);
collection.dropIndexes();
collection.drop();
response = Response.ok().build();
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "deleteCollection");
}
return response;
}
@GET
@Path("/databases/{dbName}/collections")
@Override
public Response findCollections(@PathParam("dbName") String dbName, @Context HttpHeaders headers,
@Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
List<com.github.mongorest.to.response.Collection> collections = new ArrayList<com.github.mongorest.to.response.Collection>();
for (String collName : db.getCollectionNames()) {
if (SYS_INDEXES_COLLECTION.equals(collName) || STATS_USER_COLLECTION.equals(collName)) {
continue;
}
com.github.mongorest.to.response.Collection collection = searchCollection(collName, dbName, db);
collections.add(collection);
}
response = Response.ok(collections).build();
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "findCollections");
}
return response;
}
@DELETE
@Path("/databases/{dbName}/collections")
@Override
public Response deleteCollections(@PathParam("dbName") String dbName, @Context HttpHeaders headers,
@Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
List<String> collections = new ArrayList<String>();
for (String collName : db.getCollectionNames()) {
if (collName.equals(SYS_INDEXES_COLLECTION)) {
continue;
}
collections.add(collName);
DBCollection collection = db.getCollection(collName);
collection.dropIndexes();
collection.drop();
}
response = Response.ok("Deleted collections: " + collections).build();
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "deleteCollections");
}
return response;
}
@POST
@Path("/databases/{dbName}/collections/{collName}/indexes")
@Override
public Response createIndex(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
com.github.mongorest.to.request.Index index, @Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
List<String> keys = index.getKeys();
if (keys != null && !keys.isEmpty()) {
DBObject keysObject = new BasicDBObject();
for (String key : keys) {
if (!StringUtils.isNullOrEmpty(key)) {
keysObject.put(key, 1);
}
}
dbCollection.ensureIndex(keysObject, index.getName(), index.isUnique());
URI statusSubResource = uriInfo
.getBaseUriBuilder()
.path(MongoRestServiceImpl.class)
.path("/databases/" + dbName + "/collections/" + collName + "/indexes/"
+ index.getName()).build();
response = Response.created(statusSubResource).build();
} else {
response = Response.status(ClientError.BAD_REQUEST.code())
.entity("Cannot create an index with unspecified keys").build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "createIndex");
}
return response;
}
@SuppressWarnings("unchecked")
@GET
@Path("/databases/{dbName}/collections/{collName}/indexes/{indexName}")
@Override
public Response findIndex(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@PathParam("indexName") String indexName, @Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
List<DBObject> indexInfos = dbCollection.getIndexInfo();
boolean indexFound = false;
com.github.mongorest.to.response.Index foundIndex = new com.github.mongorest.to.response.Index();
for (DBObject indexInfo : indexInfos) {
String foundIndexName = (String) indexInfo.get("name");
if (foundIndexName.equals(indexName)) {
Map<String, Object> keys = (Map<String, Object>) indexInfo.get("key");
foundIndex.setName(indexName);
foundIndex.setCollectionName(collName);
foundIndex.setDbName(dbName);
foundIndex.setKeys(keys.keySet());
foundIndex.setUnique((Boolean) indexInfo.get("unique"));
indexFound = true;
break;
}
}
if (indexFound) {
response = Response.ok(foundIndex).build();
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(indexName + " does not exist for " + collName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "findIndex");
}
return response;
}
@DELETE
@Path("/databases/{dbName}/collections/{collName}/indexes/{indexName}")
@Override
public Response deleteIndex(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@PathParam("indexName") String indexName, @Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
List<DBObject> indexInfos = dbCollection.getIndexInfo();
boolean indexFound = false;
for (DBObject indexInfo : indexInfos) {
String foundIndexName = (String) indexInfo.get("name");
if (foundIndexName.equals(indexName)) {
indexFound = true;
dbCollection.dropIndex(indexName);
break;
}
}
if (indexFound) {
response = Response.ok().build();
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(indexName + " does not exist for " + collName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "deleteIndex");
}
return response;
}
@SuppressWarnings("unchecked")
@GET
@Path("/databases/{dbName}/collections/{collName}/indexes")
@Override
public Response findIndexes(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@Context HttpHeaders headers, @Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
List<com.github.mongorest.to.response.Index> indexes = new ArrayList<com.github.mongorest.to.response.Index>();
for (DBObject indexInfo : dbCollection.getIndexInfo()) {
String indexName = (String) indexInfo.get("name");
if (FILTERED_INDEX.equals(indexName)) {
continue;
}
com.github.mongorest.to.response.Index index = new com.github.mongorest.to.response.Index();
index.setName(indexName);
index.setCollectionName(collName);
index.setDbName(dbName);
index.setUnique((Boolean) indexInfo.get("unique"));
Map<String, Object> keys = (Map<String, Object>) indexInfo.get("key");
index.setKeys(keys.keySet());
indexes.add(index);
}
response = Response.ok(indexes).build();
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "findIndexes");
}
return response;
}
@DELETE
@Path("/databases/{dbName}/collections/{collName}/indexes")
@Override
public Response deleteIndexes(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@Context HttpHeaders headers, @Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
List<DBObject> indexInfos = dbCollection.getIndexInfo();
List<String> indexNames = new ArrayList<String>();
for (DBObject indexInfo : indexInfos) {
String indexName = (String) indexInfo.get("name");
if (FILTERED_INDEX.equals(indexName)) {
continue;
}
indexNames.add(indexName);
dbCollection.dropIndex(indexName);
}
response = Response.ok("Deleted indexes: " + indexNames).build();
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "deleteIndexes");
}
return response;
}
@POST
@Path("/databases/{dbName}/collections/{collName}/documents")
@Override
public Response createDocument(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
com.github.mongorest.to.request.Document document, @Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
String documentJson = document.getJson();
if (!StringUtils.isNullOrEmpty(documentJson)) {
DBObject mongoDocument = (DBObject) JSON.parse(document.getJson());
try {
dbCollection.insert(mongoDocument, WriteConcern.SAFE);
ObjectId documentId = ((ObjectId) mongoDocument.get("_id"));
if (documentId != null && !StringUtils.isNullOrEmpty(documentId.toString())) {
URI statusSubResource = uriInfo
.getBaseUriBuilder()
.path(MongoRestServiceImpl.class)
.path("/databases/" + dbName + "/collections/" + collName + "/documents/"
+ documentId).build();
response = Response.created(statusSubResource).build();
} else {
response = Response.status(ServerError.RUNTIME_ERROR.code())
.entity(ServerError.RUNTIME_ERROR.message()).build();
}
} catch (DuplicateKey duplicateObject) {
response = Response.status(ClientError.BAD_REQUEST.code())
.entity("Document already exists and could not be created").build();
}
} else {
response = Response.status(ClientError.BAD_REQUEST.code()).entity("Document JSON is required")
.build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "createDocument");
}
return response;
}
@GET
@Path("/databases/{dbName}/collections/{collName}/documents/{docId}")
@Override
public Response findDocument(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@PathParam("docId") String docId, @Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
DBObject query = new BasicDBObject();
query.put("_id", new ObjectId(docId));
DBObject found = dbCollection.findOne(query);
if (found != null) {
com.github.mongorest.to.response.Document document = new com.github.mongorest.to.response.Document();
document.setJson(JSON.serialize(found));
response = Response.ok(document).build();
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(docId + " does not exist in " + collName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "findDocument");
}
return response;
}
@PUT
@Path("/databases/{dbName}/collections/{collName}/documents/{docId}")
@Override
public Response updateDocument(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@PathParam("docId") String docId, com.github.mongorest.to.request.Document document,
@Context HttpHeaders headers, @Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
String documentJson = document.getJson();
if (!StringUtils.isNullOrEmpty(documentJson)) {
DBObject incomingDocument = (DBObject) JSON.parse(documentJson);
DBObject query = new BasicDBObject();
query.put("_id", new ObjectId(docId));
DBObject persistedDocument = dbCollection.findOne(query);
URI statusSubResource = null;
try {
if (persistedDocument == null) {
dbCollection.insert(incomingDocument, WriteConcern.SAFE);
statusSubResource = uriInfo
.getBaseUriBuilder()
.path(MongoRestServiceImpl.class)
.path("/databases/" + dbName + "/collections/" + collName + "/documents/"
+ ((DBObject) incomingDocument.get("_id"))).build();
response = Response.created(statusSubResource).build();
} else {
dbCollection.save(incomingDocument);
statusSubResource = uriInfo
.getBaseUriBuilder()
.path(MongoRestServiceImpl.class)
.path("/databases/" + dbName + "/collections/" + collName + "/documents/"
+ docId).build();
response = Response.ok(statusSubResource).build();
}
} catch (DuplicateKey duplicateObject) {
response = Response.status(ClientError.BAD_REQUEST.code())
.entity("Document already exists and could not be created").build();
}
} else {
response = Response.status(ClientError.BAD_REQUEST.code()).entity("Document JSON is required")
.build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "updateDocument");
}
return response;
}
@DELETE
@Path("/databases/{dbName}/collections/{collName}/documents/{docId}")
@Override
public Response deleteDocument(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@PathParam("docId") String docId, @Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
if (!StringUtils.isNullOrEmpty(docId)) {
DBObject query = new BasicDBObject();
query.put("_id", new ObjectId(docId));
dbCollection.remove(query);
response = Response.ok().build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "deleteDocument");
}
return response;
}
@GET
@Path("/databases/{dbName}/collections/{collName}/documents")
@Override
public Response findDocuments(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@Context HttpHeaders headers, @Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
List<com.github.mongorest.to.response.Document> documents = new ArrayList<com.github.mongorest.to.response.Document>();
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
DBCursor cursor = dbCollection.find();
while (cursor.hasNext()) {
DBObject found = cursor.next();
if (found != null) {
com.github.mongorest.to.response.Document document = new com.github.mongorest.to.response.Document();
document.setJson(JSON.serialize(found));
documents.add(document);
}
}
response = Response.ok(documents).build();
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "findDocuments");
}
return response;
}
@DELETE
@Path("/databases/{dbName}/collections/{collName}/documents")
@Override
public Response deleteDocuments(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
@Context HttpHeaders headers, @Context UriInfo uriInfo, @Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
String dbNamespace = constructDbNamespace(credentials.getUserName(), dbName);
if (mongo.getDatabaseNames().contains(dbNamespace)) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
if (db.getCollectionNames().contains(collName)) {
DBCollection dbCollection = db.getCollection(collName);
DBCursor cursor = dbCollection.find();
while (cursor.hasNext()) {
DBObject found = cursor.next();
if (found != null) {
dbCollection.remove(found);
}
}
response = Response.ok().build();
} else {
response = Response.status(ClientError.NOT_FOUND.code())
.entity(collName + " does not exist in " + dbName).build();
}
} else {
response = Response.status(ClientError.NOT_FOUND.code()).entity(dbName + " does not exist").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "deleteDocuments");
}
return response;
}
@GET
@Path("/ping")
@Override
public Response ping(@Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
boolean alive = !shutdown && mongo.getConnector().isOpen();
if (alive) {
updateStats(user, "ping");
}
response = alive ? Response.ok().entity(Successful.SERVICE_ALIVE.message()).build() : Response
.status(ServerError.SERVICE_UNAVAILABLE.code()).entity(ServerError.SERVICE_UNAVAILABLE.message())
.build();
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
}
return response;
}
@GET
@Path("/shutdown")
@Override
public Response shutdown(@Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
// wire shiro to allow only privileged users to shutdown service
Response response = null;
try {
if (!shutdown) {
shutdown = true;
if (mongo.getConnector().isOpen()) {
updateStats(authenticateAndAuthorize(headers, uriInfo, securityContext).getUserName(), "shutdown");
mongo.close();
response = Response.ok().build();
} else {
response = Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
} else {
response = Response.notModified("Service is already shutdown.").build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
}
return response;
}
@POST
@Consumes("multipart/form-data")
@Path("/databases/{dbName}/collections/{collName}/binary")
@Override
public Response createBinaryDocument(@PathParam("dbName") String dbName, @PathParam("collName") String collName,
FormDataMultiPart document, @Context HttpHeaders headers, @Context UriInfo uriInfo,
@Context SecurityContext securityContext) {
if (shutdown) {
return Response.status(ServerError.SERVICE_UNAVAILABLE.code())
.entity(ServerError.SERVICE_UNAVAILABLE.message()).build();
}
Response response = null;
String user = null;
try {
Credentials credentials = authenticateAndAuthorize(headers, uriInfo, securityContext);
user = credentials.getUserName();
FormDataBodyPart file = document.getField("file");
String fileName = file.getContentDisposition().getFileName();
InputStream fileStream = file.getEntityAs(InputStream.class);
GridFSInputFile gridfsFile = gridFs.createFile(fileStream);
gridfsFile.setFilename(fileName);
gridfsFile.save();
ObjectId documentId = (ObjectId) gridfsFile.getId();
if (documentId != null && !StringUtils.isNullOrEmpty(documentId.toString())) {
URI statusSubResource = uriInfo.getBaseUriBuilder().path(MongoRestServiceImpl.class)
.path("/databases/" + dbName + "/collections/" + collName + "/binary/" + documentId).build();
response = Response.created(statusSubResource).build();
} else {
response = Response.status(ServerError.RUNTIME_ERROR.code())
.entity(ServerError.RUNTIME_ERROR.message()).build();
}
} catch (Exception exception) {
response = lobException(exception, headers, uriInfo);
} finally {
updateStats(user, "createBinaryDocument");
}
return response;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private com.github.mongorest.to.response.Database searchDatabase(String dbName, String dbNamespace,
boolean collDetails) {
DB db = mongo.getDB(dbNamespace);
authServiceAgainstMongo(db);
com.github.mongorest.to.response.Database database = new com.github.mongorest.to.response.Database();
database.setName(dbName);
database.setWriteConcern(com.github.mongorest.to.response.WriteConcern.fromMongoWriteConcern(db
.getWriteConcern()));
Map statsMap = db.getStats().toMap();
statsMap.remove("db");
database.setStats(Utils.CollectionUtils.stringifyMapEntries(statsMap));
if (collDetails) {
List<com.github.mongorest.to.response.Collection> collections = new ArrayList<com.github.mongorest.to.response.Collection>();
for (String collName : db.getCollectionNames()) {
if (collName.equals(SYS_INDEXES_COLLECTION) || collName.equals(STATS_USER_COLLECTION)) {
continue;
}
com.github.mongorest.to.response.Collection collection = searchCollection(collName, dbName, db);
collections.add(collection);
}
database.setCollections(collections);
}
return database;
}
@SuppressWarnings("unchecked")
private com.github.mongorest.to.response.Collection searchCollection(String collName, String dbName, DB db) {
DBCollection dbCollection = db.getCollection(collName);
com.github.mongorest.to.response.Collection collection = new com.github.mongorest.to.response.Collection();
collection.setDbName(dbName);
collection.setName(collName);
collection.setWriteConcern(com.github.mongorest.to.response.WriteConcern.fromMongoWriteConcern(dbCollection
.getWriteConcern()));
List<DBObject> indexInfos = dbCollection.getIndexInfo();
List<com.github.mongorest.to.response.Index> indexes = new ArrayList<com.github.mongorest.to.response.Index>();
for (DBObject indexInfo : indexInfos) {
Map<String, Object> indexed = (Map<String, Object>) indexInfo.get("key");
if (indexed != null) {
com.github.mongorest.to.response.Index index = new com.github.mongorest.to.response.Index();
index.setDbName(dbName);
index.setCollectionName(collName);
index.setKeys(indexed.keySet());
indexes.add(index);
}
}
collection.setIndexes(indexes);
List<com.github.mongorest.to.response.Document> documents = new ArrayList<com.github.mongorest.to.response.Document>();
DBCursor cursor = dbCollection.find();
while (cursor.hasNext()) {
com.github.mongorest.to.response.Document document = new com.github.mongorest.to.response.Document();
DBObject dbDoc = cursor.next();
document.setJson(dbDoc.toString());
documents.add(document);
}
collection.setDocuments(documents);
return collection;
}
/**
* 1. Authenticate and Authorize (SAC) via SecurityService<br>
* 2. Maintain cached Lease/Client on Server-side
**/
private Credentials authenticateAndAuthorize(HttpHeaders headers, UriInfo uriInfo, SecurityContext securityContext)
throws AuthenticationException, AuthorizationException {
if (logger.isDebugEnabled()) {
logRequestContext(headers, uriInfo);
}
String username = null, password = null;
List<String> requestHeader = headers.getRequestHeader("authorization");
try {
for (String authHeader : requestHeader) {
String[] pieces = authHeader.split(" ");
if ("basic".equalsIgnoreCase(pieces[0].trim())) {
String[] userPasswd = Utils.EncodingUtils.decodeBase64(pieces[1].trim()).split(":");
username = userPasswd[0].trim().toLowerCase();
password = userPasswd[1].trim();
break;
}
}
} catch (Exception exception) {
throw new AuthenticationException(
"Mongo Data Service expects Base64 encoded Authorization header containing username and password",
exception);
}
if (Utils.StringUtils.isNullOrEmpty(username) || Utils.StringUtils.isNullOrEmpty(password)) {
throw new AuthenticationException(
"Mongo Data Service expects Base64 encoded Authorization header containing username and password");
}
String userIP = null;
requestHeader = headers.getRequestHeader("x-real-ip");
if (requestHeader != null && !requestHeader.isEmpty()) {
userIP = requestHeader.get(0);
}
String userAgent = null;
requestHeader = headers.getRequestHeader("user-agent");
if (requestHeader != null && !requestHeader.isEmpty()) {
userAgent = requestHeader.get(0);
}
return new Credentials(null, null, username, password, userIP, userAgent, uriInfo.getRequestUri().toString());
}
private void authServiceAgainstMongo(final DB db) throws MongoException {
if (!db.isAuthenticated() && !StringUtils.isNullOrEmpty(configuration.getDataStoreUsername())
&& !StringUtils.isNullOrEmpty(configuration.getDataStorePassword())) {
db.authenticate(configuration.getDataStoreUsername(), configuration.getDataStorePassword().toCharArray());
}
}
private void logError(String message, Throwable exception, HttpHeaders headers, UriInfo uriInfo) {
logRequestContext(headers, uriInfo);
logger.error(message, exception);
}
private void logRequestContext(HttpHeaders headers, UriInfo uriInfo) {
MultivaluedMap<String, String> headerParams = headers.getRequestHeaders();
StringBuffer buffer = new StringBuffer("Headers=");
for (Entry<String, List<String>> header : headerParams.entrySet()) {
buffer.append(header.getKey()).append("=").append(header.getValue()).append(" ");
}
buffer.append("uri=").append(uriInfo.getRequestUri());
logger.debug(buffer.toString());
}
private Response lobException(Exception exception, HttpHeaders headers, UriInfo uriInfo) {
Response response = null;
if (exception instanceof AuthenticationException || exception instanceof AuthorizationException) {
logError("Service failure: user-auth", exception, headers, uriInfo);
response = Response.status(ClientError.UNAUTHORIZED.code()).entity(ClientError.UNAUTHORIZED.message())
.build();
} else if (exception instanceof MongoException) {
logError("Service failure: mongo-persistence", exception, headers, uriInfo);
response = Response.status(ServerError.RUNTIME_ERROR.code()).entity(ServerError.RUNTIME_ERROR.message())
.build();
} else {
logError("Service failure: see-stacktrace", exception, headers, uriInfo);
response = Response.status(ServerError.RUNTIME_ERROR.code()).entity(ServerError.RUNTIME_ERROR.message())
.build();
}
return response;
}
private String constructDbNamespace(String userName, String dbName) {
return "dbs:" + userName + ":" + dbName;
}
private void updateStats(String user, String op) {
if (user != null) {
BasicDBObject query = new BasicDBObject();
query.put(STATS_USER_KEY, user);
query.put(STATS_OP_KEY, op);
BasicDBObject update = new BasicDBObject();
update.put("$inc", new BasicDBObject(STATS_COUNT_KEY, 1));
statsByUser.findAndModify(query, null, update);
}
}
public void init() {
DB statsDb = mongo.getDB(STATS_DB);
statsByUser = statsDb.getCollection(STATS_USER_COLLECTION);
DBObject statsIndex = new BasicDBObject();
statsIndex.put(STATS_USER_KEY, 1);
statsByUser.ensureIndex(statsIndex, null, true);
}
@Required
public void setMongo(Mongo mongo) {
this.mongo = mongo;
}
@Required
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
// BasicConfigurator.configure(); Testing only
}
}