1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.graph.search;
25
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.concurrent.locks.ReadWriteLock;
31 import java.util.concurrent.locks.ReentrantReadWriteLock;
32 import net.jcip.annotations.GuardedBy;
33 import net.jcip.annotations.ThreadSafe;
34 import org.modeshape.common.util.CheckArg;
35 import org.modeshape.graph.ExecutionContext;
36 import org.modeshape.graph.Graph;
37 import org.modeshape.graph.GraphI18n;
38 import org.modeshape.graph.connector.RepositoryConnectionFactory;
39 import org.modeshape.graph.connector.RepositorySource;
40 import org.modeshape.graph.connector.RepositorySourceException;
41 import org.modeshape.graph.observe.Observer;
42 import org.modeshape.graph.request.InvalidWorkspaceException;
43
44
45
46
47
48
49
50
51
52 @ThreadSafe
53 public abstract class AbstractSearchEngine<WorkspaceType extends SearchEngineWorkspace, ProcessorType extends SearchEngineProcessor>
54 implements SearchEngine {
55
56 public static final boolean DEFAULT_VERIFY_WORKSPACE_IN_SOURCE = false;
57
58 private final boolean verifyWorkspaceInSource;
59 private final RepositoryConnectionFactory connectionFactory;
60 private final String sourceName;
61 private volatile Workspaces<WorkspaceType> workspaces;
62
63
64
65
66
67
68
69 protected AbstractSearchEngine( String sourceName,
70 RepositoryConnectionFactory connectionFactory ) {
71 this(sourceName, connectionFactory, DEFAULT_VERIFY_WORKSPACE_IN_SOURCE);
72 }
73
74
75
76
77
78
79
80
81
82 protected AbstractSearchEngine( String sourceName,
83 RepositoryConnectionFactory connectionFactory,
84 boolean verifyWorkspaceInSource ) {
85 CheckArg.isNotNull(sourceName, "sourceName");
86 CheckArg.isNotNull(connectionFactory, "connectionFactory");
87 this.sourceName = sourceName;
88 this.connectionFactory = connectionFactory;
89 this.verifyWorkspaceInSource = verifyWorkspaceInSource;
90 this.workspaces = new SearchWorkspaces(connectionFactory);
91 }
92
93
94
95
96 protected RepositoryConnectionFactory getConnectionFactory() {
97 return connectionFactory;
98 }
99
100
101
102
103
104
105 public String getSourceName() {
106 return sourceName;
107 }
108
109
110
111
112
113
114 public boolean isVerifyWorkspaceInSource() {
115 return verifyWorkspaceInSource;
116 }
117
118
119
120
121
122
123
124
125 protected Graph graph( ExecutionContext context ) {
126 assert context != null;
127 return Graph.create(sourceName, connectionFactory, context);
128 }
129
130
131
132
133
134
135
136
137
138 protected abstract WorkspaceType createWorkspace( ExecutionContext context,
139 String workspaceName ) throws SearchEngineException;
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 protected abstract ProcessorType createProcessor( ExecutionContext context,
156 Workspaces<WorkspaceType> workspaces,
157 Observer observer,
158 boolean readOnly );
159
160
161
162
163
164
165
166 public SearchEngineProcessor createProcessor( ExecutionContext context,
167 Observer observer,
168 boolean readOnly ) {
169 return createProcessor(context, workspaces, observer, readOnly);
170 }
171
172 public interface Workspaces<WorkspaceType extends SearchEngineWorkspace> {
173
174
175
176
177
178 RepositoryConnectionFactory getRepositoryConnectionFactory();
179
180
181
182
183
184
185
186
187
188
189 WorkspaceType getWorkspace( ExecutionContext context,
190 String workspaceName,
191 boolean createIfMissing );
192
193
194
195
196
197
198 Collection<WorkspaceType> getWorkspaces();
199
200
201
202
203
204
205
206
207 WorkspaceType removeWorkspace( String workspaceName );
208
209
210
211
212
213
214
215
216 Map<String, WorkspaceType> removeAllWorkspaces();
217 }
218
219 protected class SearchWorkspaces implements Workspaces<WorkspaceType> {
220 private final ReadWriteLock workspacesLock = new ReentrantReadWriteLock();
221 @GuardedBy( "workspacesLock" )
222 private final Map<String, WorkspaceType> workspacesByName = new HashMap<String, WorkspaceType>();
223 private final RepositoryConnectionFactory connectionFactory;
224
225 protected SearchWorkspaces( RepositoryConnectionFactory connectionFactory ) {
226 this.connectionFactory = connectionFactory;
227 }
228
229
230
231
232
233
234 public RepositoryConnectionFactory getRepositoryConnectionFactory() {
235 return connectionFactory;
236 }
237
238
239
240
241
242
243 public WorkspaceType getWorkspace( ExecutionContext context,
244 String workspaceName,
245 boolean createIfMissing ) {
246 assert context != null;
247 assert workspaceName != null;
248 WorkspaceType workspace = null;
249 try {
250 workspacesLock.readLock().lock();
251 workspace = workspacesByName.get(workspaceName);
252 } finally {
253 workspacesLock.readLock().unlock();
254 }
255
256 if (workspace == null) {
257
258 if (isVerifyWorkspaceInSource() && connectionFactory != null
259 && !graph(context).getWorkspaces().contains(workspaceName)) {
260 String msg = GraphI18n.workspaceDoesNotExistInRepository.text(workspaceName, getSourceName());
261 throw new InvalidWorkspaceException(msg);
262 }
263 try {
264 workspacesLock.writeLock().lock();
265
266 workspace = workspacesByName.get(workspaceName);
267 if (workspace == null) {
268
269 workspace = createWorkspace(context, workspaceName);
270 workspacesByName.put(workspaceName, workspace);
271 }
272 } finally {
273 workspacesLock.writeLock().unlock();
274 }
275 }
276 return workspace;
277 }
278
279
280
281
282
283
284 public Collection<WorkspaceType> getWorkspaces() {
285 try {
286 workspacesLock.writeLock().lock();
287 return new ArrayList<WorkspaceType>(workspacesByName.values());
288 } finally {
289 workspacesByName.clear();
290 workspacesLock.writeLock().unlock();
291 }
292 }
293
294
295
296
297
298
299 public WorkspaceType removeWorkspace( String workspaceName ) {
300 CheckArg.isNotNull(workspaceName, "workspaceName");
301 try {
302 workspacesLock.writeLock().lock();
303
304 return workspacesByName.remove(workspaceName);
305 } finally {
306 workspacesLock.writeLock().unlock();
307 }
308 }
309
310
311
312
313
314
315 public Map<String, WorkspaceType> removeAllWorkspaces() {
316 try {
317 workspacesLock.writeLock().lock();
318 return new HashMap<String, WorkspaceType>(workspacesByName);
319 } finally {
320 workspacesByName.clear();
321 workspacesLock.writeLock().unlock();
322 }
323 }
324 }
325 }