1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.nosql.appender.mongodb;
18
19 import java.lang.reflect.Field;
20 import java.lang.reflect.Method;
21 import java.util.List;
22
23 import com.mongodb.DB;
24 import com.mongodb.MongoClient;
25 import com.mongodb.ServerAddress;
26 import com.mongodb.WriteConcern;
27 import org.apache.logging.log4j.Logger;
28 import org.apache.logging.log4j.core.appender.AbstractAppender;
29 import org.apache.logging.log4j.core.config.plugins.Plugin;
30 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
31 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
32 import org.apache.logging.log4j.core.util.Loader;
33 import org.apache.logging.log4j.core.util.NameUtil;
34 import org.apache.logging.log4j.nosql.appender.NoSqlProvider;
35 import org.apache.logging.log4j.status.StatusLogger;
36
37
38
39
40 @Plugin(name = "MongoDb", category = "Core", printObject = true)
41 public final class MongoDbProvider implements NoSqlProvider<MongoDbConnection> {
42 private static final Logger LOGGER = StatusLogger.getLogger();
43
44 private final String collectionName;
45 private final DB database;
46 private final String description;
47
48 private final WriteConcern writeConcern;
49
50 private MongoDbProvider(final DB database, final WriteConcern writeConcern, final String collectionName,
51 final String description) {
52 this.database = database;
53 this.writeConcern = writeConcern;
54 this.collectionName = collectionName;
55 this.description = "mongoDb{ " + description + " }";
56 }
57
58 @Override
59 public MongoDbConnection getConnection() {
60 return new MongoDbConnection(this.database, this.writeConcern, this.collectionName);
61 }
62
63 @Override
64 public String toString() {
65 return this.description;
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 @PluginFactory
91 public static MongoDbProvider createNoSqlProvider(
92 @PluginAttribute("collectionName") final String collectionName,
93 @PluginAttribute("writeConcernConstant") final String writeConcernConstant,
94 @PluginAttribute("writeConcernConstantClass") final String writeConcernConstantClassName,
95 @PluginAttribute("databaseName") final String databaseName,
96 @PluginAttribute("server") final String server,
97 @PluginAttribute("port") final String port,
98 @PluginAttribute("username") final String username,
99 @PluginAttribute(value = "password", sensitive = true) final String password,
100 @PluginAttribute("factoryClassName") final String factoryClassName,
101 @PluginAttribute("factoryMethodName") final String factoryMethodName) {
102 DB database;
103 String description;
104 if (factoryClassName != null && factoryClassName.length() > 0 &&
105 factoryMethodName != null && factoryMethodName.length() > 0) {
106 try {
107 final Class<?> factoryClass = Loader.loadClass(factoryClassName);
108 final Method method = factoryClass.getMethod(factoryMethodName);
109 final Object object = method.invoke(null);
110
111 if (object instanceof DB) {
112 database = (DB) object;
113 } else if (object instanceof MongoClient) {
114 if (databaseName != null && databaseName.length() > 0) {
115 database = ((MongoClient) object).getDB(databaseName);
116 } else {
117 LOGGER.error("The factory method [{}.{}()] returned a MongoClient so the database name is "
118 + "required.", factoryClassName, factoryMethodName);
119 return null;
120 }
121 } else if (object == null) {
122 LOGGER.error("The factory method [{}.{}()] returned null.", factoryClassName, factoryMethodName);
123 return null;
124 } else {
125 LOGGER.error("The factory method [{}.{}()] returned an unsupported type [{}].", factoryClassName,
126 factoryMethodName, object.getClass().getName());
127 return null;
128 }
129
130 description = "database=" + database.getName();
131 final List<ServerAddress> addresses = database.getMongo().getAllAddress();
132 if (addresses.size() == 1) {
133 description += ", server=" + addresses.get(0).getHost() + ", port=" + addresses.get(0).getPort();
134 } else {
135 description += ", servers=[";
136 for (final ServerAddress address : addresses) {
137 description += " { " + address.getHost() + ", " + address.getPort() + " } ";
138 }
139 description += "]";
140 }
141 } catch (final ClassNotFoundException e) {
142 LOGGER.error("The factory class [{}] could not be loaded.", factoryClassName, e);
143 return null;
144 } catch (final NoSuchMethodException e) {
145 LOGGER.error("The factory class [{}] does not have a no-arg method named [{}].", factoryClassName,
146 factoryMethodName, e);
147 return null;
148 } catch (final Exception e) {
149 LOGGER.error("The factory method [{}.{}()] could not be invoked.", factoryClassName, factoryMethodName,
150 e);
151 return null;
152 }
153 } else if (databaseName != null && databaseName.length() > 0) {
154 description = "database=" + databaseName;
155 try {
156 if (server != null && server.length() > 0) {
157 final int portInt = AbstractAppender.parseInt(port, 0);
158 description += ", server=" + server;
159 if (portInt > 0) {
160 description += ", port=" + portInt;
161 database = new MongoClient(server, portInt).getDB(databaseName);
162 } else {
163 database = new MongoClient(server).getDB(databaseName);
164 }
165 } else {
166 database = new MongoClient().getDB(databaseName);
167 }
168 } catch (final Exception e) {
169 LOGGER.error("Failed to obtain a database instance from the MongoClient at server [{}] and "
170 + "port [{}].", server, port);
171 return null;
172 }
173 } else {
174 LOGGER.error("No factory method was provided so the database name is required.");
175 return null;
176 }
177
178 if (!database.isAuthenticated()) {
179 if (username != null && username.length() > 0 && password != null && password.length() > 0) {
180 description += ", username=" + username + ", passwordHash="
181 + NameUtil.md5(password + MongoDbProvider.class.getName());
182 MongoDbConnection.authenticate(database, username, password);
183 } else {
184 LOGGER.error("The database is not already authenticated so you must supply a username and password "
185 + "for the MongoDB provider.");
186 return null;
187 }
188 }
189
190 WriteConcern writeConcern;
191 if (writeConcernConstant != null && writeConcernConstant.length() > 0) {
192 if (writeConcernConstantClassName != null && writeConcernConstantClassName.length() > 0) {
193 try {
194 final Class<?> writeConcernConstantClass = Loader.loadClass(writeConcernConstantClassName);
195 final Field field = writeConcernConstantClass.getField(writeConcernConstant);
196 writeConcern = (WriteConcern) field.get(null);
197 } catch (final Exception e) {
198 LOGGER.error("Write concern constant [{}.{}] not found, using default.",
199 writeConcernConstantClassName, writeConcernConstant);
200 writeConcern = WriteConcern.ACKNOWLEDGED;
201 }
202 } else {
203 writeConcern = WriteConcern.valueOf(writeConcernConstant);
204 if (writeConcern == null) {
205 LOGGER.warn("Write concern constant [{}] not found, using default.", writeConcernConstant);
206 writeConcern = WriteConcern.ACKNOWLEDGED;
207 }
208 }
209 } else {
210 writeConcern = WriteConcern.ACKNOWLEDGED;
211 }
212
213 return new MongoDbProvider(database, writeConcern, collectionName, description);
214 }
215 }