001/* 002 * (C) Copyright 2017-2018 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Kevin Leturc 018 */ 019package org.nuxeo.runtime.mongodb; 020 021import java.util.Collection; 022import java.util.Map; 023import java.util.concurrent.ConcurrentHashMap; 024 025import org.apache.logging.log4j.LogManager; 026import org.apache.logging.log4j.Logger; 027import org.nuxeo.runtime.model.ComponentContext; 028import org.nuxeo.runtime.model.ComponentStartOrders; 029import org.nuxeo.runtime.model.DefaultComponent; 030 031import com.mongodb.client.MongoClient; 032import com.mongodb.client.MongoDatabase; 033 034/** 035 * Component used to get a database connection to MongoDB. Don't expose {@link MongoClient} directly, because it's this 036 * component which is responsible for creating and closing it. 037 * 038 * @since 9.1 039 */ 040public class MongoDBComponent extends DefaultComponent implements MongoDBConnectionService { 041 042 private static final Logger log = LogManager.getLogger(MongoDBComponent.class); 043 044 /** 045 * @since 10.3 046 */ 047 public static final String COMPONENT_NAME = "org.nuxeo.runtime.mongodb.MongoDBComponent"; 048 049 private static final String XP_CONNECTION = "connection"; 050 051 private static final String DEFAULT_CONNECTION_ID = "default"; 052 053 private final Map<String, MongoClient> clients = new ConcurrentHashMap<>(); 054 055 @Override 056 public void start(ComponentContext context) { 057 super.start(context); 058 Collection<MongoDBConnectionConfig> confs = getDescriptors(XP_CONNECTION); 059 confs.forEach(c -> { 060 log.debug("Initializing MongoClient with id={}", c::getId); 061 clients.put(c.getId(), MongoDBConnectionHelper.newMongoClient(c)); 062 }); 063 } 064 065 @Override 066 @SuppressWarnings("Java8MapForEach") 067 public void stop(ComponentContext context) throws InterruptedException { 068 super.stop(context); 069 // don't remove entrySet otherwise java will try to load mongo client classes even in a non mongo setup 070 clients.entrySet().forEach(e -> { 071 log.debug("Closing MongoClient with id={}", e::getKey); 072 e.getValue().close(); 073 }); 074 clients.clear(); 075 } 076 077 @Override 078 public int getApplicationStartedOrder() { 079 // start before repository and directories 080 return ComponentStartOrders.REPOSITORY - 10; 081 } 082 083 @SuppressWarnings("resource") // client closed by stop() 084 @Override 085 public MongoClient getClient(String id) { 086 MongoClient client = clients.get(id); 087 if (client == null) { 088 client = clients.get(DEFAULT_CONNECTION_ID); 089 } 090 return client; 091 } 092 093 @Override 094 public MongoDBConnectionConfig getConfig(String id) { 095 MongoDBConnectionConfig config = getDescriptor(XP_CONNECTION, id); 096 if (config == null) { 097 config = getDescriptor(XP_CONNECTION, DEFAULT_CONNECTION_ID); 098 } 099 return config; 100 } 101 102 @Override 103 public String getDatabaseName(String id) { 104 return getConfig(id).dbname; 105 } 106 107 @SuppressWarnings("resource") // client is closed only at stop() time 108 @Override 109 public MongoDatabase getDatabase(String id) { 110 MongoClient client = getClient(id); 111 String dbname = getDatabaseName(id); 112 return MongoDBConnectionHelper.getDatabase(client, dbname); 113 } 114 115 @Override 116 public Iterable<MongoDatabase> getDatabases() { 117 return () -> clients.entrySet().stream().map(e -> { 118 MongoDBConnectionConfig c = getDescriptor(XP_CONNECTION, e.getKey()); 119 return MongoDBConnectionHelper.getDatabase(e.getValue(), c.dbname); 120 }).iterator(); 121 } 122 123}