001    /**
002     * Copyright (c) 2000-2012 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(searchEngineId);
233    
234                    SearchEngine originalSearchEngine =
235                            SearchEngineUtil.getSearchEngineSilent(searchEngineId);
236    
237                    if (originalSearchEngine != null) {
238                            searchEngineRegistration.setOverride(true);
239    
240                            searchEngineRegistration.setOriginalSearchEngineProxyWrapper(
241                                    (SearchEngineProxyWrapper)originalSearchEngine);
242    
243                            savePreviousSearchEngineListeners(
244                                    searchReaderDestination, searchWriterDestination,
245                                    searchEngineRegistration);
246    
247                            messageBus.removeDestination(searchReaderDestination.getName());
248    
249                            searchReaderDestination = getSearchReaderDestination(
250                                    messageBus, searchEngineId, originalSearchEngine);
251    
252                            messageBus.removeDestination(searchWriterDestination.getName());
253    
254                            searchWriterDestination = getSearchWriterDestination(
255                                    messageBus, searchEngineId, originalSearchEngine);
256                    }
257    
258                    createSearchEngineListeners(
259                            searchEngineId, searchEngine, searchReaderDestination,
260                            searchWriterDestination);
261    
262                    SearchEngineProxyWrapper searchEngineProxyWrapper =
263                            new SearchEngineProxyWrapper(
264                                    searchEngine, getIndexSearcher(), getIndexWriter());
265    
266                    SearchEngineUtil.setSearchEngine(
267                            searchEngineId, searchEngineProxyWrapper);
268            }
269    
270            protected void registerInvokerMessageListener(
271                    Destination destination,
272                    List<InvokerMessageListener> invokerMessageListeners) {
273    
274                    for (InvokerMessageListener invokerMessageListener :
275                                    invokerMessageListeners) {
276    
277                            destination.register(
278                                    invokerMessageListener.getMessageListener(),
279                                    invokerMessageListener.getClassLoader());
280                    }
281            }
282    
283            protected void registerSearchEngineMessageListener(
284                    String searchEngineId, SearchEngine searchEngine,
285                    Destination destination,
286                    BaseSearchEngineMessageListener baseSearchEngineMessageListener,
287                    Object manager) {
288    
289                    baseSearchEngineMessageListener.setManager(manager);
290                    baseSearchEngineMessageListener.setMessageBus(getMessageBus());
291                    baseSearchEngineMessageListener.setSearchEngine(searchEngine);
292                    baseSearchEngineMessageListener.setSearchEngineId(searchEngineId);
293    
294                    destination.register(
295                            baseSearchEngineMessageListener, getOperatingClassloader());
296            }
297    
298            protected void savePreviousSearchEngineListeners(
299                    Destination searchReaderDestination,
300                    Destination searchWriterDestination,
301                    SearchEngineRegistration searchEngineRegistration) {
302    
303                    Set<MessageListener> searchReaderMessageListeners =
304                            searchReaderDestination.getMessageListeners();
305    
306                    for (MessageListener searchReaderMessageListener :
307                                    searchReaderMessageListeners) {
308    
309                            InvokerMessageListener invokerMessageListener =
310                                    (InvokerMessageListener)searchReaderMessageListener;
311    
312                            searchEngineRegistration.addOriginalSearchReaderMessageListener(
313                                    invokerMessageListener);
314                    }
315    
316                    Set<MessageListener> searchWriterMessageListeners =
317                            searchWriterDestination.getMessageListeners();
318    
319                    for (MessageListener searchWriterMessageListener :
320                                    searchWriterMessageListeners) {
321    
322                            InvokerMessageListener invokerMessageListener =
323                                    (InvokerMessageListener)searchWriterMessageListener;
324    
325                            searchEngineRegistration.addOriginalSearchWriterMessageListener(
326                                    invokerMessageListener);
327                    }
328            }
329    
330            private String _originalSearchEngineId;
331            private List<SearchEngineRegistration> _searchEngineRegistrations =
332                    new ArrayList<SearchEngineRegistration>();
333            private Map<String, SearchEngine> _searchEngines;
334    
335            private class SearchEngineRegistration {
336    
337                    private SearchEngineRegistration(String searchEngineId) {
338                            _searchEngineId = searchEngineId;
339                    }
340    
341                    public void addOriginalSearchReaderMessageListener(
342                            InvokerMessageListener messageListener) {
343    
344                            _originalSearchReaderMessageListeners.add(messageListener);
345                    }
346    
347                    public void addOriginalSearchWriterMessageListener(
348                            InvokerMessageListener messageListener) {
349    
350                            _originalSearchWriterMessageListeners.add(messageListener);
351                    }
352    
353                    public SearchEngineProxyWrapper getOriginalSearchEngineProxyWrapper() {
354                            return _originalSearchEngineProxyWrapper;
355                    }
356    
357                    public List<InvokerMessageListener>
358                            getOriginalSearchReaderMessageListeners() {
359    
360                            return _originalSearchReaderMessageListeners;
361                    }
362    
363                    public List<InvokerMessageListener>
364                            getOriginalSearchWriterMessageListeners() {
365    
366                            return _originalSearchWriterMessageListeners;
367                    }
368    
369                    public String getSearchEngineId() {
370                            return _searchEngineId;
371                    }
372    
373                    public String getSearchReaderDestinationName() {
374                            return _searchReaderDestinationName;
375                    }
376    
377                    public String getSearchWriterDestinationName() {
378                            return _searchWriterDestinationName;
379                    }
380    
381                    public boolean isOverride() {
382                            return _override;
383                    }
384    
385                    public void setOriginalSearchEngineProxyWrapper(
386                            SearchEngineProxyWrapper searchEngineProxyWrapper) {
387    
388                            _originalSearchEngineProxyWrapper = searchEngineProxyWrapper;
389                    }
390    
391                    public void setOverride(boolean override) {
392                            _override = override;
393                    }
394    
395                    public void setSearchReaderDestinationName(
396                            String searchReaderDestinationName) {
397    
398                            _searchReaderDestinationName = searchReaderDestinationName;
399                    }
400    
401                    public void setSearchWriterDestinationName(
402                            String searchWriterDestinationName) {
403    
404                            _searchWriterDestinationName = searchWriterDestinationName;
405                    }
406    
407                    private SearchEngineProxyWrapper _originalSearchEngineProxyWrapper;
408                    private List<InvokerMessageListener>
409                            _originalSearchReaderMessageListeners =
410                                    new ArrayList<InvokerMessageListener>();
411                    private List<InvokerMessageListener>
412                            _originalSearchWriterMessageListeners =
413                                    new ArrayList<InvokerMessageListener>();
414                    private boolean _override;
415                    private String _searchEngineId;
416                    private String _searchReaderDestinationName;
417                    private String _searchWriterDestinationName;
418    
419            }
420    
421    }