1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.allanbank.mongodb.client;
21
22 import java.lang.ref.Reference;
23 import java.lang.ref.ReferenceQueue;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ConcurrentMap;
28
29 import com.allanbank.mongodb.LambdaCallback;
30 import com.allanbank.mongodb.MongoClient;
31 import com.allanbank.mongodb.MongoClientConfiguration;
32 import com.allanbank.mongodb.MongoCursorControl;
33 import com.allanbank.mongodb.MongoDatabase;
34 import com.allanbank.mongodb.MongoIterator;
35 import com.allanbank.mongodb.StreamCallback;
36 import com.allanbank.mongodb.bson.Document;
37 import com.allanbank.mongodb.bson.DocumentAssignable;
38 import com.allanbank.mongodb.bson.element.StringElement;
39
40
41
42
43
44
45
46
47 public class MongoClientImpl implements MongoClient {
48
49
50 private final Client myClient;
51
52
53 private final ConcurrentMap<String, Reference<MongoDatabase>> myDatabases;
54
55
56 private final ReferenceQueue<MongoDatabase> myReferenceQueue = new ReferenceQueue<MongoDatabase>();
57
58
59
60
61
62
63
64 public MongoClientImpl(final Client client) {
65 myClient = client;
66
67 myDatabases = new ConcurrentHashMap<String, Reference<MongoDatabase>>();
68 }
69
70
71
72
73
74
75
76 public MongoClientImpl(final MongoClientConfiguration config) {
77 this(new ClientImpl(config));
78 }
79
80
81
82
83
84
85
86 @Override
87 public MongoClient asSerializedClient() {
88 if (myClient instanceof SerialClientImpl) {
89 return this;
90 }
91
92 return new MongoClientImpl(new SerialClientImpl((ClientImpl) myClient));
93 }
94
95
96
97
98
99
100
101 @Override
102 public void close() {
103 myClient.close();
104 }
105
106
107
108
109
110
111 public Client getClient() {
112 return myClient;
113 }
114
115
116
117
118
119
120
121 @Override
122 public MongoClientConfiguration getConfig() {
123 return myClient.getConfig();
124 }
125
126
127
128
129
130
131
132
133
134
135 @Override
136 public MongoDatabase getDatabase(final String name) {
137 MongoDatabase database = null;
138 Reference<MongoDatabase> ref = myDatabases.get(name);
139 if (ref != null) {
140 database = ref.get();
141 if (database == null) {
142
143 myDatabases.remove(name, ref);
144 }
145 }
146
147
148 if (database == null) {
149 database = new MongoDatabaseImpl(this, myClient, name);
150 ref = new NamedReference<MongoDatabase>(name, database,
151 myReferenceQueue);
152
153 final Reference<MongoDatabase> existing = myDatabases.putIfAbsent(
154 name, ref);
155 if (existing != null) {
156 final MongoDatabase existingDb = existing.get();
157 if (existingDb != null) {
158 database = existingDb;
159 }
160
161
162
163 }
164 }
165
166
167 Reference<?> polled;
168 while ((polled = myReferenceQueue.poll()) != null) {
169 if (polled instanceof NamedReference) {
170 myDatabases.remove(((NamedReference<?>) polled).getName(),
171 polled);
172 }
173 }
174
175 return database;
176 }
177
178
179
180
181
182
183
184
185
186 @Override
187 public List<String> listDatabaseNames() {
188
189 final MongoDatabase db = getDatabase("admin");
190 final Document result = db.runAdminCommand("listDatabases");
191
192 final List<String> names = new ArrayList<String>();
193 for (final StringElement nameElement : result.find(StringElement.class,
194 "databases", ".*", "name")) {
195
196 names.add(nameElement.getValue());
197 }
198
199 return names;
200 }
201
202
203
204
205 @Override
206 @Deprecated
207 public List<String> listDatabases() {
208 return listDatabaseNames();
209 }
210
211
212
213
214
215
216
217
218
219
220 @Override
221 public MongoIterator<Document> restart(
222 final DocumentAssignable cursorDocument)
223 throws IllegalArgumentException {
224 return myClient.restart(cursorDocument);
225 }
226
227
228
229
230
231
232
233
234 @Override
235 public MongoCursorControl restart(final LambdaCallback<Document> results,
236 final DocumentAssignable cursorDocument)
237 throws IllegalArgumentException {
238 return restart(new LambdaCallbackAdapter<Document>(results),
239 cursorDocument);
240 }
241
242
243
244
245
246
247
248
249
250
251
252 @Override
253 public MongoCursorControl restart(final StreamCallback<Document> results,
254 final DocumentAssignable cursorDocument)
255 throws IllegalArgumentException {
256 return myClient.restart(results, cursorDocument);
257 }
258 }