1 11 package org.eclipse.help.search; 12 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 import java.io.Reader ; 16 import java.io.StringReader ; 17 import java.net.URL ; 18 import java.util.Stack ; 19 20 import javax.xml.parsers.SAXParser ; 21 import javax.xml.parsers.SAXParserFactory ; 22 23 import org.apache.lucene.document.Document; 24 import org.apache.lucene.document.Field; 25 import org.eclipse.core.runtime.IStatus; 26 import org.eclipse.core.runtime.Status; 27 import org.eclipse.help.internal.base.HelpBasePlugin; 28 import org.eclipse.help.internal.dynamic.DocumentReader; 29 import org.eclipse.help.internal.dynamic.ExtensionHandler; 30 import org.eclipse.help.internal.dynamic.IncludeHandler; 31 import org.eclipse.help.internal.dynamic.ProcessorHandler; 32 import org.eclipse.help.internal.dynamic.XMLProcessor; 33 import org.xml.sax.Attributes ; 34 import org.xml.sax.InputSource ; 35 import org.xml.sax.SAXException ; 36 import org.xml.sax.helpers.DefaultHandler ; 37 38 44 public abstract class XMLSearchParticipant extends LuceneSearchParticipant { 45 private Stack stack = new Stack (); 46 private SAXParser parser; 47 private XMLProcessor processor; 48 private boolean hasFilters; 49 50 53 protected interface IParsedXMLContent { 54 55 60 String getLocale(); 61 62 68 void setTitle(String title); 69 70 77 void addToSummary(String summary); 78 79 85 void addText(String text); 86 } 87 88 private static class ParsedXMLContent implements IParsedXMLContent { 89 private StringBuffer buffer = new StringBuffer (); 90 private StringBuffer summary = new StringBuffer (); 91 private String title; 92 private String locale; 93 private static int SUMMARY_LENGTH = 200; 94 95 public ParsedXMLContent(String locale) { 96 this.locale = locale; 97 } 98 99 public String getLocale() { 100 return locale; 101 } 102 103 public void setTitle(String title) { 104 this.title = title; 105 } 106 107 public void addToSummary(String text) { 108 if (summary.length() >= SUMMARY_LENGTH) 109 return; 110 if (summary.length() > 0) 111 summary.append(" "); summary.append(text); 113 if (summary.length() > SUMMARY_LENGTH) 114 summary.delete(SUMMARY_LENGTH, summary.length()); 115 } 116 117 public void addText(String text) { 118 if (buffer.length() > 0) 119 buffer.append(" "); buffer.append(text); 121 } 122 123 public Reader newContentReader() { 124 return new StringReader (buffer.toString()); 125 } 126 127 public String getSummary() { 128 String summaryStr = summary.toString(); 130 if (title != null && summaryStr.length() >= title.length()) { 131 String header = summaryStr.substring(0, title.length()); 132 if (header.equalsIgnoreCase(title)) { 133 return summaryStr.substring(title.length()).trim(); 134 } 135 } 136 return summaryStr; 137 } 138 139 public String getTitle() { 140 return title; 141 } 142 } 143 144 private class XMLHandler extends DefaultHandler { 145 146 public ParsedXMLContent data; 147 148 public XMLHandler(ParsedXMLContent data) { 149 this.data = data; 150 } 151 152 public void startElement(String uri, String localName, String qName, Attributes attributes) 153 throws SAXException { 154 stack.push(qName); 155 handleStartElement(qName, attributes, data); 156 if (attributes.getValue("filter") != null || qName.equalsIgnoreCase("filter")) { hasFilters = true; 158 } 159 } 160 161 public void endElement(String uri, String localName, String qName) throws SAXException { 162 handleEndElement(qName, data); 163 String top = (String ) stack.peek(); 164 if (top != null && top.equals(qName)) 165 stack.pop(); 166 } 167 168 173 public void startDocument() throws SAXException { 174 XMLSearchParticipant.this.handleStartDocument(data); 175 } 176 177 182 public void endDocument() throws SAXException { 183 XMLSearchParticipant.this.handleEndDocument(data); 184 } 185 186 192 public void processingInstruction(String target, String pidata) throws SAXException { 193 handleProcessingInstruction(target, data); 194 } 195 196 201 public void characters(char[] characters, int start, int length) throws SAXException { 202 if (length == 0) 203 return; 204 StringBuffer buff = new StringBuffer (); 205 for (int i = 0; i < length; i++) { 206 buff.append(characters[start + i]); 207 } 208 String text = buff.toString().trim(); 209 if (text.length() > 0) 210 handleText(text, data); 211 } 212 213 219 public InputSource resolveEntity(String publicId, String systemId) throws SAXException { 220 return new InputSource (new StringReader ("")); } 222 } 223 224 234 protected abstract void handleStartElement(String name, Attributes attributes, IParsedXMLContent data); 235 236 244 protected abstract void handleEndElement(String name, IParsedXMLContent data); 245 246 252 protected void handleStartDocument(IParsedXMLContent data) { 253 } 254 255 261 protected void handleEndDocument(IParsedXMLContent data) { 262 } 263 264 272 protected void handleProcessingInstruction(String type, IParsedXMLContent data) { 273 } 274 275 284 protected abstract void handleText(String text, IParsedXMLContent data); 285 286 289 public IStatus addDocument(ISearchIndex index, String pluginId, String name, URL url, String id, 290 Document doc) { 291 InputStream stream = null; 292 try { 293 if (parser == null) { 294 parser = SAXParserFactory.newInstance().newSAXParser(); 295 } 296 stack.clear(); 297 hasFilters = false; 298 ParsedXMLContent parsed = new ParsedXMLContent(index.getLocale()); 299 XMLHandler handler = new XMLHandler(parsed); 300 stream = url.openStream(); 301 stream = preprocess(stream, name, index.getLocale()); 302 parser.parse(stream, handler); 303 doc.add(new Field("contents", parsed.newContentReader())); doc.add(new Field("exact_contents", parsed.newContentReader())); String title = parsed.getTitle(); 306 if (title != null) 307 addTitle(title, doc); 308 String summary = parsed.getSummary(); 309 if (summary != null) 310 doc.add(new Field("summary", summary, Field.Store.YES, Field.Index.NO)); if (hasFilters) { 312 doc.add(new Field("filters", "true", Field.Store.YES, Field.Index.NO)); } 314 return Status.OK_STATUS; 315 } catch (Exception e) { 316 return new Status(IStatus.ERROR, HelpBasePlugin.PLUGIN_ID, IStatus.ERROR, 317 "Exception occurred while adding document " + name + " to index.", e); 320 } finally { 321 if (stream != null) { 322 try { 323 stream.close(); 324 } catch (IOException e) { 325 } 326 stream = null; 327 } 328 } 329 } 330 331 336 337 protected String getTopElement() { 338 return (String ) stack.peek(); 339 } 340 341 346 protected String getElementStackPath() { 347 StringBuffer buf = new StringBuffer (); 348 for (int i = 0; i < stack.size(); i++) { 349 if (i > 0) 350 buf.append("/"); buf.append((String ) stack.get(i)); 352 } 353 return buf.toString(); 354 } 355 356 374 protected InputStream preprocess(InputStream in, String name, String locale) { 375 if (processor == null) { 376 DocumentReader reader = new DocumentReader(); 377 processor = new XMLProcessor(new ProcessorHandler[] { 378 new IncludeHandler(reader, locale), 379 new ExtensionHandler(reader, locale) 380 }); 381 } 382 try { 383 return processor.process(in, name, null); 384 } 385 catch (Throwable t) { 386 String msg = "An error occured while pre-processing user assistance document \"" + name + "\" for search indexing"; HelpBasePlugin.logError(msg, t); 388 return in; 389 } 390 } 391 } 392 | Popular Tags |