KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > help > search > HelpIndexBuilder


1 /*******************************************************************************
2  * Copyright (c) 2004, 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.search;
12
13 import java.io.File JavaDoc;
14 import java.io.FileInputStream JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.io.InputStream JavaDoc;
17 import java.io.InputStreamReader JavaDoc;
18 import java.net.MalformedURLException JavaDoc;
19 import java.net.URL JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collection JavaDoc;
22 import java.util.Dictionary JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.Locale JavaDoc;
26 import java.util.Properties JavaDoc;
27 import java.util.Set JavaDoc;
28 import java.util.jar.Attributes JavaDoc;
29 import java.util.jar.Manifest JavaDoc;
30
31 import javax.xml.parsers.DocumentBuilder JavaDoc;
32 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
33
34 import org.eclipse.core.runtime.CoreException;
35 import org.eclipse.core.runtime.IProgressMonitor;
36 import org.eclipse.core.runtime.IStatus;
37 import org.eclipse.core.runtime.MultiStatus;
38 import org.eclipse.core.runtime.OperationCanceledException;
39 import org.eclipse.core.runtime.Platform;
40 import org.eclipse.core.runtime.Status;
41 import org.eclipse.core.runtime.SubProgressMonitor;
42 import org.eclipse.help.internal.base.HelpBasePlugin;
43 import org.eclipse.help.internal.base.HelpBaseResources;
44 import org.eclipse.help.internal.search.AnalyzerDescriptor;
45 import org.eclipse.help.internal.search.PluginVersionInfo;
46 import org.eclipse.help.internal.search.SearchIndex;
47 import org.eclipse.osgi.util.ManifestElement;
48 import org.eclipse.osgi.util.NLS;
49 import org.osgi.framework.Constants;
50 import org.osgi.framework.Version;
51 import org.w3c.dom.Document JavaDoc;
52 import org.w3c.dom.Element JavaDoc;
53 import org.w3c.dom.NamedNodeMap JavaDoc;
54 import org.w3c.dom.Node JavaDoc;
55 import org.w3c.dom.NodeList JavaDoc;
56 import org.xml.sax.InputSource JavaDoc;
57
58 /**
59  * Builds a help search index for a plug-in by looking for the
60  * <code>org.eclipse.help.toc</code> extensions in the provided manifest file.
61  * Search index is only created if index path is specified in the extension.
62  * Index will contain data for all the topics listed in all the TOCs declared in
63  * the plug-in.
64  * <p>
65  * If the index is created for a fragment, the manifest must point at the
66  * referenced fragment plug-in, while the destination should be the fragment
67  * itself.
68  * <p>
69  * Starting from the provided destination directory, index for each locale will
70  * be placed in a directory with the following path:
71  * <p>
72  * <pre>
73  * destination/nl/country/
74  *
75  * or
76  *
77  * destination/nl/country/language/
78  * </pre>
79  * <p>
80  * The relative directory specified in the <code>index</code> element of the
81  * <code>org.eclipse.help.toc</code> extention will be created in each of the
82  * locale-specific paths (one per locale).
83  * <p>
84  * An instance of <code>HelpIndexBuilder</code> can be cached and used
85  * multiple times for different manifest and destination values.
86  *
87  * @since 3.1
88  */

89
90 public class HelpIndexBuilder {
91     private static final String JavaDoc POINT_TOC = "org.eclipse.help.toc"; //$NON-NLS-1$
92

93     private static final String JavaDoc EL_TOC = "toc"; //$NON-NLS-1$
94

95     private static final String JavaDoc EL_INDEX = "index"; //$NON-NLS-1$
96

97     private File JavaDoc manifest;
98
99     private String JavaDoc indexPath;
100
101     private File JavaDoc destination;
102     
103     private ArrayList JavaDoc tocFiles = new ArrayList JavaDoc();
104
105     private ArrayList JavaDoc localeDirs = new ArrayList JavaDoc();
106
107     private static final DocumentBuilderFactory JavaDoc documentBuilderFactory = DocumentBuilderFactory
108             .newInstance();
109
110     private DocumentBuilder JavaDoc parser;
111     
112     private static Locale JavaDoc[] legalLocales = Locale.getAvailableLocales();
113     private static HashSet JavaDoc legalLanguages = null;
114     private static HashSet JavaDoc legalCountries = null;
115
116     class PluginIdentifier {
117         String JavaDoc id;
118
119         Version version;
120
121         public PluginIdentifier(String JavaDoc id, String JavaDoc version) {
122             this.id = id;
123             this.version = new Version(version);
124         }
125     }
126
127     class LocaleDir {
128         String JavaDoc locale;
129         String JavaDoc relativePath;
130         ArrayList JavaDoc dirs = new ArrayList JavaDoc();
131
132         public LocaleDir(String JavaDoc locale, String JavaDoc relativePath) {
133             this.locale = locale;
134             this.relativePath = relativePath;
135         }
136         
137         public File JavaDoc findFile(String JavaDoc file) {
138             for (int i=0; i<dirs.size(); i++) {
139                 File JavaDoc dir = (File JavaDoc)dirs.get(i);
140                 File JavaDoc absoluteFile = new File JavaDoc(dir, file);
141                 if (absoluteFile.exists())
142                     return absoluteFile;
143             }
144             return null;
145         }
146         public URL JavaDoc findURL(String JavaDoc href) {
147             File JavaDoc file = findFile(href);
148             if (file!=null) {
149                 try {
150                         return file.toURL();
151                     }
152                 catch (MalformedURLException JavaDoc e) {
153                 }
154             }
155             return null;
156         }
157         public void addDirectory(File JavaDoc directory) {
158             dirs.add(directory);
159         }
160     }
161
162     class IndexerPluginVersionInfo extends PluginVersionInfo {
163         private static final long serialVersionUID = 1L;
164
165         public IndexerPluginVersionInfo(PluginIdentifier id,
166                 PluginIdentifier fid, File JavaDoc dir) {
167             super(SearchIndex.INDEXED_CONTRIBUTION_INFO_FILE, null, dir, false);
168             createInfo(id, fid);
169         }
170
171         protected void createTable(Collection JavaDoc docBundleIds) {
172             // do nothing
173
}
174
175         protected void createInfo(PluginIdentifier id, PluginIdentifier fid) {
176             // We will ignore docBundleIds which is null anyway,
177
// and use id and fid to create plugin info
178
// for the destination
179
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
180             appendBundleInformation(buffer, id.id, id.version.toString());
181             if (fid != null)
182                 appendBundleInformation(buffer, fid.id, fid.version.toString());
183
184             this.put(id.id, buffer.toString());
185         }
186     }
187
188     class TocFile {
189         String JavaDoc href;
190         boolean primary;
191         String JavaDoc extraDir;
192         
193         public TocFile(String JavaDoc href, boolean primary, String JavaDoc extraDir) {
194             this.href = href;
195             this.primary = primary;
196             this.extraDir = extraDir;
197         }
198     }
199
200     /**
201      * Creates a new instance of the help index builder.
202      */

203     public HelpIndexBuilder() {
204     }
205
206     /**
207      * Returns the manifest file for this builder. If the target is a plug-in,
208      * it is the absolute path of <code>plugin.xml</code> file. If the target
209      * is a fragment, it is the absolute path of <code>plugin.xml</code> of
210      * the fragment plug-in.
211      *
212      * @return the file that contains TOC extensions
213      */

214     public File JavaDoc getManifest() {
215         return manifest;
216     }
217
218     /**
219      * Sets the new manifest file (plugin.xml) to be used by this builder. If
220      * the target is a plug-in, it is the absolute path of
221      * <code>plugin.xml</code> file. If the target is a fragment, it is the
222      * absolute path of <code>plugin.xml</code> of the fragment plug-in.
223      *
224      * @param manifest
225      * the file that contains TOC extensions
226      */

227     public void setManifest(File JavaDoc manifest) {
228         if (manifest.getName().equalsIgnoreCase("MANIFEST.MF")) { //$NON-NLS-1$
229
File JavaDoc parent = manifest.getParentFile();
230             if (parent.getName().equalsIgnoreCase("META-INF")) { //$NON-NLS-1$
231
File JavaDoc project = parent.getParentFile();
232                 manifest = new File JavaDoc(project, "plugin.xml"); //$NON-NLS-1$
233
if (!manifest.exists())
234                     manifest=null;
235             }
236         }
237         this.manifest = manifest;
238     }
239
240     /**
241      * Returns the destination directory where index should be created.
242      *
243      * @return the destination index directory
244      */

245     public File JavaDoc getDestination() {
246         return destination;
247     }
248
249     /**
250      * Sets the destination directory where index should be created.
251      * Locale-specific directories will be created starting from this directory.
252      *
253      * @param destination
254      * the directory where index should be created
255      */

256     public void setDestination(File JavaDoc destination) {
257         this.destination = destination;
258     }
259
260     /**
261      * Creates the plug-in search index by parsing the provided plugin.xml file,
262      * looking for TOC extensions. If at least one of them has
263      * <code>index</code> element, all topics listed in all the TOCs in the
264      * plug-in will be indexed and stored in the path specified by the
265      * <code>index</code> element.
266      *
267      * @param monitor
268      * the monitor to track index creation progress
269      * @throws CoreException
270      * if there are problems during index creation.
271      */

272
273     public void execute(IProgressMonitor monitor) throws CoreException {
274         reset();
275         if (manifest == null || destination == null)
276             return;
277         Document JavaDoc doc = readXMLFile(manifest);
278         if (doc == null)
279             return;
280
281         PluginIdentifier pid = getPluginID(manifest.getParentFile(), doc);
282         PluginIdentifier fid = null;
283         
284         if (!manifest.getParentFile().equals(destination)) {
285             // target is a fragment, source is a plug-in
286
File JavaDoc fragmentFile = new File JavaDoc(destination, "fragment.xml"); //$NON-NLS-1$
287
Document JavaDoc fdoc=null;
288             if (fragmentFile.exists())
289                 fdoc = readXMLFile(fragmentFile);
290             fid = getPluginID(destination, fdoc);
291             fdoc=null;
292         }
293
294         Element[] extensions = getTocExtensions(doc);
295         for (int i = 0; i < extensions.length; i++) {
296             processExtension(extensions[i]);
297         }
298         if (indexPath == null) {
299             throwCoreException(HelpBaseResources.HelpIndexBuilder_noDestinationPath, null);
300         }
301         doc = null; // discard the DOM
302

303         // compute the dir tree
304
computeLocaleDirs(fid!=null);
305
306         monitor.beginTask(HelpBaseResources.HelpIndexBuilder_buildingIndex, localeDirs.size());
307         MultiStatus multiStatus = null;
308
309         for (int i=0; i<localeDirs.size(); i++) {
310             // process locale dir
311
LocaleDir localeDir = (LocaleDir) localeDirs.get(i);
312             MultiStatus localeStatus = processLocaleDir(pid, fid,
313                     localeDir, new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
314             if (localeStatus != null) {
315                 if (multiStatus == null)
316                     multiStatus = localeStatus;
317                 else
318                     multiStatus.addAll(localeStatus);
319             }
320         }
321         monitor.done();
322         if (multiStatus != null)
323             throw new CoreException(multiStatus);
324     }
325
326     /*
327      * Extracts TOCs and the index path from the extensions.
328      */

329     private void processExtension(Element extensionNode) {
330         NodeList JavaDoc children = extensionNode.getElementsByTagName(EL_TOC);
331         for (int i = 0; i < children.getLength(); i++) {
332             Node JavaDoc node = children.item(i);
333             String JavaDoc file = getAttribute(node, "file"); //$NON-NLS-1$
334
String JavaDoc primary = getAttribute(node, "primary"); //$NON-NLS-1$
335
String JavaDoc extradir = getAttribute(node, "extradir"); //$NON-NLS-1$
336
addTocFile(file, primary, extradir);
337         }
338         children = extensionNode.getElementsByTagName(EL_INDEX);
339         if (children.getLength() == 1) {
340             Node JavaDoc node = children.item(0);
341             indexPath = getAttribute(node, "path"); //$NON-NLS-1$
342
}
343     }
344
345     private void addTocFile(String JavaDoc file, String JavaDoc primary, String JavaDoc extradir) {
346         boolean isPrimary = primary != null && primary.equalsIgnoreCase("true"); //$NON-NLS-1$
347
tocFiles.add(new TocFile(file, isPrimary, extradir));
348     }
349
350     /*
351      * Computes the all os/*, ws/*, nl/language/ and
352      * nl/language/country/ locale dirs that contain files. We will
353      * produce an index for each one.
354      */

355     private void computeLocaleDirs(boolean fragment) {
356         if (!fragment) {
357             LocaleDir dir = new LocaleDir(null, "/"); //$NON-NLS-1$
358
dir.addDirectory(destination);
359             localeDirs.add(dir);
360         }
361         File JavaDoc ws = new File JavaDoc(destination, "ws"); //$NON-NLS-1$
362
computeSystem(ws, Platform.knownWSValues());
363         File JavaDoc os = new File JavaDoc(destination, "os"); //$NON-NLS-1$
364
computeSystem(os, Platform.knownOSValues());
365         
366         File JavaDoc nl = new File JavaDoc(destination, "nl"); //$NON-NLS-1$
367
if (!nl.exists() || !nl.isDirectory())
368             return;
369         File JavaDoc [] languages = nl.listFiles();
370         HashSet JavaDoc locales = new HashSet JavaDoc();
371         for (int i=0; i<languages.length; i++) {
372             File JavaDoc language = languages[i];
373             if (!language.isDirectory())
374                 continue;
375             if (!isValidLanguage(language.getName()))
376                 continue;
377             File JavaDoc [] countries = language.listFiles();
378             for (int j=0; j<countries.length; j++) {
379                 File JavaDoc country = countries[j];
380                 String JavaDoc locale;
381                 boolean hasCountry = false;
382                 if (country.isDirectory() && isValidCountry(country.getName()))
383                     hasCountry = true;
384                 if (hasCountry)
385                     locale = language.getName()+"_"+country.getName(); //$NON-NLS-1$
386
else
387                     locale = language.getName();
388                 if (isValidLocale(locale) && !locales.contains(locale)) {
389                     String JavaDoc relativePath;
390                     if (hasCountry)
391                         relativePath = "/nl/"+language.getName()+"/"+country.getName(); //$NON-NLS-1$ //$NON-NLS-2$
392
else
393                         relativePath = "/nl/"+language.getName(); //$NON-NLS-1$
394
LocaleDir dir = new LocaleDir(locale, relativePath);
395                     if (hasCountry)
396                         dir.addDirectory(country);
397                     dir.addDirectory(language);
398                     dir.addDirectory(destination);
399                     localeDirs.add(dir);
400                     locales.add(locale);
401                 }
402             }
403         }
404     }
405     
406     private void computeSystem(File JavaDoc systemRoot, String JavaDoc [] values) {
407         if (systemRoot.exists() && systemRoot.isDirectory()) {
408             // check
409
File JavaDoc [] files = systemRoot.listFiles();
410             for (int i=0; i<files.length; i++) {
411                 File JavaDoc sdir = files[i];
412                 if (!sdir.isDirectory())
413                     continue;
414                 String JavaDoc sname = sdir.getName();
415                 for (int j=0; j<values.length; j++) {
416                     if (values[j].equals(sname)) {
417                         // valid
418
String JavaDoc relativePath="/"+systemRoot.getName()+"/"+sname; //$NON-NLS-1$ //$NON-NLS-2$
419
LocaleDir dir = new LocaleDir(sname, relativePath);
420                         dir.addDirectory(sdir);
421                         dir.addDirectory(destination);
422                         localeDirs.add(dir);
423                         break;
424                     }
425                 }
426             }
427         }
428     }
429
430     /*
431      * Reject bogus directories.
432      */

433     private boolean isValidLocale(String JavaDoc locale) {
434         for (int i=0; i<legalLocales.length; i++) {
435             Locale JavaDoc legalLocale = legalLocales[i];
436             if (legalLocale.toString().equals(locale))
437                 return true;
438         }
439         return false;
440     }
441     
442     private boolean isValidLanguage(String JavaDoc language) {
443         if (legalLanguages==null) {
444             legalLanguages = new HashSet JavaDoc();
445             String JavaDoc [] choices = Locale.getISOLanguages();
446             for (int i=0; i<choices.length; i++) {
447                 legalLanguages.add(choices[i]);
448             }
449         }
450         return legalLanguages.contains(language);
451     }
452     
453     private boolean isValidCountry(String JavaDoc country) {
454         if (legalCountries==null) {
455             legalCountries = new HashSet JavaDoc();
456             String JavaDoc [] choices = Locale.getISOCountries();
457             for (int i=0; i<choices.length; i++) {
458                 legalCountries.add(choices[i]);
459             }
460         }
461         return legalCountries.contains(country);
462     }
463     
464     /*
465      * Build an index for the locale directory by collecting
466      * documents according to the tocs, then building the index.
467      */

468
469     private MultiStatus processLocaleDir(PluginIdentifier id,
470             PluginIdentifier fid, LocaleDir localeDir, IProgressMonitor monitor)
471             throws CoreException {
472         // build an index for each locale directory
473
String JavaDoc message = NLS.bind(HelpBaseResources.HelpIndexBuilder_indexFor, ((File JavaDoc)localeDir.dirs.get(0)).getName());
474         monitor.beginTask(message, 5);
475         File JavaDoc directory = (File JavaDoc)localeDir.dirs.get(0);
476         File JavaDoc indexDirectory = new File JavaDoc(directory, indexPath);
477         prepareDirectory(indexDirectory);
478         Collection JavaDoc docs = collectDocs(localeDir);
479         MultiStatus status = null;
480         if (docs.size()>0) {
481             String JavaDoc locale = localeDir.locale!=null?localeDir.locale:Platform.getNL();
482             SearchIndex index = new SearchIndex(indexDirectory, locale,
483                 new AnalyzerDescriptor(locale), null, localeDir.relativePath);
484             IndexerPluginVersionInfo docPlugins = new IndexerPluginVersionInfo(id,
485                 fid, indexDirectory);
486             index.setDocPlugins(docPlugins);
487             status = createIndex(id.id, fid!=null, localeDir, index, docs,
488                 new SubProgressMonitor(monitor, 5, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
489             index.deleteLockFile();
490         }
491         monitor.setTaskName(""); //$NON-NLS-1$
492
monitor.done();
493         return status;
494     }
495     
496     /*
497      * Using TOC files found either in the fragment or in the plug-in,
498      * collect hrefs for the topics.
499      */

500
501     private Collection JavaDoc collectDocs(LocaleDir localeDir)
502             throws CoreException {
503         HashSet JavaDoc docs = new HashSet JavaDoc();
504         for (int i = 0; i < tocFiles.size(); i++) {
505             TocFile tocFile = (TocFile) tocFiles.get(i);
506             collectDocs(docs, getTocFile(localeDir, tocFile.href));
507             if (tocFile.extraDir!=null) {
508                 //TODO also include all the indexable documents
509
//in the extraDir
510
}
511         }
512         return docs;
513     }
514     
515     /*
516      * Try to find the actual file for the TOC href. Look in the
517      * locale dirs first (best match first). If not found,
518      * look in the plug-in itself (for fragments).
519      */

520
521     private File JavaDoc getTocFile(LocaleDir localeDir, String JavaDoc href) {
522         // try the locale dir
523
File JavaDoc file = localeDir.findFile(href);
524         if (file!=null)
525             return file;
526         // try the plug-in
527
File JavaDoc pdir = manifest.getParentFile();
528         return new File JavaDoc(pdir, href);
529     }
530
531     /*
532      * Collect hrefs starting from the 'toc' element.
533      */

534     private void collectDocs(Set JavaDoc docs, File JavaDoc tocFile)
535             throws CoreException {
536         if (!tocFile.exists())
537             return;
538         Document JavaDoc doc = readXMLFile(tocFile);
539         add(doc.getDocumentElement(), docs);
540     }
541
542     /*
543      * Recursive collection of hrefs from topics.
544      */

545     private void add(Element topic, Set JavaDoc hrefs) {
546         String JavaDoc href = getAttribute(topic, "href"); //$NON-NLS-1$
547
if (topic.getTagName().equals("toc")) { //$NON-NLS-1$
548
// toc element has 'topic' attribute. Don't ask why :-)
549
href = getAttribute(topic, "topic"); //$NON-NLS-1$
550
}
551         if (href != null
552                 && !href.equals("") && !href.startsWith("http://") && !href.startsWith("https://")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
553
href = SearchIndex.getIndexableHref(href);
554             if (href != null)
555                 hrefs.add(href);
556         }
557         NodeList JavaDoc subtopics = topic.getElementsByTagName("topic"); //$NON-NLS-1$
558
for (int i = 0; i < subtopics.getLength(); i++) {
559             Element subtopic = (Element) subtopics.item(i);
560             href = getAttribute(subtopic, "href"); //$NON-NLS-1$
561
if (href != null && !href.equals("") && !href.startsWith("http://") && !href.startsWith("https://")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
562
href = SearchIndex.getIndexableHref(href);
563                 if (href != null)
564                     hrefs.add(href);
565             }
566         }
567     }
568     
569     /*
570      * Creates index for the locale dir by iterating over the doc hrefs
571      * and adding them into the index. Documents that cannot be found
572      * will be ignored.
573      */

574
575     private MultiStatus createIndex(String JavaDoc pluginId, boolean fragment, LocaleDir localeDir,
576             SearchIndex index, Collection JavaDoc addedDocs, IProgressMonitor monitor)
577             throws CoreException {
578         monitor.beginTask(HelpBaseResources.UpdatingIndex, addedDocs.size());
579         if (!index.beginAddBatch(true)) {
580             throwCoreException(HelpBaseResources.HelpIndexBuilder_error, null);
581         }
582         checkCancelled(monitor);
583         MultiStatus multiStatus = null;
584
585         for (Iterator JavaDoc it = addedDocs.iterator(); it.hasNext();) {
586             String JavaDoc href = (String JavaDoc) it.next();
587             URL JavaDoc url = localeDir.findURL(href);
588             if (url != null) {
589                 IStatus status = index
590                         .addDocument(getName(pluginId, href), url);
591                 if (status.getCode() != IStatus.OK) {
592                     if (multiStatus == null)
593                         multiStatus = createMultiStatus();
594                     multiStatus.add(status);
595                 }
596             }
597             else {
598                 // report missing document when in a plug-in
599
String JavaDoc locale = localeDir.locale!=null?localeDir.locale:Platform.getNL();
600                 String JavaDoc message = NLS.bind(HelpBaseResources.HelpIndexBuilder_cannotFindDoc, locale, href);
601                 IStatus status = new Status(IStatus.WARNING, pluginId, IStatus.OK, message, null);
602                 if (multiStatus == null)
603                     multiStatus = createMultiStatus();
604                 multiStatus.add(status);
605             }
606             checkCancelled(monitor);
607             monitor.worked(1);
608         }
609         monitor.subTask(HelpBaseResources.Writing_index);
610         if (!index.endAddBatch(true, true)) {
611             IStatus status = new Status(IStatus.ERROR, HelpBasePlugin.PLUGIN_ID,
612                     IStatus.OK, HelpBaseResources.HelpIndexBuilder_errorWriting, null);
613             if (multiStatus==null)
614                 multiStatus = createMultiStatus();
615             multiStatus.add(status);
616         }
617         monitor.done();
618         return multiStatus;
619     }
620     
621     private MultiStatus createMultiStatus() {
622         return new MultiStatus(
623                 HelpBasePlugin.PLUGIN_ID,
624                 IStatus.OK,
625                 HelpBaseResources.HelpIndexBuilder_incompleteIndex,
626                 null);
627     }
628
629     private void checkCancelled(IProgressMonitor pm)
630             throws OperationCanceledException {
631         if (pm.isCanceled())
632             throw new OperationCanceledException();
633     }
634
635     private String JavaDoc getName(String JavaDoc pluginId, String JavaDoc href) {
636         // remove query string if any
637
int i = href.indexOf('?');
638         if (i != -1)
639             href = href.substring(0, i);
640         return "/" + pluginId + "/" + href; //$NON-NLS-1$ //$NON-NLS-2$
641
}
642
643     /**
644      * If the path does not exist, create it. Otherwise, delete all the files in
645      * it.
646      *
647      * @param indexDirectory
648      */

649
650     private void prepareDirectory(File JavaDoc indexDirectory) throws CoreException {
651         if (indexDirectory.exists()) {
652             File JavaDoc[] files = indexDirectory.listFiles();
653             for (int i = 0; i < files.length; i++) {
654                 File JavaDoc file = files[i];
655                 boolean result = file.delete();
656                 if (!result)
657                     throwCoreException(
658                             HelpBaseResources.HelpIndexBuilder_cannotScrub, null);
659             }
660         } else {
661             boolean result = indexDirectory.mkdirs();
662             if (!result)
663                 throwCoreException(HelpBaseResources.HelpIndexBuilder_cannotCreateDest,
664                         null);
665         }
666     }
667
668     private void reset() {
669         localeDirs.clear();
670         tocFiles.clear();
671         indexPath = null;
672     }
673
674     private PluginIdentifier getPluginID(File JavaDoc dir, Document JavaDoc doc) throws CoreException {
675         String JavaDoc id = null;
676         String JavaDoc version = null;
677         if (doc != null) {
678             Node JavaDoc root = doc.getDocumentElement();
679             id = getAttribute(root, "id"); //$NON-NLS-1$
680
version = getAttribute(root, "version"); //$NON-NLS-1$
681
if (id != null && version != null)
682                 return new PluginIdentifier(id, version);
683         }
684         // check for the OSGi manifest
685
File JavaDoc OSGiFile = new File JavaDoc(dir,
686                 "META-INF/MANIFEST.MF"); //$NON-NLS-1$
687

688         if (OSGiFile.exists()) {
689             try {
690                 Manifest JavaDoc OSGiManifest = new Manifest JavaDoc(new FileInputStream JavaDoc(
691                         OSGiFile));
692                 Dictionary JavaDoc headers = manifestToProperties(OSGiManifest
693                         .getMainAttributes());
694                 String JavaDoc value = headers.get(Constants.BUNDLE_SYMBOLICNAME)
695                         .toString();
696                 if (value == null)
697                     return null;
698                 ManifestElement[] elements = ManifestElement.parseHeader(
699                         Constants.BUNDLE_SYMBOLICNAME, value);
700                 if (elements.length > 0)
701                     id = elements[0].getValue();
702                 value = headers.get(Constants.BUNDLE_VERSION).toString();
703                 if (value == null)
704                     return null;
705                 elements = ManifestElement.parseHeader(
706                         Constants.BUNDLE_VERSION, value);
707                 if (elements.length > 0)
708                     version = elements[0].getValue();
709                 if (id != null && version != null)
710                     return new PluginIdentifier(id, version);
711             } catch (Exception JavaDoc e1) {
712                 throwCoreException(HelpBaseResources.HelpIndexBuilder_errorExtractingId, e1);
713             }
714         }
715         return null;
716     }
717
718     private String JavaDoc getAttribute(Node JavaDoc node, String JavaDoc name) {
719         NamedNodeMap JavaDoc atts = node.getAttributes();
720         if (atts != null) {
721             Node JavaDoc att = atts.getNamedItem(name);
722             if (att != null)
723                 return att.getNodeValue();
724         }
725         return null;
726     }
727
728     private Document JavaDoc readXMLFile(File JavaDoc file) throws CoreException {
729         InputStream JavaDoc stream = null;
730         Document JavaDoc d = null;
731         try {
732             stream = new FileInputStream JavaDoc(file);
733             InputStreamReader JavaDoc reader = new InputStreamReader JavaDoc(stream, "utf-8"); //$NON-NLS-1$
734
InputSource JavaDoc inputSource = new InputSource JavaDoc(reader);
735             inputSource.setSystemId(manifest.toString());
736
737             if (parser == null)
738                 parser = documentBuilderFactory.newDocumentBuilder();
739             d = parser.parse(inputSource);
740         } catch (Exception JavaDoc e) {
741             String JavaDoc message = NLS.bind(HelpBaseResources.HelpIndexBuilder_errorParsing, file.getName());
742             throwCoreException(message, e);
743         } finally {
744             if (stream != null) {
745                 try {
746                     stream.close();
747                 } catch (IOException JavaDoc e) {
748                 }
749                 stream = null;
750             }
751         }
752         return d;
753     }
754
755     private Element[] getTocExtensions(Document JavaDoc doc) {
756         ArrayList JavaDoc list = new ArrayList JavaDoc();
757         //Node root = doc.getDocumentElement();
758
NodeList JavaDoc children = doc.getElementsByTagName("extension"); //$NON-NLS-1$
759
for (int i = 0; i < children.getLength(); i++) {
760             Node JavaDoc child = children.item(i);
761             String JavaDoc point = getAttribute(child, "point"); //$NON-NLS-1$
762
if (point.equals(POINT_TOC))
763                 list.add(child);
764         }
765         return (Element[]) list.toArray(new Element[list.size()]);
766     }
767
768     private Properties JavaDoc manifestToProperties(Attributes JavaDoc d) {
769         Iterator JavaDoc iter = d.keySet().iterator();
770         Properties JavaDoc result = new Properties JavaDoc();
771         while (iter.hasNext()) {
772             Attributes.Name JavaDoc key = (Attributes.Name JavaDoc) iter.next();
773             result.put(key.toString(), d.get(key));
774         }
775         return result;
776     }
777
778     private void throwCoreException(String JavaDoc message, Throwable JavaDoc t)
779             throws CoreException {
780         IStatus status = new Status(IStatus.ERROR, HelpBasePlugin.PLUGIN_ID,
781                 IStatus.OK, message, t);
782         throw new CoreException(status);
783     }
784 }
Popular Tags