001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.search;
016    
017    import com.liferay.portal.kernel.cluster.messaging.ClusterBridgeMessageListener;
018    import com.liferay.portal.kernel.messaging.Destination;
019    import com.liferay.portal.kernel.messaging.InvokerMessageListener;
020    import com.liferay.portal.kernel.messaging.MessageBus;
021    import com.liferay.portal.kernel.messaging.MessageListener;
022    import com.liferay.portal.kernel.messaging.ParallelDestination;
023    import com.liferay.portal.kernel.messaging.SynchronousDestination;
024    import com.liferay.portal.kernel.search.messaging.BaseSearchEngineMessageListener;
025    import com.liferay.portal.kernel.search.messaging.SearchReaderMessageListener;
026    import com.liferay.portal.kernel.search.messaging.SearchWriterMessageListener;
027    import com.liferay.portal.kernel.util.Validator;
028    
029    import java.util.ArrayList;
030    import java.util.List;
031    import java.util.Map.Entry;
032    import java.util.Map;
033    import java.util.Set;
034    
035    /**
036     * @author Michael C. Han
037     */
038    public abstract class AbstractSearchEngineConfigurator {
039    
040            public void afterPropertiesSet() {
041                    Set<Entry<String, SearchEngine>> entrySet = _searchEngines.entrySet();
042    
043                    for (Entry<String, SearchEngine> entry : entrySet) {
044                            initSearchEngine(entry.getKey(), entry.getValue());
045                    }
046    
047                    String defaultSearchEngineId = getDefaultSearchEngineId();
048    
049                    if (Validator.isNotNull(defaultSearchEngineId)) {
050                            _originalSearchEngineId =
051                                    SearchEngineUtil.getDefaultSearchEngineId();
052    
053                            SearchEngineUtil.setDefaultSearchEngineId(defaultSearchEngineId);
054                    }
055    
056                    _searchEngines.clear();
057            }
058    
059            public void destroy() {
060                    for (SearchEngineRegistration searchEngineRegistration :
061                                    _searchEngineRegistrations) {
062    
063                            destroySearchEngine(searchEngineRegistration);
064                    }
065    
066                    _searchEngineRegistrations.clear();
067    
068                    if (Validator.isNotNull(_originalSearchEngineId)) {
069                            SearchEngineUtil.setDefaultSearchEngineId(_originalSearchEngineId);
070    
071                            _originalSearchEngineId = null;
072                    }
073            }
074    
075            public void setSearchEngines(Map<String, SearchEngine> searchEngines) {
076                    _searchEngines = searchEngines;
077            }
078    
079            protected void createSearchEngineListeners(
080                    String searchEngineId, SearchEngine searchEngine,
081                    Destination searchReaderDestination,
082                    Destination searchWriterDestination) {
083    
084                    registerSearchEngineMessageListener(
085                            searchEngineId, searchEngine, searchReaderDestination,
086                            new SearchReaderMessageListener(), searchEngine.getIndexSearcher());
087    
088                    registerSearchEngineMessageListener(
089                            searchEngineId, searchEngine, searchWriterDestination,
090                            new SearchWriterMessageListener(), searchEngine.getIndexWriter());
091    
092                    if (searchEngine.isClusteredWrite()) {
093                            ClusterBridgeMessageListener clusterBridgeMessageListener =
094                                    new ClusterBridgeMessageListener();
095    
096                            clusterBridgeMessageListener.setPriority(
097                                    searchEngine.getClusteredWritePriority());
098    
099                            searchWriterDestination.register(clusterBridgeMessageListener);
100                    }
101            }
102    
103            protected void destroySearchEngine(
104                    SearchEngineRegistration searchEngineRegistration) {
105    
106                    MessageBus messageBus = getMessageBus();
107    
108                    Destination searchReaderDestination = messageBus.removeDestination(
109                            searchEngineRegistration.getSearchReaderDestinationName());
110    
111                    searchReaderDestination.close(true);
112    
113                    Destination searchWriterDestination = messageBus.removeDestination(
114                            searchEngineRegistration.getSearchWriterDestinationName());
115    
116                    searchWriterDestination.close(true);
117    
118                    SearchEngineUtil.removeSearchEngine(
119                            searchEngineRegistration.getSearchEngineId());
120    
121                    if (!searchEngineRegistration.isOverride()) {
122                            return;
123                    }
124    
125                    SearchEngineProxyWrapper originalSearchEngineProxy =
126                            searchEngineRegistration.getOriginalSearchEngineProxyWrapper();
127    
128                    SearchEngine originalSearchEngine =
129                            originalSearchEngineProxy.getSearchEngine();
130    
131                    searchReaderDestination = getSearchReaderDestination(
132                            messageBus, searchEngineRegistration.getSearchEngineId(),
133                            originalSearchEngine);
134    
135                    registerInvokerMessageListener(
136                            searchReaderDestination,
137                            searchEngineRegistration.getOriginalSearchReaderMessageListeners());
138    
139                    searchWriterDestination = getSearchWriterDestination(
140                            messageBus, searchEngineRegistration.getSearchEngineId(),
141                            originalSearchEngine);
142    
143                    registerInvokerMessageListener(
144                            searchWriterDestination,
145                            searchEngineRegistration.getOriginalSearchWriterMessageListeners());
146    
147                    SearchEngineUtil.setSearchEngine(
148                            searchEngineRegistration.getSearchEngineId(),
149                            originalSearchEngineProxy);
150            }
151    
152            protected abstract String getDefaultSearchEngineId();
153    
154            protected abstract IndexSearcher getIndexSearcher();
155    
156            protected abstract IndexWriter getIndexWriter();
157    
158            protected abstract MessageBus getMessageBus();
159    
160            protected abstract ClassLoader getOperatingClassloader();
161    
162            protected Destination getSearchReaderDestination(
163                    MessageBus messageBus, String searchEngineId,
164                    SearchEngine searchEngine) {
165    
166                    String searchReaderDestinationName =
167                            SearchEngineUtil.getSearchReaderDestinationName(searchEngineId);
168    
169                    Destination searchReaderDestination = messageBus.getDestination(
170                            searchReaderDestinationName);
171    
172                    if (searchReaderDestination == null) {
173                            SynchronousDestination synchronousDestination =
174                                    new SynchronousDestination();
175    
176                            synchronousDestination.setName(searchReaderDestinationName);
177    
178                            synchronousDestination.open();
179    
180                            searchReaderDestination = synchronousDestination;
181    
182                            messageBus.addDestination(searchReaderDestination);
183                    }
184    
185                    return searchReaderDestination;
186            }
187    
188            protected Destination getSearchWriterDestination(
189                    MessageBus messageBus, String searchEngineId,
190                    SearchEngine searchEngine) {
191    
192                    String searchWriterDestinationName =
193                            SearchEngineUtil.getSearchWriterDestinationName(searchEngineId);
194    
195                    Destination searchWriterDestination = messageBus.getDestination(
196                            searchWriterDestinationName);
197    
198                    if (searchWriterDestination == null) {
199                            ParallelDestination parallelDestination = new ParallelDestination();
200    
201                            parallelDestination.setName(searchWriterDestinationName);
202    
203                            parallelDestination.open();
204    
205                            searchWriterDestination = parallelDestination;
206    
207                            messageBus.addDestination(searchWriterDestination);
208                    }
209    
210                    return searchWriterDestination;
211            }
212    
213            protected void initSearchEngine(
214                    String searchEngineId, SearchEngine searchEngine) {
215    
216                    SearchEngineRegistration searchEngineRegistration =
217                            new SearchEngineRegistration(searchEngineId);
218    
219                    _searchEngineRegistrations.add(searchEngineRegistration);
220    
221                    MessageBus messageBus = getMessageBus();
222    
223                    Destination searchReaderDestination = getSearchReaderDestination(
224                            messageBus, searchEngineId, searchEngine);
225    
226                    searchEngineRegistration.setSearchReaderDestinationName(
227                            searchReaderDestination.getName());
228    
229                    Destination searchWriterDestination = getSearchWriterDestination(
230                            messageBus, searchEngineId, searchEngine);
231    
232                    searchEngineRegistration.setSearchWriterDestinationName(
233                            searchWriterDestination.getName());
234    
235                    SearchEngine originalSearchEngine =
236                            SearchEngineUtil.getSearchEngineSilent(searchEngineId);
237    
238                    if (originalSearchEngine != null) {
239                            searchEngineRegistration.setOverride(true);
240    
241                            searchEngineRegistration.setOriginalSearchEngineProxyWrapper(
242                                    (SearchEngineProxyWrapper)originalSearchEngine);
243    
244                            savePreviousSearchEngineListeners(
245                                    searchReaderDestination, searchWriterDestination,
246                                    searchEngineRegistration);
247    
248                            messageBus.removeDestination(searchReaderDestination.getName());
249    
250                            searchReaderDestination = getSearchReaderDestination(
251                                    messageBus, searchEngineId, originalSearchEngine);
252    
253                            messageBus.removeDestination(searchWriterDestination.getName());
254    
255                            searchWriterDestination = getSearchWriterDestination(
256                                    messageBus, searchEngineId, originalSearchEngine);
257                    }
258    
259                    createSearchEngineListeners(
260                            searchEngineId, searchEngine, searchReaderDestination,
261                            searchWriterDestination);
262    
263                    SearchEngineProxyWrapper searchEngineProxyWrapper =
264                            new SearchEngineProxyWrapper(
265                                    searchEngine, getIndexSearcher(), getIndexWriter());
266    
267                    SearchEngineUtil.setSearchEngine(
268                            searchEngineId, searchEngineProxyWrapper);
269            }
270    
271            protected void registerInvokerMessageListener(
272                    Destination destination,
273                    List<InvokerMessageListener> invokerMessageListeners) {
274    
275                    for (InvokerMessageListener invokerMessageListener :
276                                    invokerMessageListeners) {
277    
278                            destination.register(
279                                    invokerMessageListener.getMessageListener(),
280                                    invokerMessageListener.getClassLoader());
281                    }
282            }
283    
284            protected void registerSearchEngineMessageListener(
285                    String searchEngineId, SearchEngine searchEngine,
286                    Destination destination,
287                    BaseSearchEngineMessageListener baseSearchEngineMessageListener,
288                    Object manager) {
289    
290                    baseSearchEngineMessageListener.setManager(manager);
291                    baseSearchEngineMessageListener.setMessageBus(getMessageBus());
292                    baseSearchEngineMessageListener.setSearchEngine(searchEngine);
293                    baseSearchEngineMessageListener.setSearchEngineId(searchEngineId);
294    
295                    destination.register(
296                            baseSearchEngineMessageListener, getOperatingClassloader());
297            }
298    
299            protected void savePreviousSearchEngineListeners(
300                    Destination searchReaderDestination,
301                    Destination searchWriterDestination,
302                    SearchEngineRegistration searchEngineRegistration) {
303    
304                    Set<MessageListener> searchReaderMessageListeners =
305                            searchReaderDestination.getMessageListeners();
306    
307                    for (MessageListener searchReaderMessageListener :
308                                    searchReaderMessageListeners) {
309    
310                            InvokerMessageListener invokerMessageListener =
311                                    (InvokerMessageListener)searchReaderMessageListener;
312    
313                            searchEngineRegistration.addOriginalSearchReaderMessageListener(
314                                    invokerMessageListener);
315                    }
316    
317                    Set<MessageListener> searchWriterMessageListeners =
318                            searchWriterDestination.getMessageListeners();
319    
320                    for (MessageListener searchWriterMessageListener :
321                                    searchWriterMessageListeners) {
322    
323                            InvokerMessageListener invokerMessageListener =
324                                    (InvokerMessageListener)searchWriterMessageListener;
325    
326                            searchEngineRegistration.addOriginalSearchWriterMessageListener(
327                                    invokerMessageListener);
328                    }
329            }
330    
331            private String _originalSearchEngineId;
332            private List<SearchEngineRegistration> _searchEngineRegistrations =
333                    new ArrayList<SearchEngineRegistration>();
334            private Map<String, SearchEngine> _searchEngines;
335    
336            private class SearchEngineRegistration {
337    
338                    private SearchEngineRegistration(String searchEngineId) {
339                            _searchEngineId = searchEngineId;
340                    }
341    
342                    public void addOriginalSearchReaderMessageListener(
343                            InvokerMessageListener messageListener) {
344    
345                            _originalSearchReaderMessageListeners.add(messageListener);
346                    }
347    
348                    public void addOriginalSearchWriterMessageListener(
349                            InvokerMessageListener messageListener) {
350    
351                            _originalSearchWriterMessageListeners.add(messageListener);
352                    }
353    
354                    public SearchEngineProxyWrapper getOriginalSearchEngineProxyWrapper() {
355                            return _originalSearchEngineProxyWrapper;
356                    }
357    
358                    public List<InvokerMessageListener>
359                            getOriginalSearchReaderMessageListeners() {
360    
361                            return _originalSearchReaderMessageListeners;
362                    }
363    
364                    public List<InvokerMessageListener>
365                            getOriginalSearchWriterMessageListeners() {
366    
367                            return _originalSearchWriterMessageListeners;
368                    }
369    
370                    public String getSearchEngineId() {
371                            return _searchEngineId;
372                    }
373    
374                    public String getSearchReaderDestinationName() {
375                            return _searchReaderDestinationName;
376                    }
377    
378                    public String getSearchWriterDestinationName() {
379                            return _searchWriterDestinationName;
380                    }
381    
382                    public boolean isOverride() {
383                            return _override;
384                    }
385    
386                    public void setOriginalSearchEngineProxyWrapper(
387                            SearchEngineProxyWrapper searchEngineProxyWrapper) {
388    
389                            _originalSearchEngineProxyWrapper = searchEngineProxyWrapper;
390                    }
391    
392                    public void setOverride(boolean override) {
393                            _override = override;
394                    }
395    
396                    public void setSearchReaderDestinationName(
397                            String searchReaderDestinationName) {
398    
399                            _searchReaderDestinationName = searchReaderDestinationName;
400                    }
401    
402                    public void setSearchWriterDestinationName(
403                            String searchWriterDestinationName) {
404    
405                            _searchWriterDestinationName = searchWriterDestinationName;
406                    }
407    
408                    private SearchEngineProxyWrapper _originalSearchEngineProxyWrapper;
409                    private List<InvokerMessageListener>
410                            _originalSearchReaderMessageListeners =
411                                    new ArrayList<InvokerMessageListener>();
412                    private List<InvokerMessageListener>
413                            _originalSearchWriterMessageListeners =
414                                    new ArrayList<InvokerMessageListener>();
415                    private boolean _override;
416                    private String _searchEngineId;
417                    private String _searchReaderDestinationName;
418                    private String _searchWriterDestinationName;
419    
420            }
421    
422    }