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.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 /** 084 * @param id the connection id to retrieve. 085 * @return the database configured by {@link MongoDBConnectionConfig} for the input id, or the default one if it 086 * doesn't exist 087 */ 088 @Override 089 public MongoDatabase getDatabase(String id) { 090 MongoDBConnectionConfig config = getDescriptor(XP_CONNECTION, id); 091 MongoClient client = clients.get(id); 092 if (client == null) { 093 config = getDescriptor(XP_CONNECTION, DEFAULT_CONNECTION_ID); 094 client = clients.get(DEFAULT_CONNECTION_ID); 095 } 096 return MongoDBConnectionHelper.getDatabase(client, config.dbname); 097 } 098 099 /** 100 * @return all configured databases 101 */ 102 @Override 103 public Iterable<MongoDatabase> getDatabases() { 104 return () -> clients.entrySet().stream().map(e -> { 105 MongoDBConnectionConfig c = getDescriptor(XP_CONNECTION, e.getKey()); 106 return MongoDBConnectionHelper.getDatabase(e.getValue(), c.dbname); 107 }).iterator(); 108 } 109 110}