/***************************************************************************************************
 * 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.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.net.URL;

import org.eclipse.core.runtime.Platform;
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.loader.ContentProviderManager;
import org.eclipse.ui.internal.intro.impl.model.util.BundleUtil;
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;

	/**
	 * 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;

		// 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 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);
		// add the title
		head.addContent(generateTitleElement(null, 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:
		StringBuffer 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;
	}

	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$
				StringBuffer call = new StringBuffer();
				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);
				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$
				link.addContent(toggleImageClosed);
				HTMLElement toggleImageOpen = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_IMG,
						indentLevel + 2, 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$
				link.addContent(toggleImageOpen);
				childContainer = generateDivElement(clientId, indentLevel + 1);
				childContainer.addAttribute("class", "section-body"); //$NON-NLS-1$//$NON-NLS-2$
				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) && 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 = (String) 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) {
		HTMLElement anchor = generateAnchorElement(element, indentLevel);
		// add <IMG src="blank.gif">
		String blankImageURL = BundleUtil.getResolvedResourceLocation(IIntroHTMLConstants.IMAGE_SRC_BLANK,
				IIntroConstants.PLUGIN_ID);
		if (blankImageURL != null) {
			anchor.addContent(generateImageElement(blankImageURL, null, IIntroHTMLConstants.IMAGE_CLASS_BG,
					indentLevel + 1));
		}
		// add link image, if one is specified
		if (element.getImg() != null) {
			HTMLElement img = generateIntroElement(element.getImg(), indentLevel + 1);
			if (img != null)
				anchor.addContent(img);
		}
		HTMLElement imageDiv = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_DIV, indentLevel+1, false);
		imageDiv.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, 
				IIntroHTMLConstants.LINK_EXTRA_DIV);
		anchor.addContent(imageDiv);
		// add <SPAN class="link-label">linkLabel</SPAN>
		if (element.getLabel() != null) {
			HTMLElement label = generateSpanElement(IIntroHTMLConstants.SPAN_CLASS_LINK_LABEL,
					indentLevel + 1);
			label.addContent(element.getLabel());
			anchor.addContent(label);
		}
		IntroText linkText = element.getIntroText();
		if (linkText != null && linkText.getText() != null) {
			HTMLElement text = generateIntroElement(linkText, indentLevel + 1);
			if (text != null)
				anchor.addContent(text);
		}
		return anchor;
	}

	/**
	 * 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
				.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.
		StringBuffer 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();
			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());
			pw.close();
		} 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);
		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_STYLE, 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);
		// Create the enclosing text element: <P><SPAN>spanContent</SPAN></P>
		HTMLElement text = new FormattedHTMLElement(type, indentLevel, false);
		text.addContent(span);
		return text;
	}

	/**
	 * 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 imageClass,
			int indentLevel) {
		HTMLElement image = new FormattedHTMLElement(IIntroHTMLConstants.ELEMENT_IMG, indentLevel, true,
				false);
		boolean pngOnWin32 = imageSrc != null && Platform.getWS().equals(Platform.WS_WIN32)
				&& 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 (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 StringBuffer. 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 StringBuffer containing the content in the file, or null
	 */
	private StringBuffer readFromFile(String src, String charsetName) {
		if (src == null)
			return null;
		InputStream stream = null;
		StringBuffer content = new StringBuffer();
		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>
	 * </code> 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>
	 * </code>
	 * 
	 */
	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 StringBuffer tokenContent;

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

		protected PluginIdParser(char tokenBegin, BufferedReader bufferedreader) {
			reader = bufferedreader;
			tokenContent = new StringBuffer(tokenBegin);
			pluginId = new StringBuffer();
		}

		protected PluginIdParser(int tokenBegin, BufferedReader bufferedreader) {
			reader = bufferedreader;
			tokenContent = new StringBuffer();
			pluginId = new StringBuffer();
			// 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 StringBuffer 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;
			}
		}
	}

}
