001
014
015 package com.liferay.portal.kernel.search;
016
017 import com.liferay.portal.kernel.concurrent.CallerRunsPolicy;
018 import com.liferay.portal.kernel.concurrent.RejectedExecutionHandler;
019 import com.liferay.portal.kernel.concurrent.ThreadPoolExecutor;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.messaging.Destination;
023 import com.liferay.portal.kernel.messaging.DestinationConfiguration;
024 import com.liferay.portal.kernel.messaging.DestinationFactory;
025 import com.liferay.portal.kernel.messaging.DestinationFactoryUtil;
026 import com.liferay.portal.kernel.messaging.InvokerMessageListener;
027 import com.liferay.portal.kernel.messaging.MessageBus;
028 import com.liferay.portal.kernel.messaging.MessageListener;
029 import com.liferay.portal.kernel.model.CompanyConstants;
030 import com.liferay.portal.kernel.search.messaging.BaseSearchEngineMessageListener;
031 import com.liferay.portal.kernel.search.messaging.SearchReaderMessageListener;
032 import com.liferay.portal.kernel.search.messaging.SearchWriterMessageListener;
033 import com.liferay.portal.kernel.util.GetterUtil;
034 import com.liferay.portal.kernel.util.PortalRunMode;
035 import com.liferay.portal.kernel.util.PropsKeys;
036 import com.liferay.portal.kernel.util.PropsUtil;
037 import com.liferay.portal.kernel.util.StringBundler;
038 import com.liferay.portal.kernel.util.Validator;
039 import com.liferay.registry.Registry;
040 import com.liferay.registry.RegistryUtil;
041 import com.liferay.registry.dependency.ServiceDependencyListener;
042 import com.liferay.registry.dependency.ServiceDependencyManager;
043
044 import java.util.ArrayList;
045 import java.util.List;
046 import java.util.Map;
047 import java.util.Map.Entry;
048 import java.util.Set;
049
050
053 public abstract class AbstractSearchEngineConfigurator
054 implements SearchEngineConfigurator {
055
056 @Override
057 public void afterPropertiesSet() {
058 final ServiceDependencyManager serviceDependencyManager =
059 new ServiceDependencyManager();
060
061 serviceDependencyManager.addServiceDependencyListener(
062 new ServiceDependencyListener() {
063
064 @Override
065 public void dependenciesFulfilled() {
066 Registry registry = RegistryUtil.getRegistry();
067
068 _messageBus = registry.getService(MessageBus.class);
069
070 initialize();
071 }
072
073 @Override
074 public void destroy() {
075 }
076
077 });
078
079 serviceDependencyManager.registerDependencies(
080 DestinationFactory.class, MessageBus.class);
081 }
082
083 @Override
084 public void destroy() {
085 for (SearchEngineRegistration searchEngineRegistration :
086 _searchEngineRegistrations) {
087
088 destroySearchEngine(searchEngineRegistration);
089 }
090
091 _searchEngineRegistrations.clear();
092
093 if (Validator.isNotNull(_originalSearchEngineId)) {
094 SearchEngineHelper searchEngineHelper = getSearchEngineHelper();
095
096 searchEngineHelper.setDefaultSearchEngineId(
097 _originalSearchEngineId);
098
099 _originalSearchEngineId = null;
100 }
101 }
102
103 @Override
104 public void setSearchEngines(Map<String, SearchEngine> searchEngines) {
105 _searchEngines = searchEngines;
106 }
107
108 protected void createSearchEngineListeners(
109 String searchEngineId, SearchEngine searchEngine,
110 Destination searchReaderDestination,
111 Destination searchWriterDestination) {
112
113 registerSearchEngineMessageListener(
114 searchEngineId, searchEngine, searchReaderDestination,
115 new SearchReaderMessageListener(), searchEngine.getIndexSearcher());
116
117 registerSearchEngineMessageListener(
118 searchEngineId, searchEngine, searchWriterDestination,
119 new SearchWriterMessageListener(), searchEngine.getIndexWriter());
120 }
121
122 protected Destination createSearchReaderDestination(
123 String searchReaderDestinationName) {
124
125 DestinationConfiguration destinationConfiguration =
126 DestinationConfiguration.createSynchronousDestinationConfiguration(
127 searchReaderDestinationName);
128
129 return DestinationFactoryUtil.createDestination(
130 destinationConfiguration);
131 }
132
133 protected Destination createSearchWriterDestination(
134 String searchWriterDestinationName) {
135
136 DestinationConfiguration destinationConfiguration = null;
137
138 if (PortalRunMode.isTestMode()) {
139 destinationConfiguration =
140 DestinationConfiguration.
141 createSynchronousDestinationConfiguration(
142 searchWriterDestinationName);
143 }
144 else {
145 destinationConfiguration =
146 DestinationConfiguration.createParallelDestinationConfiguration(
147 searchWriterDestinationName);
148 }
149
150 if (_INDEX_SEARCH_WRITER_MAX_QUEUE_SIZE > 0) {
151 destinationConfiguration.setMaximumQueueSize(
152 _INDEX_SEARCH_WRITER_MAX_QUEUE_SIZE);
153
154 RejectedExecutionHandler rejectedExecutionHandler =
155 new CallerRunsPolicy() {
156
157 @Override
158 public void rejectedExecution(
159 Runnable runnable,
160 ThreadPoolExecutor threadPoolExecutor) {
161
162 if (_log.isWarnEnabled()) {
163 StringBundler sb = new StringBundler(4);
164
165 sb.append("The search index writer's task queue ");
166 sb.append("is at its maximum capacity. The ");
167 sb.append("current thread will handle the ");
168 sb.append("request.");
169
170 _log.warn(sb.toString());
171 }
172
173 super.rejectedExecution(runnable, threadPoolExecutor);
174 }
175
176 };
177
178 destinationConfiguration.setRejectedExecutionHandler(
179 rejectedExecutionHandler);
180 }
181
182 return DestinationFactoryUtil.createDestination(
183 destinationConfiguration);
184 }
185
186 protected void destroySearchEngine(
187 SearchEngineRegistration searchEngineRegistration) {
188
189 _messageBus.removeDestination(
190 searchEngineRegistration.getSearchReaderDestinationName());
191
192 _messageBus.removeDestination(
193 searchEngineRegistration.getSearchWriterDestinationName());
194
195 SearchEngineHelper searchEngineHelper = getSearchEngineHelper();
196
197 searchEngineHelper.removeSearchEngine(
198 searchEngineRegistration.getSearchEngineId());
199
200 if (!searchEngineRegistration.isOverride()) {
201 return;
202 }
203
204 SearchEngineProxyWrapper originalSearchEngineProxy =
205 searchEngineRegistration.getOriginalSearchEngineProxyWrapper();
206
207 Destination searchReaderDestination = getSearchReaderDestination(
208 _messageBus, searchEngineRegistration.getSearchEngineId());
209
210 registerInvokerMessageListener(
211 searchReaderDestination,
212 searchEngineRegistration.getOriginalSearchReaderMessageListeners());
213
214 Destination searchWriterDestination = getSearchWriterDestination(
215 _messageBus, searchEngineRegistration.getSearchEngineId());
216
217 registerInvokerMessageListener(
218 searchWriterDestination,
219 searchEngineRegistration.getOriginalSearchWriterMessageListeners());
220
221 setSearchEngine(
222 searchEngineRegistration.getSearchEngineId(),
223 originalSearchEngineProxy);
224 }
225
226 protected abstract String getDefaultSearchEngineId();
227
228 protected abstract IndexSearcher getIndexSearcher();
229
230 protected abstract IndexWriter getIndexWriter();
231
232 protected abstract ClassLoader getOperatingClassloader();
233
234 protected abstract SearchEngineHelper getSearchEngineHelper();
235
236 protected Destination getSearchReaderDestination(
237 MessageBus messageBus, String searchEngineId) {
238
239 SearchEngineHelper searchEngineHelper = getSearchEngineHelper();
240
241 String searchReaderDestinationName =
242 searchEngineHelper.getSearchReaderDestinationName(searchEngineId);
243
244 Destination searchReaderDestination = messageBus.getDestination(
245 searchReaderDestinationName);
246
247 if (searchReaderDestination == null) {
248 searchReaderDestination = createSearchReaderDestination(
249 searchReaderDestinationName);
250
251 messageBus.addDestination(searchReaderDestination);
252 }
253
254 return searchReaderDestination;
255 }
256
257 protected Destination getSearchWriterDestination(
258 MessageBus messageBus, String searchEngineId) {
259
260 SearchEngineHelper searchEngineHelper = getSearchEngineHelper();
261
262 String searchWriterDestinationName =
263 searchEngineHelper.getSearchWriterDestinationName(searchEngineId);
264
265 Destination searchWriterDestination = messageBus.getDestination(
266 searchWriterDestinationName);
267
268 if (searchWriterDestination == null) {
269 searchWriterDestination = createSearchWriterDestination(
270 searchWriterDestinationName);
271
272 messageBus.addDestination(searchWriterDestination);
273 }
274
275 return searchWriterDestination;
276 }
277
278 protected void initialize() {
279 Set<Entry<String, SearchEngine>> entrySet = _searchEngines.entrySet();
280
281 for (Entry<String, SearchEngine> entry : entrySet) {
282 initSearchEngine(entry.getKey(), entry.getValue());
283 }
284
285 String defaultSearchEngineId = getDefaultSearchEngineId();
286
287 if (Validator.isNotNull(defaultSearchEngineId)) {
288 SearchEngineHelper searchEngineHelper = getSearchEngineHelper();
289
290 _originalSearchEngineId =
291 searchEngineHelper.getDefaultSearchEngineId();
292
293 searchEngineHelper.setDefaultSearchEngineId(defaultSearchEngineId);
294 }
295
296 _searchEngines.clear();
297 }
298
299 protected void initSearchEngine(
300 String searchEngineId, SearchEngine searchEngine) {
301
302 SearchEngineRegistration searchEngineRegistration =
303 new SearchEngineRegistration(searchEngineId);
304
305 _searchEngineRegistrations.add(searchEngineRegistration);
306
307 Destination searchReaderDestination = getSearchReaderDestination(
308 _messageBus, searchEngineId);
309
310 searchEngineRegistration.setSearchReaderDestinationName(
311 searchReaderDestination.getName());
312
313 Destination searchWriterDestination = getSearchWriterDestination(
314 _messageBus, searchEngineId);
315
316 searchEngineRegistration.setSearchWriterDestinationName(
317 searchWriterDestination.getName());
318
319 SearchEngineHelper searchEngineHelper = getSearchEngineHelper();
320
321 SearchEngine originalSearchEngine =
322 searchEngineHelper.getSearchEngineSilent(searchEngineId);
323
324 if (originalSearchEngine != null) {
325 searchEngineRegistration.setOverride(true);
326
327 searchEngineRegistration.setOriginalSearchEngineProxyWrapper(
328 (SearchEngineProxyWrapper)originalSearchEngine);
329
330 savePreviousSearchEngineListeners(
331 searchReaderDestination, searchWriterDestination,
332 searchEngineRegistration);
333
334 _messageBus.removeDestination(
335 searchReaderDestination.getName(), false);
336
337 searchReaderDestination = getSearchReaderDestination(
338 _messageBus, searchEngineId);
339
340 _messageBus.removeDestination(
341 searchWriterDestination.getName(), false);
342
343 searchWriterDestination = getSearchWriterDestination(
344 _messageBus, searchEngineId);
345 }
346
347 createSearchEngineListeners(
348 searchEngineId, searchEngine, searchReaderDestination,
349 searchWriterDestination);
350
351 SearchEngineProxyWrapper searchEngineProxyWrapper =
352 new SearchEngineProxyWrapper(
353 searchEngine, getIndexSearcher(), getIndexWriter());
354
355 setSearchEngine(searchEngineId, searchEngineProxyWrapper);
356 }
357
358 protected void registerInvokerMessageListener(
359 Destination destination,
360 List<InvokerMessageListener> invokerMessageListeners) {
361
362 for (InvokerMessageListener invokerMessageListener :
363 invokerMessageListeners) {
364
365 destination.register(
366 invokerMessageListener.getMessageListener(),
367 invokerMessageListener.getClassLoader());
368 }
369 }
370
371 protected void registerSearchEngineMessageListener(
372 String searchEngineId, SearchEngine searchEngine,
373 Destination destination,
374 BaseSearchEngineMessageListener baseSearchEngineMessageListener,
375 Object manager) {
376
377 baseSearchEngineMessageListener.setManager(manager);
378 baseSearchEngineMessageListener.setMessageBus(_messageBus);
379 baseSearchEngineMessageListener.setSearchEngine(searchEngine);
380 baseSearchEngineMessageListener.setSearchEngineId(searchEngineId);
381
382 destination.register(
383 baseSearchEngineMessageListener, getOperatingClassloader());
384 }
385
386 protected void savePreviousSearchEngineListeners(
387 Destination searchReaderDestination,
388 Destination searchWriterDestination,
389 SearchEngineRegistration searchEngineRegistration) {
390
391 Set<MessageListener> searchReaderMessageListeners =
392 searchReaderDestination.getMessageListeners();
393
394 for (MessageListener searchReaderMessageListener :
395 searchReaderMessageListeners) {
396
397 InvokerMessageListener invokerMessageListener =
398 (InvokerMessageListener)searchReaderMessageListener;
399
400 searchEngineRegistration.addOriginalSearchReaderMessageListener(
401 invokerMessageListener);
402 }
403
404 Set<MessageListener> searchWriterMessageListeners =
405 searchWriterDestination.getMessageListeners();
406
407 for (MessageListener searchWriterMessageListener :
408 searchWriterMessageListeners) {
409
410 InvokerMessageListener invokerMessageListener =
411 (InvokerMessageListener)searchWriterMessageListener;
412
413 searchEngineRegistration.addOriginalSearchWriterMessageListener(
414 invokerMessageListener);
415 }
416 }
417
418 protected void setSearchEngine(
419 String searchEngineId, SearchEngine searchEngine) {
420
421 SearchEngineHelper searchEngineHelper = getSearchEngineHelper();
422
423 searchEngineHelper.setSearchEngine(searchEngineId, searchEngine);
424
425 searchEngine.initialize(CompanyConstants.SYSTEM);
426 }
427
428 private static final int _INDEX_SEARCH_WRITER_MAX_QUEUE_SIZE =
429 GetterUtil.getInteger(
430 PropsUtil.get(PropsKeys.INDEX_SEARCH_WRITER_MAX_QUEUE_SIZE));
431
432 private static final Log _log = LogFactoryUtil.getLog(
433 AbstractSearchEngineConfigurator.class);
434
435 private volatile MessageBus _messageBus;
436 private String _originalSearchEngineId;
437 private final List<SearchEngineRegistration> _searchEngineRegistrations =
438 new ArrayList<>();
439 private Map<String, SearchEngine> _searchEngines;
440
441 private static class SearchEngineRegistration {
442
443 public void addOriginalSearchReaderMessageListener(
444 InvokerMessageListener messageListener) {
445
446 _originalSearchReaderMessageListeners.add(messageListener);
447 }
448
449 public void addOriginalSearchWriterMessageListener(
450 InvokerMessageListener messageListener) {
451
452 _originalSearchWriterMessageListeners.add(messageListener);
453 }
454
455 public SearchEngineProxyWrapper getOriginalSearchEngineProxyWrapper() {
456 return _originalSearchEngineProxyWrapper;
457 }
458
459 public List<InvokerMessageListener>
460 getOriginalSearchReaderMessageListeners() {
461
462 return _originalSearchReaderMessageListeners;
463 }
464
465 public List<InvokerMessageListener>
466 getOriginalSearchWriterMessageListeners() {
467
468 return _originalSearchWriterMessageListeners;
469 }
470
471 public String getSearchEngineId() {
472 return _searchEngineId;
473 }
474
475 public String getSearchReaderDestinationName() {
476 return _searchReaderDestinationName;
477 }
478
479 public String getSearchWriterDestinationName() {
480 return _searchWriterDestinationName;
481 }
482
483 public boolean isOverride() {
484 return _override;
485 }
486
487 public void setOriginalSearchEngineProxyWrapper(
488 SearchEngineProxyWrapper searchEngineProxyWrapper) {
489
490 _originalSearchEngineProxyWrapper = searchEngineProxyWrapper;
491 }
492
493 public void setOverride(boolean override) {
494 _override = override;
495 }
496
497 public void setSearchReaderDestinationName(
498 String searchReaderDestinationName) {
499
500 _searchReaderDestinationName = searchReaderDestinationName;
501 }
502
503 public void setSearchWriterDestinationName(
504 String searchWriterDestinationName) {
505
506 _searchWriterDestinationName = searchWriterDestinationName;
507 }
508
509 private SearchEngineRegistration(String searchEngineId) {
510 _searchEngineId = searchEngineId;
511 }
512
513 private SearchEngineProxyWrapper _originalSearchEngineProxyWrapper;
514 private final List<InvokerMessageListener>
515 _originalSearchReaderMessageListeners = new ArrayList<>();
516 private final List<InvokerMessageListener>
517 _originalSearchWriterMessageListeners = new ArrayList<>();
518 private boolean _override;
519 private final String _searchEngineId;
520 private String _searchReaderDestinationName;
521 private String _searchWriterDestinationName;
522
523 }
524
525 }