KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > help > internal > search > LocalSearchManager


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.help.internal.search;
12
13 import java.io.IOException JavaDoc;
14 import java.net.URL JavaDoc;
15 import java.nio.channels.OverlappingFileLockException JavaDoc;
16 import java.util.ArrayList JavaDoc;
17 import java.util.Collection JavaDoc;
18 import java.util.HashMap JavaDoc;
19 import java.util.HashSet JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.Set JavaDoc;
24 import java.util.StringTokenizer JavaDoc;
25
26 import org.apache.lucene.document.Document;
27 import org.apache.lucene.search.Hits;
28 import org.eclipse.core.runtime.FileLocator;
29 import org.eclipse.core.runtime.IConfigurationElement;
30 import org.eclipse.core.runtime.IProduct;
31 import org.eclipse.core.runtime.IProgressMonitor;
32 import org.eclipse.core.runtime.OperationCanceledException;
33 import org.eclipse.core.runtime.Path;
34 import org.eclipse.core.runtime.Platform;
35 import org.eclipse.help.IHelpResource;
36 import org.eclipse.help.internal.HelpPlugin;
37 import org.eclipse.help.internal.base.BaseHelpSystem;
38 import org.eclipse.help.internal.base.HelpBasePlugin;
39 import org.eclipse.help.internal.search.IndexingOperation.IndexingException;
40 import org.eclipse.help.internal.util.URLCoder;
41 import org.eclipse.help.search.LuceneSearchParticipant;
42 import org.osgi.framework.Bundle;
43
44 /*
45  * Manages indexing and searching for all local help content.
46  */

47 public class LocalSearchManager {
48
49     private static final String JavaDoc SEARCH_PARTICIPANT_XP_FULLNAME = "org.eclipse.help.base.luceneSearchParticipants"; //$NON-NLS-1$
50
private static final String JavaDoc SEARCH_PARTICIPANT_XP_NAME = "searchParticipant"; //$NON-NLS-1$
51
private static final String JavaDoc BINDING_XP_NAME = "binding"; //$NON-NLS-1$
52
private static final Object JavaDoc PARTICIPANTS_NOT_FOUND = new Object JavaDoc();
53     private Map JavaDoc indexes = new HashMap JavaDoc();
54     private Map JavaDoc analyzerDescriptors = new HashMap JavaDoc();
55     private Map JavaDoc searchParticipantsById = new HashMap JavaDoc();
56     private Map JavaDoc searchParticipantsByPlugin = new HashMap JavaDoc();
57     private ArrayList JavaDoc globalSearchParticipants;
58
59     private static class ParticipantDescriptor implements IHelpResource {
60
61         private IConfigurationElement element;
62         private LuceneSearchParticipant participant;
63
64         public ParticipantDescriptor(IConfigurationElement element) {
65             this.element = element;
66         }
67
68         public String JavaDoc getId() {
69             return element.getAttribute("id"); //$NON-NLS-1$
70
}
71
72         public boolean matches(String JavaDoc extension) {
73             String JavaDoc ext = element.getAttribute("extensions"); //$NON-NLS-1$
74
if (ext == null)
75                 return false;
76             StringTokenizer JavaDoc stok = new StringTokenizer JavaDoc(ext, ","); //$NON-NLS-1$
77
for (; stok.hasMoreTokens();) {
78                 String JavaDoc token = stok.nextToken().trim();
79                 if (token.equalsIgnoreCase(extension))
80                     return true;
81             }
82             return false;
83         }
84
85         public boolean hasExtensions() {
86             return element.getAttribute("extensions") != null; //$NON-NLS-1$
87
}
88
89         public IHelpResource getCategory() {
90             return this;
91         }
92
93         public LuceneSearchParticipant getParticipant() {
94             if (participant == null) {
95                 try {
96                     Object JavaDoc obj = element.createExecutableExtension("participant"); //$NON-NLS-1$
97
if (obj instanceof LuceneSearchParticipant) {
98                         participant = (LuceneSearchParticipant) obj;
99                         participant.init(getId());
100                     }
101                 } catch (Throwable JavaDoc t) {
102                     HelpPlugin.logError("Exception occurred creating Lucene search participant.", t); //$NON-NLS-1$
103
}
104             }
105             return participant;
106         }
107
108         public boolean contains(IConfigurationElement el) {
109             return element.equals(el);
110         }
111
112         public String JavaDoc getHref() {
113             return null;
114         }
115
116         public String JavaDoc getLabel() {
117             return element.getAttribute("name"); //$NON-NLS-1$
118
}
119
120         public URL JavaDoc getIconURL() {
121             String JavaDoc relativePath = element.getAttribute("icon"); //$NON-NLS-1$
122
if (relativePath == null)
123                 return null;
124             String JavaDoc bundleId = element.getContributor().getName();
125             Bundle bundle = Platform.getBundle(bundleId);
126             if (bundle == null)
127                 return null;
128             return FileLocator.find(bundle, new Path(relativePath), null);
129         }
130
131         public void clear() {
132             if (participant != null) {
133                 try {
134                     participant.clear();
135                 }
136                 catch (Throwable JavaDoc t) {
137                     HelpBasePlugin.logError("Error occured in search participant's clear() operation: " + participant.getClass().getName(), t); //$NON-NLS-1$
138
}
139             }
140         }
141     }
142
143     /**
144      * Converts the given Hits object into a List of raw SearchHits.
145      * Hits objects are immutable and can't be instantiated from outside
146      * Lucene.
147      *
148      * @param hits the Hits object to convert
149      * @return a List of raw SearchHits
150      */

151     public static List JavaDoc asList(Hits hits) {
152         List JavaDoc list = new ArrayList JavaDoc(hits.length());
153         for (int i=0;i<hits.length();++i) {
154             try {
155                 Document doc = hits.doc(i);
156                 float score = hits.score(i);
157                 String JavaDoc href = doc.get("name"); //$NON-NLS-1$
158
String JavaDoc summary = doc.get("summary"); //$NON-NLS-1$
159
String JavaDoc id = doc.get("id"); //$NON-NLS-1$
160
String JavaDoc participantId = doc.get("participantId"); //$NON-NLS-1$
161
String JavaDoc label = doc.get("raw_title"); //$NON-NLS-1$
162
boolean isPotentialHit = (doc.get("filters") != null); //$NON-NLS-1$
163
list.add(new SearchHit(href, label, summary, score, null, id, participantId, isPotentialHit));
164             }
165             catch (IOException JavaDoc e) {
166                 HelpBasePlugin.logError("An error occured while reading search hits", e); //$NON-NLS-1$
167
continue;
168             }
169         }
170         return list;
171     }
172     
173     /**
174      * Public for use by indexing tool
175      */

176     public SearchIndexWithIndexingProgress getIndex(String JavaDoc locale) {
177         synchronized (indexes) {
178             Object JavaDoc index = indexes.get(locale);
179             if (index == null) {
180                 index = new SearchIndexWithIndexingProgress(locale, getAnalyzer(locale), HelpPlugin
181                         .getTocManager());
182                 indexes.put(locale, index);
183             }
184             return (SearchIndexWithIndexingProgress) index;
185         }
186     }
187
188     /**
189      * Obtains AnalyzerDescriptor that indexing and search should use for a given locale.
190      *
191      * @param locale
192      * 2 or 5 character locale representation
193      */

194     private AnalyzerDescriptor getAnalyzer(String JavaDoc locale) {
195         // get an analyzer from cache
196
AnalyzerDescriptor analyzerDesc = (AnalyzerDescriptor) analyzerDescriptors.get(locale);
197         if (analyzerDesc != null)
198             return analyzerDesc;
199
200         // obtain configured analyzer for this locale
201
analyzerDesc = new AnalyzerDescriptor(locale);
202         // save analyzer in the cache
203
analyzerDescriptors.put(locale, analyzerDesc);
204         String JavaDoc lang = analyzerDesc.getLang();
205         if (locale != null && !locale.equals(lang))
206             analyzerDescriptors.put(lang, analyzerDesc);
207
208         return analyzerDesc;
209     }
210
211     public static String JavaDoc trimQuery(String JavaDoc href) {
212         // trim the query
213
int qloc = href.indexOf('?');
214         if (qloc != -1)
215             return href.substring(0, qloc);
216         return href;
217     }
218
219     public boolean isIndexable(String JavaDoc url) {
220         url = trimQuery(url);
221         ArrayList JavaDoc list = getParticipantDescriptors(getPluginId(url));
222         if (list == null)
223             return false;
224         int dotLoc = url.lastIndexOf('.');
225         String JavaDoc ext = url.substring(dotLoc + 1);
226         for (int i = 0; i < list.size(); i++) {
227             ParticipantDescriptor desc = (ParticipantDescriptor) list.get(i);
228             if (desc.matches(ext))
229                 return true;
230         }
231         return false;
232     }
233     
234     /**
235      * Returns whether or not a participant with the given headless attribute should be
236      * enabled in the current mode. Participants that support headless are always enabled, and
237      * those that don't are only enabled when in workbench mode.
238      *
239      * @param headless whether or not the participant supports headless mode
240      * @return whether or not the participant should be enabled
241      */

242     private static boolean isParticipantEnabled(boolean headless) {
243         if (!headless) {
244             return (BaseHelpSystem.getMode() == BaseHelpSystem.MODE_WORKBENCH);
245         }
246         return true;
247     }
248
249     public static String JavaDoc getPluginId(String JavaDoc href) {
250         href = trimQuery(href);
251         // Assume the url is pluginID/path_to_topic.html
252
if (href.charAt(0) == '/')
253             href = href.substring(1);
254         int i = href.indexOf('/');
255         String JavaDoc pluginId = i == -1 ? "" : href.substring(0, i); //$NON-NLS-1$
256
pluginId = URLCoder.decode(pluginId);
257         if ("PRODUCT_PLUGIN".equals(pluginId)) { //$NON-NLS-1$
258
IProduct product = Platform.getProduct();
259             if (product != null) {
260                 pluginId = product.getDefiningBundle().getSymbolicName();
261             }
262         }
263         return pluginId;
264     }
265
266     public LuceneSearchParticipant getGlobalParticipant(String JavaDoc participantId) {
267         ParticipantDescriptor desc = getGlobalParticipantDescriptor(participantId);
268         return desc != null ? desc.getParticipant() : null;
269     }
270
271     public IHelpResource getParticipantCategory(String JavaDoc participantId) {
272         ParticipantDescriptor desc = getGlobalParticipantDescriptor(participantId);
273         return desc != null ? desc.getCategory() : null;
274     }
275
276     public URL JavaDoc getParticipantIconURL(String JavaDoc participantId) {
277         ParticipantDescriptor desc = getGlobalParticipantDescriptor(participantId);
278         return desc != null ? desc.getIconURL() : null;
279     }
280
281     private ParticipantDescriptor getGlobalParticipantDescriptor(String JavaDoc participantId) {
282         if (globalSearchParticipants == null) {
283             createGlobalSearchParticipants();
284         }
285         for (int i = 0; i < globalSearchParticipants.size(); i++) {
286             ParticipantDescriptor desc = (ParticipantDescriptor) globalSearchParticipants.get(i);
287             if (desc.getId().equals(participantId)) {
288                 return desc;
289             }
290         }
291         return null;
292     }
293
294     /**
295      * Returns the lucene search participant with the given id, or null if it could not
296      * be found.
297      *
298      * @param participantId the participant's unique id
299      * @return the participant with the given id
300      */

301     public LuceneSearchParticipant getParticipant(String JavaDoc participantId) {
302         ParticipantDescriptor desc = (ParticipantDescriptor)searchParticipantsById.get(participantId);
303         if (desc != null) {
304             return desc.getParticipant();
305         }
306         return null;
307     }
308     
309     /**
310      * Returns a TOC file participant for the provided plug-in and file name.
311      *
312      * @param pluginId
313      * @param fileName
314      * @return
315      */

316
317     public LuceneSearchParticipant getParticipant(String JavaDoc pluginId, String JavaDoc fileName) {
318         ArrayList JavaDoc list = getParticipantDescriptors(pluginId);
319         if (list == null)
320             return null;
321         int dotLoc = fileName.lastIndexOf('.');
322         String JavaDoc ext = fileName.substring(dotLoc + 1);
323         for (int i = 0; i < list.size(); i++) {
324             ParticipantDescriptor desc = (ParticipantDescriptor) list.get(i);
325             if (desc.matches(ext))
326                 return desc.getParticipant();
327         }
328         return null;
329     }
330
331     /**
332      * Returns whether or not the given search participant is bound to the given
333      * plugin.
334      *
335      * @param pluginId the id of the plugin
336      * @param participantId the id of the search participant
337      * @return whether or not the participant is bound to the plugin
338      */

339     public boolean isParticipantBound(String JavaDoc pluginId, String JavaDoc participantId) {
340         List JavaDoc list = getParticipantDescriptors(pluginId);
341         if (list != null) {
342             Iterator JavaDoc iter = list.iterator();
343             while (iter.hasNext()) {
344                 ParticipantDescriptor desc = (ParticipantDescriptor)iter.next();
345                 if (participantId.equals(desc.getId())) {
346                     return true;
347                 }
348             }
349         }
350         return false;
351     }
352     
353     /**
354      * Returns a set of plug-in Ids that have search participants or bindings.
355      *
356      * @return a set of plug-in Ids
357      */

358
359     public Set JavaDoc getPluginsWithSearchParticipants() {
360         HashSet JavaDoc set = new HashSet JavaDoc();
361         IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(
362                 SEARCH_PARTICIPANT_XP_FULLNAME);
363
364         for (int i = 0; i < elements.length; i++) {
365             IConfigurationElement element = elements[i];
366             if (element.getName().equals("binding") || element.getName().equals("searchParticipant")) //$NON-NLS-1$//$NON-NLS-2$
367
set.add(element.getContributor().getName());
368         }
369         // must ask global search participants directly
370
LuceneSearchParticipant[] gps = getGlobalParticipants();
371         for (int i = 0; i < gps.length; i++) {
372             Set JavaDoc ids;
373             try {
374                 ids = gps[i].getContributingPlugins();
375             }
376             catch (Throwable JavaDoc t) {
377                 HelpBasePlugin.logError("Error getting the contributing plugins from help search participant: " + gps[i].getClass().getName() + ". skipping this one.", t); //$NON-NLS-1$ //$NON-NLS-2$
378
continue;
379             }
380             set.addAll(ids);
381         }
382         return set;
383     }
384
385     /**
386      * Loops through all the loaded search participants and notifies them that they can drop the
387      * cached data to reduce runtime memory footprint.
388      */

389     public void clearSearchParticipants() {
390         Iterator JavaDoc iter = searchParticipantsById.values().iterator();
391         while (iter.hasNext()) {
392             ParticipantDescriptor desc = (ParticipantDescriptor)iter.next();
393             desc.clear();
394         }
395     }
396
397     private ArrayList JavaDoc createSearchParticipants(String JavaDoc pluginId) {
398         IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(
399                 SEARCH_PARTICIPANT_XP_FULLNAME);
400         if (elements.length == 0)
401             return null;
402         ArrayList JavaDoc list = null;
403
404         ArrayList JavaDoc binding = null;
405         for (int i = 0; i < elements.length; i++) {
406             IConfigurationElement element = elements[i];
407             if (!element.getContributor().getName().equals(pluginId)) {
408                 continue;
409             }
410             if (BINDING_XP_NAME.equals(element.getName())) {
411                 // binding - locate the referenced participant
412
String JavaDoc refId = element.getAttribute("participantId"); //$NON-NLS-1$
413
for (int j = 0; j < elements.length; j++) {
414                     IConfigurationElement rel = elements[j];
415                     if (!rel.getName().equals("searchParticipant")) //$NON-NLS-1$
416
continue;
417                     // don't allow binding the global participants
418
if (rel.getAttribute("extensions") == null) //$NON-NLS-1$
419
continue;
420                     String JavaDoc id = rel.getAttribute("id"); //$NON-NLS-1$
421
if (id != null && id.equals(refId)) {
422                         // match
423
if (binding == null)
424                             binding = new ArrayList JavaDoc();
425                         binding.add(rel);
426                         break;
427                     }
428                 }
429             } else if (SEARCH_PARTICIPANT_XP_NAME.equals(element.getName())) {
430                 // ignore global participant
431
if (element.getAttribute("extensions") == null) //$NON-NLS-1$
432
continue;
433                 if (!isParticipantEnabled(String.valueOf(true).equals(element.getAttribute("headless")))) //$NON-NLS-1$
434
continue;
435                 if (list == null)
436                     list = new ArrayList JavaDoc();
437                 ParticipantDescriptor desc = new ParticipantDescriptor(element);
438                 list.add(desc);
439                 searchParticipantsById.put(desc.getId(), desc);
440             }
441         }
442         if (binding != null)
443             list = addBoundDescriptors(list, binding);
444         return list;
445     }
446
447     /**
448      * Locates the
449      *
450      * @param list
451      * @param binding
452      * @return
453      */

454
455     private ArrayList JavaDoc addBoundDescriptors(ArrayList JavaDoc list, ArrayList JavaDoc binding) {
456         for (int i = 0; i < binding.size(); i++) {
457             IConfigurationElement refEl = (IConfigurationElement) binding.get(i);
458             Collection JavaDoc collection = searchParticipantsByPlugin.values();
459             boolean found = false;
460             for (Iterator JavaDoc iter = collection.iterator(); iter.hasNext();) {
461                 if (found)
462                     break;
463                 Object JavaDoc entry = iter.next();
464                 if (entry == PARTICIPANTS_NOT_FOUND)
465                     continue;
466                 ArrayList JavaDoc participants = (ArrayList JavaDoc) entry;
467                 for (int j = 0; j < participants.size(); j++) {
468                     ParticipantDescriptor desc = (ParticipantDescriptor) participants.get(j);
469                     if (desc.contains(refEl)) {
470                         // found the matching rescriptor - add it to the list
471
if (list == null)
472                             list = new ArrayList JavaDoc();
473                         list.add(desc);
474                         found = true;
475                         break;
476                     }
477                 }
478             }
479             if (!found) {
480                 if (list == null)
481                     list = new ArrayList JavaDoc();
482                 ParticipantDescriptor d = new ParticipantDescriptor(refEl);
483                 list.add(d);
484                 searchParticipantsById.put(d.getId(), d);
485             }
486         }
487         return list;
488     }
489
490     /**
491      * Returns an array of search participants with the global scope (no extensions).
492      *
493      * @return an array of the global search participants.
494      */

495
496     public LuceneSearchParticipant[] getGlobalParticipants() {
497         if (globalSearchParticipants == null) {
498             createGlobalSearchParticipants();
499         }
500         ArrayList JavaDoc result = new ArrayList JavaDoc();
501         for (int i = 0; i < globalSearchParticipants.size(); i++) {
502             ParticipantDescriptor desc = (ParticipantDescriptor) globalSearchParticipants.get(i);
503             LuceneSearchParticipant p = desc.getParticipant();
504             if (p != null)
505                 result.add(p);
506         }
507         return (LuceneSearchParticipant[]) result.toArray(new LuceneSearchParticipant[result.size()]);
508     }
509
510     private void createGlobalSearchParticipants() {
511         globalSearchParticipants = new ArrayList JavaDoc();
512         IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(
513                 SEARCH_PARTICIPANT_XP_FULLNAME);
514         for (int i = 0; i < elements.length; i++) {
515             IConfigurationElement element = elements[i];
516             if (!element.getName().equals(SEARCH_PARTICIPANT_XP_NAME))
517                 continue;
518             if (element.getAttribute("extensions") != null) //$NON-NLS-1$
519
continue;
520             if (!isParticipantEnabled(String.valueOf(true).equals(element.getAttribute("headless")))) //$NON-NLS-1$
521
continue;
522             ParticipantDescriptor desc = new ParticipantDescriptor(element);
523             globalSearchParticipants.add(desc);
524         }
525     }
526
527     private ArrayList JavaDoc getParticipantDescriptors(String JavaDoc pluginId) {
528         Object JavaDoc result = searchParticipantsByPlugin.get(pluginId);
529         if (result == null) {
530             result = createSearchParticipants(pluginId);
531             if (result == null)
532                 result = PARTICIPANTS_NOT_FOUND;
533             searchParticipantsByPlugin.put(pluginId, result);
534         }
535         if (result == PARTICIPANTS_NOT_FOUND)
536             return null;
537         return (ArrayList JavaDoc) result;
538     }
539
540     public void search(ISearchQuery searchQuery, ISearchHitCollector collector, IProgressMonitor pm)
541             throws QueryTooComplexException {
542         SearchIndexWithIndexingProgress index = getIndex(searchQuery.getLocale());
543         ensureIndexUpdated(pm, index);
544         if (index.exists()) {
545             index.search(searchQuery, collector);
546         }
547     }
548     
549     /**
550      * Updates index. Checks if all contributions were indexed. If not, it indexes them.
551      *
552      * @throws OperationCanceledException
553      * if indexing was cancelled
554      */

555     public void ensureIndexUpdated(IProgressMonitor pm, SearchIndexWithIndexingProgress index)
556             throws OperationCanceledException {
557
558         ProgressDistributor progressDistrib = index.getProgressDistributor();
559         progressDistrib.addMonitor(pm);
560         boolean configurationLocked = false;
561         try {
562             // Prevent two workbench or stand-alone help instances from updating
563
// index concurently. Lock is created for every search request, so
564
// do not use it in infocenter, for performance (administrator will
565
// need to ensure index is updated before launching another
566
// infocenter instance on the same configuration).
567
if (BaseHelpSystem.MODE_INFOCENTER != BaseHelpSystem.getMode()) {
568                 try {
569                     configurationLocked = index.tryLock();
570                     if (!configurationLocked) {
571                         // Index is being updated by another proces
572
// do not update or wait, just continue with search
573
pm.beginTask("", 1); //$NON-NLS-1$
574
pm.worked(1);
575                         pm.done();
576                         return;
577                     }
578                 } catch (OverlappingFileLockException JavaDoc ofle) {
579                     // Another thread in this process is indexing and using the
580
// lock
581
}
582             }
583             // Only one index update occurs in VM at a time,
584
// but progress SearchProgressMonitor for other locales
585
// are waiting until we know if indexing is needed
586
// to prevent showing progress on first search after launch
587
// if no indexing is needed
588
if (index.isClosed() || !index.needsUpdating()) {
589                 // very good, can search
590
pm.beginTask("", 1); //$NON-NLS-1$
591
pm.worked(1);
592                 pm.done();
593                 return;
594             }
595             if (pm instanceof SearchProgressMonitor) {
596                 ((SearchProgressMonitor) pm).started();
597             }
598             updateIndex(pm, index, progressDistrib);
599         } finally {
600             progressDistrib.removeMonitor(pm);
601             if (configurationLocked) {
602                 index.releaseLock();
603             }
604         }
605     }
606
607     private synchronized void updateIndex(IProgressMonitor pm, SearchIndex index,
608             ProgressDistributor progressDistrib) {
609         if (index.isClosed() || !index.needsUpdating()) {
610             pm.beginTask("", 1); //$NON-NLS-1$
611
pm.worked(1);
612             pm.done();
613             return;
614         }
615         try {
616             PluginVersionInfo versions = index.getDocPlugins();
617             if (versions == null) {
618                 pm.beginTask("", 1); //$NON-NLS-1$
619
pm.worked(1);
620                 pm.done();
621                 return;
622             }
623             IndexingOperation indexer = new IndexingOperation(index);
624             indexer.execute(progressDistrib);
625             return;
626         }
627         catch (OperationCanceledException e) {
628             progressDistrib.operationCanceled();
629             throw e;
630         }
631         catch (IndexingException e) {
632             String JavaDoc msg = "Error indexing documents"; //$NON-NLS-1$
633
HelpBasePlugin.logError(msg, e);
634         }
635     }
636
637     /*
638      * Closes all indexes.
639      */

640     public void close() {
641         synchronized (indexes) {
642             for (Iterator JavaDoc it = indexes.values().iterator(); it.hasNext();) {
643                 ((SearchIndex) it.next()).close();
644             }
645         }
646     }
647
648     public synchronized void tocsChanged() {
649         Collection JavaDoc activeIndexes = new ArrayList JavaDoc();
650         synchronized (indexes) {
651             activeIndexes.addAll(indexes.values());
652         }
653         for (Iterator JavaDoc it = activeIndexes.iterator(); it.hasNext();) {
654             SearchIndexWithIndexingProgress ix = (SearchIndexWithIndexingProgress) it.next();
655             ix.close();
656             synchronized (indexes) {
657                 indexes.remove(ix.getLocale());
658                 ProgressDistributor pm = ix.getProgressDistributor();
659                 pm.beginTask("", 1); //$NON-NLS-1$
660
pm.worked(1);
661                 pm.done();
662                 SearchProgressMonitor.reinit(ix.getLocale());
663             }
664         }
665     }
666 }
667
Popular Tags