/*******************************************************************************
 * Copyright (c) 2004, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.intro.impl.html;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Map;

import org.eclipse.core.runtime.Platform;
import org.eclipse.help.internal.util.ProductPreferences;
import org.eclipse.swt.browser.Browser;
import org.eclipse.ui.internal.intro.impl.FontSelection;
import org.eclipse.ui.internal.intro.impl.IIntroConstants;
import org.eclipse.ui.internal.intro.impl.IntroPlugin;
import org.eclipse.ui.internal.intro.impl.model.AbstractBaseIntroElement;
import org.eclipse.ui.internal.intro.impl.model.AbstractIntroElement;
import org.eclipse.ui.internal.intro.impl.model.AbstractIntroPage;
import org.eclipse.ui.internal.intro.impl.model.IntroContentProvider;
import org.eclipse.ui.internal.intro.impl.model.IntroGroup;
import org.eclipse.ui.internal.intro.impl.model.IntroHTML;
import org.eclipse.ui.internal.intro.impl.model.IntroHead;
import org.eclipse.ui.internal.intro.impl.model.IntroImage;
import org.eclipse.ui.internal.intro.impl.model.IntroInjectedIFrame;
import org.eclipse.ui.internal.intro.impl.model.IntroLink;
import org.eclipse.ui.internal.intro.impl.model.IntroPageTitle;
import org.eclipse.ui.internal.intro.impl.model.IntroSeparator;
import org.eclipse.ui.internal.intro.impl.model.IntroText;
import org.eclipse.ui.internal.intro.impl.model.IntroTheme;
import org.eclipse.ui.internal.intro.impl.model.loader.ContentProviderManager;
import org.eclipse.ui.internal.intro.impl.model.util.BundleUtil;
import org.eclipse.ui.internal.intro.impl.presentations.BrowserIntroPartImplementation;
import org.eclipse.ui.internal.intro.impl.util.Log;
import org.eclipse.ui.intro.config.IIntroContentProvider;
import org.eclipse.ui.intro.config.IIntroContentProviderSite;

public class IntroHTMLGenerator {

	private AbstractIntroPage introPage;

	private IIntroContentProviderSite providerSite;
	private boolean backgroundSizeWorks;

	/**
	 * Generates the HTML code that will be presented in the browser widget for the provided intro
	 * page.
	 *
	 * @param page
	 *            the page to generate HTML for
	 * @param presentation
	 *            the presentation associated with this page.
	 */
	public HTMLElement generateHTMLforPage(AbstractIntroPage page, IIntroContentProviderSite providerSite) {
		if (page == null)
			return null;
		this.introPage = page;
		this.providerSite = providerSite;

		initializeBackgroundSizeWorks();

		// generate and add the appropriate encoding to the top of the document
		// generateEncoding();
		// create the main HTML element, and all of its contents.
		return generateHTMLElement();
	}

	private void initializeBackgroundSizeWorks() {
		// Internet Explorer <= 9 doesn't properly handle background-size
		backgroundSizeWorks = true;
		try {
			if (isIE()) {
				Class<?> ieClass = Class.forName("org.eclipse.swt.browser.IE"); //$NON-NLS-1$
				Field field = ieClass.getDeclaredField("IEVersion"); //$NON-NLS-1$
				field.setAccessible(true);
				int value = field.getInt(ieClass);
				// We specifically care about background-size which works in 9+
				backgroundSizeWorks = value <= 0 || value >= 9;
			}
		} catch(Exception e) {
			// IE not found
		}
	}

	private boolean isIE() {
		return getBrowser() != null && "ie".equals(getBrowser().getBrowserType()); //$NON-NLS-1$
	}

	/**
	 * Return the SWT Browser instance being used to render the intro.
	 *
	 * @return the browser or {@code null} if the browser could not be determined
	 */
	private Browser getBrowser() {
		if (providerSite instanceof BrowserIntroPartImplementation) {
			return ((BrowserIntroPartImplementation) providerSite).getBrowser();
		}
		return null;
	}

	/*
	 * private HTMLElement generateEncoding() { HTMLElement encoding = new HTMLElement("");
	 * //$NON-NLS-1$ // TODO: figure out how to handle locale based encoding // As far as the HTML
	 * generator is concerned, this is probably as // simple as asking the model for the information
	 * return encoding; }
	 */

	/**
	 * Generates the HTML element and its content:
	 *
	 * <pre>
	 *
	 *                        &lt;HTML&gt;
	 *                        &lt;HEAD&gt;
	 *                        head content
	 *                        &lt;/HEAD&gt;
	 *                        &lt;BODY&gt;
	 *                        body content
	 *                        &lt;/BODY&gt;
	 *                        &lt;/HTML&gt;
	 *
	 * </pre>
	 *
	 * @return the html HTMLElement
	 */
	private HTMLElement generateHTMLElement() {
		// this is the outermost element, so it has no indent
		int indentLevel = 0;
		HTMLElement html = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_HTML, indentLevel, true);
		HTMLElement head = generateHeadElement(indentLevel + 1);
		HTMLElement body = generateBodyElement(indentLevel + 1, head);
		html.addContent(head);
		html.addContent(body);
		return html;
	}

	/**
	 * Generates the HEAD element and its content:
	 *
	 * <pre>
	 *
	 *
	 *                        &lt;HEAD&gt;
	 *                        &lt;BASE href=&quot;base_plugin_location&gt;
	 *                        &lt;style type=&quot;text/css&quot;&gt;HTML, IMG { border: 0px; } &lt;/style&gt;
	 *                        &lt;TITLE&gt;page title &lt;/TITLE&gt;
	 *                        &lt;LINK href=&quot;style sheet&quot;&gt;
	 *                        additional head content, if specified
	 *                        &lt;/HEAD&gt;
	 *
	 * </pre>
	 *
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return the head HTMLElement
	 */
	private HTMLElement generateHeadElement(int indentLevel) {
		HTMLElement head = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_HEAD, indentLevel, true);
		addBrowserRenderingDirectives(head, indentLevel + 1);
		// add the title
		head.addContent(generateTitleElement(introPage.getTitle(), indentLevel + 1));
		head.addContent(generateUTF8CharsetElement(indentLevel + 1));
		// create the BASE element
		String basePath = BundleUtil.getResolvedResourceLocation(introPage.getBase(), introPage.getBundle());
		HTMLElement base = generateBaseElement(indentLevel + 1, basePath);
		if (base != null)
			head.addContent(base);
		// create the HTML style block
		head.addContent(generateStyleElement(indentLevel + 1));
		// add the presentation style
		String[] presentationStyles = IntroPlugin.getDefault().getIntroModelRoot().getPresentation()
				.getImplementationStyles();
		if (presentationStyles != null && introPage.injectSharedStyle()) {
			for (int i=0; i<presentationStyles.length; i++)
				head.addContent(generateLinkElement(presentationStyles[i], indentLevel + 1));
		}
		String pageStyle = introPage.getStyle();
		if (pageStyle != null)
			head.addContent(generateLinkElement(pageStyle, indentLevel + 1));
		// add javascript
		head.addContent(generateJavascriptElement(indentLevel + 1));

		// add the page's inherited style(s)
		String[] pageStyles = introPage.getStyles();
		for (int i = 0; i < pageStyles.length; i++) {
			pageStyle = pageStyles[i];
			if (pageStyle != null)
				head.addContent(generateLinkElement(pageStyle, indentLevel + 1));
		}
		// if there is additional head conent specified in an external file,
		// include it. Additional head content can be specified at the
		// implementation level (which would apply to ALL pages) and at the
		// page level (which would apply only to that particular page).
		// For the implementation's head contribution:
		StringBuilder content = null;
		IntroHead introHead = IntroPlugin.getDefault().getIntroModelRoot().getPresentation().getHead();
		if (introHead != null) {
			content = readFromFile(introHead.getSrc(), introHead.getInlineEncoding());
			if (content != null)
				head.addContent(content);
		}
		// For the page's head contribution:
		// TODO: there should only be one of these at the page level, not a
		// collection..
		IntroHead[] htmlHeads = introPage.getHTMLHeads();
		for (int i = 0; i < htmlHeads.length; i++) {
			introHead = htmlHeads[i];
			if (introHead != null) {
				content = readFromFile(introHead.getSrc(), introHead.getInlineEncoding());
				if (content != null)
					head.addContent(content);
			}
		}
		return head;
	}

	/**
	 * Add any browser-specific rendering quirks
	 *
	 * @param indentLevel
	 */
	private void addBrowserRenderingDirectives(HTMLElement head, int indentLevel) {
		/* IE renders intranet content in Compat View by default */
		if (isIE() && "html5".equals(getThemeProperty("standardSupport"))) { //$NON-NLS-1$ //$NON-NLS-2$
			// "Edge mode tells Internet Explorer to display content in the highest mode available"
			HTMLElement meta = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_META, indentLevel, true);
			meta.addAttribute(IIntroHTMLConstants.ATTRIBUTE_HTTP_EQUIV, "X-UA-Compatible"); //$NON-NLS-1$
			meta.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CONTENT, "IE=edge"); //$NON-NLS-1$
			head.addContent(meta);
		}
	}

	private String getThemeProperty(String key) {
		IntroTheme theme = introPage.getModelRoot().getTheme();
		if (theme == null) {
			return null;
		}
		Map<String, String> properties = theme.getProperties();
		if (properties == null) {
			return null;
		}
		return properties.get(key);
	}

	private HTMLElement generateUTF8CharsetElement(int indentLevel) {
		HTMLElement meta = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_META, indentLevel, false);
		meta.addAttribute(IIntroHTMLConstants.ATTRIBUTE_HTTP_EQUIV, IIntroHTMLConstants.CONTENT_TYPE);
		meta.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CONTENT, IIntroHTMLConstants.TYPE_HTML_UTF_8);
		return meta;
	}

	private HTMLElement generateJavascriptElement(int indentLevel) {
		String rel = "javascript/common.js"; //$NON-NLS-1$
		String abs = BundleUtil.getResolvedResourceLocation(rel, IntroPlugin.getDefault().getBundle());
		HTMLElement jselement = new FormattedHTMLElement("script", indentLevel, false); //$NON-NLS-1$
		jselement.addAttribute("type", "text/javascript"); //$NON-NLS-1$ //$NON-NLS-2$
		jselement.addAttribute("src", abs); //$NON-NLS-1$
		return jselement;
	}

	/**
	 * Generates the BODY element and its content:
	 *
	 * <pre>
	 *
	 *
	 *                        &lt;BODY&gt;
	 *                        &lt;DIV id=&quot;pageId&quot; class=&quot;pageClass&quot;&gt;
	 *                        page content
	 *                        &lt;/DIV&gt;
	 *                        &lt;/BODY&gt;
	 *
	 * </pre>
	 *
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return the body HTMLElement
	 */
	private HTMLElement generateBodyElement(int indentLevel, HTMLElement head) {
		HTMLElement body = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_BODY, indentLevel, true);
		// Create the div that contains the page content
		String pageId = (introPage.getId() != null) ? introPage.getId() : IIntroHTMLConstants.DIV_ID_PAGE;
		HTMLElement pageContentDiv = generateDivElement(pageId, indentLevel + 1);
		if (introPage.getStyleId() != null)
			pageContentDiv.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, introPage.getStyleId());
		if (introPage.getBackgroundImage() != null)
			pageContentDiv.addAttribute(IIntroHTMLConstants.ATTRIBUTE_STYLE,
					"background-image : url(" + introPage.getBackgroundImage() + ")"); //$NON-NLS-1$ //$NON-NLS-2$

		// Add any children of the page, in the order they are defined
		AbstractIntroElement[] children = introPage.getChildren();
		for (int i = 0; i < children.length; i++) {
			AbstractIntroElement child = children[i];
			// use indentLevel + 2 here, since this element is contained within
			// the pageContentDiv
			HTMLElement childElement = generateIntroElement(child, indentLevel + 2);
			if (childElement != null) {
				addMixinStyle(childElement, child.getMixinStyle());
				pageContentDiv.addContent(childElement);
			}
		}
		body.addContent(pageContentDiv);
		return body;
	}

	/**
	 * Given an IntroElement, generate the appropriate HTMLElement
	 *
	 * @param element
	 *            the IntroElement
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return an HTMLElement
	 */
	private HTMLElement generateIntroElement(AbstractIntroElement element, int indentLevel) {
		if (element == null)
			return null;
		// check to see if this element should be filtered from the HTML
		// presentation
		if (filteredFromPresentation(element))
			return null;
		switch (element.getType()) {
		case AbstractIntroElement.GROUP:
			return generateIntroDiv((IntroGroup) element, indentLevel);
		case AbstractIntroElement.LINK:
			return generateIntroLink((IntroLink) element, indentLevel);
		case AbstractIntroElement.HTML:
			return generateIntroHTML((IntroHTML) element, indentLevel);
		case AbstractIntroElement.CONTENT_PROVIDER:
			return generateIntroContent((IntroContentProvider) element, indentLevel);
		case AbstractIntroElement.IMAGE:
			return generateIntroImage((IntroImage) element, indentLevel);
		case AbstractIntroElement.HR:
			return generateIntroSeparator((IntroSeparator) element, indentLevel);
		case AbstractIntroElement.TEXT:
			return generateIntroText((IntroText) element, indentLevel);
		case AbstractIntroElement.PAGE_TITLE:
			return generateIntroTitle((IntroPageTitle) element, indentLevel);
		case AbstractIntroElement.INJECTED_IFRAME:
			return generateIntroInjectedIFrame((IntroInjectedIFrame) element, indentLevel);
		default:
			return null;
		}
	}

	/**
	 * Create a div element and its content from an IntroDiv:
	 *
	 * <pre>
	 *
	 *
	 *                        &lt;div id=&quot;attrvalue&quot;&gt;
	 *                        &lt;h4&gt;&lt;span class=&quot;div-label&quot;&gt;attrvalue&lt;/span&gt;&lt;h4&gt;
	 *                        any defined divs, links, html, images, text, includes
	 *                        &lt;/div&gt;
	 *
	 * </pre>
	 *
	 * @param element
	 *            the IntroDiv
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return a div HTMLElement
	 */
	private HTMLElement generateIntroDiv(IntroGroup element, int indentLevel) {
		// Create the outer div element
		HTMLElement divElement = generateDivElement(element.getId(), indentLevel);
		HTMLElement childContainer = divElement;
		// if a div class was specified, add it
		if (element.getStyleId() != null)
			divElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, element.getStyleId());
		// Create the div label, if specified
		if (element.getLabel() != null) {
			if (element.isExpandable()) {
				HTMLElement divLabel = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_SPAN,
						indentLevel + 2, false);
				divLabel.addContent(element.getLabel());
				divLabel.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS,
												"section-title");//$NON-NLS-1$
				String clientId = element.getId() + "-content"; //$NON-NLS-1$
				String toggleClosedId = element.getId() + "-toggle-closed"; //$NON-NLS-1$
				String toggleOpenId = element.getId() + "-toggle-open"; //$NON-NLS-1$
				String href = "#"; //$NON-NLS-1$
				HTMLElement link = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_ANCHOR,
						indentLevel + 1, true);
				link.addAttribute(IIntroHTMLConstants.ATTRIBUTE_HREF, href);
				link.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, "section-title-link"); //$NON-NLS-1$
				StringBuilder call = new StringBuilder();
				call.append("return (toggleSection('");//$NON-NLS-1$
				call.append(clientId);
				call.append("','");//$NON-NLS-1$
				call.append(toggleClosedId);
				call.append("','");//$NON-NLS-1$
				call.append(toggleOpenId);
				call.append("'))"); //$NON-NLS-1$
				link.addAttribute("onClick", call.toString()); //$NON-NLS-1$
				link.addContent(divLabel);
				divElement.addContent(link);
				// Add toggle images
				HTMLElement toggleImageClosed = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_IMG,
						indentLevel + 2, false, false);
				toggleImageClosed.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, toggleClosedId);
				toggleImageClosed.addAttribute(IIntroHTMLConstants.ATTRIBUTE_SRC, BundleUtil
						.getResolvedResourceLocation(IIntroHTMLConstants.IMAGE_SRC_BLANK,
								IIntroConstants.PLUGIN_ID));
				toggleImageClosed.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, "section-toggle-image-closed"); //$NON-NLS-1$
				if (element.isExpanded())
					toggleImageClosed.addAttribute(IIntroHTMLConstants.ATTRIBUTE_STYLE, "display: none"); //$NON-NLS-1$
				link.addContent(toggleImageClosed);
				HTMLElement toggleImageOpen = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_IMG,
						indentLevel + 2, false, false);
				toggleImageOpen.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, toggleOpenId);
				toggleImageOpen.addAttribute(IIntroHTMLConstants.ATTRIBUTE_SRC, BundleUtil
						.getResolvedResourceLocation(IIntroHTMLConstants.IMAGE_SRC_BLANK,
								IIntroConstants.PLUGIN_ID));
				toggleImageOpen.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, "section-toggle-image-open"); //$NON-NLS-1$
				if (element.isExpanded())
					toggleImageOpen.addAttribute(IIntroHTMLConstants.ATTRIBUTE_STYLE, "display: inline"); //$NON-NLS-1$
				link.addContent(toggleImageOpen);
				childContainer = generateDivElement(clientId, indentLevel + 1);
				childContainer.addAttribute("class", "section-body"); //$NON-NLS-1$//$NON-NLS-2$
				if (element.isExpanded())
					childContainer.addAttribute(IIntroHTMLConstants.ATTRIBUTE_STYLE, "display: block"); //$NON-NLS-1$
				divElement.addContent(childContainer);
			} else {
				HTMLElement divLabel = generateTextElement(IIntroHTMLConstants.ELEMENT_H4, null,
						IIntroHTMLConstants.SPAN_CLASS_DIV_LABEL, element.getLabel(), indentLevel + 1);
				divElement.addContent(divLabel);
			}
		}
		if (element.getBackgroundImage() != null) {
			String imageUrl = element.getBackgroundImage();
			imageUrl = BundleUtil.getResolvedResourceLocation(element.getBase(), imageUrl, element
					.getBundle());
			String style;
			if (Platform.getWS().equals(Platform.WS_WIN32) && !backgroundSizeWorks && imageUrl.toLowerCase().endsWith(".png")) { //$NON-NLS-1$
				// IE 5.5+ does not handle alphas in PNGs without
				// this hack. Remove when IE7 becomes widespread
				style = "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + imageUrl + "', sizingMethod='crop');"; //$NON-NLS-1$ //$NON-NLS-2$
			} else {
				style = "background-image : url(" + imageUrl + ")"; //$NON-NLS-1$ //$NON-NLS-2$
			}
			divElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_STYLE, style);
		}
		// Add any children of the div, in the order they are defined
		AbstractIntroElement[] children = element.getChildren();
		for (int i = 0; i < children.length; i++) {
			AbstractIntroElement child = children[i];
			HTMLElement childElement = generateIntroElement(child, indentLevel + 1);
			if (childElement != null) {
				addMixinStyle(childElement, child.getMixinStyle());
				childContainer.addContent(childElement);
			}
		}
		return divElement;
	}

	private void addMixinStyle(HTMLElement element, String mixinStyle) {
		if (mixinStyle == null)
			return;
		String key = "class"; //$NON-NLS-1$
		String original = element.getElementAttributes().get(key);
		if (original == null)
			original = mixinStyle;
		else
			original += " " + mixinStyle; //$NON-NLS-1$
		element.addAttribute(key, original);
	}

	/**
	 * Generates an anchor (link) element and its content from an IntroLink:
	 *
	 * <pre>
	 *
	 *                        &lt;A id=linkId class=&quot;link&quot; href=linkHref&gt;
	 *                        &lt;IMG src=&quot;blank.gif&quot;&gt;
	 *                        &lt;SPAN class=&quot;link-label&quot;&gt;linkLabel &lt;/SPAN&gt;
	 *                        &lt;P&gt;&lt;SPAN&gt;text&lt;/SPAN&gt;&lt;/P&gt;
	 *                        &lt;/A&gt;
	 *
	 * </pre>
	 *
	 * @param element
	 *            the IntroLink
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return an anchor (&lt;A&gt;) HTMLElement
	 */
	private HTMLElement generateIntroLink(IntroLink element, int indentLevel) {
		String styleId = element.getStyleId();
		boolean useTable = ProductPreferences.isRTL() && "content-link".equals(styleId); //$NON-NLS-1$
		HTMLElement anchor1 = generateAnchorElement(element, indentLevel);
		HTMLElement anchor2 = null;
		HTMLElement labelAnchor = anchor1;
		int indentBase = indentLevel;
		if (useTable) {
			indentBase = indentLevel + 1;
			anchor2 = generateAnchorElement(element, indentLevel + 1);
			labelAnchor = anchor2;
		}
		// add <IMG src="blank.gif">
		String blankImageURL = BundleUtil.getResolvedResourceLocation(IIntroHTMLConstants.IMAGE_SRC_BLANK,
				IIntroConstants.PLUGIN_ID);
		if (blankImageURL != null) {
			anchor1.addContent(generateImageElement(blankImageURL, null, null, IIntroHTMLConstants.IMAGE_CLASS_BG,
					indentBase + 1));
		}
		// add link image, if one is specified
		if (element.getImg() != null) {
			HTMLElement img = generateIntroElement(element.getImg(), indentBase + 1);
			if (img != null)
				anchor1.addContent(img);
		}
		if (!useTable) {
			HTMLElement imageDiv = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_DIV, indentBase+1, false);
			imageDiv.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS,
					IIntroHTMLConstants.LINK_EXTRA_DIV);
			anchor1.addContent(imageDiv);
		}
		// add <SPAN class="link-label">linkLabel</SPAN>
		if (element.getLabel() != null) {
			HTMLElement label = generateSpanElement(IIntroHTMLConstants.SPAN_CLASS_LINK_LABEL,
					indentBase + 2);
			label.addContent(element.getLabel());
			labelAnchor.addContent(label);
		}
		IntroText linkText = element.getIntroText();
		if (linkText != null && linkText.getText() != null) {
			HTMLElement text = generateIntroElement(linkText, indentBase + 3);
			if (text != null)
				labelAnchor.addContent(text);
		}
		if (!useTable) {
			return anchor1;
		}
		HTMLElement table = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_TABLE, indentLevel, false);
		HTMLElement tr = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_TR, indentLevel + 1, false);
		table.addContent(tr);
		HTMLElement td1 = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_TD, indentLevel + 1, false);
		HTMLElement td2 = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_TD, indentLevel + 1, false);
		tr.addContent(td1);
		tr.addContent(td2);
		td1.addContent(anchor1);
		td2.addContent(anchor2);
		return table;
	}

	/**
	 * Generate the appropriate HTML from an IntroHTML. If the IntroHTML type is "inline", then the
	 * content from the referenced file is emitted as-is into a div element. If the type is "embed",
	 * an OBJECT html element is created whose <code>data</code> attribute is equal to the
	 * IntroHTML's <code>src</code> value
	 *
	 * @param element
	 *            the IntroHTML
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return an HTMLElement
	 */
	private HTMLElement generateIntroHTML(IntroHTML element, int indentLevel) {
		if (element.isInlined())
			return generateInlineIntroHTML(element, indentLevel);

		return generateEmbeddedIntroHTML(element, indentLevel);
	}

	/**
	 * Generate an image element from an IntroImage:
	 *
	 * <pre>
	 *
	 *                        &lt;IMG src=imageSrc id=imageId&gt;
	 *
	 * </pre>
	 *
	 * @param element
	 *            the IntroImage
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return an img HTMLElement
	 */
	private HTMLElement generateIntroImage(IntroImage element, int indentLevel) {
		HTMLElement imageElement = generateImageElement(element.getSrc(), element.getAlt(),element.getTitle(), element
				.getStyleId(), indentLevel);
		if (element.getId() != null)
			imageElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, element.getId());
		return imageElement;
	}

	private HTMLElement generateIntroSeparator(IntroSeparator element, int indentLevel) {
		HTMLElement hrElement = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_HR, indentLevel, false);
		if (element.getId() != null)
			hrElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, element.getId());
		if (element.getStyleId() != null)
			hrElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_STYLE, element.getStyleId());
		return hrElement;
	}

	/**
	 * Generate a paragraph (&lt;P&gt;) element from an IntroText. The paragraph element will
	 * contain a span element that will contain the actual text. Providing the span element provides
	 * additional flexibility for CSS designers.
	 *
	 * <pre>
	 *
	 *
	 *                        &lt;P&gt;&lt;SPAN&gt;spanContent&lt;/SPAN&gt;&lt;/P&gt;
	 *
	 * </pre>
	 *
	 * @param element
	 *            the IntroText
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return a paragraph HTMLElement
	 */
	private HTMLElement generateIntroText(IntroText element, int indentLevel) {
		String spanClass = (element.getStyleId() != null) ? element.getStyleId()
				: IIntroHTMLConstants.SPAN_CLASS_TEXT;
		HTMLElement textElement = generateTextElement(IIntroHTMLConstants.ELEMENT_PARAGRAPH, element.getId(),
				spanClass, element.getText(), indentLevel);
		return textElement;
	}

	/**
	 * @param element
	 * @param indentLevel
	 * @return
	 */
	private HTMLElement generateIntroInjectedIFrame(IntroInjectedIFrame element, int indentLevel) {
		HTMLElement iframe = generateIFrameElement(element.getIFrameURL(), "0", //$NON-NLS-1$
				"auto", indentLevel); //$NON-NLS-1$
		return iframe;
	}

	/**
	 * @param element
	 * @param indentLevel
	 * @return
	 */
	private HTMLElement generateIntroTitle(IntroPageTitle element, int indentLevel) {
		HTMLElement titleElement = generateHeaderDiv(element.getId(), element.getStyleId(),
				IIntroHTMLConstants.ELEMENT_H1, element.getTitle(), indentLevel);
		return titleElement;
	}

	/**
	 * Generate "inline" content from an IntroHTML. The content from the file referenced by the
	 * IntroHTML's <code>src</code> attribute is emitted as-is into a div element:
	 *
	 * <pre>
	 *
	 *
	 *                        &lt;div id=&quot;attrvalue&quot; class=&quot;attrvalue2&quot;&gt;
	 *                        content from file specified in src attribute
	 *                        &lt;/div&gt;
	 *
	 * </pre>
	 *
	 * @param element
	 *            the IntroHTML
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return a div HTMLElement, or null if there was a problem reading from the file
	 */
	private HTMLElement generateInlineIntroHTML(IntroHTML element, int indentLevel) {
		// make sure to ask model for encoding. If encoding is null (ie: not
		// specified in
		// markup, local encoding is used.
		StringBuilder content = readFromFile(element.getSrc(), element.getInlineEncoding());
		if (content != null && content.length() > 0) {
			// Create the outer div element
			String divClass = (element.getStyleId() != null) ? element.getStyleId()
					: IIntroHTMLConstants.DIV_CLASS_INLINE_HTML;
			HTMLElement divElement = generateDivElement(element.getId(), divClass, indentLevel);
			// add the content of the specified file into the div element
			divElement.addContent(content);
			return divElement;
		}
		return null;
	}

	/**
	 * Includes HTML content that is created by an IIntroContentProvider implementation.
	 *
	 * @param element
	 * @param indentLevel
	 * @return
	 */
	private HTMLElement generateIntroContent(IntroContentProvider element, int indentLevel) {
		// create a new div to wrap the content
		HTMLElement divElement = generateDivElement(element.getId(),
				IIntroHTMLConstants.DIV_CLASS_PROVIDED_CONTENT, indentLevel);

		// If we've already loaded the content provider for this element,
		// retrieve it, otherwise load the class
		IIntroContentProvider providerClass = ContentProviderManager.getInst().getContentProvider(element);
		if (providerClass == null)
			// content provider never created before, create it.
			providerClass = ContentProviderManager.getInst().createContentProvider(element, providerSite);

		if (providerClass != null) {
			StringWriter stringWriter = new StringWriter();
			try (PrintWriter pw = new PrintWriter(stringWriter)) {
				// create the specialized content
				providerClass.createContent(element.getId(), pw);
				// add the content of the specified file into the div element
				stringWriter.flush();
				divElement.addContent(stringWriter.toString());
			}
		} else {
			// we couldn't load the content provider, so add any alternate
			// text content if there is any
			IntroText htmlText = element.getIntroText();
			if (htmlText != null && htmlText.getText() != null) {
				String textClass = (htmlText.getStyleId() != null) ? htmlText.getStyleId()
						: IIntroHTMLConstants.SPAN_CLASS_TEXT;
				HTMLElement text = generateTextElement(IIntroHTMLConstants.ELEMENT_PARAGRAPH, htmlText
						.getId(), textClass, element.getText(), indentLevel);
				if (text != null)
					divElement.addContent(text);
			}
		}
		return divElement;
	}

	/**
	 * Generate "embedded" content from an IntroHTML. An OBJECT html element is created whose
	 * <code>data</code> attribute is equal to the IntroHTML's <code>src</code> value.
	 *
	 * <pre>
	 *
	 *                        &lt;OBJECT type=&quot;text/html&quot; data=&quot;attrvalue&quot;&gt;
	 *                        alternative text in case the object can not be rendered
	 *                        &lt;/OBJECT&gt;
	 *
	 * </pre>
	 *
	 * @param element
	 *            the IntroHTML
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return an object HTMLElement
	 */
	private HTMLElement generateEmbeddedIntroHTML(IntroHTML element, int indentLevel) {
		HTMLElement objectElement = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_OBJECT, indentLevel,
				true);
		objectElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_TYPE, IIntroHTMLConstants.OBJECT_TYPE);
		if (element.getId() != null)
			objectElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, element.getId());
		if (element.getSrc() != null)
			objectElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_DATA, element.getSrc());
		if (element.getStyleId() != null)
			objectElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, element.getStyleId());
		// The alternative content is added in case the browser can not render
		// the specified content.
		IntroText htmlText = element.getIntroText();
		if (htmlText != null && htmlText.getText() != null) {
			String textClass = (htmlText.getStyleId() != null) ? htmlText.getStyleId()
					: IIntroHTMLConstants.SPAN_CLASS_TEXT;
			HTMLElement text = generateTextElement(IIntroHTMLConstants.ELEMENT_PARAGRAPH, htmlText.getId(),
					textClass, element.getText(), indentLevel);
			if (text != null)
				objectElement.addContent(text);
		}
		if (element.getIntroImage() != null) {
			HTMLElement img = generateIntroImage(element.getIntroImage(), indentLevel);
			if (img != null)
				objectElement.addContent(img);
		}
		return objectElement;
	}

	/**
	 * Generates the BASE element for the head of the html document. Each document can have only one
	 * base element
	 *
	 * <pre>
	 *
	 *
	 *                      	&lt;BASE href=baseURL&gt;
	 * </pre>
	 *
	 * @param indentLevel
	 * @param baseURL
	 * @return
	 */
	private HTMLElement generateBaseElement(int indentLevel, String baseURL) {
		HTMLElement base = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_BASE, indentLevel, true,
				false);
		if (baseURL != null)
			base.addAttribute(IIntroHTMLConstants.ATTRIBUTE_HREF, baseURL);
		return base;
	}

	/**
	 * Generates the style element that goes into HEAD:
	 *
	 * <pre>
	 *
	 *                        &lt;style type=&quot;text/css&quot;&gt;HTML, IMG { border: 0px; } &lt;/style&gt;
	 *
	 * </pre>
	 *
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return the style HTMLElement
	 */
	private HTMLElement generateStyleElement(int indentLevel) {
		HTMLElement style = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_STYLE, indentLevel, false);
		style.addAttribute(IIntroHTMLConstants.ATTRIBUTE_TYPE, IIntroHTMLConstants.LINK_STYLE);
		style.addContent(IIntroHTMLConstants.STYLE_HTML);
		IntroTheme theme = introPage.getModelRoot().getTheme();
		if (theme != null && theme.isScalable()
				&& FontSelection.FONT_RELATIVE.equals(FontSelection.getFontStyle())) {
			String sizeStyle = FontSelection.generatePageFontStyle();
			style.addContent(sizeStyle);
		}
		return style;
	}

	/**
	 * Generates the title element and its content:
	 *
	 * <pre>
	 *
	 *                        &lt;TITLE&gt;intro title&lt;/TITLE&gt;
	 *
	 * </pre>
	 *
	 * @param title
	 *            the title of this intro page
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return the title HTMLElement
	 */
	private HTMLElement generateTitleElement(String title, int indentLevel) {
		HTMLElement titleElement = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_TITLE, indentLevel,
				false);
		if (title != null)
			titleElement.addContent(title);
		return titleElement;
	}

	/**
	 * Generates a link element that refers to a cascading style sheet (CSS):
	 *
	 * <pre>
	 *
	 *
	 *                        &lt;LINK rel=&quot;stylesheet&quot; style=&quot;text/css&quot; href=&quot;style sheet&quot;&gt;
	 * </pre>
	 *
	 * @param href
	 *            the value of the href attribute for this link element
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return a link HTMLElement
	 */
	private HTMLElement generateLinkElement(String href, int indentLevel) {
		HTMLElement link = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_LINK, indentLevel, true,
				false);
		link.addAttribute(IIntroHTMLConstants.ATTRIBUTE_RELATIONSHIP, IIntroHTMLConstants.LINK_REL);
		link.addAttribute(IIntroHTMLConstants.ATTRIBUTE_TYPE, IIntroHTMLConstants.LINK_STYLE);
		if (href != null)
			link.addAttribute(IIntroHTMLConstants.ATTRIBUTE_HREF, href);
		return link;
	}

	/**
	 * Generate an anchor element:
	 *
	 * <pre>
	 *
	 *                        &lt;A id=linkId class=linkClass href=linkHref&gt; &lt;/A&gt;
	 *
	 * </pre>
	 *
	 * @param link
	 *            the IntroLink element that contains the value for the id and href attributes
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return an anchor (&lt;A&gt;) HTMLElement
	 */
	private HTMLElement generateAnchorElement(IntroLink link, int indentLevel) {
		HTMLElement anchor = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_ANCHOR, indentLevel, true);
		if (link.getId() != null)
			anchor.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, link.getId());
		if (link.getUrl() != null)
			anchor.addAttribute(IIntroHTMLConstants.ATTRIBUTE_HREF, link.getUrl());
		if (link.getStyleId() != null)
			anchor.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, link.getStyleId());
		else
			anchor.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, IIntroHTMLConstants.ANCHOR_CLASS_LINK);
		return anchor;
	}

	/**
	 * Generates a div block that contains a header and span element:
	 *
	 * <pre>
	 *
	 *
	 *                        &lt;DIV id=divId&gt;
	 *                        &lt;H&gt;&lt;SPAN&gt;spanContent &lt;/SPAN&gt; &lt;/H&gt;
	 *                        &lt;/DIV&gt;
	 *
	 * </pre>
	 *
	 * @param divId
	 *            the id of the div to create
	 * @param divClass
	 *            the class of the div
	 * @param headerType
	 *            what type of header to create (e.g., H1, H2, etc)
	 * @param spanContent
	 *            the span content
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return a div HTMLElement that contains a header
	 */
	private HTMLElement generateHeaderDiv(String divId, String divClass, String headerType,
			String spanContent, int indentLevel) {
		// create the text element: <P><SPAN>spanContent</SPAN></P>
		HTMLElement text = generateTextElement(headerType, null, null, spanContent, indentLevel + 1);
		// create the containing div element
		HTMLElement div = generateDivElement(divId, divClass, indentLevel);
		div.addContent(text);
		return div;
	}

	/**
	 * Generates a span element inside a text element, where the text element can be a P
	 * (paragraph), or any of the H (Header) elements. Providing the span element provides
	 * additional flexibility for CSS designers.
	 *
	 * <pre>
	 *
	 *                        &lt;P&gt;&lt;SPAN&gt;spanContent&lt;/SPAN&gt;&lt;/P&gt;
	 *
	 * </pre>
	 *
	 * @param type
	 *            the type of text element to create (e.g., P, H1, H2, etc)
	 * @param spanID
	 *            the id of the span element, or null
	 * @param spanClass
	 *            the class of the span element, or null
	 * @param spanContent
	 *            the span content
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return a text HTMLElement that contains a span element
	 */
	private HTMLElement generateTextElement(String type, String spanID, String spanClass, String spanContent,
			int indentLevel) {
		// Create the span: <SPAN>spanContent</SPAN>
		HTMLElement span = new HTMLElement(IIntroHTMLConstants.ELEMENT_SPAN);
		if (spanID != null)
			span.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, spanID);
		if (spanClass != null)
			span.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, spanClass);
		if (spanContent != null)
			span.addContent(spanContent);
		if (type != null) {
		// Create the enclosing text element: <P><SPAN>spanContent</SPAN></P>
		HTMLElement text = new FormattedHTMLElement(type, indentLevel, false);
		text.addContent(span);
		return text;
		} else {
			return span;
		}
	}

	/**
	 * Generates a DIV element with the provided indent, id, and class.
	 *
	 * @param divId
	 *            value for the div's id attribute
	 * @param divClass
	 *            value for the div's class attribute
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return a div HTMLElement
	 */
	private HTMLElement generateDivElement(String divId, String divClass, int indentLevel) {
		HTMLElement div = generateDivElement(divId, indentLevel);
		div.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, divClass);
		return div;
	}

	/**
	 * Generates a DIV element with the provided indent and id.
	 *
	 * @param divId
	 *            value for the div's id attribute
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return a div HTMLElement
	 */
	private HTMLElement generateDivElement(String divId, int indentLevel) {
		HTMLElement div = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_DIV, indentLevel, true);
		if (divId != null)
			div.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, divId);
		return div;
	}

	/**
	 * Generates an IMG element:
	 *
	 * <pre>
	 *
	 *
	 *                        &lt;IMG src=imageSrc alt=altText&gt;
	 *
	 * </pre>
	 *
	 * @param imageSrc
	 *            the value to be supplied to the src attribute
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return an img HTMLElement
	 */
	private HTMLElement generateImageElement(String imageSrc, String altText, String title, String imageClass,
			int indentLevel) {
		HTMLElement image = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_IMG, indentLevel, true,
				false);
		boolean pngOnWin32 = imageSrc != null && Platform.getWS().equals(Platform.WS_WIN32)
				&& !backgroundSizeWorks && imageSrc.toLowerCase().endsWith(".png"); //$NON-NLS-1$
		if (imageSrc == null || pngOnWin32) {
			// we must handle PNGs here - IE does not support alpha blanding well.
			// We will set the alpha image loader and load the real image
			// that way. The 'src' attribute in the image itself will
			// get the blank image.
			String blankImageURL = BundleUtil.getResolvedResourceLocation(
					IIntroHTMLConstants.IMAGE_SRC_BLANK, IIntroConstants.PLUGIN_ID);
			if (blankImageURL != null) {
				image.addAttribute(IIntroHTMLConstants.ATTRIBUTE_SRC, blankImageURL);
				if (pngOnWin32) {
					String style = "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + imageSrc + "', sizingMethod='image')"; //$NON-NLS-1$//$NON-NLS-2$
					image.addAttribute(IIntroHTMLConstants.ATTRIBUTE_STYLE, style);
				}
			}
		} else
			image.addAttribute(IIntroHTMLConstants.ATTRIBUTE_SRC, imageSrc);
		if (altText == null)
			altText = ""; //$NON-NLS-1$
		image.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ALT, altText);
		if (title != null) {
			image.addAttribute(IIntroHTMLConstants.ATTRIBUTE_TITLE, title);
		}
		if (imageClass != null)
			image.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, imageClass);
		return image;
	}

	/**
	 * Generate a span element
	 *
	 * <pre>
	 *
	 *                        &lt;SPAN class=spanClass&gt; &lt;/SPAN&gt;
	 *
	 *
	 * </pre>
	 *
	 * @param spanClass
	 *            the value to be supplied to the class attribute
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return a span HTMLElement
	 */
	private HTMLElement generateSpanElement(String spanClass, int indentLevel) {
		HTMLElement span = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_SPAN, indentLevel, false);
		span.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, spanClass);
		return span;
	}

	/**
	 * Generate a span element
	 *
	 * <pre>
	 *
	 *                     &lt;iframe src=&quot;localPage1.xhtml&quot; frameborder=&quot;1&quot; scrolling=&quot;auto&quot; longdesc=&quot;localPage1.xhtml&quot;&gt;
	 * </pre>
	 *
	 * @param spanClass
	 *            the value to be supplied to the class attribute
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is printed
	 * @return a span HTMLElement
	 */
	private HTMLElement generateIFrameElement(String src, String frameborder, String scrolling,
			int indentLevel) {
		HTMLElement iframe = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_IFrame, indentLevel, false);
		if (src != null)
			iframe.addAttribute(IIntroHTMLConstants.ATTRIBUTE_SRC, src);
		if (frameborder != null)
			iframe.addAttribute(IIntroHTMLConstants.ATTRIBUTE_FRAMEBORDER, frameborder);
		if (scrolling != null)
			iframe.addAttribute(IIntroHTMLConstants.ATTRIBUTE_SCROLLING, scrolling);
		return iframe;
	}




	private boolean filteredFromPresentation(AbstractIntroElement element) {
		if (element.isOfType(AbstractIntroElement.BASE_ELEMENT))
			return ((AbstractBaseIntroElement) element).isFiltered();

		return false;
	}

	/**
	 * Reads the content of the file referred to by the <code>src</code> parameter and returns the
	 * content in the form of a StringBuilder. If the file read contains substitution segments of the
	 * form $plugin:plugin_id$ then this method will make the proper substitution (the segment will
	 * be replaced with the absolute path to the plugin with id plugin_id).
	 *
	 * @param src -
	 *            the file that contains the target conent
	 * @param charsetName -
	 *            the encoding of the file to be read. If null, local encoding is used. But the
	 *            default of the model is UTF-8, so we should not get a null encoding.
	 * @return a StringBuilder containing the content in the file, or null
	 */
	private StringBuilder readFromFile(String src, String charsetName) {
		if (src == null)
			return null;
		InputStream stream = null;
		StringBuilder content = new StringBuilder();
		BufferedReader reader = null;
		try {
			URL url = new URL(src);
			stream = url.openStream();
			// TODO: Do we need to worry about the encoding here? e.g.:
			// reader = new BufferedReader(new InputStreamReader(stream,
			// ResourcesPlugin.getEncoding()));
			if (charsetName == null)
				reader = new BufferedReader(new InputStreamReader(stream));
			else
				reader = new BufferedReader(new InputStreamReader(stream, charsetName));
			while (true) {
				int character = reader.read();
				if (character == -1) // EOF
					break; // done reading file

				else if (character == PluginIdParser.SUBSTITUTION_BEGIN) { // possible
					// substitution
					PluginIdParser parser = new PluginIdParser(character, reader);
					// If a valid plugin id was found in the proper format, text
					// will be the absolute path to that plugin. Otherwise, text
					// will simply be all characters read up to (but not
					// including)
					// the next dollar sign that follows the one just found.
					String text = parser.parsePluginId();
					if (text != null)
						content.append(text);
				} else {
					// make sure character is in char range before making cast
					if (character > 0x00 && character < 0xffff)
						content.append((char) character);
					else
						content.append(character);
				}
			}
		} catch (Exception exception) {
			Log.error("Error reading from file", exception); //$NON-NLS-1$
		} finally {
			try {
				if (reader != null)
					reader.close();
				if (stream != null)
					stream.close();
			} catch (IOException e) {
				Log.error("Error closing input stream", e); //$NON-NLS-1$
				return null;
			}
		}
		return content;
	}

	/**
	 * A helper class to help identify substitution strings in a content file. A properly formatted
	 * substitution string is of the form: <code>$plugin:plugin_id$</code> where plugin_id is the
	 * valid id of an installed plugin. The substitution string will be replaced with the absolute
	 * path to the plugin.
	 *
	 * An example usage of the string substution: The html file <code>inline.html</code> is
	 * included in your intro via the html inline mechanism . This file needs to reference a
	 * resource that is located in another plugin. The following might be found in inline.html:
	 * {@code
	 *    <a href="$plugin:test.plugin$html/test.html">link to file</a>
	 * } When this file
	 * is read in, the relevant section will be replaced as follows: {@code
	 *   <a href="file:/install_path/plugins/test.plugin/html/test.html">link to file</a>
	 * }
	 */
	private static class PluginIdParser {

		private BufferedReader reader;

		private static final char SUBSTITUTION_BEGIN = '$';

		private static final char SUBSTITUTION_END = '$';

		// tokenContent will contain all characters read by the parser, starting
		// with and including the initial $ token.
		private StringBuilder tokenContent;

		// pluginId will contain the content between the "$plugin:" segment
		// and the closing "$" token
		private StringBuilder pluginId;

		protected PluginIdParser(int tokenBegin, BufferedReader bufferedreader) {
			reader = bufferedreader;
			tokenContent = new StringBuilder();
			pluginId = new StringBuilder();
			// make sure tokenBegin is in char range before making cast
			if (tokenBegin > 0x00 && tokenBegin < 0xffff)
				tokenContent.append((char) tokenBegin);
		}

		/**
		 * This method should be called after the initial substitution identifier has been read in
		 * (the substition string begins and ends with the "$" character). A properly formatted
		 * substitution string is of the form: <code>"$plugin:plugin_id$</code>- the initial "$"
		 * is immediately followed by the "plugin:" segment - the <code>plugin_id </code> refers to
		 * a valid, installed plugin - the substitution string is terminated by a closing "$" If the
		 * above conditions are not met, no substitution occurs. If the above conditions are met,
		 * the content between (and including) the opening and closing "$" characters will be
		 * replaced by the absolute path to the plugin
		 *
		 * @return
		 */
		protected String parsePluginId() {
			if (reader == null || tokenContent == null || pluginId == null)
				return null;

			try {
				// Mark the current position of the reader so we can roll
				// back to this point if the proper "plugin:" segment is not
				// found.
				// Use 1024 as our readAheadLimit
				reader.mark(0x400);
				if (findValidPluginSegment()) {
					String pluginPath = getPluginPath();
					if (pluginPath == null) {
						// Didn't find a valid plugin id.
						// return tokenContent, which contains all characters
						// read up to (not including) the last $. (if the
						// last $ is part of a subsequent "$plugin:" segment
						// it can still be processed properly)
						return tokenContent.toString();
					}
					return pluginPath;
				}

				// The "plugin:" segment was not found. Reset the reader
				// so we can continue reading character by character.
				reader.reset();
				return tokenContent.toString();

			} catch (IOException exception) {
				Log.error("Error reading from file", exception); //$NON-NLS-1$
				return tokenContent.toString();
			}
		}

		/**
		 * This method should be called after an initial substitution character has been found (that
		 * is, after a $). It looks at the subsequent characters in the input stream to determine if
		 * they match the expected <code>plugin:</code> segment of the substitution string. If the
		 * expected characters are found, they will be appended to the tokenContent StringBuilder and
		 * the method will return true. If they are not found, false is returned and the caller
		 * should reset the BufferedReader to the position it was in before this method was called.
		 *
		 * Resetting the reader ensures that the characters read in this method can be re-examined
		 * in case one of them happens to be the beginning of a valid substitution segment.
		 *
		 * @return true if the next characters match <code>plugin:</code>, and false otherwise.
		 */
		private boolean findValidPluginSegment() {
			final char[] PLUGIN_SEGMENT = { 'p', 'l', 'u', 'g', 'i', 'n', ':' };
			char[] streamContent = new char[PLUGIN_SEGMENT.length];
			try {
				int peek = reader.read(streamContent, 0, PLUGIN_SEGMENT.length);
				if ((peek == PLUGIN_SEGMENT.length)
						&& (HTMLUtil.equalCharArrayContent(streamContent, PLUGIN_SEGMENT))) {
					// we have found the "$plugin:" segment
					tokenContent.append(streamContent);
					return true;
				}
				// The "plugin:" segment did not immediately follow the initial
				// $.
				return false;
			} catch (IOException exception) {
				Log.error("Error reading from file", exception); //$NON-NLS-1$
				return false;
			}
		}

		/**
		 * This method continues to read from the input stream until either the end of the file is
		 * reached, or until a character is found that indicates the end of the substitution. If the
		 * SUBSTITUTION_END character is found, the method looks up the plugin id that has been
		 * built up to see if it is a valid id. If so, return the absolute path to that plugin. If
		 * not, return null.
		 *
		 * This method assumes that the reader is positioned just after a valid <code>plugin:</code>
		 * segment in a substitution string.
		 *
		 * @return absolute path of the plugin id, if valid. null otherwise
		 */
		private String getPluginPath() {
			try {
				while (true) {
					int nextChar = reader.read();

					if (nextChar == -1) {
						// reached EOF while looking for closing $
						return null;
					} else if (nextChar == SUBSTITUTION_END) { // end of plugin
						// id
						// look up the plugin id. If it is a valid id
						// return the absolute path to this plugin.
						// otherwise return null.
						String path = BundleUtil.getResolvedBundleLocation(pluginId.toString());

						// If the plugin id was not valid, reset reader to the
						// previous mark. The mark should be at the character
						// just before the last dollar sign.
						if (path == null)
							reader.reset();

						return path;
					} else { // we have a regular character
						// mark the most recent non-dollar char in case we don't
						// find a valid plugin id and have to roll back
						// Use 1024 as our readAheadLimit
						reader.mark(0x400);
						// Add this character to the pluginId and tokenContent
						// String.
						// make sure we have a valid character before performing
						// cast
						if (nextChar > 0x00 && nextChar < 0xffff) {
							tokenContent.append((char) nextChar);
							// only include non-whitespace characters in plugin
							// id
							if (!Character.isWhitespace((char) nextChar))
								pluginId.append((char) nextChar);
						} else {
							tokenContent.append(nextChar);
							pluginId.append(nextChar);
						}
					}
				}
			} catch (IOException exception) {
				Log.error("Error reading from file", exception); //$NON-NLS-1$
				return null;
			}
		}
	}

}
