135107 [Help] Allow users to use .html/.htm file extension for XHTML content
diff --git a/org.eclipse.help.base/plugin.xml b/org.eclipse.help.base/plugin.xml
index 7f4752f..6372394 100644
--- a/org.eclipse.help.base/plugin.xml
+++ b/org.eclipse.help.base/plugin.xml
@@ -163,7 +163,7 @@
    <extension
          point="org.eclipse.help.base.luceneSearchParticipants">
       <searchParticipant
-            content-type="org.eclipse.help.xhtml"
+            extensions="xhtml"
             id="org.eclipse.help.base.xhtml"
             participant="org.eclipse.help.internal.search.XHTMLSearchParticipant"
             headless="true"/>
diff --git a/org.eclipse.help.base/schema/luceneSearchParticipants.exsd b/org.eclipse.help.base/schema/luceneSearchParticipants.exsd
index 36032cd..a339310 100644
--- a/org.eclipse.help.base/schema/luceneSearchParticipants.exsd
+++ b/org.eclipse.help.base/schema/luceneSearchParticipants.exsd
@@ -104,20 +104,7 @@
          <attribute name="extensions" type="string">
             <annotation>
                <documentation>
-                  Note: This attribute is deprecated; use the content-types attribute instead.
-&lt;p&gt;
-an optional field containing the list of file types handled by the search participant. This is a string containing comma separate file extensions (e.g. &quot;abc, xyz&quot;). This attribute should be used when files are made explicitly known to the help system in the &lt;code&gt;org.eclipse.help.toc&lt;/code&gt; extension point. The absence of this attribute is an indication that the participant will index all the documents it is responsible for by itself. 
-&lt;p&gt;Note also that participants that are registered for known documents have plug-in scope. If you want a participant to apply to documents in another plug-in, you must use the &lt;code&gt;binding&lt;/code&gt; element to extend the scope. In contrast, participants that do not specify this attribute have global scope.
-               </documentation>
-               <appInfo>
-                  <meta.attribute deprecated="true"/>
-               </appInfo>
-            </annotation>
-         </attribute>
-         <attribute name="content-type" type="string">
-            <annotation>
-               <documentation>
-                  an optional field containing the list of content types handled by the search participant. This is a string containing a comma-separated list of content type identifiers (e.g. &quot;html, xhtml&quot;). This attribute should be used when files are made explicitly known to the help system in the &lt;code&gt;org.eclipse.help.toc&lt;/code&gt; extension point. The absence of this attribute and the extensions (deprecated) attribute is an indication that the participant will index all the documents it is responsible for by itself. 
+                  an optional field containing the list of file types handled by the search participant. This is a string containing comma separate file extensions (e.g. &quot;abc, xyz&quot;). This attribute should be used when files are made explicitly known to the help system in the &lt;code&gt;org.eclipse.help.toc&lt;/code&gt; extension point. The absence of this attribute is an indication that the participant will index all the documents it is responsible for by itself. 
 &lt;p&gt;Note also that participants that are registered for known documents have plug-in scope. If you want a participant to apply to documents in another plug-in, you must use the &lt;code&gt;binding&lt;/code&gt; element to extend the scope. In contrast, participants that do not specify this attribute have global scope.
                </documentation>
             </annotation>
diff --git a/org.eclipse.help.base/src/org/eclipse/help/internal/search/HTMLSearchParticipant.java b/org.eclipse.help.base/src/org/eclipse/help/internal/search/HTMLSearchParticipant.java
index f94aceb..0311706 100644
--- a/org.eclipse.help.base/src/org/eclipse/help/internal/search/HTMLSearchParticipant.java
+++ b/org.eclipse.help.base/src/org/eclipse/help/internal/search/HTMLSearchParticipant.java
@@ -1,13 +1,17 @@
 package org.eclipse.help.internal.search;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentDescriber;
+import org.eclipse.help.internal.base.BaseHelpSystem;
 import org.eclipse.help.internal.base.HelpBasePlugin;
+import org.eclipse.help.internal.xhtml.XHTMLContentDescriber;
 import org.eclipse.help.search.ISearchIndex;
 import org.eclipse.help.search.LuceneSearchParticipant;
 
@@ -16,6 +20,7 @@
 
 	private HTMLDocParser parser;
 	private String indexPath;
+	private IContentDescriber xhtmlDescriber;
 
 	public HTMLSearchParticipant(String indexPath) {
 		parser = new HTMLDocParser();
@@ -24,35 +29,79 @@
 
 	public IStatus addDocument(ISearchIndex index, String pluginId, String name, URL url, String id,
 			Document doc) {
-		try {
+		// if it's XHTML, forward it on to the proper search participant
+		if (isXHTML(pluginId, url)) {
+			SearchManager manager = BaseHelpSystem.getSearchManager();
+			LuceneSearchParticipant xhtmlParticipant = manager.getParticipant("org.eclipse.help.base.xhtml"); //$NON-NLS-1$
+			return xhtmlParticipant.addDocument(index, pluginId, name, url, id, doc);
+		}
+		// otherwise, treat it as HTML
+		else {		
 			try {
 				try {
-					parser.openDocument(url);
-				} catch (IOException ioe) {
-					return new Status(IStatus.ERROR, HelpBasePlugin.PLUGIN_ID, IStatus.ERROR,
-							"Help document " //$NON-NLS-1$
-									+ name + " cannot be opened.", //$NON-NLS-1$
-							null);
+					try {
+						parser.openDocument(url);
+					} catch (IOException ioe) {
+						return new Status(IStatus.ERROR, HelpBasePlugin.PLUGIN_ID, IStatus.ERROR,
+								"Help document " //$NON-NLS-1$
+										+ name + " cannot be opened.", //$NON-NLS-1$
+								null);
+					}
+					ParsedDocument parsed = new ParsedDocument(parser.getContentReader());
+					doc.add(Field.Text("contents", parsed.newContentReader())); //$NON-NLS-1$
+					doc.add(Field.Text("exact_contents", parsed //$NON-NLS-1$
+							.newContentReader()));
+					String title = parser.getTitle();
+					doc.add(Field.UnStored("title", title)); //$NON-NLS-1$
+					doc.add(Field.UnStored("exact_title", title)); //$NON-NLS-1$
+					doc.add(Field.UnIndexed("raw_title", title)); //$NON-NLS-1$
+					doc.add(Field.UnIndexed("summary", parser.getSummary(title))); //$NON-NLS-1$
+				} finally {
+					parser.closeDocument();
 				}
-				ParsedDocument parsed = new ParsedDocument(parser.getContentReader());
-				doc.add(Field.Text("contents", parsed.newContentReader())); //$NON-NLS-1$
-				doc.add(Field.Text("exact_contents", parsed //$NON-NLS-1$
-						.newContentReader()));
-				String title = parser.getTitle();
-				doc.add(Field.UnStored("title", title)); //$NON-NLS-1$
-				doc.add(Field.UnStored("exact_title", title)); //$NON-NLS-1$
-				doc.add(Field.UnIndexed("raw_title", title)); //$NON-NLS-1$
-				doc.add(Field.UnIndexed("summary", parser.getSummary(title))); //$NON-NLS-1$
-			} finally {
-				parser.closeDocument();
+			} catch (IOException e) {
+				return new Status(IStatus.ERROR, HelpBasePlugin.PLUGIN_ID, IStatus.ERROR,
+						"IO exception occurred while adding document " + name //$NON-NLS-1$
+								+ " to index " + indexPath + ".", //$NON-NLS-1$ //$NON-NLS-2$
+						e);
 			}
-		} catch (IOException e) {
-			return new Status(IStatus.ERROR, HelpBasePlugin.PLUGIN_ID, IStatus.ERROR,
-					"IO exception occurred while adding document " + name //$NON-NLS-1$
-							+ " to index " + indexPath + ".", //$NON-NLS-1$ //$NON-NLS-2$
-					e);
+			return Status.OK_STATUS;
 		}
-		return Status.OK_STATUS;
 	}
-
+	
+	/**
+	 * Returns whether or not the given content should be treated as XHTML.
+	 * 
+	 * @param pluginId the plugin id containing the content
+	 * @param url the URL to the content
+	 * @return whether the content should be treated as XHTML
+	 */
+	private boolean isXHTML(String pluginId, URL url) {
+		// if the search participant isn't bound to the plugin we shouldn't use it
+		SearchManager manager = BaseHelpSystem.getSearchManager();
+		if (manager.isParticipantBound(pluginId, "org.eclipse.help.base.xhtml")) { //$NON-NLS-1$
+			if (xhtmlDescriber == null) {
+				xhtmlDescriber = new XHTMLContentDescriber();
+			}
+			InputStream in = null;
+			try {
+				in = url.openStream();
+				return (xhtmlDescriber.describe(in, null) == IContentDescriber.VALID);
+			}
+			catch (Exception e) {
+				// if anything goes wrong, treat it as not xhtml
+			}
+			finally {
+				if (in != null) {
+					try {
+						in.close();
+					}
+					catch (IOException e) {
+						// nothing we can do
+					}
+				}
+			}
+		}
+		return false;
+	}
 }
diff --git a/org.eclipse.help.base/src/org/eclipse/help/internal/search/SearchIndex.java b/org.eclipse.help.base/src/org/eclipse/help/internal/search/SearchIndex.java
index aac11fe..29eace5 100644
--- a/org.eclipse.help.base/src/org/eclipse/help/internal/search/SearchIndex.java
+++ b/org.eclipse.help.base/src/org/eclipse/help/internal/search/SearchIndex.java
@@ -197,7 +197,7 @@
 				participant = BaseHelpSystem.getSearchManager().getGlobalParticipant(pid);
 			// NEW: check for file extension-based search participant;
 			if (participant == null)
-				participant = BaseHelpSystem.getSearchManager().getParticipant(pluginId, name, url);
+				participant = BaseHelpSystem.getSearchManager().getParticipant(pluginId, name);
 			if (participant != null) {
 				IStatus status = participant.addDocument(this, pluginId, name, url, id, doc);
 				if (status.getSeverity() == IStatus.OK) {
@@ -214,7 +214,8 @@
 			// default to html
 			IStatus status = htmlSearchParticipant.addDocument(this, pluginId, name, url, id, doc);
 			if (status.getSeverity() == IStatus.OK) {
-				indexedDocs.put(name, "0"); //$NON-NLS-1$
+				String filters = doc.get("filters"); //$NON-NLS-1$
+				indexedDocs.put(name, filters != null ? filters : "0"); //$NON-NLS-1$
 				iw.addDocument(doc);
 			}
 			return status;
@@ -1029,7 +1030,7 @@
 	public IStatus addDocument(String pluginId, String name, URL url, String id, Document doc) {
 		// try a registered participant for the file format
 		LuceneSearchParticipant participant = BaseHelpSystem.getSearchManager()
-				.getParticipant(pluginId, name, url);
+				.getParticipant(pluginId, name);
 		if (participant != null) {
 			return participant.addDocument(this, pluginId, name, url, id, doc);
 		}
diff --git a/org.eclipse.help.base/src/org/eclipse/help/internal/search/SearchManager.java b/org.eclipse.help.base/src/org/eclipse/help/internal/search/SearchManager.java
index e63f0b6..f11cd52 100644
--- a/org.eclipse.help.base/src/org/eclipse/help/internal/search/SearchManager.java
+++ b/org.eclipse.help.base/src/org/eclipse/help/internal/search/SearchManager.java
@@ -32,7 +32,6 @@
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.content.IContentType;
 import org.eclipse.help.HelpSystem;
 import org.eclipse.help.IHelpResource;
 import org.eclipse.help.internal.HelpPlugin;
@@ -65,11 +64,8 @@
 	/** Caches analyzer descriptors for each locale */
 	private Map analyzerDescriptors = new HashMap();
 
-	/**
-	 * Caches search participants
-	 */
-	private Map searchParticipants = new HashMap();
-
+	private Map searchParticipantsById = new HashMap();
+	private Map searchParticipantsByPlugin = new HashMap();
 	private ArrayList globalSearchParticipants;
 
 	private static class ParticipantDescriptor implements IHelpResource {
@@ -85,31 +81,7 @@
 			return element.getAttribute("id"); //$NON-NLS-1$
 		}
 
-		public boolean matchesContentType(String fileName) {
-			return matchesContentType(fileName, null);
-		}
-		
-		public boolean matchesContentType(String fileName, URL url) {
-			String contentType = element.getAttribute("content-type"); //$NON-NLS-1$
-			IContentType type = null;
-			if (url == null) {
-				type = Platform.getContentTypeManager().findContentTypeFor(fileName);
-			}
-			else {
-				try {
-					type = Platform.getContentTypeManager().findContentTypeFor(url.openStream(), fileName);
-				}
-				catch (IOException e) {
-					return false;
-				}
-			}
-			if (type != null) {
-				return type.getId().equals(contentType);
-			}
-			return false;
-		}
-		
-		public boolean matchesExtension(String extension) {
+		public boolean matches(String extension) {
 			String ext = element.getAttribute("extensions"); //$NON-NLS-1$
 			if (ext == null)
 				return false;
@@ -122,10 +94,6 @@
 			return false;
 		}
 
-		public boolean hasContentType() {
-			return element.getAttribute("content-type") != null; //$NON-NLS-1$
-		}
-		
 		public boolean hasExtensions() {
 			return element.getAttribute("extensions") != null; //$NON-NLS-1$
 		}
@@ -300,20 +268,10 @@
 			return false;
 		int dotLoc = url.lastIndexOf('.');
 		String ext = url.substring(dotLoc + 1);
-		String fileName = url.substring(url.lastIndexOf('/') + 1);
 		for (int i = 0; i < list.size(); i++) {
 			ParticipantDescriptor desc = (ParticipantDescriptor) list.get(i);
-			if (desc.hasContentType()) {
-				if (desc.matchesContentType(fileName)) {
-					return true;
-				}
-			}
-			// extensions attribute deprecated
-			else if (desc.hasExtensions()) {
-				if (desc.matchesExtension(ext)) {
-					return true;
-				}
-			}
+			if (desc.matches(ext))
+				return true;
 		}
 		return false;
 	}
@@ -379,45 +337,65 @@
 	}
 
 	/**
+	 * Returns the lucene search participant with the given id, or null if it could not
+	 * be found.
+	 * 
+	 * @param participantId the participant's unique id
+	 * @return the participant with the given id
+	 */
+	public LuceneSearchParticipant getParticipant(String participantId) {
+		ParticipantDescriptor desc = (ParticipantDescriptor)searchParticipantsById.get(participantId);
+		if (desc != null) {
+			return desc.getParticipant();
+		}
+		return null;
+	}
+	
+	/**
 	 * Returns a TOC file participant for the provided plug-in and file name.
 	 * 
 	 * @param pluginId
-	 * @param path
+	 * @param fileName
 	 * @return
 	 */
 
-	public LuceneSearchParticipant getParticipant(String pluginId, String path, URL url) {
+	public LuceneSearchParticipant getParticipant(String pluginId, String fileName) {
 		ArrayList list = getParticipantDescriptors(pluginId);
 		if (list == null)
 			return null;
-		int dotLoc = path.lastIndexOf('.');
-		int lastSlash = path.lastIndexOf('/');
-		String ext = path.substring(dotLoc + 1);
-		String fileName;
-		if (lastSlash == -1) {
-			fileName = path;
-		}
-		else {
-			fileName = path.substring(lastSlash + 1);
-		}
+		int dotLoc = fileName.lastIndexOf('.');
+		String ext = fileName.substring(dotLoc + 1);
 		for (int i = 0; i < list.size(); i++) {
 			ParticipantDescriptor desc = (ParticipantDescriptor) list.get(i);
-			if (desc.hasContentType()) {
-				if (desc.matchesContentType(fileName, url)) {
-					return desc.getParticipant();
-				}
-			}
-			// extensions attribute deprecated
-			else if (desc.hasExtensions()) {
-				if (desc.matchesExtension(ext)) {
-					return desc.getParticipant();
-				}
-			}
+			if (desc.matches(ext))
+				return desc.getParticipant();
 		}
 		return null;
 	}
 
 	/**
+	 * Returns whether or not the given search participant is bound to the given
+	 * plugin.
+	 * 
+	 * @param pluginId the id of the plugin
+	 * @param participantId the id of the search participant
+	 * @return whether or not the participant is bound to the plugin
+	 */
+	public boolean isParticipantBound(String pluginId, String participantId) {
+		List list = getParticipantDescriptors(pluginId);
+		if (list != null) {
+			Iterator iter = list.iterator();
+			while (iter.hasNext()) {
+				ParticipantDescriptor desc = (ParticipantDescriptor)iter.next();
+				if (participantId.equals(desc.getId())) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	
+	/**
 	 * Returns a set of plug-in Ids that have search participants or bindings.
 	 * 
 	 * @return a set of plug-in Ids
@@ -446,26 +424,11 @@
 	 * Loops through all the loaded search participants and notifies them that they can drop the
 	 * cached data to reduce runtime memory footprint.
 	 */
-
 	public void clearSearchParticipants() {
-		// global participants
-		if (globalSearchParticipants != null) {
-			for (int i = 0; i < globalSearchParticipants.size(); i++) {
-				ParticipantDescriptor desc = (ParticipantDescriptor) globalSearchParticipants.get(i);
-				desc.clear();
-			}
-		}
-		// file search participants
-		Collection values = searchParticipants.values();
-		for (Iterator iter=values.iterator(); iter.hasNext();) {
-			Object slot = iter.next();
-			if (slot instanceof ArrayList) {
-				ArrayList list = (ArrayList)slot;
-				for (int i = 0; i < list.size(); i++) {
-					ParticipantDescriptor desc = (ParticipantDescriptor) list.get(i);
-					desc.clear();
-				}
-			}
+		Iterator iter = searchParticipantsById.values().iterator();
+		while (iter.hasNext()) {
+			ParticipantDescriptor desc = (ParticipantDescriptor)iter.next();
+			desc.clear();
 		}
 	}
 
@@ -490,7 +453,7 @@
 					if (!rel.getName().equals("searchParticipant")) //$NON-NLS-1$
 						continue;
 					// don't allow binding the global participants
-					if (rel.getAttribute("content-type") == null && rel.getAttribute("extensions") == null) //$NON-NLS-1$ //$NON-NLS-2$
+					if (rel.getAttribute("extensions") == null) //$NON-NLS-1$
 						continue;
 					String id = rel.getAttribute("id"); //$NON-NLS-1$
 					if (id != null && id.equals(refId)) {
@@ -509,7 +472,9 @@
 					continue;
 				if (list == null)
 					list = new ArrayList();
-				list.add(new ParticipantDescriptor(element));
+				ParticipantDescriptor desc = new ParticipantDescriptor(element); 
+				list.add(desc);
+				searchParticipantsById.put(desc.getId(), desc);
 			}
 		}
 		if (binding != null)
@@ -528,7 +493,7 @@
 	private ArrayList addBoundDescriptors(ArrayList list, ArrayList binding) {
 		for (int i = 0; i < binding.size(); i++) {
 			IConfigurationElement refEl = (IConfigurationElement) binding.get(i);
-			Collection collection = searchParticipants.values();
+			Collection collection = searchParticipantsByPlugin.values();
 			boolean found = false;
 			for (Iterator iter = collection.iterator(); iter.hasNext();) {
 				if (found)
@@ -552,7 +517,9 @@
 			if (!found) {
 				if (list == null)
 					list = new ArrayList();
-				list.add(new ParticipantDescriptor(refEl));
+				ParticipantDescriptor d = new ParticipantDescriptor(refEl);
+				list.add(d);
+				searchParticipantsById.put(d.getId(), d);
 			}
 		}
 		return list;
@@ -596,12 +563,12 @@
 	}
 
 	private ArrayList getParticipantDescriptors(String pluginId) {
-		Object result = searchParticipants.get(pluginId);
+		Object result = searchParticipantsByPlugin.get(pluginId);
 		if (result == null) {
 			result = createSearchParticipants(pluginId);
 			if (result == null)
 				result = PARTICIPANTS_NOT_FOUND;
-			searchParticipants.put(pluginId, result);
+			searchParticipantsByPlugin.put(pluginId, result);
 		}
 		if (result == PARTICIPANTS_NOT_FOUND)
 			return null;
diff --git a/org.eclipse.help/plugin.properties b/org.eclipse.help/plugin.properties
index 22b0e41..099400c 100644
--- a/org.eclipse.help/plugin.properties
+++ b/org.eclipse.help/plugin.properties
@@ -15,5 +15,3 @@
 content_producer_extension_point_name = Help Content Producer
 index_extension_point_name = Help Index Contributions
 content_extension_point_name = Help Content Extensions
-content_type_html = HTML File
-content_type_xhtml = XHTML File
diff --git a/org.eclipse.help/plugin.xml b/org.eclipse.help/plugin.xml
index 0cdf964..a344315 100644
--- a/org.eclipse.help/plugin.xml
+++ b/org.eclipse.help/plugin.xml
@@ -13,24 +13,5 @@
          point="org.eclipse.help.contentProducer">
       <contentProducer producer="org.eclipse.help.internal.DynamicContentProducer"/>
    </extension>
-   
-   <extension
-         point="org.eclipse.core.runtime.contentTypes">
-      <content-type
-            base-type="org.eclipse.core.runtime.text"
-            file-extensions="htm,html"
-            id="html"
-            name="%content_type_html"
-            priority="high">
-      </content-type>
-      <content-type
-            base-type="org.eclipse.core.runtime.xml"
-            describer="org.eclipse.help.internal.xhtml.XHTMLContentDescriber"
-            file-extensions="htm,html,xhtml"
-            id="xhtml"
-            name="%content_type_xhtml"
-            priority="high">
-      </content-type>
-   </extension>
 
 </plugin>
diff --git a/org.eclipse.help/src/org/eclipse/help/internal/DynamicContentProducer.java b/org.eclipse.help/src/org/eclipse/help/internal/DynamicContentProducer.java
index d3210f5..06d7a34 100644
--- a/org.eclipse.help/src/org/eclipse/help/internal/DynamicContentProducer.java
+++ b/org.eclipse.help/src/org/eclipse/help/internal/DynamicContentProducer.java
@@ -14,11 +14,12 @@
 import java.util.Locale;
 
 import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.content.IContentDescriber;
 import org.eclipse.help.IHelpContentProducer;
 import org.eclipse.help.internal.util.ResourceLocator;
 import org.eclipse.help.internal.xhtml.UAContentParser;
 import org.eclipse.help.internal.xhtml.UATransformManager;
+import org.eclipse.help.internal.xhtml.XHTMLContentDescriber;
 import org.eclipse.help.internal.xhtml.XHTMLSupport;
 import org.osgi.framework.Bundle;
 import org.w3c.dom.Document;
@@ -30,13 +31,16 @@
 
 public class DynamicContentProducer implements IHelpContentProducer {
 
+	private IContentDescriber xhtmlDescriber;
+
 	public InputStream getInputStream(String pluginID, String href, Locale locale) {
-		String file = href;
-		int qloc = href.indexOf('?');
-		if (qloc != -1) {
-			file = href.substring(0, qloc);
-		}
 		if (isXHTML(pluginID, href, locale)) {
+			String file = href;
+			int qloc = href.indexOf('?');
+			if (qloc != -1) {
+				file = href.substring(0, qloc);
+			}
+
 			/*
 			 * Filtering can be turned off when, for example,
 			 * indexing documents.
@@ -60,43 +64,34 @@
 	 * @param locale the document's locale
 	 * @return whether or not the document is XHTML
 	 */
-	private static boolean isXHTML(String pluginID, String href, Locale locale) {
+	private boolean isXHTML(String pluginID, String href, Locale locale) {
 		String file = href;
 		int qloc = href.indexOf('?');
 		if (qloc != -1) {
 			file = href.substring(0, qloc);
 		}
-		int lastSlash = file.lastIndexOf('/');
-		String fileName;
-		if (lastSlash != -1) {
-			fileName = file.substring(lastSlash + 1);
-		}
-		else {
-			fileName = file;
+		if (xhtmlDescriber == null) {
+			xhtmlDescriber = new XHTMLContentDescriber();
 		}
 		// first open it to peek inside to see whether it's really XHTML
-		InputStream contents = openXHTMLFromPluginRaw(pluginID, file, locale.toString());
-		IContentType type = null;
+		InputStream in = null;
 		try {
-			type = Platform.getContentTypeManager().findContentTypeFor(contents, fileName);
+			in = openXHTMLFromPluginRaw(pluginID, file, locale.toString());
+			return (xhtmlDescriber.describe(in, null) == IContentDescriber.VALID);
 		}
-		catch (IOException e) {
+		catch (Exception e) {
 			HelpPlugin.logError("An error occured in DynamicContentProducer while trying to determine the content type", e); //$NON-NLS-1$
 		}
 		finally {
-			if (contents != null) {
+			if (in != null) {
 				try {
-					contents.close();
+					in.close();
 				}
 				catch (IOException e) {
 					// nothing we can do
 				}
 			}
 		}
-		// if it has the right content type it's XHTML
-		if (type != null) {
-			return "org.eclipse.help.xhtml".equals(type.getId()); //$NON-NLS-1$
-		}
 		return false;
 	}
 	
diff --git a/org.eclipse.ua.tests/data/help/producer/xhtml/invalid/html_doctype.html b/org.eclipse.ua.tests/data/help/producer/xhtml/invalid/html_doctype.html
deleted file mode 100644
index 2a81988..0000000
--- a/org.eclipse.ua.tests/data/help/producer/xhtml/invalid/html_doctype.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
-        
-<!--
-   This file is used to test whether or not the dynamic producer will be used
-   when loading an xhtml document from outside a doc.zip. The paragraph at the
-   bottom should always be filtered out by the producer.
--->
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>test</title>
-</head>
-<body>
-
-<h1>test</h1>
-<p>
-Test
-</p>
-
-</body>
-</html>
diff --git a/org.eclipse.ua.tests/data/help/producer/xhtml/invalid/missing_doctype.html b/org.eclipse.ua.tests/data/help/producer/xhtml/invalid/missing_doctype.html
deleted file mode 100644
index b639180..0000000
--- a/org.eclipse.ua.tests/data/help/producer/xhtml/invalid/missing_doctype.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>test</title>
-</head>
-<body>
-
-<h1>test</h1>
-<p>
-Test
-</p>
-
-</body>
-</html>
diff --git a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/frameset.html b/org.eclipse.ua.tests/data/help/producer/xhtml/valid/frameset.html
deleted file mode 100644
index b30156e..0000000
--- a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/frameset.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
-
-<!--
-   This file is used to test whether or not the dynamic producer will be used
-   when loading an xhtml document from outside a doc.zip. The paragraph at the
-   bottom should always be filtered out by the producer.
--->
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>test</title>
-</head>
-<body>
-
-<h1>test</h1>
-<p>
-Test
-</p>
-
-</body>
-</html>
diff --git a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/frameset.xhtml b/org.eclipse.ua.tests/data/help/producer/xhtml/valid/frameset.xhtml
deleted file mode 100644
index b30156e..0000000
--- a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/frameset.xhtml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
-
-<!--
-   This file is used to test whether or not the dynamic producer will be used
-   when loading an xhtml document from outside a doc.zip. The paragraph at the
-   bottom should always be filtered out by the producer.
--->
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>test</title>
-</head>
-<body>
-
-<h1>test</h1>
-<p>
-Test
-</p>
-
-</body>
-</html>
diff --git a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/normal.html b/org.eclipse.ua.tests/data/help/producer/xhtml/valid/normal.html
deleted file mode 100644
index 44165bd..0000000
--- a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/normal.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
-<!--
-   This file is used to test whether or not the dynamic producer will be used
-   when loading an xhtml document from outside a doc.zip. The paragraph at the
-   bottom should always be filtered out by the producer.
--->
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>test</title>
-</head>
-<body>
-
-<h1>test</h1>
-<p>
-Test
-</p>
-
-</body>
-</html>
diff --git a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/normal.xhtml b/org.eclipse.ua.tests/data/help/producer/xhtml/valid/normal.xhtml
deleted file mode 100644
index 44165bd..0000000
--- a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/normal.xhtml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
-<!--
-   This file is used to test whether or not the dynamic producer will be used
-   when loading an xhtml document from outside a doc.zip. The paragraph at the
-   bottom should always be filtered out by the producer.
--->
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>test</title>
-</head>
-<body>
-
-<h1>test</h1>
-<p>
-Test
-</p>
-
-</body>
-</html>
diff --git a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/strict.html b/org.eclipse.ua.tests/data/help/producer/xhtml/valid/strict.html
deleted file mode 100644
index 443c3da..0000000
--- a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/strict.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<!--
-   This file is used to test whether or not the dynamic producer will be used
-   when loading an xhtml document from outside a doc.zip. The paragraph at the
-   bottom should always be filtered out by the producer.
--->
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>test</title>
-</head>
-<body>
-
-<h1>test</h1>
-<p>
-Test
-</p>
-
-</body>
-</html>
diff --git a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/strict.xhtml b/org.eclipse.ua.tests/data/help/producer/xhtml/valid/strict.xhtml
deleted file mode 100644
index 443c3da..0000000
--- a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/strict.xhtml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<!--
-   This file is used to test whether or not the dynamic producer will be used
-   when loading an xhtml document from outside a doc.zip. The paragraph at the
-   bottom should always be filtered out by the producer.
--->
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>test</title>
-</head>
-<body>
-
-<h1>test</h1>
-<p>
-Test
-</p>
-
-</body>
-</html>
diff --git a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/with_xml_decl.xhtml b/org.eclipse.ua.tests/data/help/producer/xhtml/valid/with_xml_decl.xhtml
deleted file mode 100644
index 44460c3..0000000
--- a/org.eclipse.ua.tests/data/help/producer/xhtml/valid/with_xml_decl.xhtml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
-<!--
-   This file is used to test whether or not the dynamic producer will be used
-   when loading an xhtml document from outside a doc.zip. The paragraph at the
-   bottom should always be filtered out by the producer.
--->
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>test</title>
-</head>
-<body>
-
-<h1>test</h1>
-<p>
-Test
-</p>
-
-</body>
-</html>
diff --git a/org.eclipse.ua.tests/help/org/eclipse/ua/tests/help/producer/AllProducerTests.java b/org.eclipse.ua.tests/help/org/eclipse/ua/tests/help/producer/AllProducerTests.java
index 17336eb..ed30f03 100644
--- a/org.eclipse.ua.tests/help/org/eclipse/ua/tests/help/producer/AllProducerTests.java
+++ b/org.eclipse.ua.tests/help/org/eclipse/ua/tests/help/producer/AllProducerTests.java
@@ -30,6 +30,5 @@
 	 */
 	public AllProducerTests() {
 		addTest(DynamicContentTest.suite());
-		addTest(XHTMLContentDescriberTest.suite());
 	}
 }
diff --git a/org.eclipse.ua.tests/help/org/eclipse/ua/tests/help/producer/XHTMLContentDescriberTest.java b/org.eclipse.ua.tests/help/org/eclipse/ua/tests/help/producer/XHTMLContentDescriberTest.java
deleted file mode 100644
index 9d0aa7a..0000000
--- a/org.eclipse.ua.tests/help/org/eclipse/ua/tests/help/producer/XHTMLContentDescriberTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.ua.tests.help.producer;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-
-import junit.framework.Assert;
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.content.IContentType;
-import org.eclipse.ua.tests.plugin.UserAssistanceTestPlugin;
-import org.eclipse.ua.tests.util.ResourceFinder;
-
-public class XHTMLContentDescriberTest extends TestCase {
-	
-	/*
-	 * Returns an instance of this Test.
-	 */
-	public static Test suite() {
-		return new TestSuite(XHTMLContentDescriberTest.class);
-	}
-	
-	public void testValidXHTML() throws IOException {
-		URL[] urls = ResourceFinder.findFiles(UserAssistanceTestPlugin.getDefault(), "data/help/producer/xhtml/valid", "html", true);
-		for (int i=0;i<urls.length;++i) {
-			InputStream in = urls[i].openStream();
-			String url = urls[i].toExternalForm();
-			String fileName = url.substring(url.lastIndexOf('/') + 1);
-			IContentType type = Platform.getContentTypeManager().findContentTypeFor(in, fileName);
-			Assert.assertEquals("The supplied valid XHTML was mistakenly recognized as invalid XHTML by the type describer: file=" + fileName, "org.eclipse.help.xhtml", type.getId());
-			in.close();
-		}
-	}
-
-	public void testInvalidXHTML() throws IOException {
-		URL[] urls = ResourceFinder.findFiles(UserAssistanceTestPlugin.getDefault(), "data/help/producer/xhtml/invalid", "html", true);
-		for (int i=0;i<urls.length;++i) {
-			InputStream in = urls[i].openStream();
-			String url = urls[i].toExternalForm();
-			String fileName = url.substring(url.lastIndexOf('/') + 1);
-			IContentType type = Platform.getContentTypeManager().findContentTypeFor(in, fileName);
-			Assert.assertFalse("The supplied invalid XHTML was not properly recognized by the XHTML content type describer: file= " + fileName + " type=" + type.getId(), "org.eclipse.help.xhtml".equals(type.getId()));
-			in.close();
-		}
-	}
-}