Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMazen Faraj2005-11-28 03:38:50 +0000
committerMazen Faraj2005-11-28 03:38:50 +0000
commit94b0333b1532bbc381b6190eaa74cb37af4ece29 (patch)
treedd9abb481ea8c73b90f9f0222b64c7512b2d4cc9 /org.eclipse.help
parent3e91317d66d832f76be14e2f55fd57ba41bc8148 (diff)
downloadeclipse.platform.ua-94b0333b1532bbc381b6190eaa74cb37af4ece29.tar.gz
eclipse.platform.ua-94b0333b1532bbc381b6190eaa74cb37af4ece29.tar.xz
eclipse.platform.ua-94b0333b1532bbc381b6190eaa74cb37af4ece29.zip
*** empty log message ***
Diffstat (limited to 'org.eclipse.help')
-rw-r--r--org.eclipse.help/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.help/plugin.xml1
-rw-r--r--org.eclipse.help/src/org/eclipse/help/internal/util/ResourceLocator.java209
-rw-r--r--org.eclipse.help/src/org/eclipse/help/internal/xhtml/AbstractUAElement.java94
-rw-r--r--org.eclipse.help/src/org/eclipse/help/internal/xhtml/BundleUtil.java32
-rw-r--r--org.eclipse.help/src/org/eclipse/help/internal/xhtml/DOMUtil.java239
-rw-r--r--org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentFilterProcessor.java135
-rw-r--r--org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentMergeProcessor.java104
-rw-r--r--org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentParser.java194
-rw-r--r--org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAInclude.java50
-rw-r--r--org.eclipse.help/src/org/eclipse/help/internal/xhtml/UATransformManager.java114
11 files changed, 1059 insertions, 116 deletions
diff --git a/org.eclipse.help/META-INF/MANIFEST.MF b/org.eclipse.help/META-INF/MANIFEST.MF
index f99303ff1..a12eff88f 100644
--- a/org.eclipse.help/META-INF/MANIFEST.MF
+++ b/org.eclipse.help/META-INF/MANIFEST.MF
@@ -13,6 +13,7 @@ Export-Package: org.eclipse.help,
org.eclipse.help.internal.model;x-friends:="org.eclipse.help.base,org.eclipse.help.ui,org.eclipse.help.webapp",
org.eclipse.help.internal.protocols;x-friends:="org.eclipse.help.base,org.eclipse.help.ui,org.eclipse.help.webapp",
org.eclipse.help.internal.toc;x-friends:="org.eclipse.help.base,org.eclipse.help.ui,org.eclipse.help.webapp",
- org.eclipse.help.internal.util;x-friends:="org.eclipse.help.base,org.eclipse.help.ui,org.eclipse.help.webapp"
+ org.eclipse.help.internal.util;x-friends:="org.eclipse.help.base,org.eclipse.help.ui,org.eclipse.help.webapp",
+ org.eclipse.help.internal.xhtml;x-friends:="org.eclipse.help.ui"
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.1.0,4.0.0)"
Eclipse-LazyStart: true
diff --git a/org.eclipse.help/plugin.xml b/org.eclipse.help/plugin.xml
index 47e42c42a..ddcb4154e 100644
--- a/org.eclipse.help/plugin.xml
+++ b/org.eclipse.help/plugin.xml
@@ -7,4 +7,5 @@
<extension-point id="contentProducer" name="%content_producer_extension_point_name" schema="schema/contentProducer.exsd"/>
<extension-point id="index" name="%index_extension_point_name"/>
+
</plugin>
diff --git a/org.eclipse.help/src/org/eclipse/help/internal/util/ResourceLocator.java b/org.eclipse.help/src/org/eclipse/help/internal/util/ResourceLocator.java
index 4d7ce1e3e..68ca4595c 100644
--- a/org.eclipse.help/src/org/eclipse/help/internal/util/ResourceLocator.java
+++ b/org.eclipse.help/src/org/eclipse/help/internal/util/ResourceLocator.java
@@ -1,25 +1,25 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 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
+/***************************************************************************************************
+ * Copyright (c) 2000, 2004 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
- *******************************************************************************/
+ * Contributors: IBM Corporation - initial API and implementation
+ **************************************************************************************************/
package org.eclipse.help.internal.util;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
-import java.util.*;
import java.util.ArrayList;
+import java.util.Enumeration;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
@@ -36,6 +36,7 @@ import org.eclipse.help.internal.HelpPlugin;
import org.osgi.framework.Bundle;
public class ResourceLocator {
+
public static final String CONTENTPRODUCER_XP_NAME = "contentProducer"; //$NON-NLS-1$
public static final String CONTENTPRODUCER_XP_FULLNAME = HelpPlugin.PLUGIN_ID
@@ -51,32 +52,31 @@ public class ResourceLocator {
// Map of document content providers by plug-in ID;
private static Map contentProducers = new HashMap(2, 0.5f);
static {
- Platform.getExtensionRegistry().addRegistryChangeListener(
- new IRegistryChangeListener() {
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.core.runtime.IRegistryChangeListener#registryChanged(org.eclipse.core.runtime.IRegistryChangeEvent)
- */
- public void registryChanged(IRegistryChangeEvent event) {
- IExtensionDelta[] deltas = event.getExtensionDeltas(
- HelpPlugin.PLUGIN_ID, CONTENTPRODUCER_XP_NAME);
- for (int i = 0; i < deltas.length; i++) {
- IExtension extension = deltas[i].getExtension();
- String affectedPlugin = extension.getNamespace();
- // reset producer for the affected plugin,
- // it will be recreated on demand
- synchronized (contentProducers) {
- contentProducers.remove(affectedPlugin);
- }
- }
+ Platform.getExtensionRegistry().addRegistryChangeListener(new IRegistryChangeListener() {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IRegistryChangeListener#registryChanged(org.eclipse.core.runtime.IRegistryChangeEvent)
+ */
+ public void registryChanged(IRegistryChangeEvent event) {
+ IExtensionDelta[] deltas = event.getExtensionDeltas(HelpPlugin.PLUGIN_ID,
+ CONTENTPRODUCER_XP_NAME);
+ for (int i = 0; i < deltas.length; i++) {
+ IExtension extension = deltas[i].getExtension();
+ String affectedPlugin = extension.getNamespace();
+ // reset producer for the affected plugin,
+ // it will be recreated on demand
+ synchronized (contentProducers) {
+ contentProducers.remove(affectedPlugin);
}
- });
+ }
+ }
+ });
}
/**
- * Obtains content proivider for a documentation plug-in, creates one if
- * necessary.
+ * Obtains content proivider for a documentation plug-in, creates one if necessary.
*
* @param pluginId
* @return ITopicContentProvider or null
@@ -107,8 +107,7 @@ public class ResourceLocator {
* @return ITopicContentProvider or null
*/
private static IHelpContentProducer createContentProducer(String pluginId) {
- IExtensionPoint xp = Platform.getExtensionRegistry().getExtensionPoint(
- CONTENTPRODUCER_XP_FULLNAME);
+ IExtensionPoint xp = Platform.getExtensionRegistry().getExtensionPoint(CONTENTPRODUCER_XP_FULLNAME);
if (xp == null) {
return null;
}
@@ -117,15 +116,13 @@ public class ResourceLocator {
if (!extensions[i].getNamespace().equals(pluginId)) {
continue;
}
- IConfigurationElement[] elements = extensions[i]
- .getConfigurationElements();
+ IConfigurationElement[] elements = extensions[i].getConfigurationElements();
for (int j = 0; j < elements.length; j++) {
if (!CONTENTPRODUCER_XP_NAME.equals(elements[j].getName())) {
continue;
}
try {
- Object o = elements[j]
- .createExecutableExtension("producer"); //$NON-NLS-1$
+ Object o = elements[j].createExecutableExtension("producer"); //$NON-NLS-1$
if (o instanceof IHelpContentProducer) {
return (IHelpContentProducer) o;
}
@@ -140,13 +137,10 @@ public class ResourceLocator {
}
/**
- * Opens an input stream to a file contained in a plugin. This includes NL
- * lookup.
+ * Opens an input stream to a file contained in a plugin. This includes NL lookup.
*/
- public static InputStream openFromProducer(Bundle pluginDesc, String file,
- String locale) {
- IHelpContentProducer producer = getContentProducer(pluginDesc
- .getSymbolicName());
+ public static InputStream openFromProducer(Bundle pluginDesc, String file, String locale) {
+ IHelpContentProducer producer = getContentProducer(pluginDesc.getSymbolicName());
if (producer == null) {
return null;
}
@@ -165,23 +159,19 @@ public class ResourceLocator {
}
/**
- * Opens an input stream to a file contained in a plugin. This includes
- * includes OS, WS and NL lookup.
+ * Opens an input stream to a file contained in a plugin. This includes includes OS, WS and NL
+ * lookup.
*
* @param pluginId
- * the plugin id of the plugin that contains the file you are
- * trying to find
+ * the plugin id of the plugin that contains the file you are trying to find
* @param file
* the relative path of the file to find
* @param locale
- * the locale used as an override or <code>null</code> to use
- * the default locale
+ * the locale used as an override or <code>null</code> to use the default locale
*
- * @return an InputStream to the file or <code>null</code> if the file
- * wasn't found
+ * @return an InputStream to the file or <code>null</code> if the file wasn't found
*/
- public static InputStream openFromPlugin(String pluginId, String file,
- String locale) {
+ public static InputStream openFromPlugin(String pluginId, String file, String locale) {
Bundle bundle = Platform.getBundle(pluginId);
if (bundle != null)
return openFromPlugin(bundle, file, locale);
@@ -189,32 +179,29 @@ public class ResourceLocator {
}
/**
- * Opens an input stream to a file contained in a zip in a plugin. This
- * includes OS, WS and NL lookup.
+ * Opens an input stream to a file contained in a zip in a plugin. This includes OS, WS and NL
+ * lookup.
*
* @param pluginDesc
- * the plugin description of the plugin that contains the file
- * you are trying to find
+ * the plugin description of the plugin that contains the file you are trying to find
* @param file
* the relative path of the file to find
* @param locale
- * the locale used as an override or <code>null</code> to use
- * the default locale
+ * the locale used as an override or <code>null</code> to use the default locale
*
- * @return an InputStream to the file or <code>null</code> if the file
- * wasn't found
+ * @return an InputStream to the file or <code>null</code> if the file wasn't found
*/
public static InputStream openFromZip(Bundle pluginDesc, String zip, String file, String locale) {
-
+
String pluginID = pluginDesc.getSymbolicName();
Map cache = zipCache;
ArrayList pathPrefix = getPathPrefix(locale);
-
+
for (int i = 0; i < pathPrefix.size(); i++) {
-
+
// finds the zip file by either using a cached location, or
// calling Platform.find - the result is cached for future use.
- Object cached = cache.get(pluginID + '/'+ pathPrefix.get(i) + zip);
+ Object cached = cache.get(pluginID + '/' + pathPrefix.get(i) + zip);
if (cached == null) {
try {
URL url = Platform.find(pluginDesc, new Path(pathPrefix.get(i) + zip));
@@ -229,11 +216,11 @@ public class ResourceLocator {
}
// cache it
cache.put(pluginID + '/' + pathPrefix.get(i) + zip, cached);
- }
+ }
if (cached == ZIP_NOT_FOUND || cached.toString().startsWith("jar:")) //$NON-NLS-1$
continue;
-
+
// cached should be a zip file that is actually on the filesystem
// now check if the file is in this zip
try {
@@ -246,32 +233,29 @@ public class ResourceLocator {
// a file not found exception is an io exception
continue;
}
-
+
} // end for loop
-
+
// we didn't find the file in any zip
return null;
}
/**
- * Opens an input stream to a file contained in a plugin. This includes
- * includes OS, WS and NL lookup.
+ * Opens an input stream to a file contained in a plugin. This includes includes OS, WS and NL
+ * lookup.
*
* @param pluginDesc
- * the plugin description of the plugin that contains the file
- * you are trying to find
+ * the plugin description of the plugin that contains the file you are trying to find
* @param file
* the relative path of the file to find
* @param locale
- * the locale used as an override or <code>null</code> to use
- * the default locale
+ * the locale used as an override or <code>null</code> to use the default locale
*
- * @return an InputStream to the file or <code>null</code> if the file
- * wasn't found
+ * @return an InputStream to the file or <code>null</code> if the file wasn't found
*/
public static InputStream openFromPlugin(Bundle pluginDesc, String file, String locale) {
+
ArrayList pathPrefix = getPathPrefix(locale);
-
URL flatFileURL = find(pluginDesc, new Path(file), pathPrefix);
if (flatFileURL != null)
try {
@@ -282,79 +266,75 @@ public class ResourceLocator {
return null;
}
+
+
/*
- * Search the ws, os then nl for a resource. Platform.find can't be used
- * directly with $nl$, $os$ or $ws$ becuase the root directory will be
- * searched too early.
+ * Search the ws, os then nl for a resource. Platform.find can't be used directly with $nl$,
+ * $os$ or $ws$ becuase the root directory will be searched too early.
*/
- private static URL find(Bundle pluginDesc, IPath flatFilePath, ArrayList pathPrefix) {
-
- // try to find the actual file.
+ public static URL find(Bundle pluginDesc, IPath flatFilePath, ArrayList pathPrefix) {
+
+ // try to find the actual file.
for (int i = 0; i < pathPrefix.size(); i++) {
- URL url = Platform.find(pluginDesc, new Path((String)pathPrefix.get(i) + flatFilePath));
+ URL url = Platform.find(pluginDesc, new Path((String) pathPrefix.get(i) + flatFilePath));
if (url != null)
return url;
}
- return null;
+ return null;
}
-
+
public static void clearZipCache() {
zipCache = new Hashtable();
}
-
+
/*
* Gets an ArrayList that has the path prefixes to search.
*
- * @param locale
- * the locale used as an override or <code>null</code> to use
- * the default locale
- * @return an ArrayList that has path prefixes that need to be search. The
- * returned ArrayList will have an entry for the root of the plugin.
+ * @param locale the locale used as an override or <code>null</code> to use the default locale
+ * @return an ArrayList that has path prefixes that need to be search. The returned ArrayList
+ * will have an entry for the root of the plugin.
*/
public static ArrayList getPathPrefix(String locale) {
- ArrayList pathPrefix = new ArrayList(5);
- // TODO add override for ws and os similar to how it's done with locale now
+ ArrayList pathPrefix = new ArrayList(5);
+ // TODO add override for ws and os similar to how it's done with locale
+ // now
String ws = Platform.getWS();
String os = Platform.getOS();
if (locale == null)
locale = Platform.getNL();
-
- if (ws != null)
+
+ if (ws != null)
pathPrefix.add("ws/" + ws + '/'); //$NON-NLS-1$
-
+
if (os != null && !os.equals("OS_UNKNOWN")) //$NON-NLS-1$
pathPrefix.add("os/" + os + '/'); //$NON-NLS-1$
-
- if (locale != null && locale.length() >= 5)
+
+ if (locale != null && locale.length() >= 5)
pathPrefix.add("nl/" + locale.substring(0, 2) + '/' + locale.substring(3, 5) + '/'); //$NON-NLS-1$
-
+
if (locale != null && locale.length() >= 2)
pathPrefix.add("nl/" + locale.substring(0, 2) + '/'); //$NON-NLS-1$
-
+
// the plugin root
- pathPrefix.add(""); //$NON-NLS-1$
-
+ pathPrefix.add(""); //$NON-NLS-1$
+
return pathPrefix;
}
/**
- * Finds all topics under specified directory (recursively). This includes
- * includes OS, WS and NL lookup.
+ * Finds all topics under specified directory (recursively). This includes includes OS, WS and
+ * NL lookup.
*
* @param pluginDesc
- * the plugin description of the plugin that contains the file
- * you are trying to find
+ * the plugin description of the plugin that contains the file you are trying to find
* @param directory
* the relative path of the directory
* @param locale
- * the locale used as an override or <code>null</code> to use
- * the default locale
+ * the locale used as an override or <code>null</code> to use the default locale
*
- * @return an InputStream to the file or <code>null</code> if the file
- * wasn't found
+ * @return an InputStream to the file or <code>null</code> if the file wasn't found
*/
- public static Set findTopicPaths(Bundle pluginDesc, String directory,
- String locale) {
+ public static Set findTopicPaths(Bundle pluginDesc, String directory, String locale) {
Set ret = new HashSet();
findTopicPaths(pluginDesc, directory, locale, ret);
return ret;
@@ -366,8 +346,7 @@ public class ResourceLocator {
* @param locale
* @param paths
*/
- private static void findTopicPaths(Bundle pluginDesc, String directory,
- String locale, Set paths) {
+ private static void findTopicPaths(Bundle pluginDesc, String directory, String locale, Set paths) {
if (directory.endsWith("/")) //$NON-NLS-1$
directory = directory.substring(0, directory.length() - 1);
ArrayList pathPrefix = getPathPrefix(locale);
diff --git a/org.eclipse.help/src/org/eclipse/help/internal/xhtml/AbstractUAElement.java b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/AbstractUAElement.java
new file mode 100644
index 000000000..8f85f11b2
--- /dev/null
+++ b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/AbstractUAElement.java
@@ -0,0 +1,94 @@
+/***************************************************************************************************
+ * Copyright (c) 2004, 2005 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.help.internal.xhtml;
+
+import org.osgi.framework.Bundle;
+import org.w3c.dom.Element;
+
+
+public abstract class AbstractUAElement {
+
+ private Bundle bundle;
+
+ AbstractUAElement() {
+ }
+
+
+ /**
+ * Constructor used when model elements are being loaded from an xml content file. Bundle is
+ * propagated down the model to enable resolving resources relative to the base of the bundle.
+ *
+ * @param element
+ * @param pd
+ */
+ AbstractUAElement(Element element, Bundle bundle) {
+ this.bundle = bundle;
+ }
+
+
+ /**
+ * Constructor used when model elements are being loaded from an xml content file. Bundle AND
+ * base is propagated down the model to enable resolving resources relative to the xml content
+ * file. The base is set to point to the relative location of the parent folder that holds the
+ * content file. In the case of a configExtension, it is set to point to the relative position
+ * of the parent folder that holds the extension. Only when needed, the base field is stored in
+ * a model element. This saves memory.
+ *
+ * @param element
+ * @param pd
+ */
+ AbstractUAElement(Element element, Bundle bundle, String base) {
+ this(element, bundle);
+ }
+
+
+
+ /**
+ * DOM getAttribute retruns an empty string (not null) if attribute is not defined. Override
+ * this behavior.
+ *
+ * @param element
+ * @param att
+ * @return
+ */
+ protected String getAttribute(Element element, String att) {
+ if (element.hasAttribute(att))
+ return element.getAttribute(att);
+ return null;
+ }
+
+ /**
+ * Util method to parse a comma separated list of values
+ *
+ * @param element
+ * @param att
+ * @return
+ */
+ protected String[] getAttributeList(Element element, String att) {
+ if (element.hasAttribute(att))
+ return element.getAttribute(att).split(","); //$NON-NLS-1$
+ return null;
+ }
+
+
+ /**
+ * Returns the plugin descriptor of the plugin from which this element was loaded. In the case
+ * of extension, returns the plugin descriptor of the plugin defining the extension.
+ *
+ * @return
+ */
+ public Bundle getBundle() {
+ return bundle;
+ }
+
+
+
+
+} \ No newline at end of file
diff --git a/org.eclipse.help/src/org/eclipse/help/internal/xhtml/BundleUtil.java b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/BundleUtil.java
new file mode 100644
index 000000000..3268c5bfb
--- /dev/null
+++ b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/BundleUtil.java
@@ -0,0 +1,32 @@
+/***************************************************************************************************
+ * Copyright (c) 2004, 2005 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.help.internal.xhtml;
+
+import java.net.URL;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+
+/**
+ * Bundle convenience methods.
+ */
+public class BundleUtil {
+
+ /*
+ * Util method to return an URL to a plugin relative resource.
+ */
+ public static URL getResourceAsURL(String resource, String pluginId) {
+ Bundle bundle = Platform.getBundle(pluginId);
+ URL localLocation = localLocation = Platform.find(bundle, new Path(resource));
+ return localLocation;
+ }
+
+}
diff --git a/org.eclipse.help/src/org/eclipse/help/internal/xhtml/DOMUtil.java b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/DOMUtil.java
new file mode 100644
index 000000000..bde650ec9
--- /dev/null
+++ b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/DOMUtil.java
@@ -0,0 +1,239 @@
+/***************************************************************************************************
+ * Copyright (c) 2004, 2005 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.help.internal.xhtml;
+
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/**
+ * Util class for model. Has methods for resolving model attributes, and methods for manipulating
+ * XHTML DOM.
+ */
+public class DOMUtil {
+
+ public static String TAG_BODY = "body"; //$NON-NLS-1$
+ private static String TAG_HEAD = "head"; //$NON-NLS-1$
+ public static String TAG_BASE = "base"; //$NON-NLS-1$
+ public static String TAG_DIV = "div"; //$NON-NLS-1$
+ public static String TAG_HEAD_LINK = "link"; //$NON-NLS-1$
+ public static String TAG_FILTER = "filter"; //$NON-NLS-1$
+ public static String ATT_HREF = "href"; //$NON-NLS-1$
+ public static String ATT_REL = "rel"; //$NON-NLS-1$
+ public static String ATT_TYPE = "type"; //$NON-NLS-1$
+ public static String ATT_FILTER = "filter"; //$NON-NLS-1$
+
+
+
+
+ public static void insertBase(Document dom, String baseURL) {
+ // there should only be one head and one base element dom.
+ NodeList headList = dom.getElementsByTagName(TAG_HEAD);
+ Element head = (Element) headList.item(0);
+ NodeList baseList = head.getElementsByTagName(TAG_BASE);
+ if (baseList.getLength() == 0) {
+ // insert a base element, since one is not defined already.
+ Element base = dom.createElement(TAG_BASE);
+ base.setAttribute(ATT_HREF, baseURL);
+ head.insertBefore(base, head.getFirstChild());
+ }
+ }
+
+
+ public static Element getBase(Document dom) {
+ // there should only be one head and one base element dom.
+ NodeList headList = dom.getElementsByTagName(TAG_HEAD);
+ Element head = (Element) headList.item(0);
+ NodeList baseList = head.getElementsByTagName(TAG_BASE);
+ if (baseList.getLength() == 0)
+ // no base defined, signal failure.
+ return null;
+
+ return (Element) baseList.item(baseList.getLength() - 1);
+
+ }
+
+
+ // <link rel="stylesheet" href="shared.css" type="text/css" />
+ public static void insertStyle(Document dom, String cssUrl) {
+ // there should only be one head and one base element dom.
+ NodeList headList = dom.getElementsByTagName(TAG_HEAD);
+ Element head = null;
+ // Element base = getBase(dom);
+ NodeList styleList = null;
+ // there can be more than one style. DO not add style if it exists.
+ if (headList.getLength() >= 1) {
+ head = (Element) headList.item(0);
+ styleList = head.getElementsByTagName(TAG_HEAD_LINK);
+ for (int i = 0; i < styleList.getLength(); i++) {
+ Element style = (Element) styleList.item(0);
+ String styleString = style.getAttribute(ATT_HREF);
+ if (styleString.equals(cssUrl))
+ return;
+ }
+ }
+
+ // insert the style, since it is not defined.
+ Element styleToAdd = dom.createElement(TAG_HEAD_LINK);
+ styleToAdd.setAttribute(ATT_HREF, cssUrl);
+ styleToAdd.setAttribute(ATT_REL, "stylesheet"); //$NON-NLS-1$
+ styleToAdd.setAttribute(ATT_TYPE, "text/css"); //$NON-NLS-1$
+ if (styleList != null && styleList.getLength() >= 1)
+ styleList.item(0).getParentNode().insertBefore(styleToAdd, styleList.item(0));
+ else
+ head.appendChild(styleToAdd);
+
+ }
+
+ /**
+ * Returns a reference to the body of the DOM.
+ *
+ * @param dom
+ * @return
+ */
+ public static Element getBodyElement(Document dom) {
+ // there should only be one body element dom.
+ NodeList bodyList = dom.getElementsByTagName(TAG_BODY);
+ Element body = (Element) bodyList.item(0);
+ return body;
+ }
+
+
+
+ public static Element createElement(Document dom, String elementName, Properties attributes) {
+
+ // make sure to create element with any namespace uri to enable finding
+ // it again using Dom.getElementsByTagNameNS()
+ Element element = dom.createElementNS("", elementName);
+ if (attributes != null) {
+ Enumeration e = attributes.keys();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ element.setAttribute(key, attributes.getProperty(key));
+ }
+ }
+ return element;
+ }
+
+ public static Element createAndAppendChild(Element parentElement, String elementName,
+ Properties attributes) {
+
+ Element element = createElement(parentElement.getOwnerDocument(), elementName, attributes);
+ parentElement.appendChild(element);
+ return element;
+ }
+
+
+
+ /**
+ * Returns an Element array of all first level descendant Elements with a given tag name, in the
+ * order in which they are encountered in the DOM. Unlike the JAXP apis, which returns preorder
+ * traversal of this Element tree, this method filters out children deeper than first level
+ * child nodes.
+ */
+ public static Element[] getElementsByTagName(Element parent, String tagName) {
+ NodeList allChildElements = parent.getElementsByTagName(tagName);
+ Vector vector = new Vector();
+ for (int i = 0; i < allChildElements.getLength(); i++) {
+ // we know that the nodelist is of elements.
+ Element aElement = (Element) allChildElements.item(i);
+ if (aElement.getParentNode().equals(parent))
+ // first level child element. add it.
+ vector.add(aElement);
+ }
+ Element[] filteredElements = new Element[vector.size()];
+ vector.copyInto(filteredElements);
+ return filteredElements;
+ }
+
+ /**
+ * Same as getElementsByTagName(Element parent, String tagName) but the parent element is
+ * assumed to be the root of the document.
+ *
+ * @see getElementsByTagName(Element parent, String tagName)
+ */
+ public static Element[] getElementsByTagName(Document dom, String tagName) {
+ NodeList allChildElements = dom.getElementsByTagName(tagName);
+ Vector vector = new Vector();
+ for (int i = 0; i < allChildElements.getLength(); i++) {
+ // we know that the nodelist is of elements.
+ Element aElement = (Element) allChildElements.item(i);
+ if (aElement.getParentNode().equals(dom.getDocumentElement()))
+ // first level child element. add it. Cant use getParent
+ // here.
+ vector.add(aElement);
+ }
+ Element[] filteredElements = new Element[vector.size()];
+ vector.copyInto(filteredElements);
+ return filteredElements;
+ }
+
+
+ /*
+ * Util method similar to DOM getElementById() method, but it works without an id attribute
+ * being specified. Deep searches all children in this container's DOM for the first child with
+ * the given id. The element retrieved must have the passed local name. Note that in an XHTML
+ * file (aka DOM) elements should have a unique id within the scope of a document. We use local
+ * name because this allows for finding anchors and includes regardless of whether or not an
+ * xmlns was used in the xml.
+ */
+ public static Element getElementById(Document dom, String id, String localElementName) {
+
+ NodeList children = dom.getElementsByTagNameNS("*", localElementName); //$NON-NLS-1$
+ for (int i = 0; i < children.getLength(); i++) {
+ Element element = (Element) children.item(i);
+ if (element.getAttribute("id").equals(id)) //$NON-NLS-1$
+ return element;
+ }
+ // non found.
+ return null;
+
+ }
+
+
+
+
+ /**
+ * Returns an array version of the passed NodeList. Used to work around DOM design issues.
+ */
+ public static Node[] getArray(NodeList nodeList) {
+ Node[] nodes = new Node[nodeList.getLength()];
+ for (int i = 0; i < nodeList.getLength(); i++)
+ nodes[i] = nodeList.item(i);
+ return nodes;
+ }
+
+
+ /**
+ * Remove all instances of the element from the DOM.
+ *
+ */
+ public static void removeAllElements(Document dom, String elementLocalName) {
+ // get all elements in DOM and remove them.
+ NodeList elements = dom.getElementsByTagNameNS("*", //$NON-NLS-1$
+ elementLocalName);
+ // get the array version of the nodelist to work around DOM api design.
+ Node[] elementsArray = DOMUtil.getArray(elements);
+ for (int i = 0; i < elementsArray.length; i++) {
+ Node element = elementsArray[i];
+ element.getParentNode().removeChild(element);
+ }
+
+ }
+
+
+
+}
diff --git a/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentFilterProcessor.java b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentFilterProcessor.java
new file mode 100644
index 000000000..0efa772d3
--- /dev/null
+++ b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentFilterProcessor.java
@@ -0,0 +1,135 @@
+/***************************************************************************************************
+ * Copyright (c) 2004, 2005 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.help.internal.xhtml;
+
+import org.eclipse.core.runtime.Platform;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Handles content manipulation. Filters filter content in as opposed to filtering out. ie: if a
+ * filter passes, content is displayed.
+ *
+ */
+public class UAContentFilterProcessor {
+
+ public Document applyFilters(Document dom) {
+ Element body = DOMUtil.getBodyElement(dom);
+ NodeList allChildElements = body.getChildNodes();
+ for (int i = 0; i < allChildElements.getLength(); i++) {
+ // not all nodes are Elements.
+ Node node = (Node) allChildElements.item(i);
+ if (!(node instanceof Element))
+ continue;
+ applyFilters((Element) node);
+
+ }
+ return dom;
+ }
+
+ public void applyFilters(Element element) {
+ if (hasFilterAttribute(element)) {
+ boolean filteredIn = false;
+ filteredIn = processFilterAttribute(element);
+ if (!filteredIn)
+ // element failed filter, and is filtered out.
+ return;
+ }
+
+ NodeList allChildElements = element.getChildNodes();
+ for (int i = 0; i < allChildElements.getLength(); i++) {
+ // not all nodes are Elements.
+ Node node = (Node) allChildElements.item(i);
+ if (!(node instanceof Element))
+ continue;
+ Element childElement = (Element) node;
+ applyFilters(childElement);
+ }
+ }
+
+ private static boolean hasFilterAttribute(Element element) {
+ // getAttribute returns an empty string if att is not defined.
+ if (element.getAttribute(DOMUtil.ATT_FILTER).equals(""))
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns true is filter passes and Element is to be included.
+ *
+ * @param element
+ * @return
+ */
+ private boolean processFilterAttribute(Element element) {
+ String filterString = element.getAttribute(DOMUtil.ATT_FILTER);
+ String[] parsedFilterString = filterString.split("=");
+ String filter = parsedFilterString[0];
+ String value = parsedFilterString[1];
+
+ boolean filtered_in = isFilteredIn(filter, value);
+
+ if (!filtered_in)
+ element.getParentNode().removeChild(element);
+ return false;
+ }
+
+ /**
+ * FIltering capabilities. Can be overiden by subclasses to add more filtering capabilities.
+ *
+ * @param filter
+ * @param value
+ * @return
+ */
+ protected boolean isFilteredIn(String filter, String value) {
+ boolean filtered_in = false;
+ if (filter.equals("ws")) {
+ filtered_in = filterByWS(value);
+ } else if (filter.equals("os")) {
+ filtered_in = filterByOS(value);
+ } else
+ filtered_in = filterBySystemProperty(filter, value);
+
+ return filtered_in;
+ }
+
+ /**
+ * evaluates WS filter.
+ */
+ private static boolean filterByWS(String ws) {
+ String currentWS = Platform.getWS();
+ if (currentWS.equals(ws))
+ return true;
+ return false;
+ }
+
+ /**
+ * evaluates OS filter.
+ */
+ private static boolean filterByOS(String os) {
+ String currentOS = Platform.getOS();
+ if (currentOS.equals(os))
+ return true;
+ return false;
+ }
+
+
+ /**
+ * evaluates system property filter.
+ */
+ private static boolean filterBySystemProperty(String property, String value) {
+ String currentValue = System.getProperty(property);
+ if (currentValue != null && currentValue.equals(value))
+ return true;
+ return false;
+ }
+
+}
diff --git a/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentMergeProcessor.java b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentMergeProcessor.java
new file mode 100644
index 000000000..c591d4038
--- /dev/null
+++ b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentMergeProcessor.java
@@ -0,0 +1,104 @@
+/***************************************************************************************************
+ * Copyright (c) 2004, 2005 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.help.internal.xhtml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.help.internal.HelpPlugin;
+import org.eclipse.help.internal.util.ResourceLocator;
+import org.osgi.framework.Bundle;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/**
+ * Handles content manipulation to resolve includes.
+ *
+ */
+public class UAContentMergeProcessor {
+
+
+ public Document resolveIncludes(Document document, String locale) {
+
+ NodeList includes = document.getElementsByTagNameNS("*", "include");
+ Node[] nodes = getArray(includes);
+ for (int i = 0; i < nodes.length; i++) {
+ Element includeElement = (Element) nodes[i];
+ UAInclude include = new UAInclude(includeElement);
+ Element targetElement = findIncludeTarget(include, locale);
+ if (targetElement == null) {
+ String message = "Could not resolve following include: "; //$NON-NLS-1$;
+ HelpPlugin.logWarning(message);
+ return null;
+ }
+ Node targetNode = document.importNode(targetElement, true);
+ includeElement.getParentNode().replaceChild(targetNode, includeElement);
+ }
+ return document;
+ }
+
+
+
+
+ /**
+ * Find the target Element pointed to by the path in the include. It is assumed that configId
+ * always points to an external config, and not the same config of the inlcude.
+ *
+ * @param include
+ * @param path
+ * @return
+ */
+ private Element findIncludeTarget(UAInclude include, String locale) {
+ String path = include.getPath();
+ int index = path.indexOf("/");
+ if (index < 0)
+ return null;
+ String pluginID = path.substring(0, index);
+ int lastIndex = path.lastIndexOf("/");
+ String pluginRelativePath = path.substring(index + 1, lastIndex);
+ String include_id = path.substring(lastIndex + 1, path.length());
+
+ Bundle bundle = Platform.getBundle(pluginID);
+ ArrayList pathPrefix = ResourceLocator.getPathPrefix(locale);
+ URL flatFileURL = ResourceLocator.find(bundle, new Path(pluginRelativePath), pathPrefix);
+ if (flatFileURL != null)
+ try {
+ InputStream inputStream = flatFileURL.openStream();
+ UAContentParser parser = new UAContentParser(inputStream);
+ Document dom = parser.getDocument();
+ return DOMUtil.getElementById(dom, include_id, "*");
+ } catch (IOException e) {
+ return null;
+ }
+ return null;
+ }
+
+
+
+ /**
+ * Returns an array version of the passed NodeList. Used to work around DOM design issues.
+ */
+ public static Node[] getArray(NodeList nodeList) {
+ Node[] nodes = new Node[nodeList.getLength()];
+ for (int i = 0; i < nodeList.getLength(); i++)
+ nodes[i] = nodeList.item(i);
+ return nodes;
+ }
+
+
+
+}
diff --git a/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentParser.java b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentParser.java
new file mode 100644
index 000000000..26bef5426
--- /dev/null
+++ b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAContentParser.java
@@ -0,0 +1,194 @@
+/***************************************************************************************************
+ * Copyright (c) 2004, 2005 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.help.internal.xhtml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Hashtable;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.eclipse.help.internal.HelpPlugin;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+
+/**
+ *
+ */
+public class UAContentParser {
+
+ private static String TAG_HTML = "html"; //$NON-NLS-1$
+ protected static String XHTML1_TRANSITIONAL = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"; //$NON-NLS-1$
+ protected static String XHTML1_STRICT = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"; //$NON-NLS-1$
+ protected static String XHTML1_FRAMESET = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"; //$NON-NLS-1$
+
+
+ protected static Hashtable dtdMap = new Hashtable();
+
+ static {
+ String dtdBaseLocation = "dtds/xhtml1-20020801/"; //$NON-NLS-1$
+
+ String dtdLocation = dtdBaseLocation + "xhtml1-transitional.dtd"; //$NON-NLS-1$
+ URL dtdURL_T = BundleUtil.getResourceAsURL(dtdLocation, "org.eclipse.ui.intro");
+ dtdMap.put(XHTML1_TRANSITIONAL, dtdURL_T);
+
+ dtdLocation = dtdBaseLocation + "xhtml1-strict.dtd"; //$NON-NLS-1$
+ URL dtdURL_S = BundleUtil.getResourceAsURL(dtdLocation, "org.eclipse.ui.intro");
+ dtdMap.put(XHTML1_STRICT, dtdURL_S);
+
+ dtdLocation = dtdBaseLocation + "xhtml1-frameset.dtd"; //$NON-NLS-1$
+ URL dtdURL_F = BundleUtil.getResourceAsURL(dtdLocation, "org.eclipse.ui.intro");
+ dtdMap.put(XHTML1_FRAMESET, dtdURL_F);
+ }
+
+
+
+ private Document document;
+ private boolean hasXHTMLContent;
+
+ public UAContentParser(String content) {
+ parseDocument(content);
+ }
+
+ public UAContentParser(InputStream content) {
+ parseDocument(content);
+ }
+
+ /**
+ * Creates a config parser assuming that the passed content represents a URL to the content
+ * file.
+ */
+ public void parseDocument(Object content) {
+ try {
+ document = doParse(content);
+ if (document != null) {
+ // xml file is loaded. check that it is XHTML
+ Element rootElement = document.getDocumentElement();
+ // DocumentType docType = document.getDoctype();
+ if (rootElement.getTagName().equals(TAG_HTML)) {
+ // rely on root element to detect if we have an XHTML file
+ // and not on doctype. We need to support xhtml files with
+ // no doctype.
+ hasXHTMLContent = true;
+ } else
+ // not XHTML.
+ document = null;
+ }
+ } catch (Exception e) {
+ HelpPlugin.logError("Could not load content file: " + content, e); //$NON-NLS-1$
+ }
+ }
+
+ private DocumentBuilder createParser() {
+
+ try {
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ docFactory.setValidating(false);
+ // if this is not set, Document.getElementsByTagNameNS() will fail.
+ docFactory.setNamespaceAware(true);
+ docFactory.setExpandEntityReferences(false);
+ DocumentBuilder parser = docFactory.newDocumentBuilder();
+
+ parser.setEntityResolver(new EntityResolver() {
+
+ public InputSource resolveEntity(String publicId, String systemId) throws SAXException,
+ IOException {
+
+ if (systemId.equals(XHTML1_TRANSITIONAL) || systemId.equals(XHTML1_STRICT)
+ || systemId.equals(XHTML1_FRAMESET)) {
+
+ // be carefull here to support running as a jarred
+ // plugin.
+ URL dtdURL = (URL) dtdMap.get(systemId);
+ InputSource in = new InputSource(dtdURL.openStream());
+ in.setSystemId(dtdURL.toExternalForm());
+ return in;
+ }
+ return null;
+ }
+ });
+ return parser;
+ } catch (ParserConfigurationException pce) {
+ // Parser with specified options can't be built
+ HelpPlugin.logError(pce.getMessage(), pce);
+ }
+ return null;
+ }
+
+
+ /**
+ * General parser method that can accept both String and InputStream for parsing.
+ *
+ * @param fileObject
+ * @return
+ */
+ private Document doParse(Object fileObject) {
+ Document document = null;
+ try {
+ DocumentBuilder parser = createParser();
+ if (fileObject instanceof String)
+ document = parser.parse((String) fileObject);
+ else if (fileObject instanceof InputStream)
+ document = parser.parse((InputStream) fileObject);
+
+ return document;
+
+ } catch (SAXParseException spe) {
+ StringBuffer buffer = new StringBuffer("Parser error in line "); //$NON-NLS-1$
+ buffer.append(spe.getLineNumber());
+ buffer.append(", uri "); //$NON-NLS-1$
+ buffer.append(spe.getSystemId());
+ buffer.append("\n"); //$NON-NLS-1$
+ buffer.append(spe.getMessage());
+
+ // Use the contained exception.
+ Exception x = spe;
+ if (spe.getException() != null)
+ x = spe.getException();
+ HelpPlugin.logError(buffer.toString(), x);
+
+ } catch (SAXException sxe) {
+ Exception x = sxe;
+ if (sxe.getException() != null)
+ x = sxe.getException();
+ HelpPlugin.logError(x.getMessage(), x);
+
+ } catch (IOException ioe) {
+ HelpPlugin.logError(ioe.getMessage(), ioe);
+ }
+ return null;
+ }
+
+ /**
+ * Returned the DOM representing the xml content file. May return null if parsing the file
+ * failed.
+ *
+ * @return Returns the document.
+ */
+ public Document getDocument() {
+ return document;
+ }
+
+ public boolean hasXHTMLContent() {
+ return hasXHTMLContent;
+ }
+
+
+
+
+}
diff --git a/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAInclude.java b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAInclude.java
new file mode 100644
index 000000000..2681005b4
--- /dev/null
+++ b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UAInclude.java
@@ -0,0 +1,50 @@
+/***************************************************************************************************
+ * Copyright (c) 2004, 2005 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.help.internal.xhtml;
+
+import org.w3c.dom.Element;
+
+
+public class UAInclude extends AbstractUAElement {
+
+ protected static final String TAG_INCLUDE = "include"; //$NON-NLS-1$
+ protected static final String ATT_PATH = "path"; //$NON-NLS-1$
+ /**
+ * boolean attribute, default is false.
+ */
+ private static final String ATT_MERGE_STYLE = "merge-style"; //$NON-NLS-1$
+
+ private String path;
+ private boolean mergeStyle = false;
+
+ public UAInclude(Element element) {
+ path = getAttribute(element, ATT_PATH);
+ String mergeStyleString = getAttribute(element, ATT_MERGE_STYLE);
+ mergeStyle = (mergeStyleString != null && mergeStyleString.equalsIgnoreCase("true")) ? true : false; //$NON-NLS-1$
+ }
+
+
+ /**
+ * @return Returns the mergeStyle.
+ */
+ public boolean getMergeStyle() {
+ return mergeStyle;
+ }
+
+ /**
+ * @return Returns the path.
+ */
+ public String getPath() {
+ return path;
+ }
+
+
+
+}
diff --git a/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UATransformManager.java b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UATransformManager.java
new file mode 100644
index 000000000..76f421793
--- /dev/null
+++ b/org.eclipse.help/src/org/eclipse/help/internal/xhtml/UATransformManager.java
@@ -0,0 +1,114 @@
+/***************************************************************************************************
+ * Copyright (c) 2004, 2005 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.help.internal.xhtml;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.help.internal.HelpPlugin;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+
+
+/**
+ * Handles all XSL transforms applied to XHTML UA content.
+ */
+public class UATransformManager {
+
+
+ private static Transformer createTransformer(Document document) {
+ try {
+ // identity xslt.
+ TransformerFactory tFactory = TransformerFactory.newInstance();
+ Transformer transformer = tFactory.newTransformer();
+
+ // setup properties, for doctype.
+ DocumentType docType = document.getDoctype();
+ if (docType != null) {
+ String value = docType.getSystemId();
+ // transformer.clearParameters();
+ transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, value);
+ value = document.getDoctype().getPublicId();
+ transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, value);
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$
+ // transformer.setOutputProperty(OutputKeys.MEDIA_TYPE,
+ // "text/html");
+ // transformer
+ // .setOutputProperty(OutputKeys.ENCODING, "iso-8859-1");
+ } else
+ ;
+
+ return transformer;
+
+ } catch (TransformerConfigurationException tce) {
+ // Error generated by the parser
+ HelpPlugin.logError("Transformer Config error: " + tce.getMessage(), null); //$NON-NLS-1$
+ // Use the contained exception, if any
+ Throwable x = tce;
+ if (tce.getException() != null)
+ x = tce.getException();
+ HelpPlugin.logError("Transformer Stack trace: ", x); //$NON-NLS-1$
+ System.out.println(x);
+ }
+ return null;
+ }
+
+ public static String convertToString(Document document) {
+ try {
+ // identity xslt.
+ Transformer transformer = createTransformer(document);
+
+ DOMSource source = new DOMSource(document);
+
+ StringWriter stringBuffer = new StringWriter();
+ StreamResult result = new StreamResult(stringBuffer);
+
+ transformer.transform(source, result);
+ return stringBuffer.toString();
+
+ } catch (TransformerException te) {
+ // Error generated by the parser
+ HelpPlugin.logError("Transformer error: " + te.getMessage(), te); //$NON-NLS-1$
+ // Use the contained exception, if any
+ Throwable x = te;
+ if (te.getException() != null)
+ x = te.getException();
+ HelpPlugin.logError("Transformer Stack trace: ", x); //$NON-NLS-1$
+ System.out.println(x);
+ }
+ return null;
+
+ }
+
+ public static InputStream getAsInputStream(Document document) {
+ byte[] ba = null;
+ String xhtml = convertToString(document);
+ try {
+ ba = xhtml.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException ue) {
+ ;
+ }
+ ByteArrayInputStream is = new ByteArrayInputStream(ba);
+ return is;
+ }
+
+
+}

Back to the top